From: drowe67 Date: Wed, 16 Jul 2014 00:56:21 +0000 (+0000) Subject: modify ADC driver for two channels, untested X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=3422f5f4e22b6de5c17dbbf5e21456107e3edcca;p=freetel-svn-tracking.git modify ADC driver for two channels, untested git-svn-id: https://svn.code.sf.net/p/freetel/code@1762 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/stm32/inc/stm32f4_adc.h b/codec2-dev/stm32/inc/stm32f4_adc.h index b14110cb..17c318e0 100644 --- a/codec2-dev/stm32/inc/stm32f4_adc.h +++ b/codec2-dev/stm32/inc/stm32f4_adc.h @@ -4,7 +4,7 @@ AUTHOR......: David Rowe DATE CREATED: 30 May 2014 - ADC driver module for STM32F4. + Two channel FIFO buffered ADC driver module for STM32F4. \*---------------------------------------------------------------------------*/ @@ -29,6 +29,7 @@ #define __STM32F4_ADC__ void adc_open(void); -int adc_read(short buf[], int n); +int adc1_read(short buf[], int n); /* ADC1 Pin PA1 */ +int adc2_read(short buf[], int n); /* ADC2 Pin PA2 */ #endif diff --git a/codec2-dev/stm32/inc/stm32f4_dac.h b/codec2-dev/stm32/inc/stm32f4_dac.h index 3a298321..9950f36a 100644 --- a/codec2-dev/stm32/inc/stm32f4_dac.h +++ b/codec2-dev/stm32/inc/stm32f4_dac.h @@ -4,7 +4,7 @@ AUTHOR......: David Rowe DATE CREATED: 1 June 2013 - DAC driver module for STM32F4. + Two channel FIFO buffered DAC driver module for STM32F4. \*---------------------------------------------------------------------------*/ @@ -29,6 +29,7 @@ #define __STM32F4_DAC__ void dac_open(void); -int dac_write(short buf[], int n); +int dac1_write(short buf[], int n); /* DAC1 pin PA4 */ +int dac2_write(short buf[], int n); /* DAC2 pin PA5 */ #endif diff --git a/codec2-dev/stm32/src/adc_rec.c b/codec2-dev/stm32/src/adc_rec.c index 3d5992f9..c20516d9 100644 --- a/codec2-dev/stm32/src/adc_rec.c +++ b/codec2-dev/stm32/src/adc_rec.c @@ -4,7 +4,7 @@ AUTHOR......: David Rowe DATE CREATED: 30 May 2014 - Recordss a 16 kHz sample rate raw file from the STM32F4 ADC. + Records a 16 kHz sample rate raw file from the STM32F4 ADC Pin PA1. \*---------------------------------------------------------------------------*/ @@ -49,7 +49,7 @@ int main(void){ printf("Starting!\n"); for(i=0; iODR = (1 << 13); diff --git a/codec2-dev/stm32/src/stm32f4_adc.c b/codec2-dev/stm32/src/stm32f4_adc.c index 62fe8a99..264186a2 100644 --- a/codec2-dev/stm32/src/stm32f4_adc.c +++ b/codec2-dev/stm32/src/stm32f4_adc.c @@ -6,24 +6,6 @@ ADC driver module for STM32F4. - TODO: - [X] just get ADC to run at all, prove its sampling something.... - [X] as above with DMA - [X] half and finished interrupts, ISR - [X] timer config to drive ADC conversion, measure sample rate and confirm 16kHz - + larger ADC DMA buffer - + fifos - + work out a way to unit test - [ ] ADC working at same time as DAC - [X] remove (or make optional) the TIM_Config() code that sends PWM output to pins - [ ] check comments still valid - [X] convert to driver - [ ] way to determine which timers are used so they don't get re-sued - [ ] way to select different pins/ADCs for multiple channels, multiple channel support - [ ] access functions for halff/full/overflow to trap any issues - [ ] should FIFOs be in this drivr or in UTs connected to stdio? SmartMic will just need - 40ms of buffering - \*---------------------------------------------------------------------------*/ /* @@ -56,31 +38,28 @@ #include "stm32f4_adc.h" #define ADC_BUF_SZ 320 -#define FIFO_SZ 1000 +#define FIFO_SZ 4*ADC_BUF_SZ -struct FIFO *DMA2_Stream0_fifo; -unsigned short adc_buf[ADC_BUF_SZ]; -int adc_overflow; -int half,full; +static struct FIFO *adc1_fifo; +static struct FIFO *adc2_fifo; +static unsigned short adc_buf[ADC_BUF_SZ]; +static int adc_overflow; +static int half,full; #define ADCx_DR_ADDRESS ((uint32_t)0x4001204C) #define DMA_CHANNELx DMA_Channel_0 #define DMA_STREAMx DMA2_Stream0 -#define ADCx ADC1 #define TIM1_CCR3_ADDRESS 0x4001223C -TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; -TIM_OCInitTypeDef TIM_OCInitStructure; -uint16_t uhTimerPeriod; -uint16_t aSRC_Buffer[3] = {0, 0, 0}; - -void Timer1Config(); -void adc_configure(); +static void Timer1Config(); +static void adc_configure(); void adc_open(void) { - DMA2_Stream0_fifo = fifo_create(FIFO_SZ); - assert(DMA2_Stream0_fifo != NULL); + adc1_fifo = fifo_create(FIFO_SZ); + adc2_fifo = fifo_create(FIFO_SZ); + assert(adc1_fifo != NULL); + assert(adc2_fifo != NULL); Timer1Config(); adc_configure(); @@ -89,11 +68,17 @@ void adc_open(void) { /* n signed 16 bit samples in buf[] if return != -1 */ -int adc_read(short buf[], int n) { - return fifo_read(DMA2_Stream0_fifo, buf, n); +int adc1_read(short buf[], int n) { + return fifo_read(adc1_fifo, buf, n); +} + +int adc2_read(short buf[], int n) { + return fifo_read(adc2_fifo, buf, n); } void Timer1Config() { + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + uint16_t uhTimerPeriod; /* TIM1 example ------------------------------------------------- @@ -106,32 +91,21 @@ void Timer1Config() { TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClock SystemCoreClock is set to 168 MHz for STM32F4xx devices. - The objective is to configure TIM1 channel 3 to generate complementary PWM - signal with a frequency equal to F KHz: - - TIM1_Period = (SystemCoreClock / F) - 1 + The objective is to configure TIM1 channel 3 to generate a + clock with a frequency equal to F KHz: + + TIM1_Period = (SystemCoreClock / F) - 1 - The number of this repetitive requests is defined by the TIM1 Repetion counter, - each 3 Update Requests, the TIM1 Channel 3 Duty Cycle changes to the next new - value defined by the aSRC_Buffer. - - Note: - SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file. - Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate() - function to update SystemCoreClock variable value. Otherwise, any configuration - based on this variable will be incorrect. -----------------------------------------------------------------------------*/ - /* Compute the value to be set in ARR regiter to generate signal frequency at 16.00 Khz */ + /* Compute the value to be set in ARR regiter to generate signal frequency at 16.00 KHz */ + uhTimerPeriod = (SystemCoreClock / 16000 ) - 1; - /* Compute CCR1 value to generate a duty cycle at 50% */ - aSRC_Buffer[0] = (uint16_t) (((uint32_t) 5 * (uhTimerPeriod - 1)) / 10); - /* Compute CCR1 value to generate a duty cycle at 37.5% */ - aSRC_Buffer[1] = (uint16_t) (((uint32_t) 375 * (uhTimerPeriod - 1)) / 1000); - /* Compute CCR1 value to generate a duty cycle at 25% */ - aSRC_Buffer[2] = (uint16_t) (((uint32_t) 25 * (uhTimerPeriod - 1)) / 100); /* TIM1 Peripheral Configuration -------------------------------------------*/ + /* TIM1 clock enable */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); /* Time Base configuration */ @@ -145,33 +119,12 @@ void Timer1Config() { TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); - /* Channel 3 Configuration in PWM mode */ - - /* I think we just ned to enable channel 3 somehow, but without - (or optionally with) actual ouput to a GPIO pin. */ - - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; - TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; - TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; - TIM_OCInitStructure.TIM_Pulse = aSRC_Buffer[0]; - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; - TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; - TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; - TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; - - TIM_OC3Init(TIM1, &TIM_OCInitStructure); - - /* Enable preload feature */ - TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable); - /* TIM1 counter enable */ + TIM_Cmd(TIM1, ENABLE); - - /* Main Output Enable */ - TIM_CtrlPWMOutputs(TIM1, ENABLE); } -void adc_configure(){ +void adc_configure() { ADC_InitTypeDef ADC_init_structure; GPIO_InitTypeDef GPIO_initStructre; DMA_InitTypeDef DMA_InitStructure; @@ -179,18 +132,19 @@ void adc_configure(){ // Clock configuration - RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOCEN,ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); - // Analog pin configuration + // Analog pin configuration ADC1->PA1, ADC2->PA2 - GPIO_initStructre.GPIO_Pin = GPIO_Pin_0; // ADC Channel 10 is connected to PC0 + GPIO_initStructre.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2; GPIO_initStructre.GPIO_Mode = GPIO_Mode_AN; GPIO_initStructre.GPIO_PuPd = GPIO_PuPd_NOPULL; - GPIO_Init(GPIOC,&GPIO_initStructre); + GPIO_Init(GPIOA,&GPIO_initStructre); - // ADC structure configuration + // ADC structure configuration. Note we are just using one ADC, which samples + // two analog channels when triggered by the timer. ADC_DeInit(); ADC_init_structure.ADC_DataAlign = ADC_DataAlign_Left; @@ -198,18 +152,19 @@ void adc_configure(){ ADC_init_structure.ADC_ContinuousConvMode = DISABLE; ADC_init_structure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC3; ADC_init_structure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; - ADC_init_structure.ADC_NbrOfConversion = 1; - ADC_init_structure.ADC_ScanConvMode = DISABLE; - ADC_Init(ADCx,&ADC_init_structure); + ADC_init_structure.ADC_NbrOfConversion = 2; + ADC_init_structure.ADC_ScanConvMode = ENABLE; + ADC_Init(ADC1,&ADC_init_structure); - // Select the channel to be read from + // Select the channels to be read from - ADC_RegularChannelConfig(ADCx,ADC_Channel_10,1,ADC_SampleTime_144Cycles); + ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_144Cycles); + ADC_RegularChannelConfig(ADC1,ADC_Channel_2,2,ADC_SampleTime_144Cycles); /* DMA configuration **************************************/ - DMA_DeInit(DMA_STREAMx); - DMA_InitStructure.DMA_Channel = DMA_CHANNELx; + DMA_DeInit(DMA2_Stream0); + DMA_InitStructure.DMA_Channel = DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADCx_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)adc_buf; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; @@ -224,19 +179,19 @@ void adc_configure(){ DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; - DMA_Init(DMA_STREAMx, &DMA_InitStructure); + DMA_Init(DMA2_Stream0, &DMA_InitStructure); /* Enable DMA request after last transfer (Single-ADC mode) */ - ADC_DMARequestAfterLastTransferCmd(ADCx, ENABLE); + ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); /* Enable ADC1 DMA */ - ADC_DMACmd(ADCx, ENABLE); + ADC_DMACmd(ADC1, ENABLE); /* DMA2_Stream0 enable */ - DMA_Cmd(DMA_STREAMx, ENABLE); + DMA_Cmd(DMA2_Stream0, ENABLE); /* Enable DMA Half & Complete interrupts */ @@ -260,8 +215,9 @@ void adc_configure(){ */ void DMA2_Stream0_IRQHandler(void) { - int i, sam; - short signed_buf[ADC_BUF_SZ/2]; + int i, j, sam1, sam2; + short signed_buf1[ADC_BUF_SZ/4]; + short signed_buf2[ADC_BUF_SZ/4]; /* Half transfer interrupt */ @@ -270,15 +226,19 @@ void DMA2_Stream0_IRQHandler(void) { /* convert to signed */ - for(i=0; i