FIR Filter
Dependencies: CMSIS_DSP_401 mbed
main.cpp
- Committer:
- jlsmith10
- Date:
- 2016-05-29
- Revision:
- 1:a2238b2df415
- Parent:
- 0:5cd703c0576c
File content as of revision 1:a2238b2df415:
/******************************************************************************* * main.cpp * by Jason Shen, James Smith and Luis Sanchez * * Acoustic Location System Filtering * * This C module implements the DSP filtering of an input signal for the * STM33F446RE Nucleo board.. The input signal will be passed in through * on board ADC connected to a transponder that receives accoustic waves * delivered by three transponders at 3 different frequencies. The coeffecients * used for the filter are defined in main.h and implement bandpass filters for * 35kHz, 40kHz and 45kHz with a pass bandwith of 500Hz. * * This program will output the time difference of arrival of the three * varying frequency signals. the default for for output is: * * [ A vs B time difference, B vs C time difference, A vs C time difference ] * * Currently the algorithm will first FIR filter the data for each of the 3 * frequencies. Then it will use an in place moving average function to * smooth the data. Finally, it will run a peak detection function and find the * peak of each of the 3 filtered signals which will then be placed on an output * pin to be available for beagle bone on OpenROV. * * * * * TODO: * 1. Test on different location inputs from python script, * 2. Integrate ADC and filter code * 3. If current filtering and smoothing is innaccurate develop new algorithm * 4. Clean up code *******************************************************************************/ /* Includes */ #include "main.h" /* FIR filter variables */ static float firStateF[BLOCK_SIZE + NUM_TAPS - 1]; unsigned int blockSize = BLOCK_SIZE; unsigned int numBlocks = NUM_SAMPLES/BLOCK_SIZE; /* Function Prototypes */ float calculateSoundSpeedInWater(float temp, float salinity, float depth); int singleThresholdDetection(const float sampleData[], int startPosition); void filterAndSmooth(float signal[], float filterCoeffs[], int smoothingCoeff, float * filteredSignal); void movAvg(float signal[]); int findMax(float signal[]); /*------------------------------------ * Hyperterminal configuration * 9600 bauds, 8-bit data, no parity ************************************/ Serial pc(SERIAL_TX, SERIAL_RX); DigitalOut myled(LED1); //Debug LED int main(void) { printf("---------------------------------------------------------------- "); printf(" "); printf(" Underwater Acoustic Location System DSP\n"); printf(" "); printf("---------------------------------------------------------------- "); printf(" Running Filter... "); printf("---------------------------------------------------------------- "); printf(" Number of Samples: %d\n", NUM_SAMPLES); printf(" Moving Average window: %d samples\n", MOV_AVG_WIND); /* float velocity = calculateSoundSpeedInWater(temp, salinity, depth); pc.printf("The velocity is %lf", velocity); */ // Fir instance variables arm_fir_instance_f32 S1, S2, S3; arm_status status; float32_t *input, *output; // Fir Coefficients float coeffsA_f32[NUM_TAPS]; float output_f32[NUM_SAMPLES]; /* Input is the signal with all 3 frequencies present. */ input = &signalABC[0]; output = &output_f32[0]; /* The array of time differences to place on output pin */ int toReturn[3]; /*************************************************************************** ****************** Filtering for f = 35kHz (from buoy A) ******************* ***************************************************************************/ if(UALS_DEBUG) { printf("Beginning filtering for f = 35kHz (buoy A)\n"); } /* Initialize FIR instance structure */ arm_fir_init_f32(&S1, NUM_TAPS, (float *) &coeffsA[0], &firStateF[0], blockSize); int i = 0; /* FIR Filtering */ for( i = 0; i < numBlocks; i++) { arm_fir_f32(&S1, input + (i * blockSize), output + (i * blockSize), blockSize); } /* Take the absolute value of the filtered signal */ for(i = 0; i < NUM_SAMPLES; i++ ) { if(output[i] < 0) { output[i] = -1 * output[i]; } } /* Print before moving average */ printf("----------Before moving average-------------\n"); if(UALS_DEBUG) { for(i = 0; i < NUM_SAMPLES; i++) { printf("%lf\n", output[i]); } } float * avgSignal[NUM_SAMPLES]; // Calculate moving average and do peak detection; movAvg(output); /* Print signal after moving average */ printf("----------After moving average-------------\n"); if(UALS_DEBUG) { for(i = 0; i < NUM_SAMPLES; i++) { printf("%lf\n", output[i]); } } /* Find the maximum value of the filtered signal */ int maxA = findMax(output); /*************************************************************************** ********************* Filtering for f = 40kHz (from buoy B) **************** ***************************************************************************/ if(UALS_DEBUG) { printf("Beginning filtering for f = 40kHz (buoy B)\n"); } /* Initialize FIR instance structure */ arm_fir_init_f32(&S2, NUM_TAPS, (float *) &coeffsB[0], &firStateF[0], blockSize); /* FIR Filtering */ for( i = 0; i < numBlocks; i++) { arm_fir_f32(&S2, input + (i * blockSize), output + (i * blockSize), blockSize); } /* Take the absolute value of the filtered signal */ for(i = 0; i < NUM_SAMPLES; i++ ) { if(output[i] < 0) { output[i] = -1 * output[i]; } } /* Print before moving average */ if(UALS_DEBUG) { printf("----------Before moving average-------------\n"); for(i = 0; i < NUM_SAMPLES; i++) { printf("%lf\n", output[i]); } } /* Perform moving average */ movAvg(output); /* Print signal after moving average */ if(UALS_DEBUG) { printf("----------After moving average-------------\n"); for(i = 0; i < NUM_SAMPLES; i++) { printf("%lf\n", output[i]); } } /* Find the maximum value of the filtered signal */ int maxB = findMax(output); /*************************************************************************** ******************** Filtering for f = 45kHz (from buoy C) ***************** ***************************************************************************/ if(UALS_DEBUG) { printf("Beginning filtering for f = 45kHz (buoy C)\n"); } /* Initialize FIR instance structure */ arm_fir_init_f32(&S3, NUM_TAPS, (float *) &coeffsC[0], &firStateF[0], blockSize); /* FIR Filtering */ for( i = 0; i < numBlocks; i++) { arm_fir_f32(&S3, input + (i * blockSize), output + (i * blockSize), blockSize); } /* Take the absolute value of the filtered signal */ for(i = 0; i < NUM_SAMPLES; i++ ) { if(output[i] < 0) { output[i] = -1 * output[i]; } } /* Print before moving average */ if(UALS_DEBUG) { printf("----------Before moving average-------------\n"); for(i = 0; i < NUM_SAMPLES; i++) { printf("%lf\n", output[i]); } } /* Perform moving average */ movAvg(output); /* Print signal after moving average */ if(UALS_DEBUG) { printf("----------After moving average-------------\n"); for(i = 0; i < NUM_SAMPLES; i++) { printf("%lf\n", output[i]); } } /* Find the maximum value of the filtered signal */ int maxC = findMax(output); /* The time differences to be returned */ /* TODO: should we take the absolute value? What does TDOA take in */ float tdAB = maxB - maxA; float tdBC = maxB - maxC; float tdAC = maxC - maxA; printf("tdAB = %f\n", tdAB); printf("tdBC = %f\n", tdBC); printf("tdAC = %f\n", tdAC); toReturn[0] = tdAB; toReturn[1] = tdBC; toReturn[2] = tdAC; } /* * Function Name: singleThresholdDetection() * Function Declaration: int singleThresholdDetection(const float sampleData[], int startPosition) * Function Description: Calculates the first occurrence of a value over the * threshold value and returns the position. * * Params: * arg1: sampleData - sample data to find position of first peak * arg2: startPosition - threshold value to search for * * Return Value: position where threshold is first reached * */ int singleThresholdDetection(const float sampleData[], int startPosition) { int i; for(i = startPosition; i < NUM_SAMPLES; i++) { if (sampleData[i] >= DETECT_THRESH) { return i; } } return -1; } /* * Function Name: movAvg(); * Function Declaration: void movAvg(float signal[]); * Function Description: This function takes an input signal and does an in * place moving average algorithm. The window size is defined by MOV_AVG_WIND * in main.h. * * This function serves a dual purpose of finding the position of the largest * peak and returning that position. * * Return Value: None * */ void movAvg(float signal[]) { int i = 0; int start = 0; int finish = 0; float total = 0; // Buffer to hold the most recent samples float buffer[MOV_AVG_WIND*2]; // Go through signal array and calculate moving average for(i = 0; i < NUM_SAMPLES; i++) { start = i - MOV_AVG_WIND; finish = i + MOV_AVG_WIND; if(start < 0) { start = 0; } if(finish > NUM_SAMPLES) { finish = NUM_SAMPLES; } total = 0; for(int j = start; j < finish; j++) { total += signal[j]; } if(i > MOV_AVG_WIND*2 - 1) { signal[i-(MOV_AVG_WIND*2)] = buffer[i % (MOV_AVG_WIND*2)]; } // Rotating buffer to save the avg buffer[i%(MOV_AVG_WIND*2)] = total / (finish - start); } for(int i = NUM_SAMPLES-MOV_AVG_WIND*2; i < NUM_SAMPLES; i++) { signal[i] = buffer[i %(MOV_AVG_WIND*2)]; } if(UALS_DEBUG) { for(int i = 0; i < NUM_SAMPLES; i++) { printf("averagedSignal[i] = %f\n", signal[i]); } } } /* * Function Name: findMax(); * Function Declaration: int findMax(float signal[]); * Function Description: This function takes an input signal and returns the * position of the maximum valued sample. * */ int findMax(float signal[]) { float maxVal = 0.0; int maxPosition = -1; int i; /* Go through each element searching for maximum */ for(i = 0; i < NUM_SAMPLES; i++) { if(signal[i] > maxVal) { /* We've found a new max, replace */ maxVal = signal[i]; maxPosition = i; } } if(maxPosition > 0) { printf("Max position found at %d\n", maxPosition); return maxPosition; } else { printf("Error: no max found\n"); return -1; } }