Part Number: MSP432P401R
Hi,
I am currently trying to obtain an approximate frequency value using the MSP432 & AUDIO BOOSTXL boosterpack. The "boostxl_edumkii_microphonefft_msp432p401r_MSP_EXP432P401R_nortos_ccs" seemed like a good starting point as it already has ADC/DMA/PWM modules as well as the CMSIS DSP libraries already set up. I have made the following modifications to the code: removal of all code having to do with the display, adding a few lines to power on the AUDIO BOOSTXL mic, adding uart functionality to print results, turning off bitReverse for the FFT, and performing a simple frequency calculation once the index of the maximum energy bin has been obtained. I also double checked that the microphone output pin matches up with the correct ADC14 channel and that the ADC pin is in the correct mode.
However, I always end up getting zero for my frequency. Has anyone used the AUDIO BOOSTXL with the MSP432401R to do something like this? Are there any other items I'm missing?
I've attached my code. If anyone could offer me any insights, I would greatly appreciate it.
/* --COPYRIGHT--,BSD * Copyright (c) 2015, 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--*/ //**************************************************************************** // // main.c - MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT // // CMSIS DSP Software Library is used to perform 512-point FFT on // the audio samples collected with MSP432's ADC14 from the Education // Boosterpack's onboard microhpone. The resulting frequency bin data // is displayed on the BoosterPack's 128x128 LCD. // //**************************************************************************** #include <ti/devices/msp432p4xx/inc/msp.h> #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <ti/grlib/grlib.h> #include <stdio.h> #include <arm_math.h> #include <arm_const_structs.h> #include <uart_driver.h> #define TEST_LENGTH_SAMPLES 512 #define SAMPLE_LENGTH 512 /* ------------------------------------------------------------------ * Global variables for FFT Bin Example * ------------------------------------------------------------------- */ uint32_t fftSize = SAMPLE_LENGTH; uint32_t ifftFlag = 0; uint32_t doBitReverse = 0; volatile arm_status status; #define SMCLK_FREQUENCY 48000000 #define SAMPLE_FREQUENCY 8000 /* DMA Control Table */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=1024 #elif defined(__GNUC__) __attribute__ ((aligned (1024))) #elif defined(__CC_ARM) __align(1024) #endif static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32]; /* FFT data/processing buffers*/ float hann[SAMPLE_LENGTH]; int16_t data_array1[SAMPLE_LENGTH]; int16_t data_array2[SAMPLE_LENGTH]; int16_t data_input[SAMPLE_LENGTH * 2]; int16_t data_output[SAMPLE_LENGTH]; q15_t maxValue; uint32_t maxIndex = 0; uint32_t frequency=0; volatile int switch_data = 0; /* Timer_A PWM Configuration Parameter */ Timer_A_PWMConfig pwmConfig = { TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY / SAMPLE_FREQUENCY), TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY / SAMPLE_FREQUENCY) / 2 }; int main(void) { //intialize uart uartInit(); /* Halting WDT and disabling master interrupts */ MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); /* Set the core voltage level to VCORE1 */ MAP_PCM_setCoreVoltageLevel(PCM_VCORE1); /* Set 2 flash wait states for Flash bank 0 and 1*/ MAP_FlashCtl_setWaitState(FLASH_BANK0, 2); MAP_FlashCtl_setWaitState(FLASH_BANK1, 2); /* Initializes Clock System */ MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); // Initialize Hann Window int n; for(n = 0; n < SAMPLE_LENGTH; n++) { hann[n] = 0.5f - 0.5f * cosf((2 * PI * n) / (SAMPLE_LENGTH - 1)); } /* Configuring Timer_A to have a period of approximately 0.125us and * an initial duty cycle of 50% of that (3000 ticks) */ Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig); /* Initializing ADC (MCLK/1/1) */ ADC14_enableModule(); ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 1); ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); /* Power up the audio booster-pack preamp. Output high = power on */ GPIO_setAsOutputPin(GPIO_PORT_P4, GPIO_PIN1); GPIO_setOutputHighOnPin(GPIO_PORT_P4, GPIO_PIN1); /* Configuring GPIOs (4.3 A10) */ GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN3, GPIO_TERTIARY_MODULE_FUNCTION); /* Configuring ADC Memory */ ADC14_configureSingleSampleMode(ADC_MEM0, true); ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A10, false); /* Set ADC result format to signed binary */ ADC14_setResultFormat(ADC_SIGNED_BINARY); /* Configuring DMA module */ DMA_enableModule(); DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); /* Setting Control Indexes. In this case we will set the source of the * DMA transfer to ADC14 Memory 0 * and the destination to the * destination data array. */ MAP_DMA_setChannelControl( UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array1, SAMPLE_LENGTH); MAP_DMA_setChannelControl( UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array2, SAMPLE_LENGTH); /* Assigning/Enabling Interrupts */ MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_assignChannel(DMA_CH7_ADC14); MAP_DMA_clearInterruptFlag(7); MAP_Interrupt_enableMaster(); /* Now that the DMA is primed and setup, enabling the channels. The ADC14 * hardware should take over and transfer/receive all bytes */ MAP_DMA_enableChannel(7); MAP_ADC14_enableConversion(); char *string = ""; while(1) { MAP_PCM_gotoLPM0(); int i = 0; /* Compute real FFT using the completed data buffer */ if(switch_data) { for(i = 0; i < 512; i++) { data_array1[i] = (int16_t)(hann[i] * data_array1[i]); } arm_rfft_instance_q15 instance; status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, doBitReverse); arm_rfft_q15(&instance, data_array1, data_input); } else { for(i = 0; i < 512; i++) { data_array2[i] = (int16_t)(hann[i] * data_array2[i]); } arm_rfft_instance_q15 instance; status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, doBitReverse); arm_rfft_q15(&instance, data_array2, data_input); } /* Calculate magnitude of FFT complex output */ //arm_cmplx_mag_q15(data_input, data_output, SAMPLE_LENGTH); for(i = 0; i < 1024; i += 2) { data_output[i / 2] = (int32_t)(sqrtf((data_input[i] * data_input[i]) + (data_input[i + 1] * data_input[i + 1]))); } q15_t maxValue; uint32_t maxIndex = 0; uint32_t frequency=0; arm_max_q15(data_output, fftSize, &maxValue, &maxIndex); frequency= (uint32_t)maxIndex*SAMPLE_FREQUENCY/SAMPLE_LENGTH/2; snprintf(test.txString, 50,"Frequency: %d \n\r",frequency); if(string != test.txString) { sendText(); string = test.txString; } } } /* Completion interrupt for ADC14 MEM0 */ void DMA_INT1_IRQHandler(void) { /* Switch between primary and alternate bufferes with DMA's PingPong mode */ if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { DMA_setChannelControl( UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array1, SAMPLE_LENGTH); switch_data = 1; } else { DMA_setChannelControl( UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_array2, SAMPLE_LENGTH); switch_data = 0; } }