Initial support for I2C soft pots on Module17
Initial support for I2C soft pots on Module17, ADC1 driver for input voltage reading. Cherry-picked from Mathis DB9MAT repo. TG-398
This commit is contained in:
parent
d4ba8a5b9c
commit
2fdbf0f236
|
|
@ -310,12 +310,14 @@ dm1801_def = def + mk22fn512_def + {'PLATFORM_DM1801': ''}
|
|||
##
|
||||
mod17_src = src + stm32f405_src + ['platform/targets/Module17/platform.c',
|
||||
'platform/drivers/display/SH110x_Mod17.c',
|
||||
'platform/drivers/ADC/ADC1_Mod17.c',
|
||||
'platform/drivers/keyboard/keyboard_Mod17.c',
|
||||
'platform/drivers/NVM/nvmem_Mod17.c',
|
||||
'platform/drivers/baseband/radio_Mod17.cpp',
|
||||
'platform/drivers/audio/inputStream_Mod17.cpp',
|
||||
'platform/drivers/audio/outputStream_Mod17.c',
|
||||
'platform/drivers/audio/audio_Mod17.c']
|
||||
'platform/drivers/audio/audio_Mod17.c',
|
||||
'platform/drivers/baseband/MCP4551_Mod17.cpp']
|
||||
|
||||
mod17_inc = inc + stm32f405_inc + ['platform/targets/Module17']
|
||||
mod17_def = def + stm32f405_def + {'PLATFORM_MOD17': ''}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ static const uint16_t bat_v_max = 0x0819; // 8.10V
|
|||
#elif defined BAT_LIPO_3S
|
||||
static const uint16_t bat_v_min = 0x0AD4; // 10.83V
|
||||
static const uint16_t bat_v_max = 0x0C73; // 12.45V
|
||||
#elif defined BAT_MOD17
|
||||
static const uint16_t bat_v_min = 0x0600; // 6.00V
|
||||
static const uint16_t bat_v_max = 0x0DCD; // 13.8V
|
||||
#elif defined BAT_NONE
|
||||
static const uint16_t bat_v_min = 0;
|
||||
static const uint16_t bat_v_max = 0;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 by Silvano Seva IU2KWO and Niccolò Izzo IU2KIN *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#include <interfaces/gpio.h>
|
||||
#include <hwconfig.h>
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include "ADC1_Mod17.h"
|
||||
|
||||
pthread_mutex_t adcMutex;
|
||||
|
||||
void adc1_init()
|
||||
{
|
||||
pthread_mutex_init(&adcMutex, NULL);
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
||||
__DSB();
|
||||
|
||||
/*
|
||||
* Configure GPIOs to analog input mode:
|
||||
*/
|
||||
gpio_setMode(AIN_VBAT, INPUT_ANALOG);
|
||||
|
||||
/*
|
||||
* ADC clock is APB2 frequency divided by 8, giving 10.5MHz.
|
||||
* We set the sample time of each channel to 84 ADC cycles and we have that
|
||||
* a conversion takes 12 cycles: total conversion time is then of ~9us.
|
||||
*/
|
||||
ADC->CCR |= ADC_CCR_ADCPRE;
|
||||
ADC1->SMPR2 = ADC_SMPR2_SMP3_2;
|
||||
|
||||
/*
|
||||
* Convert one channel, no overrun interrupt, 12-bit resolution,
|
||||
* no analog watchdog, discontinuous mode, no end of conversion interrupts,
|
||||
* turn on ADC.
|
||||
*/
|
||||
ADC1->SQR1 = 0;
|
||||
ADC1->CR2 = ADC_CR2_ADON;
|
||||
}
|
||||
|
||||
void adc1_terminate()
|
||||
{
|
||||
pthread_mutex_destroy(&adcMutex);
|
||||
|
||||
ADC1->CR2 &= ~ADC_CR2_ADON;
|
||||
RCC->APB2ENR &= ~RCC_APB2ENR_ADC1EN;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
uint16_t adc1_getRawSample(uint8_t ch)
|
||||
{
|
||||
if(ch > 15) return 0;
|
||||
|
||||
pthread_mutex_lock(&adcMutex);
|
||||
|
||||
ADC1->SQR3 = ch;
|
||||
ADC1->CR2 |= ADC_CR2_SWSTART;
|
||||
while((ADC1->SR & ADC_SR_EOC) == 0) ;
|
||||
uint16_t value = ADC1->DR;
|
||||
|
||||
pthread_mutex_unlock(&adcMutex);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
uint16_t adc1_getMeasurement(uint8_t ch)
|
||||
{
|
||||
/*
|
||||
* To avoid using floats, we convert the raw ADC sample to mV using 16.16
|
||||
* fixed point math. The equation for conversion is (sample * 3300)/4096 but,
|
||||
* since converting the raw ADC sample to 16.16 notation requires a left
|
||||
* shift by 16 and dividing by 4096 is equivalent to shifting right by 12,
|
||||
* we just shift left by four and then multiply by 3300.
|
||||
* With respect to using floats, maximum error is -1mV.
|
||||
*/
|
||||
uint32_t sample = (adc1_getRawSample(ch) << 4) * 3300;
|
||||
return ((uint16_t) (sample >> 16));
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 by Silvano Seva IU2KWO and Niccolò Izzo IU2KIN *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef ADC1_H
|
||||
#define ADC1_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Driver for ADC1, used on Module 17 to sample input voltage
|
||||
*
|
||||
* NOTE: values inside the enum are the channel numbers of STM32 ADC1 peripheral.
|
||||
*/
|
||||
|
||||
enum adcCh
|
||||
{
|
||||
ADC_VBAT_CH = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialise ADC1.
|
||||
*/
|
||||
void adc1_init();
|
||||
|
||||
/**
|
||||
* Turn off ADC1.
|
||||
*/
|
||||
void adc1_terminate();
|
||||
|
||||
/**
|
||||
* Get current measurement of a given channel returning the raw ADC value.
|
||||
*
|
||||
* NOTE: the mapping provided in enum adcCh DOES NOT correspond to the physical
|
||||
* ADC channel mapping!
|
||||
*
|
||||
* @param ch: channel number.
|
||||
* @return current value of the specified channel, in ADC counts.
|
||||
*/
|
||||
uint16_t adc1_getRawSample(uint8_t ch);
|
||||
|
||||
/**
|
||||
* Get current measurement of a given channel.
|
||||
*
|
||||
* NOTE: the mapping provided in enum adcCh DOES NOT correspond to the physical
|
||||
* ADC channel mapping!
|
||||
*
|
||||
* @param ch: channel number.
|
||||
* @return current value of the specified channel in mV.
|
||||
*/
|
||||
uint16_t adc1_getMeasurement(uint8_t ch);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ADC1_H */
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
* Mathis Schmieder DB9MAT *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MCP4551_H
|
||||
#define MCP4551_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <datatypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Common WIPER values
|
||||
#define MCP4551_WIPER_MID 0x080
|
||||
#define MCP4551_WIPER_A 0x100
|
||||
#define MCP4551_WIPER_B 0x000
|
||||
|
||||
// Command definitions (sent to WIPER register)
|
||||
#define MCP4551_CMD_WRITE 0x00
|
||||
#define MCP4551_CMD_INC 0x04
|
||||
#define MCP4551_CMD_DEC 0x08
|
||||
#define MCP4551_CMD_READ 0x0C
|
||||
|
||||
/**
|
||||
* Initialise I2C.
|
||||
*/
|
||||
void i2c_init();
|
||||
|
||||
void mcp4551_init(uint8_t addr);
|
||||
void mcp4551_setWiper(uint8_t devAddr, uint16_t value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MCP4551_H */
|
||||
|
|
@ -0,0 +1,203 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN *
|
||||
* Frederik Saraci IU2NRO *
|
||||
* Silvano Seva IU2KWO *
|
||||
* Mathis Schmieder DB9MAT *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
||||
#include <interfaces/gpio.h>
|
||||
#include <interfaces/delays.h>
|
||||
#include <hwconfig.h>
|
||||
#include "MCP4551.h"
|
||||
|
||||
/*
|
||||
* Implementation of MCP4551 I2C interface.
|
||||
*
|
||||
* Hardware I2C is not yet implemented. Bit-bang, baby!
|
||||
*/
|
||||
|
||||
void _i2c_start();
|
||||
void _i2c_stop();
|
||||
void _i2c_write(uint8_t val);
|
||||
uint8_t _i2c_read(bool ack);
|
||||
|
||||
void i2c_init()
|
||||
{
|
||||
gpio_setMode(I2C_SDA, INPUT);
|
||||
gpio_setMode(I2C_SCL, OUTPUT);
|
||||
gpio_clearPin(I2C_SCL);
|
||||
}
|
||||
|
||||
void mcp4551_init(uint8_t addr)
|
||||
{
|
||||
mcp4551_setWiper(addr, MCP4551_WIPER_MID);
|
||||
}
|
||||
|
||||
void mcp4551_setWiper(uint8_t devAddr, uint16_t value)
|
||||
{
|
||||
_i2c_start();
|
||||
_i2c_write(devAddr << 1);
|
||||
uint8_t temp = ((value >> 8 & 0x01) | MCP4551_CMD_WRITE);
|
||||
_i2c_write(temp);
|
||||
temp = (value & 0xFF);
|
||||
_i2c_write(temp);
|
||||
_i2c_stop();
|
||||
}
|
||||
|
||||
/*uint16_t i2c_readReg16(uint8_t devAddr, uint8_t reg)
|
||||
{
|
||||
_i2c_start();
|
||||
_i2c_write(devAddr << 1);
|
||||
_i2c_write(reg);
|
||||
_i2c_start();
|
||||
_i2c_write(devAddr | 0x01);
|
||||
uint8_t valHi = _i2c_read(true);
|
||||
uint8_t valLo = _i2c_read(false);
|
||||
_i2c_stop();
|
||||
|
||||
return (valHi << 8) | valLo;
|
||||
} */
|
||||
|
||||
/*
|
||||
* Software I2C routine
|
||||
*/
|
||||
|
||||
void _i2c_start()
|
||||
{
|
||||
gpio_setMode(I2C_SDA, OUTPUT);
|
||||
|
||||
/*
|
||||
* Lines commented to keep SCL high when idle
|
||||
*
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(2);
|
||||
*/
|
||||
|
||||
gpio_setPin(I2C_SDA);
|
||||
delayUs(5);
|
||||
|
||||
gpio_setPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
|
||||
gpio_clearPin(I2C_SDA);
|
||||
delayUs(5);
|
||||
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(6);
|
||||
}
|
||||
|
||||
void _i2c_stop()
|
||||
{
|
||||
gpio_setMode(I2C_SDA, OUTPUT);
|
||||
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
|
||||
gpio_clearPin(I2C_SDA);
|
||||
delayUs(5);
|
||||
|
||||
gpio_setPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
|
||||
gpio_setPin(I2C_SDA);
|
||||
delayUs(5);
|
||||
|
||||
/*
|
||||
* Lines commented to keep SCL high when idle
|
||||
*
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
*/
|
||||
}
|
||||
|
||||
void _i2c_write(uint8_t val)
|
||||
{
|
||||
gpio_setMode(I2C_SDA, OUTPUT);
|
||||
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(1);
|
||||
|
||||
if(val & 0x80)
|
||||
{
|
||||
gpio_setPin(I2C_SDA);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_clearPin(I2C_SDA);
|
||||
}
|
||||
|
||||
val <<= 1;
|
||||
delayUs(1);
|
||||
gpio_setPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
}
|
||||
|
||||
/* Ensure SCL is low before releasing SDA */
|
||||
gpio_clearPin(I2C_SCL);
|
||||
|
||||
/* Clock cycle for slave ACK/NACK */
|
||||
gpio_setMode(I2C_SDA, INPUT_PULL_UP);
|
||||
delayUs(5);
|
||||
gpio_setPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(1);
|
||||
|
||||
/* Asserting SDA pin allows to fastly bring the line to idle state */
|
||||
gpio_setPin(I2C_SDA);
|
||||
gpio_setMode(I2C_SDA, OUTPUT);
|
||||
delayUs(6);
|
||||
}
|
||||
|
||||
uint8_t _i2c_read(bool ack)
|
||||
{
|
||||
gpio_setMode(I2C_SDA, INPUT_PULL_UP);
|
||||
gpio_clearPin(I2C_SCL);
|
||||
|
||||
uint8_t value = 0;
|
||||
for(uint8_t i = 0; i < 8; i++)
|
||||
{
|
||||
delayUs(5);
|
||||
gpio_setPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
|
||||
value <<= 1;
|
||||
value |= gpio_readPin(I2C_SDA);
|
||||
|
||||
gpio_clearPin(I2C_SCL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set ACK/NACK state BEFORE putting SDA gpio to output mode.
|
||||
* This avoids spurious spikes which can be interpreted as NACKs
|
||||
*/
|
||||
gpio_clearPin(I2C_SDA);
|
||||
gpio_setMode(I2C_SDA, OUTPUT);
|
||||
delayUs(5);
|
||||
if(!ack) gpio_setPin(I2C_SDA);
|
||||
|
||||
/* Clock cycle for ACK/NACK */
|
||||
delayUs(5);
|
||||
gpio_setPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
gpio_clearPin(I2C_SCL);
|
||||
delayUs(5);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
|
@ -15,6 +15,16 @@
|
|||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* As a special exception, if other files instantiate templates or use *
|
||||
* macros or inline functions from this file, or you compile this file *
|
||||
* and link it with other works to produce a work based on this file, *
|
||||
* this file does not by itself cause the resulting work to be covered *
|
||||
* by the GNU General Public License. However the source code for this *
|
||||
* file must still be made available in accordance with the GNU General *
|
||||
* Public License. This exception does not invalidate any other reasons *
|
||||
* why a work based on this file might be covered by the GNU General *
|
||||
* Public License. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/> *
|
||||
***************************************************************************/
|
||||
|
|
@ -80,41 +90,36 @@ void display_init()
|
|||
gpio_clearPin(LCD_RS);
|
||||
|
||||
gpio_clearPin(LCD_RST); /* Reset controller */
|
||||
delayMs(1);
|
||||
delayMs(50);
|
||||
gpio_setPin(LCD_RST);
|
||||
delayMs(5);
|
||||
delayMs(50);
|
||||
|
||||
gpio_clearPin(LCD_CS);
|
||||
|
||||
gpio_clearPin(LCD_RS); /* RS low -> command mode */
|
||||
spi2_sendRecv(0xAE); /* Disable Display */
|
||||
spi2_sendRecv(0x20); /* Set Memory Addressing Mode to horizontal addressing Mode */
|
||||
spi2_sendRecv(0xAE); // SH110X_DISPLAYOFF,
|
||||
spi2_sendRecv(0xd5); // SH110X_SETDISPLAYCLOCKDIV, 0x51,
|
||||
spi2_sendRecv(0x51);
|
||||
//spi2_sendRecv(0x20); // SH110X_MEMORYMODE,
|
||||
spi2_sendRecv(0x81); // SH110X_SETCONTRAST, 0x4F,
|
||||
spi2_sendRecv(0x4F);
|
||||
spi2_sendRecv(0xAD); // SH110X_DCDC, 0x8A,
|
||||
spi2_sendRecv(0x8A);
|
||||
spi2_sendRecv(0xA0); // SH110X_SEGREMAP,
|
||||
spi2_sendRecv(0xC0); // SH110X_COMSCANINC,
|
||||
spi2_sendRecv(0xDC); // SH110X_SETDISPSTARTLINE, 0x0,
|
||||
spi2_sendRecv(0x00);
|
||||
spi2_sendRecv(0xB0); /* Set Page Start Address for Page Addressing Mode */
|
||||
spi2_sendRecv(0xC8); /* Set COM Output Scan Direction */
|
||||
spi2_sendRecv(0x00); /* Set low column address */
|
||||
spi2_sendRecv(0x10); /* Set high column address */
|
||||
spi2_sendRecv(0x40); /* Set start line address */
|
||||
spi2_sendRecv(0x81); /* Set contrast */
|
||||
spi2_sendRecv(0xCF);
|
||||
spi2_sendRecv(0xA1); /* Set segment re-map 0 to 127 */
|
||||
spi2_sendRecv(0xA6); /* Set normal color */
|
||||
spi2_sendRecv(0xA8); /* Set multiplex ratio (1 to 64) */
|
||||
spi2_sendRecv(0x3F);
|
||||
spi2_sendRecv(0xA4); /* Output follows RAM content */
|
||||
spi2_sendRecv(0xD3); /* Set display offset */
|
||||
spi2_sendRecv(0x00); /* Not offset */
|
||||
spi2_sendRecv(0xD5); /* Set display clock divide ratio/oscillator frequency */
|
||||
spi2_sendRecv(0xF0); /* Set divide ratio */
|
||||
spi2_sendRecv(0xD9); /* Set pre-charge period */
|
||||
spi2_sendRecv(0xd3); // SH110X_SETDISPLAYOFFSET, 0x60,
|
||||
spi2_sendRecv(0x60);
|
||||
spi2_sendRecv(0xd9); // SH110X_SETPRECHARGE, 0x22,
|
||||
spi2_sendRecv(0x22);
|
||||
spi2_sendRecv(0xDA); /* Set com pins hardware configuration */
|
||||
spi2_sendRecv(0x12);
|
||||
spi2_sendRecv(0xDB); /* Set vcomh */
|
||||
spi2_sendRecv(0x40);
|
||||
spi2_sendRecv(0x8D); /* Set DC-DC enable */
|
||||
spi2_sendRecv(0x14);
|
||||
spi2_sendRecv(0xAF); /* Enable Display */
|
||||
spi2_sendRecv(0xdb); // SH110X_SETVCOMDETECT, 0x35,
|
||||
spi2_sendRecv(0x35);
|
||||
spi2_sendRecv(0xa8); // SH110X_SETMULTIPLEX, 0x3F,
|
||||
spi2_sendRecv(0x3f);
|
||||
spi2_sendRecv(0xa4); // SH110X_DISPLAYALLON_RESUME,
|
||||
spi2_sendRecv(0xa6); // SH110X_NORMALDISPLAY,
|
||||
spi2_sendRecv(0xAF); // SH110x_DISPLAYON
|
||||
gpio_setPin(LCD_CS);
|
||||
}
|
||||
|
||||
|
|
@ -130,36 +135,26 @@ void display_terminate()
|
|||
|
||||
void display_renderRow(uint8_t row)
|
||||
{
|
||||
/* magic stuff */
|
||||
uint8_t *buf = (frameBuffer + 128 * row);
|
||||
for (uint8_t i = 0; i<16; i++)
|
||||
{
|
||||
uint8_t tmp[8] = {0};
|
||||
for (uint8_t j = 0; j < 8; j++)
|
||||
{
|
||||
uint8_t tmp_buf = buf[j*16 + i];
|
||||
int count = __builtin_popcount(tmp_buf);
|
||||
while (count > 0)
|
||||
{
|
||||
int pos = __builtin_ctz(tmp_buf);
|
||||
tmp[pos] |= 1UL << j;
|
||||
tmp_buf &= ~(1 << pos);
|
||||
count--;
|
||||
}
|
||||
}
|
||||
uint8_t *buf = (frameBuffer);
|
||||
|
||||
for (uint8_t s = 0; s < 8; s++)
|
||||
{
|
||||
(void) spi2_sendRecv(tmp[s]);
|
||||
}
|
||||
}
|
||||
for(uint16_t i=0; i<64; i++)
|
||||
{
|
||||
uint8_t out=0, tmp=buf[i*16 + 15-row];
|
||||
|
||||
for(uint8_t j=0; j<8; j++)
|
||||
{
|
||||
out|=((tmp>>(7-j))&1)<<j;
|
||||
}
|
||||
|
||||
spi2_sendRecv(out);
|
||||
}
|
||||
}
|
||||
|
||||
void display_renderRows(uint8_t startRow, uint8_t endRow)
|
||||
{
|
||||
gpio_clearPin(LCD_CS);
|
||||
|
||||
for(uint8_t row = startRow; row < endRow; row++)
|
||||
|
||||
for(uint8_t row = startRow; row <= endRow; row++)
|
||||
{
|
||||
gpio_clearPin(LCD_RS); /* RS low -> command mode */
|
||||
(void) spi2_sendRecv(0xB0 | row); /* Set Y position */
|
||||
|
|
@ -168,13 +163,13 @@ void display_renderRows(uint8_t startRow, uint8_t endRow)
|
|||
gpio_setPin(LCD_RS); /* RS high -> data mode */
|
||||
display_renderRow(row);
|
||||
}
|
||||
|
||||
|
||||
gpio_setPin(LCD_CS);
|
||||
}
|
||||
|
||||
void display_render()
|
||||
{
|
||||
display_renderRows(0, SCREEN_HEIGHT / 8);
|
||||
display_renderRows(0, SCREEN_WIDTH / 8 - 1);
|
||||
}
|
||||
|
||||
bool display_renderingInProgress()
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
#define PIX_FMT_BW
|
||||
|
||||
/* Device has no battery */
|
||||
#define BAT_NONE
|
||||
#define BAT_MOD17
|
||||
|
||||
/* Signalling LEDs */
|
||||
#define PTT_LED GPIOC,8
|
||||
|
|
@ -75,4 +75,12 @@
|
|||
#define MIC_MUTE GPIOC,4
|
||||
#define MIC_GAIN GPIOC,5
|
||||
|
||||
#define AIN_VBAT GPIOA,3
|
||||
|
||||
/* I2C for MCP4551 */
|
||||
#define I2C_SDA GPIOB,7
|
||||
#define I2C_SCL GPIOB,6
|
||||
#define SOFTPOT_RX 0x2E
|
||||
#define SOFTPOT_TX 0x2F
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@
|
|||
#include <backlight.h>
|
||||
#include <interfaces/rtc.h>
|
||||
#include <interfaces/audio.h>
|
||||
#include <ADC1_Mod17.h>
|
||||
#include <interfaces/nvmem.h>
|
||||
#include <MCP4551.h>
|
||||
|
||||
void platform_init()
|
||||
{
|
||||
|
|
@ -39,6 +42,14 @@ void platform_init()
|
|||
gpio_setMode(PTT_OUT, OUTPUT);
|
||||
gpio_clearPin(PTT_OUT);
|
||||
|
||||
nvm_init();
|
||||
adc1_init();
|
||||
i2c_init();
|
||||
mcp4551_init(SOFTPOT_RX);
|
||||
mcp4551_init(SOFTPOT_TX);
|
||||
//mcp4551_setWiper(SOFTPOT_RX, MCP4551_WIPER_A);
|
||||
//mcp4551_setWiper(SOFTPOT_TX, MCP4551_WIPER_A);
|
||||
|
||||
audio_init();
|
||||
}
|
||||
|
||||
|
|
@ -48,11 +59,15 @@ void platform_terminate()
|
|||
gpio_clearPin(PTT_LED);
|
||||
gpio_clearPin(SYNC_LED);
|
||||
gpio_clearPin(ERR_LED);
|
||||
|
||||
adc1_terminate();
|
||||
nvm_terminate();
|
||||
audio_terminate();
|
||||
}
|
||||
|
||||
uint16_t platform_getVbat()
|
||||
{
|
||||
return 0;
|
||||
return adc1_getMeasurement(ADC_VBAT_CH)*5;
|
||||
}
|
||||
|
||||
uint8_t platform_getMicLevel()
|
||||
|
|
|
|||
Loading…
Reference in New Issue