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.

This commit is contained in:
Michael Colton 2014-07-14 01:41:46 -06:00
parent 71b87a38d7
commit 31de146601
9 changed files with 458 additions and 292 deletions

Binary file not shown.

View file

@ -50,6 +50,9 @@
__IO uint32_t timingDelay;
// gpio pins // gpio pins
// extern const Gpio_Pin RX_TO_GSM; // extern const Gpio_Pin RX_TO_GSM;
// extern const Gpio_Pin TX_FROM_GSM; // extern const Gpio_Pin TX_FROM_GSM;

View file

@ -16,6 +16,8 @@
#include "Adafruit_GFX.h" #include "Adafruit_GFX.h"
#include "Adafruit_ILI9340.h" #include "Adafruit_ILI9340.h"
#include "stm32f4xx_hal.h" #include "stm32f4xx_hal.h"
//#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_def.h"
#include "string.h" #include "string.h"
#include "math.h" #include "math.h"
#include "arm_math.h" #include "arm_math.h"
@ -28,3 +30,4 @@
#include "stm32f4xx_hal_dac.h" #include "stm32f4xx_hal_dac.h"
TIM_HandleTypeDef TimHandle; TIM_HandleTypeDef TimHandle;
TIM_HandleTypeDef TimHandle4;

View file

@ -244,6 +244,8 @@ void Adafruit_ILI9340_begin(void) {
HAL_GPIO_WritePin(LCD_RESET.port, LCD_RESET.pin, 1); HAL_GPIO_WritePin(LCD_RESET.port, LCD_RESET.pin, 1);
hal_delay_ms(150); hal_delay_ms(150);
HAL_GPIO_WritePin(LCD_NSS.port, LCD_NSS.pin, 0); //I'm going to try leaving this low the WHOLE TIME!
/* /*
uint8_t x = readcommand8(ILI9340_RDMODE); uint8_t x = readcommand8(ILI9340_RDMODE);
Serial.print("\nDisplay Power Mode: 0x"); Serial.println(x, HEX); Serial.print("\nDisplay Power Mode: 0x"); Serial.println(x, HEX);

View file

@ -119,7 +119,7 @@ const Gpio_Pin dac2 = { GPIOA, GPIO_PIN_5 };
//}; //};
static uint32_t halMilliseconds; static uint32_t halMilliseconds;
static uint32_t timingDelay; //static uint32_t timingDelay;
static hal_sysTickCallback sysTickCallback = 0; //Was NULL, but NULL isn't defined? Where is it defined? static hal_sysTickCallback sysTickCallback = 0; //Was NULL, but NULL isn't defined? Where is it defined?
@ -164,14 +164,14 @@ void hal_delay_ms(uint32_t ms)
{ {
// busy wait for ms milliseconds // busy wait for ms milliseconds
//TEMP ////TEMP
int delay, extra; //int delay, extra;
for(delay = 0; delay < ms; delay++) //for(delay = 0; delay < ms; delay++)
for(extra = 0; extra < 1000; extra++); // for(extra = 0; extra < 1000; extra++);
// timingDelay = ms; timingDelay = ms;
// while (timingDelay) while (timingDelay)
// ; ;
} }

View file

@ -60,17 +60,18 @@ uint16_t filterKernelLength = 100; //what's a good value? How does it relate to
uint16_t menuState = 0; uint16_t menuState = 0;
uint16_t menuLastState = 1; uint16_t menuLastState = 1;
uint16_t menuCount = 10; uint16_t menuCount = 9;
uint32_t frequencyDialMultiplier = 1; uint32_t frequencyDialMultiplier = 1;
long vfoAFrequency = 7260000; long vfoAFrequency = 7058960;
long vfoALastFreq = 7260000; long vfoALastFreq = 0;
int encoderPos, encoderLastPos; int encoderPos, encoderLastPos;
int16_t filterUpperLimit = 10; int16_t filterUpperLimit = 68;
int16_t filterLowerLimit = 0; int16_t filterLowerLimit = 0;
float agcLevel = 0; float agcLevel = 0;
float agcScale = 160; //Higher is lower volume.. for now
void polarToRect(float m, float a, float32_t* x, float32_t* y) void polarToRect(float m, float a, float32_t* x, float32_t* y)
{ {
@ -224,6 +225,7 @@ SysTick_Handler (void)
millis++; millis++;
timer_tick (); timer_tick ();
Tick(); Tick();
if(timingDelay > 0) timingDelay--;
} }
int clickMultiply; int clickMultiply;
@ -302,9 +304,13 @@ int isFwd;
float samplesA[FFT_BUFFER_SIZE]; float samplesA[FFT_BUFFER_SIZE];
float samplesB[FFT_BUFFER_SIZE]; float samplesB[FFT_BUFFER_SIZE];
float samplesC[FFT_BUFFER_SIZE]; float samplesC[FFT_BUFFER_SIZE];
float samplesDisplay[FFT_BUFFER_SIZE];
int sampleBankAReady = 0; int sampleBankAReady = 0;
int sampleBankBReady = 0; int sampleBankBReady = 0;
int sampleBankCReady = 0; int sampleBankCReady = 0;
uint8_t waterfallBusy = 0;
//float outputSamplesA[512]; //float outputSamplesA[512];
//float outputSamplesB[512]; //float outputSamplesB[512];
int sampleBank = 0; int sampleBank = 0;
@ -328,8 +334,16 @@ int isFwd;
if(samplesB[sampleIndex*2] > agcLevel) agcLevel = samplesB[sampleIndex*2]; if(samplesB[sampleIndex*2] > agcLevel) agcLevel = samplesB[sampleIndex*2];
if(samplesB[sampleIndex*2+1] > agcLevel) agcLevel = samplesB[sampleIndex*2+1]; if(samplesB[sampleIndex*2+1] > agcLevel) agcLevel = samplesB[sampleIndex*2+1];
dac1SetValue(samplesB[sampleIndex*2] / (agcLevel * 40) * 4096 * gain + 2048); // if(sampleIndex < filterKernelLength)
dac2SetValue(samplesB[sampleIndex*2+1] / (agcLevel * 40) * 4096 * gain + 2048); // {
// 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; break;
case 1: case 1:
@ -339,8 +353,16 @@ int isFwd;
if(samplesC[sampleIndex*2] > agcLevel) agcLevel =samplesC[sampleIndex*2]; if(samplesC[sampleIndex*2] > agcLevel) agcLevel =samplesC[sampleIndex*2];
if(samplesC[sampleIndex*2+1] > agcLevel) agcLevel = samplesC[sampleIndex*2+1]; if(samplesC[sampleIndex*2+1] > agcLevel) agcLevel = samplesC[sampleIndex*2+1];
dac1SetValue(samplesC[sampleIndex*2] / (agcLevel * 40) * 4096 * gain + 2048); // if(sampleIndex < filterKernelLength)
dac2SetValue(samplesC[sampleIndex*2+1] / (agcLevel * 40) * 4096 * gain + 2048); // {
// 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; break;
case 2: case 2:
@ -350,8 +372,16 @@ int isFwd;
if(samplesA[sampleIndex*2] > agcLevel) agcLevel = samplesA[sampleIndex*2]; if(samplesA[sampleIndex*2] > agcLevel) agcLevel = samplesA[sampleIndex*2];
if(samplesA[sampleIndex*2+1] > agcLevel) agcLevel = samplesA[sampleIndex*2+1]; if(samplesA[sampleIndex*2+1] > agcLevel) agcLevel = samplesA[sampleIndex*2+1];
dac1SetValue(samplesA[sampleIndex*2] / (agcLevel * 40) * 4096 * gain + 2048); // if(sampleIndex < filterKernelLength)
dac2SetValue(samplesA[sampleIndex*2+1] / (agcLevel * 40) * 4096 * gain + 2048); // {
// 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; break;
} }
//dac1SetValue(outputSamplesA[sampleIndex*2]); //dac1SetValue(outputSamplesA[sampleIndex*2]);
@ -359,7 +389,7 @@ int isFwd;
agcLevel = agcLevel * (1 - 0.0001); agcLevel = agcLevel * (1 - 0.0001);
sampleIndex++; sampleIndex++;
if(sampleIndex >= FFT_SIZE - filterKernelLength) if(sampleIndex >= FFT_SIZE /*- filterKernelLength*/)
{ {
sampleRun = 1; sampleRun = 1;
sampleIndex = 0; sampleIndex = 0;
@ -408,7 +438,6 @@ void zeroSampleBank(float *samples)
for(i = 0; i < FFT_BUFFER_SIZE; i++) samples[i] = 0; for(i = 0; i < FFT_BUFFER_SIZE; i++) samples[i] = 0;
} }
int int
main(int argc, char* argv[]) main(int argc, char* argv[])
{ {
@ -711,117 +740,122 @@ main(int argc, char* argv[])
float fftMaxMax = 0; // float fftMaxMax = 0;
if(sampleRun) // 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_cmplx_mag_f32(samplesDisplay, magnitudes, FFT_SIZE);
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;
float fftMax = 0; float fftMax = 0;
// float fftMin = 100; float fftMin = 100;
// float logMax; float fftMaxMax = 0;
// uint8_t i; float logMax;
// for(i = 0; i < 255; i++) uint8_t i;
// { for(i = 0; i < 255; i++)
// float mags = magnitudes[i]; {
// if(mags > fftMax) fftMax = mags; float mags = magnitudes[i];
// if(mags < fftMin) fftMin = mags; if(mags > fftMax) fftMax = mags;
// } if(mags < fftMin) fftMin = mags;
// //logMax = log2(fftMax); }
// //logMax = log2(fftMax);
// if(fftMax > fftMaxMax) fftMaxMax = fftMax;
// logMax = log2(fftMaxMax); if(fftMax > fftMaxMax) fftMaxMax = fftMax;
logMax = log2(fftMaxMax);
//TODOne: SWITCH THESE AND FLIP THEM. So that higher frequencies appear higher on screen. // 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? // 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.... // 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. // Will that be better when I lower the sample frequency? Maybe I should do that next.
// for(i = 1; i < 120; i++) //uint16_t i;
// { for(i = 1; i < 120; i++)
// mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32; {
// //mags = magnitudes[i] / fftMaxMax * 32; mags = (log2(magnitudes[i] + 1)) / fftMaxMax * 32;
// Adafruit_ILI9340_drawPixel(waterfallScanLine, (120 - i), gradient[(uint8_t) mags]); //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; 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) 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() void updateVfo()
{ {
encoderPos = getPos(); encoderPos = getPos();
@ -897,105 +1065,105 @@ void updateVfo()
} }
//TIM_TimeBaseInitTypeDef timeBaseStructure; //TIM_TimeBaseInitTypeDef timeBaseStructure;
//
TIM_OC_InitTypeDef tsConfig; //TIM_OC_InitTypeDef tsConfig;
#define PULSE1_VALUE 40961 /* Capture Compare 1 Value */ //#define PULSE1_VALUE 40961 /* Capture Compare 1 Value */
uint32_t uwPrescalerValue = 0; uint32_t uwPrescalerValue = 0;
void TIM_setup() //void TIM_setup()
{ //{
/*##-1- Configure the TIM peripheral #######################################*/ // /*##-1- Configure the TIM peripheral #######################################*/
/* ----------------------------------------------------------------------- // /* -----------------------------------------------------------------------
In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1), // In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),
since APB1 prescaler is different from 1. // since APB1 prescaler is different from 1.
TIM3CLK = 2 * PCLK1 // TIM3CLK = 2 * PCLK1
PCLK1 = HCLK / 4 // PCLK1 = HCLK / 4
=> TIM3CLK = HCLK / 2 = SystemCoreClock /2 // => TIM3CLK = HCLK / 2 = SystemCoreClock /2
To get TIM3 counter clock at 60 KHz, the Prescaler is computed as following: // To get TIM3 counter clock at 60 KHz, the Prescaler is computed as following:
Prescaler = (TIM3CLK / TIM3 counter clock) - 1 // Prescaler = (TIM3CLK / TIM3 counter clock) - 1
Prescaler = ((SystemCoreClock /2) /60 KHz) - 1 // Prescaler = ((SystemCoreClock /2) /60 KHz) - 1
//
Note: // Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file. // 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 // Each time the core clock (HCLK) changes, user had to update SystemCoreClock
variable value. Otherwise, any configuration based on this variable will be incorrect. // variable value. Otherwise, any configuration based on this variable will be incorrect.
This variable is updated in three ways: // This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate() // 1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetSysClockFreq() // 2) by calling HAL API function HAL_RCC_GetSysClockFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency // 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 */ // /* Compute the prescaler value to have TIM3 counter clock equal to 60 KHz */
uwPrescalerValue = (uint32_t) ((SystemCoreClock/2) / 60000) - 1; // uwPrescalerValue = (uint32_t) ((SystemCoreClock/2) / 60000) - 1;
//
/* Set TIMx instance */ // /* Set TIMx instance */
TimHandle.Instance = TIM3; //TIMx; // TimHandle.Instance = TIM3; //TIMx;
//
/* Initialize TIM3 peripheral as follow: // /* Initialize TIM3 peripheral as follow:
+ Period = 65535 // + Period = 65535
+ Prescaler = (SystemCoreClock/2)/60000 // + Prescaler = (SystemCoreClock/2)/60000
+ ClockDivision = 0 // + ClockDivision = 0
+ Counter direction = Up // + 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_Config(void) // TimHandle.Init.Period = 65535;
{ // TimHandle.Init.Prescaler = uwPrescalerValue;
NVIC_InitTypeDef NVIC_InitStructure; // TimHandle.Init.ClockDivision = 0;
// TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
/* TIM3 clock enable */ // if(HAL_TIM_OC_Init(&TimHandle) != HAL_OK)
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // {
__TIM3_CLK_ENABLE(); // /* Initialization Error */
// //Error_Handler();
/* Enable the TIM3 gloabal Interrupt */ // doNothing();
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; // }
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // /*##-2- Configure the PWM channels #########################################*/
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // /* Common configuration */
NVIC_Init(&NVIC_InitStructure); // 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_TypeDef timTimBase;
//TIM_HandleTypeDef timHandle; //TIM_HandleTypeDef timHandle;
@ -1009,6 +1177,7 @@ void TIM_Try(void)
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
__TIM3_CLK_ENABLE(); __TIM3_CLK_ENABLE();
TimHandle.Instance = TIM3; TimHandle.Instance = TIM3;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP; TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
TimHandle.Init.Period = 1050; TimHandle.Init.Period = 1050;
@ -1016,6 +1185,8 @@ void TIM_Try(void)
TimHandle.Init.ClockDivision = 0; TimHandle.Init.ClockDivision = 0;
HAL_TIM_Base_Init(&TimHandle); HAL_TIM_Base_Init(&TimHandle);
HAL_TIM_Base_Start_IT(&TimHandle); HAL_TIM_Base_Start_IT(&TimHandle);
/*##-2- Configure the NVIC for TIMx #########################################*/ /*##-2- Configure the NVIC for TIMx #########################################*/
@ -1026,6 +1197,27 @@ void TIM_Try(void)
HAL_NVIC_EnableIRQ(TIMx_IRQn); 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; // int tim3;
// while(1) // while(1)
// { // {

View file

@ -9,63 +9,23 @@
#include <hal.h> #include <hal.h>
#include <stm32f4xx_hal_spi.h> #include <stm32f4xx_hal_spi.h>
#include <stm32f4xx_hal_gpio.h> #include <stm32f4xx_hal_gpio.h>
//#include <stm32f415xx.h>
#include <stm32f4xx_hal.h> #include <stm32f4xx_hal.h>
//static int spi2Semaphore;
//SPI_HandleTypeDef SpiHandle;
void spi_init(void) void spi_init(void)
{ {
// set up the used SPI (SPI2) and pins
SPI_InitTypeDef spiInitStructure; SPI_InitTypeDef spiInitStructure;
GPIO_InitTypeDef gpioInitStructure; GPIO_InitTypeDef gpioInitStructure;
HAL_SPI_MspInit(&SpiHandle); HAL_SPI_MspInit(&SpiHandle);
__SPI1_CLK_ENABLE(); __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 // SPI2 SCK and MOSI
gpioInitStructure.Pin = SPI1_SCK.pin; gpioInitStructure.Pin = SPI1_SCK.pin;
gpioInitStructure.Speed = GPIO_SPEED_FAST; gpioInitStructure.Speed = GPIO_SPEED_FAST;
gpioInitStructure.Mode = GPIO_MODE_AF_PP; gpioInitStructure.Mode = GPIO_MODE_AF_PP;
gpioInitStructure.Alternate = GPIO_AF5_SPI1; gpioInitStructure.Alternate = GPIO_AF5_SPI1;
//gpioInitStructure.Mode = GPIO_MODE_OUTPUT_PP;
gpioInitStructure.Pull = GPIO_NOPULL; gpioInitStructure.Pull = GPIO_NOPULL;
//gpioInitStructure.Alternate = 1; //gpioInitStructure.Alternate = 1;
HAL_GPIO_Init(SPI1_SCK.port, &gpioInitStructure); HAL_GPIO_Init(SPI1_SCK.port, &gpioInitStructure);
@ -73,7 +33,6 @@ void spi_init(void)
gpioInitStructure.Pin = SPI1_MOSI.pin; gpioInitStructure.Pin = SPI1_MOSI.pin;
gpioInitStructure.Speed = GPIO_SPEED_FAST; gpioInitStructure.Speed = GPIO_SPEED_FAST;
gpioInitStructure.Mode = GPIO_MODE_AF_PP; gpioInitStructure.Mode = GPIO_MODE_AF_PP;
//gpioInitStructure.Mode = GPIO_MODE_OUTPUT_PP;
gpioInitStructure.Pull = GPIO_NOPULL; gpioInitStructure.Pull = GPIO_NOPULL;
gpioInitStructure.Alternate = GPIO_AF5_SPI1; gpioInitStructure.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(SPI1_MOSI.port, &gpioInitStructure); HAL_GPIO_Init(SPI1_MOSI.port, &gpioInitStructure);
@ -95,36 +54,26 @@ void spi_init(void)
HAL_GPIO_Init(LCD_NSS.port, &gpioInitStructure); HAL_GPIO_Init(LCD_NSS.port, &gpioInitStructure);
HAL_GPIO_WritePin(LCD_NSS.port, LCD_NSS.pin, 1); // TBD - should this be before init? 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 SpiHandle.Instance = SPI1;
// spi2Semaphore = 1; SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
SpiHandle.Init.Mode = SPI_MODE_MASTER;
//GPIO_PinRemapConfig(GPIO_Remap_SPI1, ENABLE); //So I can use the other SPI1 pins? (To keep the DACs availble) SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
//GPIO_Remap_SPI1 SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH;
SpiHandle.Init.CLKPhase = SPI_PHASE_2EDGE;
// SPI 1 SpiHandle.Init.NSS = SPI_NSS_SOFT; //SPI_NSS_SOFT;
// SPI_StructInit(&spiInitStructure); SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
//spiInitStructure. SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
//HAL_SPI_ SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED;
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.Init.CRCPolynomial = 7; SpiHandle.Init.CRCPolynomial = 7;
if(HAL_SPI_Init(&SpiHandle) != HAL_OK) if(HAL_SPI_Init(&SpiHandle) != HAL_OK)
@ -132,9 +81,6 @@ void spi_init(void)
/* Initialization Error */ /* Initialization Error */
//Error_Handler(); //Error_Handler();
} }
//HAL_SPI_TransmitReceive();
//SPI_Cmd(SPI2, ENABLE);
} }

View file

@ -160,6 +160,21 @@ void TIM3_IRQHandler(void)
{ {
HAL_TIM_IRQHandler(&TimHandle); 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) //void TIM3_IRQHandler(void)
//{ //{
// __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE); // __HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);

View file

@ -2885,6 +2885,11 @@ void HAL_TIM_IRQHandler(TIM_HandleTypeDef *htim)
} }
} }
void clearTimUpdateFlag(TIM_HandleTypeDef *htim)
{
__HAL_TIM_CLEAR_IT(htim, TIM_IT_UPDATE);
}
/** /**
* @} * @}
*/ */