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.

CCS/MSP-EXP430F5438: Audio Play thorugh PWM Output from internal Flash audio text file

Part Number: MSP-EXP430F5438

Tool/software: Code Composer Studio

Hi ,

I am currently working on MSP-EXP430F5438 experiementer board.

Default User experience Demo program is not working to validate Audio Play and record functions. I am Hardware enginerr,not familiar with much of coding.

Managed to rin few programs of LED blink with polling and Interrupt, Timer PWM Output, and LCD slide Show.

I Need somebody,who has worked on playing a small Audio bit (less than a second like YES or NO word) from internal Flash (256KB for this device) through PWM port.

I have tried few expamles form Resource centre,nothing is working as of now.

Regards,

VR

  • Could you please specify what code examples you have tried?
  • Hi

    I have tried ez430-speech MSP430FG4618PlaybackWAV code and modified as per MSP430F5438A resources of Timer B0 and P4.4 as my PWM port to play Audio via jack.

    When I tried to debug, it is going to ISR Trap.

    Regards,

    Raju

  • The basic is going to be set a PWM using one of the timers with CCR0 as period and CCR1 as duty cycle. Then based on the value of the digitized Audio, you update the duty cycle at the same rate as your audio signal's sample rate. On the hardware side you will need a low pass filter with cut off frequency below the frequency of your PWM signal. You will also need an amplifier for the output of the LPF. Could you draft an initial code so i can take a look at it. It should not be a very long code.

  • Hi Nima Eskandari,

    Thanks for your reply and offering Support to Review my code. As I mentioned, I am using MSP-EXP430f5438 experimenter board,which has Headphone jack connected to P4.4 with RC filter and Amplifier already.

    Once I could here some Audio(even noise ) from Headset, then I will move on to external Speaker with RC filter on other P4.5 or P.4.6 Pins with PWM Output. I have derived this code from another expamle code of ez-430 speech board. I have changed all port assignemnts as per my board. I would like to run SMCLK at 16 MHz or 8 MHz as I Need to integrate this code with LCD also. Instead of Audio.h , i would like to try some junk data, thqat can produce noise as a first step.

    #include <msp430.h>

    #include <stdint.h>

    #include "Audio1.h" // Audio file from ez-430 playback source code.

    #include "Audio2.h" // Audio file from ez-430 playback source code.

     

    typedef unsigned char u8_t;

    typedef unsigned short int u16_t;

    typedef signed char i8_t;

    typedef short int i16_t;

     

    #define BUFF_SZ 64

    uint8_t Buffer[ BUFF_SZ ];

    // If this variable is locally declared as uint32_t in main it is not

    // properly allocated/handled by the compiler unless optimization is

    // turned on

    uint32_t ImgSize = 0;

    uint8_t uAvgCntr;

    uint8_t uAudioSample1;

    uint8_t uAudioSample2;

    int iAudioSampleDifference;

    uint32_t lAudioSampleCnt;

    uint32_t lAudioSampleLength;

    char * pAudio;

    void initTA0(void)

    {

    // Initialise Timer_A for PWM output

    TBCTL = TBSSEL_2 | ID_1 | TBCLR; //|TAIE; // clock = SMCLK /2 = 16 MHz / 2

    // overflow interrupt enabled

    TBCCTL0 = CM_0 | OUTMOD_7 | CCIE;

    TBCCTL4 = CM_0 | OUTMOD_7 | CCIE; // CM_0: Compare mode (no capture mode)

    // OUTMOD_7 set/rest mode PWm

    // CCIE: Compare Interrupt Enabled

    TBCCR0 = 0xFF; // 8-bit counter from 00h to FFh---sri Notes: Usually this goes as PWM period

    // Set P1.2 as output for PWM signals

    //sri Notes: P1.1 cannot be used for PWM output

    P4DIR |= BIT4; // Pin4-P1.2/TA0.1 is output

    P4SEL |= BIT4; // Pin4-P1.2/TA0.1 is TA1 output WITH PWM functionality

    }

    #define StartTimer() TBCTL |= MC_1; //START TIMER IN UP MODE

    #define StopTimer() TBCTL |= MC_0;

    void readImgSz(void)

    {

    // Read the header of the binary image to get its size. Start

    // reading from memory address 0.

    Buffer[0] = 0x00;

    Buffer[1] = 0x00;

    // I2CWrite( EEPROM_ADDR , Buffer , 2 );

    // I2CRead( EEPROM_ADDR , Buffer , 4 );

    // 32-bit size value

    /*ImgSize = (uint32_t) Buffer[0];

    ImgSize <<= 8;

    ImgSize |= (uint32_t) Buffer[1];

    ImgSize <<= 8;

    ImgSize |= (uint32_t) Buffer[2];

    ImgSize <<= 8;

    ImgSize |= (uint32_t) Buffer[3];*/

    ImgSize = 19878;

    }

    void main (void)

    {

    WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

    //DCOCTL = CALDCO_16MHZ; // Select DCO@16MHz as clock sources

    //BCSCTL1 = CALBC1_16MHZ;

    P1DIR |= 0x03;

    //********************Configure clock SMCLK to 8MHz*****************************//

    UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO

    UCSCTL4 |= SELA_2; // Set ACLK = REFO

    __bis_SR_register(SCG0); // Disable the FLL control loop

    UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx

    UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation

    UCSCTL2 = FLLD_1 + 488; // Set DCO Multiplier for 8MHz

    // (N + 1) * FLLRef = Fdco

    // (249 + 1) * 32768 = 8MHz ,// (488 + 1) * 32768 = 16MHz

    // Set FLL Div = fDCOCLK/2

    __bic_SR_register(SCG0); // Enable the FLL control loop

    //__delay_cycles(250000);

    // Loop until XT1,XT2 & DCO fault flag is cleared

    do

    {

    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);

    // Clear XT2,XT1,DCO fault flags

    SFRIFG1 &= ~OFIFG; // Clear fault flags

    }while (SFRIFG1&OFIFG); // Test oscillator fault flag

    //********************Configure clock SMCLK to 8MHz*****************************//

    P11DIR |= 0x07; // Set P11.0,1,2 as O/P for ACLK,SMCLK and MCLK

    P11SEL |= 0x07; // Enable P11.0,1,2 for ACLK,SMCLK and MCLK

    //I2CInit(); // Initialise I2C

    //_enable_interrupt(); // Enable interrupts

    initTA0(); //Initialise TimerA

    __bis_SR_register(GIE);

    while(1)

    {

    readImgSz();

    //I2CRead( EEPROM_ADDR , Buffer , 2 );

    pAudio = (char *) &Audio2; // set pointer to Audio2 data byte

    *(((char*)(&lAudioSampleLength))+0) = *(pAudio++);

    *(((char*)(&lAudioSampleLength))+1) = *(pAudio++);

    *(((char*)(&lAudioSampleLength))+2) = *(pAudio++);

    *(((char*)(&lAudioSampleLength))+3) = *(pAudio++);

    uAudioSample1 = Buffer[0];

    uAudioSample2 = Buffer[1];

    uAvgCntr = 0;

    StartTimer();

    for (lAudioSampleCnt = ImgSize-1; lAudioSampleCnt > 0; lAudioSampleCnt--)

    {

    //__bis_SR_register(LPM0_bits + GIE); // LPM0: keep DCO running

    //I2CRead( EEPROM_ADDR , Buffer , 1 );

    uAudioSample1 = uAudioSample2;

    uAudioSample2 = Buffer[0];

    }

    StopTimer();

    P1OUT = 0x03;

    }

    }

    //******************************************************************************

    // Timer B0 interrupt service routine

    //******************************************************************************

    #pragma vector=TIMERB0_VECTOR

    __interrupt void TIMERB0_ISR (void)

    { // Timer interrupt (PWM, one sample)

    switch (__even_in_range(TBIV,10))

    {

    case 2: // Vector 2: TBCCR1

    break;

    case 4: // Vector 4: TBCCR2

    break;

    case 8: // Vector 4: TBCCR4

    P1OUT = 0x01;

    iAudioSampleDifference = (int) uAudioSample2 - (int) uAudioSample1;

    if (iAudioSampleDifference > 68)

    {

    TBCTL &= ~TAIFG; // clear overflow flag TAIFG IFG

    TBCTL |= TAIE; // enable overflow interrupt TAIFG

    TBCCTL4 &= ~CCIE; // turn off TBCCR4 IFG

    }

    switch (__even_in_range(uAvgCntr,6))

    {

    case 0: TBCCR4 = (uAudioSample1

    + uAudioSample1

    + uAudioSample1

    + uAudioSample2) >> 2;

    break;

    case 2: TBCCR4 = (uAudioSample1

    + uAudioSample2) >> 1;

    break;

    case 4: TBCCR4 = (uAudioSample1

    + uAudioSample2

    + uAudioSample2

    + uAudioSample2) >> 2;

    break;

    case 6: TBCCR4 = uAudioSample2;

    __bic_SR_register_on_exit(LPM4_bits);

    // Clear all LPM bits from 0(SR)

    // this restarts audio output loop

    // and read next audio sample from

    // SPI-Flash memory

    break;

    }

    uAvgCntr+=2; // increment averaging counter (always by 2)

    uAvgCntr = uAvgCntr & 0x06; // averaging counter range: 0, 2, 4, 6

    break;

    case 10: // Vector 10: TAIFG Flag

    P1OUT = 0x02;

    TBCCTL4 &= ~CCIFG; // clear TBCCR4 IFG

    TBCCTL4 |= CCIE; // enable TBCCR4 IFG

    TBCTL &= ~TBIE; // turn off overflow interrupt TAIFG

    break;

    }

    } // __interrupt void TimerA1 (void)

    Looking Forward for your reply.

    Thanks,

    Raju

     

  • Could you also share the original code before you changed the port assignments?
  • Hi Nima Eskandari,

    Thanks for your reply. I have used follwoing thread link and ez-430 slaa405a\eZ430-speech\MSP430FG4618PlaybackWAV Software Folder as referecnes for my code.

    https://e2e.ti.com/support/microcontrollers/msp430/f/166/t/219093

    Can you help me with MSP-EXP430F5438 User Expereicne Demo code, which never worked on my board. If i can make it work the Demo user code, i could make use of it mostly.

    Regards,

    Raju

  • Yes let me see if I can acquire the hardware. If not I will try to give you some feedback based on the code.
  • Hi Nima Eskandari,

    Thanks for your reply.

    Please find below code. With this code, I could see PWM data toggle on both P4.4 and P4.5.

    However, I can hear some buzz noise at 4KHz PWM frequency or below.

    No voice or Audio above that freqncy. I have all Audio Header files with 8 bit, 8ksps mono data string generated from.wav files of 1 second Audio.

    I have used SMCLK of 8MHz and tried TBCTL with ID_0 and 256 delay cycles for 32KHz PWM frequency and ID_3 and 2048 delay cycles for 4KHz.

    Hope this will help you to give me some Inputs to generate Audio from Headset of MSP-EXP430f5438 experimenter board.

    #include <msp430.h>

    #include <stdint.h>

    #include "Audio1.h" // Audio file from ez-430 playback source code.

    #include "Audio2.h" // Audio file from ez-430 playback source code.

    #include "Chirp.h" // Audio file from ez-430 playback source code.

    #include "Beep.h" // Audio file from ez-430 playback source code.

    typedef unsigned char u8_t;

    typedef unsigned short int u16_t;

    typedef signed char i8_t;

    typedef short int i16_t;

    #define BUFF_SZ 64

    uint8_t Buffer[ BUFF_SZ ];

    // If this variable is locally declared as uint32_t in main it is not

    // properly allocated/handled by the compiler unless optimization is

    // turned on

    uint32_t ImgSize = 0;

    uint8_t uAvgCntr;

    uint8_t uAudioSample1;

    uint8_t uAudioSample2;

    int iAudioSampleDifference;

    uint32_t lAudioSampleCnt;

    uint32_t lAudioSampleLength;

    char * pAudio;

    unsigned count ;

    unsigned long SYSCLK;

    unsigned long FPWM;

    unsigned int D;

     

    void main (void)

    {

    WDTCTL = WDTPW+WDTHOLD; // Stop WDT

    //********************Configure clock SMCLK to 8MHz*****************************//

    unsigned char FD;

    UCSCTL3 |= SELREF_2; // Set DCO FLL reference = REFO

    UCSCTL4 |= SELA_2; // Set ACLK = REFO

    __bis_SR_register(SCG0); // Disable the FLL control loop

    UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx

    UCSCTL1 = DCORSEL_5; // Select DCO range 16MHz operation

    FD = 244; // N = 244 for 8MHz and 488 for 16MHz

    UCSCTL2 = FLLD_1 + FD; // Set DCO Multiplier for 8MHz

    // (N + 1) * FLLRef = Fdco

    // (244 + 1) * 32768 = 8MHz ,// (487 + 1) * 32768 = 16MHz

    // Set FLL Div = fDCOCLK/2

    __bic_SR_register(SCG0); // Enable the FLL control loop

    __delay_cycles(250000);

    // Loop until XT1,XT2 & DCO fault flag is cleared

    do

    {

    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);

    // Clear XT2,XT1,DCO fault flags

    SFRIFG1 &= ~OFIFG; // Clear fault flags

    }while (SFRIFG1&OFIFG); // Test oscillator fault flag

    //********************End of Configure clock SMCLK to 8MHz*****************************//

    //P4SEL |= 0xFF; // P4 option select

    // P4DIR |= 0xFF; // P4 outputs

    SYSCLK = 32768 * (FD+1);

    P11DIR |= 0x07; // Set P11.0,1,2 as O/P for ACLK,SMCLK and MCLK

    P11SEL|= 0x07; // Enable P11.0,1,2 for ACLK,SMCLK and MCLK

    P2REN |= 0x40; // Enable P1.4 internal resistance

    P2OUT |= 0x40; // Set P2.6 as pull-Up resistance

    P2IE |= 0x40; // P2.6 interrupt enabled

    P2IES |= 0x40; // P2.6 Hi/Lo edge

    P2IFG &= ~0x40; // P2.6 IFG cleared

    __bis_SR_register(GIE); // Enter LPM4 w/interrupt

    }

     

    void delay(unsigned int cycles )

    {

    unsigned int i;

    for (i = 0; i<= cycles; i++)

    __delay_cycles(1);

    }

    // Port 2 interrupt service routine

    #pragma vector=PORT2_VECTOR

    __interrupt void Port_2(void)

    {

    unsigned int x = 0;

    /*

    * For 8MHz SMCLK, TBSSEL_2 and ID_0 with SMCLK as reference, TBCCR0 of 0xFF makes it Fpwm = 31,360KHz, keep delay cycles as 0XFF/256

    * For 8MHz SMCLK, TBSSEL_2 and ID_3 with SMCLK/8 as reference , TBCCR0 of 0xFF makes it Fpwm = 31,360Hz/8 = 3920Hz, keep delay cycles as 0XFF*8/256*8 = 2048

    *

    */

    P4SEL |= 0xFF; // P4 option select

    P4DIR |= 0xFF; // P4 outputs

    TBCCR0 = 0xFF; // Fpwm = Fclk/tbccr0

    TBCCTL4 = OUTMOD_7;

    TBCCTL5 = OUTMOD_7;

    TBCTL = TBSSEL_2 + TBCLR; // SMCLK(TBSSEL_2),ACLK(TBSSEL_1), clear TBR

    TBCTL |= ID_3;

    FPWM = SYSCLK/TBCCR0;

    D = SYSCLK/FPWM ;

    pAudio = (char *) &Audio1; // set pointer to Audio header file data byte

    for( x = 0; x <15516; x++ )

    {

    uAudioSample1 = *(pAudio); // read first audio sample

    uAudioSample2 = *(pAudio+1); // read second audio sample

    TBCCR4 = uAudioSample1; // CCR4 PWM duty cycle

    TBCCR5 = uAudioSample1;

    TBCTL |= MC_1 ; // Start UPmode Timer

    __delay_cycles(2048);

    for( uAvgCntr = 0; uAvgCntr <3; uAvgCntr++ ) // To extrapolate 8ksps data to 32ksps, have to create 3 additional samples for each sample

    {

    switch (uAvgCntr)

    {

    case 0: TBCCR4 = (uAudioSample1 + uAudioSample1 + uAudioSample1 + uAudioSample2) >> 2; //((s1 × 3) + s2) / 4

    __delay_cycles(25048);

    break;

    case 1: TBCCR4 = (uAudioSample1 + uAudioSample2) >> 1; //(s1 + s2) / 2

    __delay_cycles(2048);

    break;

    case 2: TBCCR4 = (uAudioSample1 + uAudioSample2 + uAudioSample2 + uAudioSample2) >> 2; //(s1 + (s2 × 3)) / 4

    __delay_cycles(2048);

    break;

    default:

    uAvgCntr=0;

    break;

    }

    __no_operation();

    }

    __no_operation();

    }

    P2IFG &= ~0x40; // P2.6 IFG cleared

    TBCCTL4 &= ~(OUTMOD_7 | OUT); // CCR4 reset/set

    TBCCTL5 &= ~(OUTMOD_7 | OUT); // CCR4 reset/set

    TBCTL &= ~MC_0;

    P4SEL &= ~ 0xFF; // P4 option select

    P4DIR &= ~ 0xFF; // P4 outputs

    }

  • Can you take a scope measurement of the signal at the output of the buffer amplifier?
    Also can you let me know the size of the data inside Audio.h files?
  • Hi Nima Eskandari,

    Yes, I was able to measre the Signal at buffer amplifier Output. It is amlost similar frequncy as PWM Output of P4.4, just smoothened Signal.I could hear some buzz noise at 4KHz PWM frequncy, anything above that I cannot hear from Headset jack. But, I could observe singal in scope.

    I have tried different data sizes ranging from 4004, 15536 and 19378, which are converted from .wav files. You can provide a sample code for Audio Play with a small buffer.

    So, I can try that code with my board. It would be easy solution.

    Regards,

    Raju

  • I can put together a quick example of outputting a sine wave, using a timer (PWM). Would that help?

  • Hi Nima Eskandari,

    That would be great help.

    It would be great, if you can provide a small voice( a second) Play code through P4.4.

    Let me know your contact Details, either phone or email, i will not take more than 10 mins to explain the issue.

    Regards,

    Raju

  • I have sent you a private message.
  • As I mentioned in the email. The pin P6.6 must be pulled low to enable the audio amplifier. After adding the code to enable P6.6 as digital output and pulling the pin low, everything works.
  • Many Thanks Nima.

    Problem of Audio Play is resolved by keeping P6.6  low.

    Thanks,

    Raju

**Attention** This is a public forum