Restructured ADC1_MDx code and extended its support also to MD-9600

This commit is contained in:
Silvano Seva 2021-03-26 09:11:51 +01:00
parent 6b541a8ba1
commit e157fc361d
6 changed files with 84 additions and 33 deletions

View File

@ -24,7 +24,7 @@
/*
* The sample buffer is structured as follows:
*
* | vbat | vol | rssi | vox |
* | vol | vbat | vox | rssi | sw1 | sw2 | rssi2 | htemp |
*
* NOTE: we are forced to allocate it through a malloc in order to make it be
* in the "large" 128kB RAM. This because the linker script maps the .data and
@ -32,6 +32,14 @@
*/
uint16_t *sampleBuf = NULL;
#if defined(PLATFORM_MD9600)
static const size_t nChannels = 8;
#elif defined(PLATFORM_MD3x0)
static const size_t nChannels = 4;
#else
static const size_t nChannels = 2;
#endif
void adc1_init()
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
@ -42,16 +50,18 @@ void adc1_init()
/*
* Configure GPIOs to analog input mode:
* - PA0: volume potentiometer level
* - PA1: battery voltage
* - PA3: vox level
* - PB0: RSSI level
*/
gpio_setMode(AIN_VBAT, INPUT_ANALOG);
gpio_setMode(AIN_VOLUME, INPUT_ANALOG);
#if defined(PLATFORM_MD3x0)
gpio_setMode(AIN_MIC, INPUT_ANALOG);
gpio_setMode(AIN_RSSI, INPUT_ANALOG);
#if defined(PLATFORM_MD3x0) || defined(PLATFORM_MD9600)
gpio_setMode(AIN_MIC, INPUT_ANALOG);
gpio_setMode(AIN_RSSI, INPUT_ANALOG);
#if defined(PLATFORM_MD9600)
gpio_setMode(AIN_SW2, INPUT_ANALOG);
gpio_setMode(AIN_SW1, INPUT_ANALOG);
gpio_setMode(AIN_RSSI2, INPUT_ANALOG);
gpio_setMode(AIN_HTEMP, INPUT_ANALOG);
#endif
#endif
/*
@ -64,7 +74,11 @@ void adc1_init()
ADC1->SMPR2 = ADC_SMPR2_SMP0
| ADC_SMPR2_SMP1
| ADC_SMPR2_SMP3
| ADC_SMPR2_SMP8;
| ADC_SMPR2_SMP6
| ADC_SMPR2_SMP7
| ADC_SMPR2_SMP8
| ADC_SMPR2_SMP9;
ADC1->SMPR1 = ADC_SMPR1_SMP15;
/*
* No overrun interrupt, 12-bit resolution, no analog watchdog, no
@ -78,7 +92,17 @@ void adc1_init()
| ADC_CR2_ADON;
/* Scan sequence config. */
#if defined(PLATFORM_MD3x0)
#if defined(PLATFORM_MD9600)
ADC1->SQR1 = 7 << 20; /* Eight channels to be converted */
ADC1->SQR3 |= (0 << 0) /* CH0, volume potentiometer level on PA0 */
| (1 << 5) /* CH1, battery voltage on PA1 */
| (3 << 10) /* CH3, vox level on PA3 */
| (8 << 15) /* CH8, RSSI value on PB0 */
| (7 << 20) /* CH7, SW1 value on PA7 */
| (6 << 25); /* CH6, SW2 value on PA6 */
ADC1->SQR2 |= (9 << 0) /* CH9, RSSI2 value on PB1 */
| (15 << 5); /* CH15, HTEMP value on PC5 */
#elif defined(PLATFORM_MD3x0)
ADC1->SQR1 = 3 << 20; /* Four channels to be converted */
ADC1->SQR3 |= (1 << 0) /* CH1, battery voltage on PA1 */
| (0 << 5) /* CH0, volume potentiometer level on PA0 */
@ -86,8 +110,8 @@ void adc1_init()
| (3 << 15); /* CH3, vox level on PA3 */
#else
ADC1->SQR1 = 1 << 20; /* Convert two channel */
ADC1->SQR3 |= (1 << 0) /* CH1, battery voltage on PA1 */
| (0 << 15); /* CH0, volume potentiometer level on PA0 */
ADC1->SQR3 |= (0 << 0) /* CH0, volume potentiometer level on PA0 */
| (1 << 5); /* CH1, battery voltage on PA1 */
#endif
/* DMA2 Stream 0 configuration:
@ -101,7 +125,7 @@ void adc1_init()
*/
DMA2_Stream0->PAR = ((uint32_t) &(ADC1->DR));
DMA2_Stream0->M0AR = ((uint32_t) sampleBuf);
DMA2_Stream0->NDTR = 4;
DMA2_Stream0->NDTR = nChannels;
DMA2_Stream0->CR = DMA_SxCR_MSIZE_0 /* Memory size: 16 bit */
| DMA_SxCR_PSIZE_0 /* Peripheral size: 16 bit */
| DMA_SxCR_PL_0 /* Medium priority */
@ -125,7 +149,7 @@ void adc1_terminate()
float adc1_getMeasurement(uint8_t ch)
{
if((ch > 3) || (sampleBuf == NULL)) return 0.0f;
if((ch > (nChannels-1)) || (sampleBuf == NULL)) return 0.0f;
float value = ((float) sampleBuf[ch]);
return (value * 3300.0f)/4096.0f;

View File

@ -21,13 +21,37 @@
#include <stdint.h>
/**
* Driver for ADC1, used to continuously sample the following channels:
* - ADC1_CH0 (PA0): output value of the volume potentiometer;
* - ADC1_CH1 (PA1): battery voltage through 1:3 resistor divider;
* - ADC1_CH3 (PA3): vox level;
* - ADC1_CH8 (PB0): RSSI level;
* Driver for ADC1, used on all the MDx devices to continuously sample battery
* voltage and other values.
*
* Channel mapping for MDx platforms:
*
* +--------+----------+---------+
* | MD-3x0 | MD-UV3x0 | MD-9600 |
* +-----+------+-----------------+--------+----------+---------+
* | PA0 | IN0 | volume level | x | x | |
* | PA1 | IN1 | supply voltage | x | x | x |
* | PA3 | IN3 | mic level (VOX) | x | x | x |
* | PA6 | IN6 | mic SW2 line | | | x |
* | PA7 | IN7 | mic SW1 line | | | x |
* | PB0 | IN8 | RSSI | x | | x |
* | PB1 | IN9 | | | | x |
* | PC5 | IN15 | heatsink temp. | | | x |
* +-----+------+-----------------+--------+----------+---------+
*/
enum adcCh
{
ADC_VOL_CH = 0,
ADC_VBAT_CH = 1,
ADC_VOX_CH = 2,
ADC_RSSI_CH = 3,
ADC_SW1_CH = 4,
ADC_SW2_CH = 5,
ADC_RSSI2_CH = 6,
ADC_HTEMP_CH = 7
};
/**
* Initialise and start ADC1 and DMA2 Stream 0.
*
@ -47,16 +71,12 @@ void adc1_init();
void adc1_terminate();
/**
* Get current measurement of a given channel, mapped as below:
* - channel 0: battery voltage
* - channel 1: volume level
* - channel 2: RSSI level
* - channel 3: vox level
* Get current measurement of a given channel.
*
* NOTE: the mapping above DOES NOT correspond to the physical ADC channel
* mapping!
* NOTE: the mapping provided in enum adcCh DOES NOT correspond to the physical
* ADC channel mapping!
*
* @param ch: channel number, between 0 and 3.
* @param ch: channel number.
* @return current value of the specified channel in mV.
*/
float adc1_getMeasurement(uint8_t ch);

View File

@ -290,7 +290,7 @@ float radio_getRssi(const freq_t rxFreq)
if(rxFreq < 401035000) offset_index = 0;
if(rxFreq > 479995000) offset_index = 8;
float rssi_mv = adc1_getMeasurement(2);
float rssi_mv = adc1_getMeasurement(ADC_RSSI_CH);
float rssi_dbm = (rssi_mv - rssi_offset[offset_index]) / rssi_gain;
return rssi_dbm;
}

View File

@ -118,17 +118,17 @@ float platform_getVbat()
* adc1_getMeasurement returns a value in mV. Thus, to have effective
* battery voltage multiply by three and divide by 1000
*/
return adc1_getMeasurement(0)*3.0f/1000.0f;
return adc1_getMeasurement(ADC_VBAT_CH)*3.0f/1000.0f;
}
float platform_getMicLevel()
{
return adc1_getMeasurement(2);
return adc1_getMeasurement(ADC_VOX_CH);
}
float platform_getVolumeLevel()
{
return adc1_getMeasurement(3);
return adc1_getMeasurement(ADC_VOL_CH);
}
int8_t platform_getChSelector()

View File

@ -62,7 +62,14 @@
#define LCD_CS GPIOD,14
/* Analog inputs */
#define AIN_VOLUME GPIOA,0
#define AIN_VBAT GPIOA,1
#define AIN_MIC GPIOA,3
#define AIN_SW2 GPIOA,6
#define AIN_SW1 GPIOA,7
#define AIN_RSSI GPIOB,0
#define AIN_RSSI2 GPIOB,1
#define AIN_HTEMP GPIOC,5
/* Channel selection rotary encoder */
#define CH_SELECTOR_0 GPIOB,10

View File

@ -186,7 +186,7 @@ float platform_getVbat()
* adc1_getMeasurement returns a value in mV. Thus, to have effective
* battery voltage multiply by three and divide by 1000
*/
return adc1_getMeasurement(0)*3.0f/1000.0f;
return adc1_getMeasurement(ADC_VBAT_CH)*3.0f/1000.0f;
}
float platform_getMicLevel()
@ -196,7 +196,7 @@ float platform_getMicLevel()
float platform_getVolumeLevel()
{
return adc1_getMeasurement(1);
return adc1_getMeasurement(ADC_VOL_CH);
}
int8_t platform_getChSelector()