This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Compiler/MSP-EXP432P401R: I need to help for doing change for codes

Part Number: MSP-EXP432P401R

Tool/software: TI C/C++ Compiler

Real-time FIR filtering with triple buffering


#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>  //Exact-width integer types
#include <ti\devices\msp432p4xx\driverlib\driverlib.h>  //Driver library

#define CLOCK_HF    48000000 //48MHz
#define CLOCK_LF    32000 //32kHz

#define TIMER0_FREQ    1  //unit: Hz

#define SAMPLE_FREQ    8000 //Frequency in Hz, common sampling rates for digital audio: 8000, 32000, 44100, 48000

#define MCP4921_SPI_BITRATE    20e6 //needs to > SAMPLE_FREQ*16, and < SMCLK/2, max 20M
#define MCP4921_SPI_DATA_MASK    0x0FFF //See datasheet, MCP4921
#define MCP4921_SPI_CTRL_MASK    0x7000 //See datasheet, MCP4921

#define RED_LED    GPIO_PIN0
#define GREEN_LED    GPIO_PIN1
#define BLUE_LED    GPIO_PIN2

#define NUM_DISP_TEXT_LINE    4

// Definitions for triple buffering.
#define NUM_DATA_BUFFER    3
#define DATA_BUFFER_LEN    200

#define FILTER_LEN_M    28


//Function prototypes
void initDevice_HFXT(void);
void initGPIO(void);
void initTimer(void);
void initUART(void);
void initADC14(void);
void initSPI(void);

void initDataBuffer(void);
void processData(void);

void uart0_transmitStr(const char *str);


//Global variables
uint32_t clockMCLK, clockSMCLK;
uint8_t currentLED = RED_LED;

volatile uint32_t dataBuffer[NUM_DATA_BUFFER][DATA_BUFFER_LEN];
volatile uint32_t buf_inputIndex=0, buf_outputIndex=1, buf_dataIndex=2;
volatile bool buf_dataReady=false, buf_overrunError=false;

float filter_Bcoef[FILTER_LEN_M+1] =
{
    -0.0014541062, -0.0012749733, -0.0009739225, +0.0000396414, +0.0024743259,
    +0.0070030369, +0.0140943302, +0.0238646359, +0.0359851042, +0.0496673460,
    +0.0637372145, +0.0767880565, +0.0873882711, +0.0943060927, +0.0967098938,
    +0.0943060927, +0.0873882711, +0.0767880565, +0.0637372145, +0.0496673460,
    +0.0359851042, +0.0238646359, +0.0140943302, +0.0070030369, +0.0024743259,
    +0.0000396414, -0.0009739225, -0.0012749733, -0.0014541062
};

const char *terminalDisplayText[NUM_DISP_TEXT_LINE] =
{
    "\r\n",
    "Real-time FIR filtering with triple buffering\r\n",
    "R: Red, G: Green, B: Blue, H: Help\r\n",
    "> "
};


void main(void)
{
    uint32_t i;
    uint8_t data;

    initDevice_HFXT();
    initGPIO();
    initTimer();
    initUART();
    initADC14();
    initSPI();

    initDataBuffer();

    Interrupt_enableMaster();
    Timer32_startTimer(TIMER32_0_BASE, false);
    Timer32_startTimer(TIMER32_1_BASE, false);

    // Initial display on terminal.
    for(i=0; i<NUM_DISP_TEXT_LINE; i++)
    {
        uart0_transmitStr(terminalDisplayText[i]);
    }

    while(1)
    {
        if(UART_getInterruptStatus(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG))
        {
            data = UART_receiveData(EUSCI_A0_BASE);
            UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG);

            switch(data)
            {
                case 'R':
                case 'r':
                    currentLED = RED_LED;
                    uart0_transmitStr("Blink red LED.\r\n> ");
                    break;

                case 'G':
                case 'g':
                    currentLED = GREEN_LED;
                    uart0_transmitStr("Blink green LED.\r\n> ");
                    break;

                case 'B':
                case 'b':
                    currentLED = BLUE_LED;
                    uart0_transmitStr("Blink blue LED.\r\n> ");
                    break;

                case 'H':
                case 'h':
                    for(i=0; i<NUM_DISP_TEXT_LINE; i++)
                    {
                        uart0_transmitStr(terminalDisplayText[i]);
                    }
                    break;
            }
        } //end of if

        if(buf_overrunError)
        {
            //This error indicates the processData() routine takes too much time to complete.
            //Optimize this routine to run faster or set the BUFFER_LEN larger.
            //uart0_transmitStr("Error: buffer overrun!\r\n");
            printf("Error: buffer overrun!\r\n");
            buf_overrunError = false;
        }

        if(buf_dataReady)
        {
            processData();
            buf_dataReady = false;
        }

    } //end of while
}


void initDevice_HFXT(void)
{
    WDT_A_holdTimer();  //Stop watchdog timer

    //Change VCORE to 1 to support a frequency higher than 24MHz.
    //See data sheet for Flash wait-state requirement for a given frequency.
    PCM_setPowerState(PCM_AM_DCDC_VCORE1);
    FlashCtl_setWaitState(FLASH_BANK0, 1);
    FlashCtl_setWaitState(FLASH_BANK1, 1);

    FPU_enableModule();
    FPU_enableLazyStacking(); //Required to use FPU within ISR.

    //Configure PJ.2 and PJ.3 in HFXT mode.
    //Initialize external clock sources HFXT.
    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN2|GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);
    CS_setExternalClockSourceFrequency(CLOCK_LF, CLOCK_HF);
    CS_startHFXT(false);

    CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1);
    CS_initClockSignal(CS_HSMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_16);
    CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1); //48MHz to support SPI

    clockMCLK = CS_getMCLK();
    clockSMCLK = CS_getSMCLK();
}


void initGPIO(void)
{
    //Configure P2.0, P2.1, P2.2 as output.
    //P2.0, P2.1, P2.2 are connected to a RGB tri-color LED on LaunchPad.
    GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
}


void initTimer(void)
{
    // TIMER32_0 to blink heartbeat LED
    Timer32_initModule(TIMER32_0_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
    Timer32_setCount(TIMER32_0_BASE, clockMCLK/TIMER0_FREQ - 1);
    Timer32_enableInterrupt(TIMER32_0_BASE);
    Interrupt_enableInterrupt(INT_T32_INT1); //Enable Timer32_0 interrupt in the interrupt controller.

    // TIMER32_1 to do input/ADC and output/DAC
    Timer32_initModule(TIMER32_1_BASE, TIMER32_PRESCALER_1, TIMER32_32BIT, TIMER32_PERIODIC_MODE);
    Timer32_setCount(TIMER32_1_BASE, clockMCLK/SAMPLE_FREQ - 1);
    Timer32_enableInterrupt(TIMER32_1_BASE);
    Interrupt_enableInterrupt(INT_T32_INT2); //Enable Timer32_1 interrupt in the interrupt controller.
}


void initUART(void)
{
    //Configuration for 48MHz SMCLK, 115200 baud rate.
    //Calculated using the online calculator that TI provides at:
    //software-dl.ti.com/.../index.html
    const eUSCI_UART_Config config =
    {
        EUSCI_A_UART_CLOCKSOURCE_SMCLK, //SMCLK Clock Source, 48MHz
        26, //BRDIV
        0, //UCxBRF
        111, //UCxBRS
        EUSCI_A_UART_NO_PARITY, //No Parity
        EUSCI_A_UART_LSB_FIRST, //MSB First
        EUSCI_A_UART_ONE_STOP_BIT, //One stop bit
        EUSCI_A_UART_MODE, //UART mode
        EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION //Oversampling
    };

    // Configure GPIO pins for UART. RX: P1.2, TX:P1.3.
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2|GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION);

    UART_initModule(EUSCI_A0_BASE, &config);
    UART_enableModule(EUSCI_A0_BASE);
}


//Use P6.1/A14 to sample
void initADC14(void)
{
    ADC14_enableModule();
    ADC14_initModule(ADC_CLOCKSOURCE_SMCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, ADC_NOROUTE);

    //Configure P6.1 as A14
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P6, GPIO_PIN1, GPIO_TERTIARY_MODULE_FUNCTION);

    ADC14_setResolution(ADC_12BIT);
    ADC14_configureSingleSampleMode(ADC_MEM0, true); //repeatMode = true
    ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A14, false);

    //See TechRef Section 20.2.6 for sample timing consideration.
    ADC14_enableSampleTimer(ADC_MANUAL_ITERATION);
    ADC14_setSampleHoldTime(ADC_PULSE_WIDTH_4, ADC_PULSE_WIDTH_4);

    ADC14_enableConversion();
}


void initSPI(void)
{
    const eUSCI_SPI_MasterConfig spiMasterConfig =
    {
        EUSCI_B_SPI_CLOCKSOURCE_SMCLK,             //SMCLK Clock Source
        clockSMCLK,                                //Clock source frequency
        MCP4921_SPI_BITRATE,                       //desiredSpiClock
        EUSCI_B_SPI_MSB_FIRST,                     //MSB First
        EUSCI_B_SPI_PHASE_DATA_CHANGED_ONFIRST_CAPTURED_ON_NEXT,    //Phase
        EUSCI_B_SPI_CLOCKPOLARITY_INACTIVITY_LOW,  //Low polarity
        EUSCI_B_SPI_3PIN                           //3Wire SPI Mode
    };

    //P1.5: SCK, P1.6: SDI, P5.2: CS
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN5|GPIO_PIN6, GPIO_PRIMARY_MODULE_FUNCTION);
    GPIO_setAsOutputPin(GPIO_PORT_P5, GPIO_PIN2);
    GPIO_setOutputHighOnPin(GPIO_PORT_P5, GPIO_PIN2);

    //Configuring SPI in 3wire master mode
    SPI_initMaster(EUSCI_B0_BASE, &spiMasterConfig);

    //Enable SPI module
    SPI_enableModule(EUSCI_B0_BASE);
}


void initDataBuffer(void)
{
    uint32_t i, j;

    for(i=0; i<NUM_DATA_BUFFER; i++)
    {
        for(j=0; j<DATA_BUFFER_LEN; j++)
        {
            dataBuffer[i][j] = 0;
        }
    }
}


void processData(void)
{
    static float data[DATA_BUFFER_LEN + FILTER_LEN_M] = {0}; //augmented data frame, initialized to 0
    float y;
    uint32_t *pBuf = (uint32_t *) dataBuffer[buf_dataIndex];
    uint32_t i, j, k;

    // Copy data from the data frame to the augmented data frame.
    // Start to fill ater FILTER_LEN_M elements.
    for(i=0, j=FILTER_LEN_M; i<DATA_BUFFER_LEN; i++, j++)
    {
        data[j] = (float) pBuf[i];
    }

    // FIR filtering: y[n] = sum_{i=0}^{M}(B[i]x[n-i]).
    for(i=0; i<DATA_BUFFER_LEN; i++)
    {
        y = 0;
        for(j=0, k=i; j<=FILTER_LEN_M; j++, k++)
        {
            y += filter_Bcoef[j]*data[k];
        }
        pBuf[i] = (uint32_t) y;
    }

    // Save the last FILTER_LEN_M number of samples to the beginning of the augmented data frame.
    for(i=0; i<FILTER_LEN_M; i++)
    {
        data[i] = data[DATA_BUFFER_LEN+i];
    }
}


//Transmit a string through UART0.
void uart0_transmitStr(const char *str)
{
    uint32_t len, i=0;

    len = strlen(str);
    while(i < len)
    {
        UART_transmitData(EUSCI_A0_BASE, str[i++]);
        while(!UART_getInterruptStatus(EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG));
        UART_clearInterruptFlag(EUSCI_A0_BASE, EUSCI_A_UART_TRANSMIT_COMPLETE_INTERRUPT_FLAG);
    }
}


//Timer32_0 ISR
void T32_INT1_IRQHandler(void)
{
    Timer32_clearInterruptFlag(TIMER32_0_BASE);

    if(GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2))
    {
        GPIO_setOutputLowOnPin(GPIO_PORT_P2, GPIO_PIN0|GPIO_PIN1|GPIO_PIN2);
    }
    else
    {
        GPIO_setOutputHighOnPin(GPIO_PORT_P2, currentLED);
    }
}


//Timer32_1 ISR
void T32_INT2_IRQHandler(void)
{
    static uint32_t sampleIndex=0;
    uint32_t tmpIndex;
    uint16_t data;
    uint8_t byte1, byte0;

    Timer32_clearInterruptFlag(TIMER32_1_BASE);

    //Read from ADC.
    ADC14_toggleConversionTrigger();

    while(!(ADC_INT0 & ADC14_getInterruptStatus()));
    ADC14_clearInterruptFlag(ADC_INT0);

    dataBuffer[buf_inputIndex][sampleIndex] = ADC14_getResult(ADC_MEM0);

    //Prepare data for SPI.
    data = MCP4921_SPI_CTRL_MASK | (MCP4921_SPI_DATA_MASK & dataBuffer[buf_outputIndex][sampleIndex]);
    byte1 = (uint8_t) (data>>8);
    byte0 = (uint8_t) data;

    //SPI is written with register-level operation to support 16-bit operation.
    P5->OUT &= ~BIT2; //Set CS to LOW on SPI slave.

    EUSCI_B0->TXBUF = byte1; //Transmit Byte 1
    EUSCI_B0->TXBUF = byte0; //Transmit Byte 0

    while(!(EUSCI_B0->IFG & EUSCI_B_IFG_TXIFG)); //Check if TX buffer is ready.
    P5->OUT |= BIT2; //Set CS to HIGH on SPI slave.

    //Update buffer indices and sample index.
    if(++sampleIndex >= DATA_BUFFER_LEN)
    {
        sampleIndex = 0;
        if(buf_dataReady)
        {
            buf_overrunError = true;
        }

        tmpIndex = buf_inputIndex;
        buf_inputIndex = buf_outputIndex;
        buf_outputIndex = buf_dataIndex;
        buf_dataIndex = tmpIndex;
        buf_dataReady = true;
    }
}

problem 2. How to do FIR filter design with Matlab.
 1• In Matlab, use “filterDesigner” to design a lowpass FIR equiripple filter, with order 50 =M , sampling frequency kHz 8=sF , passband cutoff frequency Hz 1500=passF , stopband cutoff frequency Hz 2000=stopF , and equal weight 1 for both passband and stopband.  Export the designed filter to the Matlab workspace as a coefficient variable and plot its time domain unit sample response using the Matlab function “plot” and plot its frequency response using the Matlab function “freqz”. 
 
2• Create a new CCS project “Lab9_2”.  Add the sample code “Lab9_1_main.c” to the project. • The input and output setup of this lab is exactly same as Problem 1.
 
3• Replace the filter used in “Lab9_1_main.c” with the new FIR filter that you just design.  Some of the parameter/variable values in “Lab9_1_main.c” will need to be changed according the specification of your new filter. • Repeat the filtering experiment procedure using the test signals in Problem 1 to test the implementation of your new FIR filter design. • Explain your code and experiment results in your report.
 
 
Problem 3. Real-time FIR filtering with Ping-Pong buffering.
 
• Create a new CCS project “Lab9_3”. • The input and output setup of this lab is exactly same as Problem 1. • Use the Ping-Pong buffering technique to implement the same real-time FIR filtering functionality as in Lab9_2.   • Explain in your report how the Ping-Pong buffering based FIR filtering works. • Explain your own code in your report.
 
 

**Attention** This is a public forum