主题中讨论的其他器件:BOOSTXL-AUDIO、
工具/软件:Code Composer Studio
我想处理音频、因此我 将使用 BOOSTXL-AUDIO_430BOOST-SHARPLCD_FFT_FIR_LEA_MSP430FR5994示例作为起点。 所有内容都可以与原始代码一起使用。 我将需要更多的点、即512或1024。 我尝试修改了512个点的代码、但它不适用于 LEA。 在本测试中、我将向系统馈送一个2.2kHz 正弦信号。 如果没有 LEA、它就可以工作、使用 LEA、我得到2个峰值、预期峰值为2.2k、但我得到第二个峰值为1.8k。 第二个峰值始终为4K 减去输入频率。
对于512点测试、水平面被压缩、因此所有4个测试看起来应该一样。 左侧的两张图片是 LEA、右侧的两张图片没有。
您可以通过搜索 vector_size_256找到我所做的更改。
我使用的是 CCS 9.3。 几天前我就下载了示例代码。
我使用的是 BoostXL-Audio 和 Sharp 128 x 128 LCD。
FFT.h
/*-版权所有-、BSD *版权所有(c) 2016、德州仪器(TI)公司 *保留所有权利。 * * 只要 符合以下条件*、允许以源代码和二进制形式重新分发和使用: * *源代码的重新分发必须保留上述版权 声明*、此条件列表和以下免责声明。 * ***二进制形式的再发行必须在 *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。 * ***未经 事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。 * *本软件由版权所有者和贡献者"按原样"提供 *、 不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或 *贡献者都不对任何直接、间接、偶然、特殊、 *模范、 或相应的损害(包括但不限于 *采购替代产品或服务;丧失使用、数据或利润; *或业务中断)、但出于任何责任理论 、*无论是在合同中、严格责任还是由于 使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他) 、*即使已获悉可能会发生此类损坏。 *--/版权--*//********* //! TI 在 MSP430FR5994上使用 LEA 设计信号处理 //! //! William Goh 先生/! 德州仪器公司 //! 2016年4月 //********* #ifndef FFT_H #define FFT_H //#define vector_size_256 //注释掉512 #ifdef vector_size_256 #define vector_size 256 #define Twiddle 表 MSP_cmplx_Twiddle 表_256_Q15 #else #define vector_size 512 #define Twiddle 表 MSP_cmplx_twiddle_table_512_Q15 #endif //#define log2_size 8. //未使用 //#define SQRT_SIZE 16. //未使用 //#define SCALE_FACTOR 0x00026000 //未使用 extern void initFft (void); extern void shutdownActivity (void); extern void runFftWithoutLea (void); extern void runFWithLea (void); extern void testFft (void); #endif /* FFT_H */
FFT.c
/*-版权所有-、BSD *版权所有(c) 2016、德州仪器(TI)公司 *保留所有权利。 * * 只要 符合以下条件*、允许以源代码和二进制形式重新分发和使用: * *源代码的重新分发必须保留上述版权 声明*、此条件列表和以下免责声明。 * ***二进制形式的再发行必须在 *随发行提供的文档和/或其他材料中复制上述版权声明、本条件列表和以下免责声明。 * ***未经 事先书面许可、不得使用德州仪器公司的名称或*其贡献者的名称认可或推广从本软件衍生的产品*。 * *本软件由版权所有者和贡献者"按原样"提供 *、 不承担任何明示或暗示的保证、包括但不限于*适销性和特定用途适用性的暗示保证*。 在任何情况下、版权所有者或 *贡献者都不对任何直接、间接、偶然、特殊、 *模范、 或相应的损害(包括但不限于 *采购替代产品或服务;丧失使用、数据或利润; *或业务中断)、但出于任何责任理论 、*无论是在合同中、严格责任还是由于 使用本软件而以任何方式产生的侵权行为(包括疏忽或*其他) 、*即使已获悉可能会发生此类损坏。 *--/版权--*//********* //! TI 在 MSP430FR5994上使用 LEA 设计信号处理 //! //! William Goh、L Reynoso //! 德州仪器公司 //! 2019年8月 //********* #include #include #include #include #include #include "DSPLib.h" #include "FFT.h" #include "FFT_430/h" #include "benchmark.h" #include "audio_collect.h" #include "application.h" #ifdef _ SHARP96x96_ #include "Sharp96x96.h"#include "sharpx96_enrand_digure_lcd" (#128_lcd_recture_lcd_recture_128 );#def_rectangle_arpx128_rularpx128/e_rularf = 128_r_ar_rularpx128/en_r_r_rularf = 128/en_r_ar_r_rand_digure_en_r_r_r const Graphics_Rectangle clearSpaceTopText ={0、0、LCD_Vertical _MAX、7}; const Graphics_Rectangle clearSpaceText ={10、LCD_Vertical _MAX-11、65、LCD_Vertical _MAX}; #if defined (__IAR_systems_ICC__) //用户应用程序可以使用的实数 FFT 值 __int_vector ={0_int_int_vector =} //在计算 __persistent Int16_t FBuff[vector_size * 2]={0}之后包含实值和虚值的 FFT 缓冲区; //由 FFT 算法处理 的原始数据缓冲区__persistent Int16_t voical_data[vector_size * 2]={0}; #elif defined (__TI_Compiler_version__) //用户应用程序可以使用的实数 FFT 值 #pragma PERSISTENT (FFT_DATA) int16_t FFT_DATA[vector_size]={0}; //在计算 #pragma PERSISTENT (FFFF) int16_t REF_SIZE ={0*}之后包含实值和虚值的 FFT 缓冲区 //由 FFT 算法#pragma PERSISTENT (VOICE_DATA) Int16_t VOICY_DATA[VECTOR _SIZE * 2]={0}; #endif #ifdef Vector_SIZE 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、 实数、实数_abs、imag_abs、mag、max、 min; int16_t scale; MSP_cmplx_FFT_Q15_params sqfftParams; static uint8_t refreshDisp = 0; static int8_t str[20]; void initFft (void) { resetBenchmark(); //为最低功耗配置禁用音频回放 Audio_stopPlayback (&gPlaybackConfig); //初始化 FFT 参数 cinfrftParams.length = vector_size; sqinfftParams.bitReverse = 1; // fqftParams.TwidleTable = MSP_cmplx_twiddle_table_256_Q15; sbidfftParams.TwiddletTable = Twiddle_table; //初始化麦克风以进行录制 gAudioConfig.audioBuffer1 =(int16_t *) adcBuffer0; gAudioConfig.audioBuffer2 =(int16_t *) adcBuffer1; gAudioConfig.buffersize = vector_size; gAudioConfig.sample.Rate = FFT_SAMPLING_FREQUENCY; gAudioConfig.twosComplement= true; AUDIO_setupCollect (&gAudioConfig); //通过启用计时器开始录制 Audio_startCollect (&gAudioConfig); } /******** //** *@brief 运行 FFT。 执行 FFT 并将其放入 FFT_DATA 缓冲器中。 * *@param none * *@return none /void runFftWithoutLea (void) { int16_t * currentAdcBuffer; //初始化刷新显示的次数 refreshDisp = 2; //首先清除屏幕 graphics_clearDisplay (&g_sContext); //绘制基本结构 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); //画标题一次 graphics_drawstring (&g_sContext、"FFT w/o LEA"、 AUTO_STRING_LENGTH、0、0、 图形不透明文本); //将缓冲器刷新到 LCD graphics_flushBuffer (&g_sContext); keepAppRunning = true; while (keepAppRunning) { _bis_SR_register (LPM3_bits + GIE); //将记录的 ADC 数据复制到 LEA RAM 缓冲器以进行 FFT 处理 currentAdcBuffer = Audio_getActiveBuffer (&gAudioConfig); for (i = 0;i <(vector_size);i++) { (((int32_t *) voice_data)[i]= currentAdcBuffer[i]; } resetBenchmark(); startBenchmark(); //执行 FFT 并存储 FFT_prog (); stopBenchmark(); //计算正频域的幅度 for (i = 0;i <(vector_size / 2);i++) { 索引= bit_rev_index[i]; 实数= FBuff[2 *索引]; Imag = FBuff[2 *索引+ 1]; if (实数< 0) { Real_Abs =~Real + 1; } 其他 { Real_Abs = Real; } if (imag < 0) { Imag_abs =~μ s imag + 1; } 其他 { Imag_abs = imag; } if (REAL_ABS >= imag_abs) { MAX = REAL_ABS; 最小值= imag_abs; } 其他 { Max = imag_abs; 最小值= REALL_ABS; } MAG =最大值+ 3 *(最小值>> 3); FFT_DATA[i]= MAG; } #ifndef PWR_Benchmark if (refreshDisp) { sprintf ((char *) str、"cyc:%lu"、cycleCounts); } //通过绘制框来清除线条 graphics_setForegroundColor (&g_sContext、ClrWhite); graphics_fillRectangle (&g_sContext、clearSpace); if (refreshDisp) { graphics_fillRectangle (&g_sContext、clearSpaceCyclpleText); } graphics_setForegroundColor (&g_sContext、ClrBlack); if (refreshDisp) { graphics_drawstring (&g_sContext、str、 AUTO_STRING_LENGTH、10、LCD_Vertical _MAX-10、 图形不透明文本); refreshDisc-; } //绘制 FFT 幅度,但将其限制为仅96像素屏幕 对于(I = 0;I < LCD_Horize_MAX;I++) { //将其限制为仅96像素屏幕 if (i < LCD_Horize_MAX) { #ifdef vector_size_256 //设置比例并将其限制为显示的大小 换算=((FFT_DATA[i])>> 6); #else // 512 //设置比例并将其限制为显示的大小 //由于我们有256个数据点,而且显示宽度只有128个,因此压缩2 换算=((FFT_DATA[I*2]+ FFT_DATA[I*2+1])>> 6); #endif //检查是否超出范围。 if (换算< 0) { 比例= 12; } 否则、如果(Scale > LCD_Vertical _MAX-24) { 换算= LCD_Vertical _MAX-25; } if (比例!= 0) { //仅在缩放 MAG 为0像素时绘制每一行 graphics_drawLineV (&g_sContext、I、LCD_Vertical _MAX-13、LCD_Vertical _MAX- 13 - Scale); } } //刷新此内容以显示 graphics_flushBuffer (&g_sContext); #endif } Audio_stopCollect (&gAudioConfig); Audio_shutdownCollect (&gAudioConfig); } void runFftWithLea (void) { MSP_STATUS 状态; uint16_t i; int16_t * currentAdcBuffer; //初始化刷新显示的次数 refreshDisp = 2; //首先清除屏幕 graphics_clearDisplay (&g_sContext); //绘制基本结构 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_Horizontale_MAX、LCD_Vertical _MAX-12); //画标题一次 GrStringDraw (&g_sContext、"FFT w/LEA"、 AUTO_STRING_LENGTH、0、0、 图形不透明文本); //将缓冲器刷新到 LCD graphics_flushBuffer (&g_sContext); //初始化 LEA 模块 initFft(); keepAppRunning = true; while (keepAppRunning) { _bis_SR_register (LPM3_bits + GIE); //获取要复制的最新缓冲区指针 currentAdcBuffer = Audio_getActiveBuffer (&gAudioConfig); //将记录的 ADC 数据复制到 LEA RAM 缓冲器以进行 FFT 处理 for (i = 0;i <(vector_size);i++) { (((int32_t *) leaMemoryStartAdd.fftDataParam.fftInputOutput)[i]= currentAdcBuffer[i]& 0x0000FFFF; } resetBenchmark(); startBenchmark(); //调用固定缩放 FFT 函数。 状态= MSP_cmplx_FFT_fixed_q15 (&sqFftParams、 leaMemoryStartAdd.fftDataParam.fftInputOutput); //检查状态标志。 if (status!= MSP_SUCCESS) { //错误! __no_operation(); } stopBenchmark(); //计算正频域的幅度 for (i = 0;i <(vector_size / 2);i++) { Real = leaMemoryStartAdd.fftDataParam.fftInputOutput[2 * i]; Imag = leaMemoryStartAdd.fftDataParam.fftInputOutput[2 * I + 1]; if (实数< 0) { Real_Abs =~Real + 1; } 其他 { Real_Abs = Real; } if (imag < 0) { Imag_abs =~μ s imag + 1; } 其他 { Imag_abs = imag; } if (REAL_ABS >= imag_abs) { MAX = REAL_ABS; 最小值= imag_abs; } 其他 { Max = imag_abs; 最小值= REALL_ABS; } MAG =最大值+ 3 *(最小值>> 3); FFT_DATA[i]= MAG; } #ifndef PWR_Benchmark //刷新显示 if (refreshDisp) { sprintf ((char *) str、"cyc:%lu"、cycleCounts); } //通过绘制框来清除线条 graphics_setForegroundColor (&g_sContext、ClrWhite); if (refreshDisp) { graphics_fillRectangle (&g_sContext、clearSpaceCyclpleText); } 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、 图形不透明文本); refreshDisc-; } //绘制 FFT 幅度,但将其限制为仅96像素屏幕 对于(I = 0;I < LCD_Horize_MAX;I++) { #ifdef vector_size_256 //设置比例并将其限制为显示的大小 换算=((FFT_DATA[i])>> 6); #else // 512 //设置比例并将其限制为显示的大小 //由于我们有256个数据点,而且显示宽度只有128个,因此压缩2 换算=((FFT_DATA[I*2]+ FFT_DATA[I*2+1])>> 6); #endif //检查是否超出范围。 if (换算< 0) { 比例= 12; } 否则、如果(Scale > LCD_Vertical _MAX-24) { 换算= LCD_Vertical _MAX-25; } if (比例!= 0) { //仅在缩放 MAG 为0像素时绘制每一行 graphics_drawLineV (&g_sContext、I、LCD_Vertical _MAX-13、LCD_Vertical _MAX-13 - Scale); } } //刷新此内容以显示 graphics_flushBuffer (&g_sContext); #endif } }