ReSpeaker DSP V02
Dependencies: mbed MbedJSONValue
filters.h
- Committer:
- Arkadi
- Date:
- 2019-06-20
- Revision:
- 14:8a4699aa69b5
- Parent:
- 12:9d30df1529be
File content as of revision 14:8a4699aa69b5:
//////////////////////
// Operation Modes //
//////////////////////
/////////////////
// Variables: //
/////////////////
// Filter mode - Regular / efficient
//#define EFFICIENT_FILTER
// second-order sections filter variables - upto 8 sections
#define MAX_SECTION_NUMBER 5
// convertions
#define ADC2Float (2.0f/4095.0f) // 0.0004884f//
#define Float2ADC (4095.0f/2.0f) // 2047.5f //
// Filter variables
//SOS Matrix limited to order 10
int FilterSections=1;
float SOSMat[5][6]= { // Predefined SOS Matrix (second order 5Khz filter
1, -2, 1, 1, -1.961, 0.9624,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0
};
float Gscale = 0.9810f;
float filterCurrInput[MAX_SECTION_NUMBER+1] = {0};
float filterLastInput[MAX_SECTION_NUMBER+1] = {0};
float filterLLastInput[MAX_SECTION_NUMBER+1] = {0};
// Trigger mode variables
float signalGain = 1.0; // Signal Gain
float trigTresh = 0.5; // threshold for trigger mode
uint32_t trigDelaySet = 5000; // counter for pulse pass
uint32_t trigDelay = trigDelaySet; // counter for pulse pass
uint32_t trigPause = 10; // pause after trigger in microseconds
// Buffer mode variables - Mid work
uint32_t bufferSizeSet = 5000;
uint32_t bufferSize = bufferSizeSet;
uint32_t preBufferSizeSet = 1000;
uint32_t bufferCountDown = bufferSizeSet - preBufferSizeSet;
float bufferADC[5000] = {0};
// gains vector
#define GAIN_VECTOR_SIZE 5
int gainsVectorSize = 5;
float GainVector[] = {0.1 , 0.2 , 0.4 , 0.8 , 1.6};
///////////////////////////////
// available filters: //
///////////////////////////////
// off mode, output vdd/2
inline void offMode(void);
// passthrough function (output equals input)
inline void passthrough(void);
// highpass filter
inline void highpass(void);
// highpass filter + trigger mode
inline void highpassTrig(void);
// highpass filter + trigger mode + Gains vector
inline void GainsTrig(void);
// highpass filter + trigger mode + Delays vector
inline void DelaysTrig(void);
// highpass filter + trigger mode + FIR Filter (Convolution)
inline void FIRTrig(void);
// filter_implementation
inline float HPF_Function(float ADCFloat);
//////////////////////////////
// Filter Function: //
//////////////////////////////
// filter_implementation
inline float HPF_Function(float ADCFloat)
{
// filter local variable
float ADCFloatFiltered;
// filter mode:
#ifdef EFFICIENT_FILTER
// filter coeficients best performance if defined in loop
float SOSMatHP[2][6] = { // 25khz cutoff at 920 kHz sample rate // closer to 30kHz when io toggle switched off.
1.000000, -2.000000, 1.000000, 1.000000, -1.706510, 0.731145,
1.000000, -2.000000, 1.000000, 1.000000, -1.852377, 0.879117
};
float GscaleHP = 0.801724;
// num sections
int NumSectionsHP = sizeof(SOSMatHP)/sizeof(float)/6;
// filter stages variables
static float CurrInput [MAX_SECTION_NUMBER+1];
static float LastInput [MAX_SECTION_NUMBER+1];
static float LLastInput [MAX_SECTION_NUMBER+1];
//////////////////
// Apply Filter //
//////////////////
LLastInput[0] = LastInput[0];
LastInput[0] = CurrInput[0];
CurrInput[0] = ADCFloat;
for (int ii=1; ii <= NumSectionsHP; ii++) {
LLastInput[ii] = LastInput[ii];
LastInput[ii] = CurrInput[ii];
CurrInput[ii] = SOSMatHP[ii-1][0]*CurrInput[ii-1] + SOSMatHP[ii-1][1]*LastInput[ii-1] +
SOSMatHP[ii-1][2]*LLastInput[ii-1] -
SOSMatHP[ii-1][4]*LastInput[ii] - SOSMatHP[ii-1][5]*LLastInput[ii];
ADCFloatFiltered = CurrInput[ii];
}
ADCFloatFiltered = ADCFloatFiltered * GscaleHP * signalGain;
#else
filterLLastInput[0] = filterLastInput[0];
filterLastInput[0] = filterCurrInput[0];
filterCurrInput[0] = ADCFloat;
for (int ii=1; ii <= FilterSections; ii++) {
filterLLastInput[ii] = filterLastInput[ii];
filterLastInput[ii] = filterCurrInput[ii];
filterCurrInput[ii] = SOSMat[ii-1][0]*filterCurrInput[ii-1] + SOSMat[ii-1][1]*filterLastInput[ii-1] +
SOSMat[ii-1][2]*filterLLastInput[ii-1] -
SOSMat[ii-1][4]*filterLastInput[ii] - SOSMat[ii-1][5]*filterLLastInput[ii];
}
ADCFloatFiltered = filterCurrInput[FilterSections];
ADCFloatFiltered = ADCFloatFiltered * Gscale * signalGain;
#endif
return ADCFloatFiltered;
}
///////////////////////////////
// Operation Functions: //
///////////////////////////////
// off mode, output vdd/2
inline void offMode(void)
{
// generate some delay (limit loop speeds, creates crashes to the Switch mcu
// for (int ii=0; ii<10; ii++){
// __ASM volatile ("nop"); // one tick operation, Use to adjust frequency by slowing down the proccess
// }
uint16_t ADCValueOut;
// set to vdd/2
ADCValueOut=(uint16_t)((0.0f +1.0f) * Float2ADC);
// Output value using DAC
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
}// end off mode
// passthrough function (output equals input)
inline void passthrough(void)
{
uint32_t ADCValue;
// Read ADC input
ADCValue = hadc1.Instance->DR;
// Output value using DAC
*(__IO uint32_t *) Dac_Reg = ADCValue;
} // end passthrough
// high pass filter
inline void highpass(void)
{
// Dac output variable
uint16_t ADCValueOut;
// Read ADC input
float ADCFloat=((uint16_t)(hadc1.Instance->DR) * ADC2Float)-1.0f;
// Apply Filter
float ADCFloatFiltered = HPF_Function( ADCFloat );
// Apply Saturation to Output
if (ADCFloatFiltered < -1.0f) {
ADCValueOut=0; // Min value
} else if (ADCFloatFiltered > 1.0f) {
ADCValueOut=0xFFF; // Max value
} else {
ADCValueOut=(uint16_t)((ADCFloatFiltered +1.0f) * Float2ADC);
}
// Output value using DAC
// HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValueOut);
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
} // end high pass filter
// highpass filter + trigger mode
inline void highpassTrig(void)
{
// trigger variables
static bool trigFlag=0; // flag to indicate trigger event
// Dac output variable
uint16_t ADCValueOut;
// Read ADC input
float ADCFloat=((uint16_t)(hadc1.Instance->DR) * ADC2Float)-1.0f;
// Apply Filter
float ADCFloatFiltered = HPF_Function( ADCFloat );
///////////////////////////////////////////////
// Event detection //
///////////////////////////////////////////////
if (trigFlag) { // event already detected
trigDelay--;
if (trigDelay == 0) { // pulse pass run out, perform delay and reset variables
trigDelay = trigDelaySet; //reset counter for next iteration
trigFlag=0;
// reset filter
ADCFloatFiltered = 0;
// update dac
ADCValueOut=(uint16_t)((ADCFloatFiltered +1.0f) * Float2ADC);
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
//*(__IO uint32_t *) Dac_Reg = 0; // test triggered mode
// delay for set time
wait_ms(trigPause);
}
} else if (ADCFloatFiltered >= trigTresh) {
trigFlag=1;
}
////////////////////////////////
// Apply Saturation to Output //
////////////////////////////////
if (ADCFloatFiltered < -1.0f) {
ADCValueOut=0; // Min value
} else if (ADCFloatFiltered > 1.0f) {
ADCValueOut=0xFFF; // Max value
} else {
ADCValueOut=(uint16_t)((ADCFloatFiltered +1.0f) * Float2ADC);
}
// Output value using DAC
// HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValueOut);
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
//wait_us(1);
} // end high pass filter + trigger mode
// highpass filter + trigger mode + Gains vector
inline void GainsTrig(void)
{
// Gains variables:
static int GainVectorIndex = 0;
// trigger variables
static bool trigFlag=0; // flag to indicate trigger event
// Dac output variable
uint16_t ADCValueOut;
// Read ADC input
float ADCFloat=((uint16_t)(hadc1.Instance->DR) * ADC2Float)-1.0f;
// Apply Filter
float ADCFloatFiltered = HPF_Function( ADCFloat );
///////////////////////////////////////////////
// Event detection //
///////////////////////////////////////////////
if (trigFlag) { // event already detected
trigDelay--;
if (trigDelay == 0) { // pulse pass run out, perform delay and reset variables
trigDelay = trigDelaySet; //reset counter for next iteration
trigFlag=0;
// reset filter
ADCFloatFiltered = 0;
// update dac
ADCValueOut=(uint16_t)((ADCFloatFiltered +1.0f) * Float2ADC);
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
//*(__IO uint32_t *) Dac_Reg = 0; // test triggered mode
// delay for set time
wait_ms(trigPause);
// change gain settings
GainVectorIndex++;
GainVectorIndex = GainVectorIndex % gainsVectorSize;
}
} else if (ADCFloatFiltered >= trigTresh) {
trigFlag=1;
}
//////////////////////////
// Apply Gain to Output //
//////////////////////////
ADCFloatFiltered = ADCFloatFiltered * GainVector[GainVectorIndex];
if (ADCFloatFiltered < -1.0f) {
ADCValueOut=0; // Min value
} else if (ADCFloatFiltered > 1.0f) {
ADCValueOut=0xFFF; // Max value
} else {
ADCValueOut=(uint16_t)((ADCFloatFiltered +1.0f) * Float2ADC);
}
// Output value using DAC
// HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValueOut);
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
//wait_us(1);
} // end GainsTrig
//////////////////////////////////////////////
/////////////////// Implement
//////////////////////////////////////////////
// highpass filter + trigger mode + Delays vector
inline void DelaysTrig(void) // - mid work feature. (not working yet)
{
///////////////////////////////
// Gains variables: //
///////////////////////////////
#define DELAY_VECTOR_SIZE 5
uint32_t DelayVector[] = {100 , 200 , 300 , 400 , 500}; // millis
static uint16_t DelayVectorIndex = 0;
static uint32_t BufferIndex = 0;
//uint32_t bufferSizeSet = 5000;
//uint32_t preBufferSizeSet = 1000;
//uint32_t bufferCountDown = bufferSizeSet - preBufferSizeSet;
//float bufferADC[bufferSizeSet] = {0};
///////////////////////////////
// filter variables: //
///////////////////////////////
// filter coeficients best performance if defined in loop
float SOSMatHP[2][6] = { // 25khz cutoff at 920 kHz sample rate // closer to 30kHz when io toggle switched off.
1.000000, -2.000000, 1.000000, 1.000000, -1.706510, 0.731145,
1.000000, -2.000000, 1.000000, 1.000000, -1.852377, 0.879117
};
float GscaleHP = 0.801724;
// num sections
int NumSectionsHP = sizeof(SOSMatHP)/sizeof(float)/6;
float ADCFloat;
float ADCFloatFiltered;
uint16_t ADCValueOut;
// filter stages variables
static float CurrInput [MAX_SECTION_NUMBER+1];
static float LastInput [MAX_SECTION_NUMBER+1];
static float LLastInput [MAX_SECTION_NUMBER+1];
// trigger variables
static bool trigFlag=0; // flag to indicate trigger event
////////////////////
// Read ADC input //
////////////////////
ADCFloat=((uint16_t)(hadc1.Instance->DR) * ADC2Float)-1.0f;
//////////////////////////////////////////////////////
// Apply Filter to input //
//////////////////////////////////////////////////////
LLastInput[0] = LastInput[0];
LastInput[0] = CurrInput[0];
CurrInput[0] = ADCFloat;
for (int ii=1; ii <= NumSectionsHP; ii++) {
LLastInput[ii] = LastInput[ii];
LastInput[ii] = CurrInput[ii];
CurrInput[ii] = SOSMatHP[ii-1][0]*CurrInput[ii-1] + SOSMatHP[ii-1][1]*LastInput[ii-1] +
SOSMatHP[ii-1][2]*LLastInput[ii-1] -
SOSMatHP[ii-1][4]*LastInput[ii] - SOSMatHP[ii-1][5]*LLastInput[ii];
ADCFloatFiltered = CurrInput[ii];
}
ADCFloatFiltered = ADCFloatFiltered * GscaleHP;
////////////////////////////////
// Fill in buffer //
////////////////////////////////
bufferADC[BufferIndex] = ADCFloatFiltered;
BufferIndex++;
BufferIndex = BufferIndex % bufferSize;
///////////////////////////////////////////////
// Event detection //
///////////////////////////////////////////////
if (trigFlag) { // event already detected
bufferCountDown--; // count down
if (bufferCountDown == 0) { // pulse pass run out, perform delay and reset variables
bufferCountDown = bufferSizeSet - preBufferSizeSet; //reset counter for next iteration
trigFlag=0;
// reset filter
for (int ii=1; ii <= NumSectionsHP; ii++) {
LLastInput[ii] = 0;
LastInput[ii] = 0;
CurrInput[ii] = 0;
ADCFloatFiltered = 0;
}
// generate delay
// delay for set time
wait_ms(DelayVector[DelayVectorIndex]);
// change delay settings
DelayVectorIndex++;
DelayVectorIndex = DelayVectorIndex % DELAY_VECTOR_SIZE;
// play out buffer
for (int ii=0 ; ii<bufferSize ; ii++) {
ADCFloatFiltered = bufferADC[BufferIndex];
BufferIndex++;
BufferIndex = BufferIndex % bufferSize;
////////////////////////////////
// Apply Saturation to Output //
////////////////////////////////
if (ADCFloatFiltered < -1.0f) {
ADCValueOut=0; // Min value
} else if (ADCFloatFiltered > 1.0f) {
ADCValueOut=0xFFF; // Max value
} else {
ADCValueOut=(uint16_t)((ADCFloatFiltered +1.0f) * Float2ADC);
}
// Output value using DAC
// HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, ADCValueOut);
*(__IO uint32_t *) Dac_Reg = ADCValueOut;
//wait_us(1);
}
}
} else if (ADCFloatFiltered >= trigTresh) {
trigFlag=1;
}
} // end GainsTrig