Other Parts Discussed in Thread: BOOSTXL-AUDIO,
Tool/software: Code Composer Studio
I want to process audio, so I am using the BOOSTXL-AUDIO_430BOOST-SHARPLCD_FFT_FIR_LEA_MSP430FR5994 example as a starting point. Everything works fine with the original code. I will need more points, either 512 or 1024. I have attempted to modify the code for 512 points, but it doesn't work with the LEA. For this test, I am feeding a 2.2 kHz sine into the system. Without the LEA it works, with the LEA, I get 2 peaks, the expected peak at 2.2k, but I get a second peak at 1.8k. The second peak is always 4k minus the input frequency.
The horizontal is compressed for the 512 point tests, so all 4 of these should look the same. The left two pictures are with the LEA, the right two are without.
You can find the changes that I have made by searching for VECTOR_SIZE_256.
I am using CCS 9.3. I just downloaded the example code a few days ago.
I am using the BoostXL-Audio and the Sharp 128 x 128 LCD.
FFT.h
/* --COPYRIGHT--,BSD * Copyright (c) 2016, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ //****************************************************************************** //! TI-Design Signal Processing with LEA on MSP430FR5994 //! //! William Goh //! Texas Instruments Inc. //! April 2016 //****************************************************************************** #ifndef FFT_H #define FFT_H //#define VECTOR_SIZE_256 // Comment out for 512 #ifdef VECTOR_SIZE_256 #define VECTOR_SIZE 256 #define TWIDDLE_TABLE msp_cmplx_twiddle_table_256_q15 #else #define VECTOR_SIZE 512 #define TWIDDLE_TABLE msp_cmplx_twiddle_table_512_q15 #endif //#define LOG2_SIZE 8 // Not used //#define SQRT_SIZE 16 // Not used //#define SCALE_FACTOR 0x00026000 // Not used extern void initFft(void); extern void shutdownActivity(void); extern void runFftWithoutLea(void); extern void runFftWithLea(void); extern void testFft(void); #endif /* FFT_H */
FFT.c
/* --COPYRIGHT--,BSD * Copyright (c) 2016, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ //****************************************************************************** //! TI-Design Signal Processing with LEA on MSP430FR5994 //! //! William Goh, L Reynoso //! Texas Instruments Inc. //! August 2019 //****************************************************************************** #include <driverlib.h> #include <stdint.h> #include <grlib.h> #include <stdio.h> #include <math.h> #include "DSPLib.h" #include "FFT.h" #include "FFT_430.h" #include "benchmark.h" #include "audio_collect.h" #include "global.h" #include "application.h" #ifdef __SHARP96x96__ #include "Sharp96x96.h" #elif defined (__SHARP128x128__) #include "Sharp128x128.h" #endif // Rectangular to clear my FFT image after every round const Graphics_Rectangle clearSpace = { 0, 10, LCD_HORIZONTAL_MAX, LCD_VERTICAL_MAX-13 }; const Graphics_Rectangle clearSpaceTopText = { 0, 0, LCD_VERTICAL_MAX, 7 }; const Graphics_Rectangle clearSpaceCycleText = { 10, LCD_VERTICAL_MAX-11, 65, LCD_VERTICAL_MAX }; #if defined(__IAR_SYSTEMS_ICC__) // Real FFT values that can be used by user application __persistent int16_t FFT_data[VECTOR_SIZE] = {0}; // FFT buffer that contains real and imaginary values after being calculated __persistent int16_t FBuff[VECTOR_SIZE * 2] = {0}; // raw data buffer for processing by the FFT algorithm __persistent int16_t voice_data[VECTOR_SIZE * 2] = {0}; #elif defined(__TI_COMPILER_VERSION__) // Real FFT values that can be used by user application #pragma PERSISTENT(FFT_data) int16_t FFT_data[VECTOR_SIZE] = {0}; // FFT buffer that contains real and imaginary values after being calculated #pragma PERSISTENT(FBuff) int16_t FBuff[VECTOR_SIZE * 2] = {0}; // raw data buffer for processing by the FFT algorithm #pragma PERSISTENT(voice_data) int16_t voice_data[VECTOR_SIZE * 2] = {0}; #endif #ifdef VECTOR_SIZE_256 const int bit_rev_index[] = {0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; #else const int bit_rev_index[] = { 0x0, 0x100, 0x80, 0x180, 0x40, 0x140, 0xC0, 0x1C0, 0x20, 0x120, 0xA0, 0x1A0, 0x60, 0x160, 0xE0, 0x1E0, 0x10, 0x110, 0x90, 0x190, 0x50, 0x150, 0xD0, 0x1D0, 0x30, 0x130, 0xB0, 0x1B0, 0x70, 0x170, 0xF0, 0x1F0, 0x8, 0x108, 0x88, 0x188, 0x48, 0x148, 0xC8, 0x1C8, 0x28, 0x128, 0xA8, 0x1A8, 0x68, 0x168, 0xE8, 0x1E8, 0x18, 0x118, 0x98, 0x198, 0x58, 0x158, 0xD8, 0x1D8, 0x38, 0x138, 0xB8, 0x1B8, 0x78, 0x178, 0xF8, 0x1F8, 0x4, 0x104, 0x84, 0x184, 0x44, 0x144, 0xC4, 0x1C4, 0x24, 0x124, 0xA4, 0x1A4, 0x64, 0x164, 0xE4, 0x1E4, 0x14, 0x114, 0x94, 0x194, 0x54, 0x154, 0xD4, 0x1D4, 0x34, 0x134, 0xB4, 0x1B4, 0x74, 0x174, 0xF4, 0x1F4, 0xC, 0x10C, 0x8C, 0x18C, 0x4C, 0x14C, 0xCC, 0x1CC, 0x2C, 0x12C, 0xAC, 0x1AC, 0x6C, 0x16C, 0xEC, 0x1EC, 0x1C, 0x11C, 0x9C, 0x19C, 0x5C, 0x15C, 0xDC, 0x1DC, 0x3C, 0x13C, 0xBC, 0x1BC, 0x7C, 0x17C, 0xFC, 0x1FC, 0x2, 0x102, 0x82, 0x182, 0x42, 0x142, 0xC2, 0x1C2, 0x22, 0x122, 0xA2, 0x1A2, 0x62, 0x162, 0xE2, 0x1E2, 0x12, 0x112, 0x92, 0x192, 0x52, 0x152, 0xD2, 0x1D2, 0x32, 0x132, 0xB2, 0x1B2, 0x72, 0x172, 0xF2, 0x1F2, 0xA, 0x10A, 0x8A, 0x18A, 0x4A, 0x14A, 0xCA, 0x1CA, 0x2A, 0x12A, 0xAA, 0x1AA, 0x6A, 0x16A, 0xEA, 0x1EA, 0x1A, 0x11A, 0x9A, 0x19A, 0x5A, 0x15A, 0xDA, 0x1DA, 0x3A, 0x13A, 0xBA, 0x1BA, 0x7A, 0x17A, 0xFA, 0x1FA, 0x6, 0x106, 0x86, 0x186, 0x46, 0x146, 0xC6, 0x1C6, 0x26, 0x126, 0xA6, 0x1A6, 0x66, 0x166, 0xE6, 0x1E6, 0x16, 0x116, 0x96, 0x196, 0x56, 0x156, 0xD6, 0x1D6, 0x36, 0x136, 0xB6, 0x1B6, 0x76, 0x176, 0xF6, 0x1F6, 0xE, 0x10E, 0x8E, 0x18E, 0x4E, 0x14E, 0xCE, 0x1CE, 0x2E, 0x12E, 0xAE, 0x1AE, 0x6E, 0x16E, 0xEE, 0x1EE, 0x1E, 0x11E, 0x9E, 0x19E, 0x5E, 0x15E, 0xDE, 0x1DE, 0x3E, 0x13E, 0xBE, 0x1BE, 0x7E, 0x17E, 0xFE, 0x1FE, 0x1, 0x101, 0x81, 0x181, 0x41, 0x141, 0xC1, 0x1C1, 0x21, 0x121, 0xA1, 0x1A1, 0x61, 0x161, 0xE1, 0x1E1, 0x11, 0x111, 0x91, 0x191, 0x51, 0x151, 0xD1, 0x1D1, 0x31, 0x131, 0xB1, 0x1B1, 0x71, 0x171, 0xF1, 0x1F1, 0x9, 0x109, 0x89, 0x189, 0x49, 0x149, 0xC9, 0x1C9, 0x29, 0x129, 0xA9, 0x1A9, 0x69, 0x169, 0xE9, 0x1E9, 0x19, 0x119, 0x99, 0x199, 0x59, 0x159, 0xD9, 0x1D9, 0x39, 0x139, 0xB9, 0x1B9, 0x79, 0x179, 0xF9, 0x1F9, 0x5, 0x105, 0x85, 0x185, 0x45, 0x145, 0xC5, 0x1C5, 0x25, 0x125, 0xA5, 0x1A5, 0x65, 0x165, 0xE5, 0x1E5, 0x15, 0x115, 0x95, 0x195, 0x55, 0x155, 0xD5, 0x1D5, 0x35, 0x135, 0xB5, 0x1B5, 0x75, 0x175, 0xF5, 0x1F5, 0xD, 0x10D, 0x8D, 0x18D, 0x4D, 0x14D, 0xCD, 0x1CD, 0x2D, 0x12D, 0xAD, 0x1AD, 0x6D, 0x16D, 0xED, 0x1ED, 0x1D, 0x11D, 0x9D, 0x19D, 0x5D, 0x15D, 0xDD, 0x1DD, 0x3D, 0x13D, 0xBD, 0x1BD, 0x7D, 0x17D, 0xFD, 0x1FD, 0x3, 0x103, 0x83, 0x183, 0x43, 0x143, 0xC3, 0x1C3, 0x23, 0x123, 0xA3, 0x1A3, 0x63, 0x163, 0xE3, 0x1E3, 0x13, 0x113, 0x93, 0x193, 0x53, 0x153, 0xD3, 0x1D3, 0x33, 0x133, 0xB3, 0x1B3, 0x73, 0x173, 0xF3, 0x1F3, 0xB, 0x10B, 0x8B, 0x18B, 0x4B, 0x14B, 0xCB, 0x1CB, 0x2B, 0x12B, 0xAB, 0x1AB, 0x6B, 0x16B, 0xEB, 0x1EB, 0x1B, 0x11B, 0x9B, 0x19B, 0x5B, 0x15B, 0xDB, 0x1DB, 0x3B, 0x13B, 0xBB, 0x1BB, 0x7B, 0x17B, 0xFB, 0x1FB, 0x7, 0x107, 0x87, 0x187, 0x47, 0x147, 0xC7, 0x1C7, 0x27, 0x127, 0xA7, 0x1A7, 0x67, 0x167, 0xE7, 0x1E7, 0x17, 0x117, 0x97, 0x197, 0x57, 0x157, 0xD7, 0x1D7, 0x37, 0x137, 0xB7, 0x1B7, 0x77, 0x177, 0xF7, 0x1F7, 0xF, 0x10F, 0x8F, 0x18F, 0x4F, 0x14F, 0xCF, 0x1CF, 0x2F, 0x12F, 0xAF, 0x1AF, 0x6F, 0x16F, 0xEF, 0x1EF, 0x1F, 0x11F, 0x9F, 0x19F, 0x5F, 0x15F, 0xDF, 0x1DF, 0x3F, 0x13F, 0xBF, 0x1BF, 0x7F, 0x17F, 0xFF, 0x1FF }; #endif uint16_t i, index; int16_t imag, real, real_abs, imag_abs, mag, max, min; int16_t scale; msp_cmplx_fft_q15_params complexFftParams; static uint8_t refreshDisp = 0; static int8_t str[20]; void initFft(void) { resetBenchmark(); // Disable the audio playback for lowest power configuration Audio_stopPlayback(&gPlaybackConfig); // Initializes the FFT parameters complexFftParams.length = VECTOR_SIZE; complexFftParams.bitReverse = 1; // complexFftParams.twiddleTable = msp_cmplx_twiddle_table_256_q15; complexFftParams.twiddleTable = TWIDDLE_TABLE; // Initialize the microphone for recording gAudioConfig.audioBuffer1 = (int16_t *) adcBuffer0; gAudioConfig.audioBuffer2 = (int16_t *) adcBuffer1; gAudioConfig.bufferSize = VECTOR_SIZE; gAudioConfig.sampleRate = FFT_SAMPLING_FREQUENCY; gAudioConfig.twosComplement = true; Audio_setupCollect(&gAudioConfig); // Start the recording by enabling the timer Audio_startCollect(&gAudioConfig); } /**********************************************************************//** * @brief Runs the FFT. Performs the FFT and puts it in FFT_data buffer. * * @param none * * @return none *************************************************************************/ void runFftWithoutLea(void) { int16_t * currentAdcBuffer; // Initialize the number of times to refresh the display refreshDisp = 2; // Clear the screen first Graphics_clearDisplay(&g_sContext); // Draw the basic structure GrStringDraw(&g_sContext, "0", AUTO_STRING_LENGTH, 1, LCD_VERTICAL_MAX-10, TRANSPARENT_TEXT); GrStringDraw(&g_sContext, "Fs 2", AUTO_STRING_LENGTH, 70, LCD_VERTICAL_MAX-10, TRANSPARENT_TEXT); GrLineDrawH(&g_sContext, 0, LCD_VERTICAL_MAX, LCD_VERTICAL_MAX-12); // Draw the title once Graphics_drawString(&g_sContext, "FFT w/o LEA", AUTO_STRING_LENGTH, 0, 0, GRAPHICS_OPAQUE_TEXT); // Flush Buffer to LCD Graphics_flushBuffer(&g_sContext); keepAppRunning = true; while(keepAppRunning) { __bis_SR_register(LPM3_bits + GIE); // Copy recorded ADC data to LEA RAM buffer for FFT processing currentAdcBuffer = Audio_getActiveBuffer(&gAudioConfig); for(i = 0; i < (VECTOR_SIZE); i++) { ((int32_t *)voice_data)[i] = currentAdcBuffer[i]; } resetBenchmark(); startBenchmark(); // Perform FFT and store FFT_prog(); stopBenchmark(); // Calculate magnitude for the positive frequency domain for(i = 0; i < (VECTOR_SIZE / 2); i++) { index = bit_rev_index[i]; real = FBuff[2 * index]; imag = FBuff[2 * index + 1]; if(real < 0) { real_abs = ~real + 1; } else { real_abs = real; } if(imag < 0) { imag_abs = ~imag + 1; } else { imag_abs = imag; } if(real_abs >= imag_abs) { max = real_abs; min = imag_abs; } else { max = imag_abs; min = real_abs; } mag = max + 3 * (min >> 3); FFT_data[i] = mag; } #ifndef PWR_BENCHMARK if(refreshDisp) { sprintf((char *) str, "Cyc:%lu", cycleCounts); } // Clear the lines by drawing a box Graphics_setForegroundColor(&g_sContext, ClrWhite); Graphics_fillRectangle(&g_sContext, &clearSpace); if(refreshDisp) { Graphics_fillRectangle(&g_sContext, &clearSpaceCycleText); } Graphics_setForegroundColor(&g_sContext, ClrBlack); if(refreshDisp) { Graphics_drawString(&g_sContext, str, AUTO_STRING_LENGTH, 10, LCD_VERTICAL_MAX-10, GRAPHICS_OPAQUE_TEXT); refreshDisp--; } // Draw the FFT magnitudes but restricting it to only 96 pixel screen for(i = 0; i < LCD_HORIZONTAL_MAX; i++) { // Restricting it to only 96 pixel screen if(i < LCD_HORIZONTAL_MAX) { #ifdef VECTOR_SIZE_256 // set the scale and restrict it to the size of the display scale = ((FFT_data[i]) >> 6); #else // 512 // Set the scale and restrict it to the size of the display // Since we have 256 data points and the display is only 128 wide, compress by 2 scale = ((FFT_data[i*2] + FFT_data[i*2+1]) >> 6); #endif // Check if is out of bounds. if(scale < 0) { scale = 12; } else if(scale > LCD_VERTICAL_MAX-24) { scale = LCD_VERTICAL_MAX-25; } if(scale != 0) { // Draw each line only if scale the mag is 0 pixels Graphics_drawLineV(&g_sContext, i, LCD_VERTICAL_MAX-13, LCD_VERTICAL_MAX- 13 - scale); } } } // Flush this content to display Graphics_flushBuffer(&g_sContext); #endif } Audio_stopCollect(&gAudioConfig); Audio_shutdownCollect(&gAudioConfig); } void runFftWithLea(void) { msp_status status; uint16_t i; int16_t * currentAdcBuffer; // Initialize the number of times to refresh the display refreshDisp = 2; // Clear the screen first Graphics_clearDisplay(&g_sContext); // Draw the basic structure GrStringDraw(&g_sContext, "0", AUTO_STRING_LENGTH, 1, LCD_VERTICAL_MAX-10, TRANSPARENT_TEXT); GrStringDraw(&g_sContext, "Fs 2", AUTO_STRING_LENGTH, 70, LCD_VERTICAL_MAX-10, TRANSPARENT_TEXT); GrLineDrawH(&g_sContext, 0, LCD_HORIZONTAL_MAX, LCD_VERTICAL_MAX-12); // Draw the title once GrStringDraw(&g_sContext, "FFT w/ LEA", AUTO_STRING_LENGTH, 0, 0, GRAPHICS_OPAQUE_TEXT); // Flush Buffer to LCD Graphics_flushBuffer(&g_sContext); // Initialize LEA module initFft(); keepAppRunning = true; while(keepAppRunning) { __bis_SR_register(LPM3_bits + GIE); // Get the latest buffer pointer to be copied currentAdcBuffer = Audio_getActiveBuffer(&gAudioConfig); // Copy recorded ADC data to LEA RAM buffer for FFT processing for(i = 0; i < (VECTOR_SIZE); i++) { ((int32_t *)leaMemoryStartAdd.fftDataParam.fftInputOutput)[i] = currentAdcBuffer[i] & 0x0000FFFF; } resetBenchmark(); startBenchmark(); // Call fixed scaling fft function. status = msp_cmplx_fft_fixed_q15(&complexFftParams, leaMemoryStartAdd.fftDataParam.fftInputOutput); // Check status flag. if(status != MSP_SUCCESS) { // ERROR! __no_operation(); } stopBenchmark(); // Calculate magnitude for the positive frequency domain for(i = 0; i < (VECTOR_SIZE / 2); i++) { real = leaMemoryStartAdd.fftDataParam.fftInputOutput[2 * i]; imag = leaMemoryStartAdd.fftDataParam.fftInputOutput[2 * i + 1]; if(real < 0) { real_abs = ~real + 1; } else { real_abs = real; } if(imag < 0) { imag_abs = ~imag + 1; } else { imag_abs = imag; } if(real_abs >= imag_abs) { max = real_abs; min = imag_abs; } else { max = imag_abs; min = real_abs; } mag = max + 3 * (min >> 3); FFT_data[i] = mag; } #ifndef PWR_BENCHMARK // Refresh the display if(refreshDisp) { sprintf((char *) str, "Cyc:%lu", cycleCounts); } // Clear the lines by drawing a box Graphics_setForegroundColor(&g_sContext, ClrWhite); if(refreshDisp) { Graphics_fillRectangle(&g_sContext, &clearSpaceCycleText); } Graphics_fillRectangle(&g_sContext, &clearSpace); Graphics_setForegroundColor(&g_sContext, ClrBlack); if(refreshDisp) { Graphics_drawString(&g_sContext, str, AUTO_STRING_LENGTH, 10, LCD_VERTICAL_MAX-10, GRAPHICS_OPAQUE_TEXT); refreshDisp--; } // Draw the FFT magnitudes but restricting it to only 96 pixel screen for(i = 0; i < LCD_HORIZONTAL_MAX; i++) { #ifdef VECTOR_SIZE_256 // set the scale and restrict it to the size of the display scale = ((FFT_data[i]) >> 6); #else // 512 // Set the scale and restrict it to the size of the display // Since we have 256 data points and the display is only 128 wide, compress by 2 scale = ((FFT_data[i*2] + FFT_data[i*2+1]) >> 6); #endif // Check if is out of bounds. if(scale < 0) { scale = 12; } else if(scale > LCD_VERTICAL_MAX-24) { scale = LCD_VERTICAL_MAX-25; } if(scale != 0) { // Draw each line only if scale the mag is 0 pixels Graphics_drawLineV(&g_sContext, i, LCD_VERTICAL_MAX-13, LCD_VERTICAL_MAX-13 - scale); } } // Flush this content to display Graphics_flushBuffer(&g_sContext); #endif } }