From 31de146601be5e7b58494295310a3ee93ce30f6f Mon Sep 17 00:00:00 2001 From: Michael Colton Date: Mon, 14 Jul 2014 01:41:46 -0600 Subject: [PATCH] The main thing here is moving the FFT/Filtering/IFFT to a timer interrupt that has a lower priority than the audio capture/playback timer interrupt. This way I don't care how slow the display code runs in the main loop (for now) enabling me to have the audio processing and the display working at the same time. --- Hardware/PSDR.sch | Bin 271752 -> 271752 bytes Source/include/hal.h | 3 + Source/include/main.h | 3 + Source/src/Adafruit_ILI9340.c | 2 + Source/src/hal.c | 16 +- Source/src/main.c | 616 ++++++++++++------ Source/src/spi.c | 90 +-- Source/src/stm32f4xx_it.c | 15 + .../src/stm32f4-hal/stm32f4xx_hal_tim.c | 5 + 9 files changed, 458 insertions(+), 292 deletions(-) diff --git a/Hardware/PSDR.sch b/Hardware/PSDR.sch index 5086ec783a39db6da59fb88bbb90fb98e569b626..8057e6bed9be0f2c528bf65fcf75ffeb1eeea8cb 100644 GIT binary patch delta 4142 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 KpN}(*iTyvr;6?8M delta 4143 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 0) timingDelay--; } int clickMultiply; @@ -302,9 +304,13 @@ int isFwd; float samplesA[FFT_BUFFER_SIZE]; float samplesB[FFT_BUFFER_SIZE]; float samplesC[FFT_BUFFER_SIZE]; + float samplesDisplay[FFT_BUFFER_SIZE]; int sampleBankAReady = 0; int sampleBankBReady = 0; int sampleBankCReady = 0; + + uint8_t waterfallBusy = 0; + //float outputSamplesA[512]; //float outputSamplesB[512]; int sampleBank = 0; @@ -328,8 +334,16 @@ int isFwd; if(samplesB[sampleIndex*2] > agcLevel) agcLevel = samplesB[sampleIndex*2]; if(samplesB[sampleIndex*2+1] > agcLevel) agcLevel = samplesB[sampleIndex*2+1]; - dac1SetValue(samplesB[sampleIndex*2] / (agcLevel * 40) * 4096 * gain + 2048); - dac2SetValue(samplesB[sampleIndex*2+1] / (agcLevel * 40) * 4096 * gain + 2048); +// if(sampleIndex < filterKernelLength) +// { +// dac1SetValue(samplesB[sampleIndex*2] + samplesA[(FFT_SIZE - filterKernelLength) +// + sampleIndex * 2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// dac2SetValue(samplesB[sampleIndex*2+1] + samplesA[(FFT_SIZE - filterKernelLength) +// + sampleIndex * 2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// } else { + dac1SetValue(samplesB[sampleIndex*2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); + dac2SetValue(samplesB[sampleIndex*2+1] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// } break; case 1: @@ -339,8 +353,16 @@ int isFwd; if(samplesC[sampleIndex*2] > agcLevel) agcLevel =samplesC[sampleIndex*2]; if(samplesC[sampleIndex*2+1] > agcLevel) agcLevel = samplesC[sampleIndex*2+1]; - dac1SetValue(samplesC[sampleIndex*2] / (agcLevel * 40) * 4096 * gain + 2048); - dac2SetValue(samplesC[sampleIndex*2+1] / (agcLevel * 40) * 4096 * gain + 2048); +// if(sampleIndex < filterKernelLength) +// { +// dac1SetValue(samplesC[sampleIndex*2] + samplesB[(FFT_SIZE - filterKernelLength) +// + sampleIndex * 2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// dac2SetValue(samplesC[sampleIndex*2+1] + samplesB[(FFT_SIZE - filterKernelLength) +// + sampleIndex * 2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// } else { + dac1SetValue(samplesC[sampleIndex*2] / (agcLevel * agcScale) * 4096 * gain + 2048); + dac2SetValue(samplesC[sampleIndex*2+1] / (agcLevel * agcScale) * 4096 * gain + 2048); +// } break; case 2: @@ -350,8 +372,16 @@ int isFwd; if(samplesA[sampleIndex*2] > agcLevel) agcLevel = samplesA[sampleIndex*2]; if(samplesA[sampleIndex*2+1] > agcLevel) agcLevel = samplesA[sampleIndex*2+1]; - dac1SetValue(samplesA[sampleIndex*2] / (agcLevel * 40) * 4096 * gain + 2048); - dac2SetValue(samplesA[sampleIndex*2+1] / (agcLevel * 40) * 4096 * gain + 2048); +// if(sampleIndex < filterKernelLength) +// { +// dac1SetValue(samplesA[sampleIndex*2] + samplesC[(FFT_SIZE - filterKernelLength) +// + sampleIndex * 2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// dac2SetValue(samplesA[sampleIndex*2+1] + samplesC[(FFT_SIZE - filterKernelLength) +// + sampleIndex * 2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// } else { + dac1SetValue(samplesA[sampleIndex*2] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); + dac2SetValue(samplesA[sampleIndex*2+1] /*/ (agcLevel * agcScale)*/ * 4096 * gain + 2048); +// } break; } //dac1SetValue(outputSamplesA[sampleIndex*2]); @@ -359,7 +389,7 @@ int isFwd; agcLevel = agcLevel * (1 - 0.0001); sampleIndex++; - if(sampleIndex >= FFT_SIZE - filterKernelLength) + if(sampleIndex >= FFT_SIZE /*- filterKernelLength*/) { sampleRun = 1; sampleIndex = 0; @@ -408,7 +438,6 @@ void zeroSampleBank(float *samples) for(i = 0; i < FFT_BUFFER_SIZE; i++) samples[i] = 0; } - int main(int argc, char* argv[]) { @@ -711,117 +740,122 @@ main(int argc, char* argv[]) - float fftMaxMax = 0; - if(sampleRun) - { +// float fftMaxMax = 0; +// if(sampleRun) +// { +// +// timeMeasurement = millis; +// arm_cfft_radix4_instance_f32 fft_inst; +// //arm_cfft_radix4_init_q31(&fft_inst, FFT_SIZE, 0, 1); +// //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); +// +// if (sampleBankAReady == 1) +// { +// blink_led_on(); +// arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); +// +// +// //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); +// +// arm_cfft_radix4_f32(&fft_inst, samplesA); +// // Calculate magnitude of complex numbers output by the FFT. +// //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); +// +// //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); +// +// //applyCoeficient(samplesA); +// +// arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); +// arm_cfft_radix4_f32(&fft_inst, samplesA); +// +// sampleBankAReady = 0; +// blink_led_off(); +// } +// else if(sampleBankBReady == 1) +// { +// blink_led_on(); +// arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); +// +// //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); +// +// arm_cfft_radix4_f32(&fft_inst, samplesB); +// // Calculate magnitude of complex numbers output by the FFT. +// //arm_cmplx_mag_f32(samplesB, magnitudes, FFT_SIZE); +// //applyCoeficient(samplesB); +// +// arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); +// arm_cfft_radix4_f32(&fft_inst, samplesB); +// sampleBankBReady = 0; +// blink_led_off(); +// +// } +// else if (sampleBankCReady == 1) +// { +// blink_led_on(); +// arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); +// +// +// //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); +// +// arm_cfft_radix4_f32(&fft_inst, samplesC); +// // Calculate magnitude of complex numbers output by the FFT. +// //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); +// +// //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); +// //applyCoeficient(samplesC); +// arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); +// arm_cfft_radix4_f32(&fft_inst, samplesC); +// +// sampleBankCReady = 0; +// blink_led_off(); +// } +// timeMeasurement = millis - timeMeasurement; +// - timeMeasurement = millis; - arm_cfft_radix4_instance_f32 fft_inst; - //arm_cfft_radix4_init_q31(&fft_inst, FFT_SIZE, 0, 1); - //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); - - if (sampleBankAReady == 1) - { - blink_led_on(); - arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); - - - //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); - - arm_cfft_radix4_f32(&fft_inst, samplesA); - // Calculate magnitude of complex numbers output by the FFT. - //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); - - //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); - - applyCoeficient(samplesA); - - arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); - arm_cfft_radix4_f32(&fft_inst, samplesA); - - sampleBankAReady = 0; - blink_led_off(); - } - else if(sampleBankBReady == 1) - { - blink_led_on(); - arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); - - //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); - - arm_cfft_radix4_f32(&fft_inst, samplesB); - // Calculate magnitude of complex numbers output by the FFT. - //arm_cmplx_mag_f32(samplesB, magnitudes, FFT_SIZE); - applyCoeficient(samplesB); - - arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); - arm_cfft_radix4_f32(&fft_inst, samplesB); - sampleBankBReady = 0; - blink_led_off(); - - } - else if (sampleBankCReady == 1) - { - blink_led_on(); - arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); - - - //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); - - arm_cfft_radix4_f32(&fft_inst, samplesC); - // Calculate magnitude of complex numbers output by the FFT. - //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); - - //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); - applyCoeficient(samplesC); - arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); - arm_cfft_radix4_f32(&fft_inst, samplesC); - - sampleBankCReady = 0; - blink_led_off(); - } - timeMeasurement = millis - timeMeasurement; + arm_cmplx_mag_f32(samplesDisplay, magnitudes, FFT_SIZE); float fftMax = 0; - // float fftMin = 100; - // float logMax; - // uint8_t i; - // for(i = 0; i < 255; i++) - // { - // float mags = magnitudes[i]; - // if(mags > fftMax) fftMax = mags; - // if(mags < fftMin) fftMin = mags; - // } - // //logMax = log2(fftMax); - // - // if(fftMax > fftMaxMax) fftMaxMax = fftMax; - // logMax = log2(fftMaxMax); + float fftMin = 100; + float fftMaxMax = 0; + float logMax; + uint8_t i; + for(i = 0; i < 255; i++) + { + float mags = magnitudes[i]; + if(mags > fftMax) fftMax = mags; + if(mags < fftMin) fftMin = mags; + } + //logMax = log2(fftMax); + + if(fftMax > fftMaxMax) fftMaxMax = fftMax; + logMax = log2(fftMaxMax); - //TODOne: SWITCH THESE AND FLIP THEM. So that higher frequencies appear higher on screen. - //TODO: Got rid of the first bin because it's just DC offset, right? - //but now narrow signal can disappear when they are right at the center.... - //Will that be better when I lower the sample frequency? Maybe I should do that next. - // for(i = 1; i < 120; i++) - // { - // mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; - // //mags = magnitudes[i] / fftMaxMax * 32; - // Adafruit_ILI9340_drawPixel(waterfallScanLine, (120 - i), gradient[(uint8_t) mags]); - // } - // - // for(i = 135; i < 255; i++) - // { - // mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; - // //mags = magnitudes[i] / fftMaxMax * 32; - // Adafruit_ILI9340_drawPixel(waterfallScanLine, 359 - (i - 15), gradient[(uint8_t) mags]); - // } - // - // waterfallScanLine++; - // if(waterfallScanLine > 119) waterfallScanLine = 0; - // Adafruit_ILI9340_setVertialScrollStartAddress((119 - waterfallScanLine) + 200); +// TODOne: SWITCH THESE AND FLIP THEM. So that higher frequencies appear higher on screen. +// TODO: Got rid of the first bin because it's just DC offset, right? +// but now narrow signal can disappear when they are right at the center.... +// Will that be better when I lower the sample frequency? Maybe I should do that next. + //uint16_t i; + for(i = 1; i < 120; i++) + { + mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; + //mags = magnitudes[i] / fftMaxMax * 32; + Adafruit_ILI9340_drawPixel(waterfallScanLine, (120 - i), gradient[(uint8_t) mags]); + } - sampleRun = 0; - } + for(i = 135; i < 255; i++) + { + mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; + //mags = magnitudes[i] / fftMaxMax * 32; + Adafruit_ILI9340_drawPixel(waterfallScanLine, 359 - (i - 15), gradient[(uint8_t) mags]); + } + + waterfallScanLine++; + if(waterfallScanLine > 119) waterfallScanLine = 0; + Adafruit_ILI9340_setVertialScrollStartAddress((119 - waterfallScanLine) + 200); +// +// sampleRun = 0; +// } if(vfoAFrequency != vfoALastFreq) { @@ -881,6 +915,140 @@ main(int argc, char* argv[]) } } +void processStream() +{ + + + + float fftMaxMax = 0; + if(sampleRun) + { + + //timeMeasurement = millis; + arm_cfft_radix4_instance_f32 fft_inst; + //arm_cfft_radix4_init_q31(&fft_inst, FFT_SIZE, 0, 1); + //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); + + if (sampleBankAReady == 1) + { + blink_led_on(); + arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); + + + //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); + + arm_cfft_radix4_f32(&fft_inst, samplesA); + // Calculate magnitude of complex numbers output by the FFT. + if(waterfallBusy != 1) + { + uint16_t i; + for(i = 0; i < FFT_BUFFER_SIZE; i++) samplesDisplay[i] = samplesA[i]; + //waterfallBusy = 1; + } + //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); + + //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); + + applyCoeficient(samplesA); + + arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); + arm_cfft_radix4_f32(&fft_inst, samplesA); + + sampleBankAReady = 0; + blink_led_off(); + } + else if(sampleBankBReady == 1) + { + blink_led_on(); + arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); + + //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); + + arm_cfft_radix4_f32(&fft_inst, samplesB); + // Calculate magnitude of complex numbers output by the FFT. + //arm_cmplx_mag_f32(samplesB, magnitudes, FFT_SIZE); + applyCoeficient(samplesB); + + arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); + arm_cfft_radix4_f32(&fft_inst, samplesB); + sampleBankBReady = 0; + blink_led_off(); + + } + else if (sampleBankCReady == 1) + { + blink_led_on(); + arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 1); + + + //arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 0, 2); + + arm_cfft_radix4_f32(&fft_inst, samplesC); + // Calculate magnitude of complex numbers output by the FFT. + //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); + + //arm_cmplx_mag_f32(samplesA, magnitudes, FFT_SIZE); + applyCoeficient(samplesC); + arm_cfft_radix4_init_f32(&fft_inst, FFT_SIZE, 1, 1); + arm_cfft_radix4_f32(&fft_inst, samplesC); + + sampleBankCReady = 0; + blink_led_off(); + } + //timeMeasurement = millis - timeMeasurement; + + float fftMax = 0; + // float fftMin = 100; + // float logMax; + // uint8_t i; + // for(i = 0; i < 255; i++) + // { + // float mags = magnitudes[i]; + // if(mags > fftMax) fftMax = mags; + // if(mags < fftMin) fftMin = mags; + // } + // //logMax = log2(fftMax); + // + // if(fftMax > fftMaxMax) fftMaxMax = fftMax; + // logMax = log2(fftMaxMax); + + + //TODOne: SWITCH THESE AND FLIP THEM. So that higher frequencies appear higher on screen. + //TODO: Got rid of the first bin because it's just DC offset, right? + //but now narrow signal can disappear when they are right at the center.... + //Will that be better when I lower the sample frequency? Maybe I should do that next. + // for(i = 1; i < 120; i++) + // { + // mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; + // //mags = magnitudes[i] / fftMaxMax * 32; + // Adafruit_ILI9340_drawPixel(waterfallScanLine, (120 - i), gradient[(uint8_t) mags]); + // } + // + // for(i = 135; i < 255; i++) + // { + // mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; + // //mags = magnitudes[i] / fftMaxMax * 32; + // Adafruit_ILI9340_drawPixel(waterfallScanLine, 359 - (i - 15), gradient[(uint8_t) mags]); + // } + // + // waterfallScanLine++; + // if(waterfallScanLine > 119) waterfallScanLine = 0; + // Adafruit_ILI9340_setVertialScrollStartAddress((119 - waterfallScanLine) + 200); + + sampleRun = 0; + } + + + + + + + + //wrongThings++; + //__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); + clearTimUpdateFlag(&TimHandle4); +} + void updateVfo() { encoderPos = getPos(); @@ -897,105 +1065,105 @@ void updateVfo() } //TIM_TimeBaseInitTypeDef timeBaseStructure; - -TIM_OC_InitTypeDef tsConfig; -#define PULSE1_VALUE 40961 /* Capture Compare 1 Value */ +// +//TIM_OC_InitTypeDef tsConfig; +//#define PULSE1_VALUE 40961 /* Capture Compare 1 Value */ uint32_t uwPrescalerValue = 0; -void TIM_setup() -{ - /*##-1- Configure the TIM peripheral #######################################*/ - /* ----------------------------------------------------------------------- - In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1), - since APB1 prescaler is different from 1. - TIM3CLK = 2 * PCLK1 - PCLK1 = HCLK / 4 - => TIM3CLK = HCLK / 2 = SystemCoreClock /2 - To get TIM3 counter clock at 60 KHz, the Prescaler is computed as following: - Prescaler = (TIM3CLK / TIM3 counter clock) - 1 - Prescaler = ((SystemCoreClock /2) /60 KHz) - 1 - - Note: - SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file. - Each time the core clock (HCLK) changes, user had to update SystemCoreClock - variable value. Otherwise, any configuration based on this variable will be incorrect. - This variable is updated in three ways: - 1) by calling CMSIS function SystemCoreClockUpdate() - 2) by calling HAL API function HAL_RCC_GetSysClockFreq() - 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency - ----------------------------------------------------------------------- */ - - /* Compute the prescaler value to have TIM3 counter clock equal to 60 KHz */ - uwPrescalerValue = (uint32_t) ((SystemCoreClock/2) / 60000) - 1; - - /* Set TIMx instance */ - TimHandle.Instance = TIM3; //TIMx; - - /* Initialize TIM3 peripheral as follow: - + Period = 65535 - + Prescaler = (SystemCoreClock/2)/60000 - + ClockDivision = 0 - + Counter direction = Up - */ - TimHandle.Init.Period = 65535; - TimHandle.Init.Prescaler = uwPrescalerValue; - TimHandle.Init.ClockDivision = 0; - TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; - if(HAL_TIM_OC_Init(&TimHandle) != HAL_OK) - { - /* Initialization Error */ - //Error_Handler(); - doNothing(); - } - - /*##-2- Configure the PWM channels #########################################*/ - /* Common configuration */ - tsConfig.OCMode = TIM_OCMODE_TIMING; - tsConfig.OCPolarity = TIM_OCPOLARITY_HIGH; - tsConfig.OCFastMode = TIM_OCFAST_DISABLE; - - /* Set the pulse value for channel 1 */ - tsConfig.Pulse = PULSE1_VALUE; - if(HAL_TIM_OC_ConfigChannel(&TimHandle, &tsConfig, TIM_CHANNEL_1) != HAL_OK) - { - /* Initialization Error */ - //Error_Handler(); - doNothing(); - } - - /*##-4- Start the Output Compare mode in interrupt mode ####################*/ - /* Start Channel1 */ - if(HAL_TIM_OC_Start_IT(&TimHandle, TIM_CHANNEL_1) != HAL_OK) - { - /* Initialization Error */ - //Error_Handler(); - doNothing(); - } - -} - - -///** -// * @brief Configures the TIM IRQ Handler. -// * @param None -// * @retval None +//void TIM_setup() +//{ +// /*##-1- Configure the TIM peripheral #######################################*/ +// /* ----------------------------------------------------------------------- +// In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1), +// since APB1 prescaler is different from 1. +// TIM3CLK = 2 * PCLK1 +// PCLK1 = HCLK / 4 +// => TIM3CLK = HCLK / 2 = SystemCoreClock /2 +// To get TIM3 counter clock at 60 KHz, the Prescaler is computed as following: +// Prescaler = (TIM3CLK / TIM3 counter clock) - 1 +// Prescaler = ((SystemCoreClock /2) /60 KHz) - 1 +// +// Note: +// SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file. +// Each time the core clock (HCLK) changes, user had to update SystemCoreClock +// variable value. Otherwise, any configuration based on this variable will be incorrect. +// This variable is updated in three ways: +// 1) by calling CMSIS function SystemCoreClockUpdate() +// 2) by calling HAL API function HAL_RCC_GetSysClockFreq() +// 3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency +// ----------------------------------------------------------------------- */ +// +// /* Compute the prescaler value to have TIM3 counter clock equal to 60 KHz */ +// uwPrescalerValue = (uint32_t) ((SystemCoreClock/2) / 60000) - 1; +// +// /* Set TIMx instance */ +// TimHandle.Instance = TIM3; //TIMx; +// +// /* Initialize TIM3 peripheral as follow: +// + Period = 65535 +// + Prescaler = (SystemCoreClock/2)/60000 +// + ClockDivision = 0 +// + Counter direction = Up // */ -void TIM_Config(void) -{ - NVIC_InitTypeDef NVIC_InitStructure; - - /* TIM3 clock enable */ - //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); - __TIM3_CLK_ENABLE(); - - /* Enable the TIM3 gloabal Interrupt */ - NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; - NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; - NVIC_Init(&NVIC_InitStructure); +// TimHandle.Init.Period = 65535; +// TimHandle.Init.Prescaler = uwPrescalerValue; +// TimHandle.Init.ClockDivision = 0; +// TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; +// if(HAL_TIM_OC_Init(&TimHandle) != HAL_OK) +// { +// /* Initialization Error */ +// //Error_Handler(); +// doNothing(); +// } +// +// /*##-2- Configure the PWM channels #########################################*/ +// /* Common configuration */ +// tsConfig.OCMode = TIM_OCMODE_TIMING; +// tsConfig.OCPolarity = TIM_OCPOLARITY_HIGH; +// tsConfig.OCFastMode = TIM_OCFAST_DISABLE; +// +// /* Set the pulse value for channel 1 */ +// tsConfig.Pulse = PULSE1_VALUE; +// if(HAL_TIM_OC_ConfigChannel(&TimHandle, &tsConfig, TIM_CHANNEL_1) != HAL_OK) +// { +// /* Initialization Error */ +// //Error_Handler(); +// doNothing(); +// } +// +// /*##-4- Start the Output Compare mode in interrupt mode ####################*/ +// /* Start Channel1 */ +// if(HAL_TIM_OC_Start_IT(&TimHandle, TIM_CHANNEL_1) != HAL_OK) +// { +// /* Initialization Error */ +// //Error_Handler(); +// doNothing(); +// } +// +//} -} +/////** +//// * @brief Configures the TIM IRQ Handler. +//// * @param None +//// * @retval None +//// */ +//void TIM_Config(void) +//{ +// NVIC_InitTypeDef NVIC_InitStructure; +// +// /* TIM3 clock enable */ +// //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); +// __TIM3_CLK_ENABLE(); +// +// /* Enable the TIM3 gloabal Interrupt */ +// NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; +// NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; +// NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; +// NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; +// NVIC_Init(&NVIC_InitStructure); +// +// +//} TIM_TypeDef timTimBase; //TIM_HandleTypeDef timHandle; @@ -1009,6 +1177,7 @@ void TIM_Try(void) //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); __TIM3_CLK_ENABLE(); + TimHandle.Instance = TIM3; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimHandle.Init.Period = 1050; @@ -1016,6 +1185,8 @@ void TIM_Try(void) TimHandle.Init.ClockDivision = 0; HAL_TIM_Base_Init(&TimHandle); + + HAL_TIM_Base_Start_IT(&TimHandle); /*##-2- Configure the NVIC for TIMx #########################################*/ @@ -1026,6 +1197,27 @@ void TIM_Try(void) HAL_NVIC_EnableIRQ(TIMx_IRQn); + + + __TIM4_CLK_ENABLE(); + TimHandle4.Instance = TIM4; + TimHandle4.Init.CounterMode = TIM_COUNTERMODE_UP; + TimHandle4.Init.Period = 1050; + TimHandle4.Init.Prescaler = uwPrescalerValue; + TimHandle4.Init.ClockDivision = 0; + + HAL_TIM_Base_Init(&TimHandle4); + HAL_TIM_Base_Start_IT(&TimHandle4); + + /*##-2- Configure the NVIC for TIMx #########################################*/ + /* Set the TIMx priority */ + HAL_NVIC_SetPriority(TIM4_IRQn, 2, 4); + + /* Enable the TIMx global Interrupt */ + HAL_NVIC_EnableIRQ(TIM4_IRQn); + + + // int tim3; // while(1) // { diff --git a/Source/src/spi.c b/Source/src/spi.c index 5b7528f..90d93e6 100644 --- a/Source/src/spi.c +++ b/Source/src/spi.c @@ -9,63 +9,23 @@ #include #include #include -//#include #include -//static int spi2Semaphore; - -//SPI_HandleTypeDef SpiHandle; - void spi_init(void) { - // set up the used SPI (SPI2) and pins - - - - SPI_InitTypeDef spiInitStructure; GPIO_InitTypeDef gpioInitStructure; HAL_SPI_MspInit(&SpiHandle); - __SPI1_CLK_ENABLE(); - - - - -// // SPI2 SCK and MOSI -// gpioInitStructure.GPIO_Pin = SPI1_SCK.pin; -// gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz; -// gpioInitStructure.GPIO_Mode = GPIO_Mode_AF_PP; -// GPIO_Init(SPI1_SCK.port, &gpioInitStructure); -// -// gpioInitStructure.GPIO_Pin = SPI1_MOSI.pin; -// gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz; -// gpioInitStructure.GPIO_Mode = GPIO_Mode_AF_PP; -// GPIO_Init(SPI1_MOSI.port, &gpioInitStructure); -// -// // SPI2 MISO -// gpioInitStructure.GPIO_Pin = SPI1_MISO.pin; -// gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz; -// gpioInitStructure.GPIO_Mode = GPIO_Mode_IPU; -// GPIO_Init(SPI1_MISO.port, &gpioInitStructure); -// -// // RFID NSS -// gpioInitStructure.GPIO_Pin = LCD_NSS.pin; -// gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz; -// gpioInitStructure.GPIO_Mode = GPIO_Mode_Out_PP; -// GPIO_Init(LCD_NSS.port, &gpioInitStructure); -// GPIO_WriteBit(LCD_NSS.port, LCD_NSS.pin, (BitAction)1); // TBD - should this be before init? - // SPI2 SCK and MOSI gpioInitStructure.Pin = SPI1_SCK.pin; gpioInitStructure.Speed = GPIO_SPEED_FAST; gpioInitStructure.Mode = GPIO_MODE_AF_PP; gpioInitStructure.Alternate = GPIO_AF5_SPI1; - //gpioInitStructure.Mode = GPIO_MODE_OUTPUT_PP; gpioInitStructure.Pull = GPIO_NOPULL; //gpioInitStructure.Alternate = 1; HAL_GPIO_Init(SPI1_SCK.port, &gpioInitStructure); @@ -73,7 +33,6 @@ void spi_init(void) gpioInitStructure.Pin = SPI1_MOSI.pin; gpioInitStructure.Speed = GPIO_SPEED_FAST; gpioInitStructure.Mode = GPIO_MODE_AF_PP; - //gpioInitStructure.Mode = GPIO_MODE_OUTPUT_PP; gpioInitStructure.Pull = GPIO_NOPULL; gpioInitStructure.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(SPI1_MOSI.port, &gpioInitStructure); @@ -95,36 +54,26 @@ void spi_init(void) HAL_GPIO_Init(LCD_NSS.port, &gpioInitStructure); HAL_GPIO_WritePin(LCD_NSS.port, LCD_NSS.pin, 1); // TBD - should this be before init? +// gpioInitStructure.Pin = LCD_NSS.pin; +// gpioInitStructure.Speed = GPIO_SPEED_FAST; +// gpioInitStructure.Mode = GPIO_MODE_AF_PP; +// gpioInitStructure.Pull = GPIO_NOPULL; +// gpioInitStructure.Alternate = GPIO_AF5_SPI1; +// HAL_GPIO_Init(LCD_NSS.port, &gpioInitStructure); +// //HAL_GPIO_WritePin(LCD_NSS.port, LCD_NSS.pin, 1); // TBD - should this be before init? - // Accelerometer NSS -// gpioInitStructure.GPIO_Pin = ACCEL_NSS.pin; -// gpioInitStructure.GPIO_Speed = GPIO_Speed_2MHz; -// gpioInitStructure.GPIO_Mode = GPIO_Mode_Out_PP; -// GPIO_Init(ACCEL_NSS.port, &gpioInitStructure); -// GPIO_WriteBit(ACCEL_NSS.port, ACCEL_NSS.pin, (BitAction)1); // TBD - should this be before init? - // init semaphore -// spi2Semaphore = 1; - - //GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE); //So I can use the other SPI1 pins? (To keep the DACs availble) - //GPIO_Remap_SPI1 - - // SPI 1 - // SPI_StructInit(&spiInitStructure); - //spiInitStructure. - //HAL_SPI_ - - SpiHandle.Instance = SPI1; - SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;// SPI_Direction_2Lines_FullDuplex; - SpiHandle.Init.Mode = SPI_MODE_MASTER; // SPI_Mode_Master; - SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; // SPI_DataSize_8b; - SpiHandle.Init.CLKPolarity /*CPOL*/ = SPI_POLARITY_HIGH; // SPI_C SPI_CPOL_High; - SpiHandle.Init.CLKPhase /*CPHA*/ = SPI_PHASE_2EDGE; // SPI_CPHA_2Edge; - SpiHandle.Init.NSS = SPI_NSS_SOFT; // SPI_NSS_Soft; - SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; //SPI_BaudRatePrescaler_2; - SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; // SPI_FirstBit_MSB; - SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; - SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED; + SpiHandle.Instance = SPI1; + SpiHandle.Init.Direction = SPI_DIRECTION_2LINES; + SpiHandle.Init.Mode = SPI_MODE_MASTER; + SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; + SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH; + SpiHandle.Init.CLKPhase = SPI_PHASE_2EDGE; + SpiHandle.Init.NSS = SPI_NSS_SOFT; //SPI_NSS_SOFT; + SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; + SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; + SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED; SpiHandle.Init.CRCPolynomial = 7; if(HAL_SPI_Init(&SpiHandle) != HAL_OK) @@ -132,9 +81,6 @@ void spi_init(void) /* Initialization Error */ //Error_Handler(); } - //HAL_SPI_TransmitReceive(); - - //SPI_Cmd(SPI2, ENABLE); } diff --git a/Source/src/stm32f4xx_it.c b/Source/src/stm32f4xx_it.c index 3ec43c7..b310912 100644 --- a/Source/src/stm32f4xx_it.c +++ b/Source/src/stm32f4xx_it.c @@ -160,6 +160,21 @@ void TIM3_IRQHandler(void) { HAL_TIM_IRQHandler(&TimHandle); } + +/** + * @brief This function handles TIM4 global interrupt request. + * @param None + * @retval None + */ +void TIM4_IRQHandler(void) +{ + //HAL_TIM_IRQHandler(&TimHandle); +// HAL_TIM_IRQHandler(&TimHandle); +processStream(); + //clearTimUpdateFlag(&TimHandle); + //__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); +} + //void TIM3_IRQHandler(void) //{ // __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); diff --git a/Source/system/src/stm32f4-hal/stm32f4xx_hal_tim.c b/Source/system/src/stm32f4-hal/stm32f4xx_hal_tim.c index 5e4ddf6..7056f62 100644 --- a/Source/system/src/stm32f4-hal/stm32f4xx_hal_tim.c +++ b/Source/system/src/stm32f4-hal/stm32f4xx_hal_tim.c @@ -2885,6 +2885,11 @@ void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim) } } +void clearTimUpdateFlag(TIM_HandleTypeDef *htim) +{ + __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); +} + /** * @} */