I am trying to play some WAV files turned into hex code as in the TI application note SLAA405 and this question.
My setup is like this:
MSP4302452
P1.0 -> LED
P1.2 -> RC filter (8khz low pass) -> Speaker
P1.3 <- Button
I can get it to work with a simple while loop like this in the button ISR:
#pragma vector=PORT1_VECTOR __interrupt void Port_1(void) { while (lAudioSampleCnt <= lAudioSampleLength) { TA0CCR1 = Audio1[lAudioSampleCnt]; lAudioSampleCnt++; delay_ms(368); } P1IFG &= ~BIT3; }
But I understand this is not optimal or accurate with its timing. I want to but cannot get it to work with the code provided by the application note and the question. There is no sound. For reference:
#include "msp430g2452.h" #include "Audio1.h" char * pAudio; unsigned int uAvgCntr; unsigned int uAudioSample1; unsigned int uAudioSample2; int iAudioSampleDifference; unsigned long lAudioSampleCnt; unsigned long lAudioSampleLength; void main (void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer P1DIR |= BIT2 | BIT0; // P1.0 and P1.2 output P1SEL |= BIT2 | BIT0; // P1.0 and P1.2 options select P1OUT |= BIT0; /* Set up button interrupt */ P1DIR &= ~BIT3; P1OUT |= BIT3; P1REN |= BIT3; P1IES |= BIT3; P1IE |= BIT3; // P1.3 interrupt enabled P1IFG &= ~BIT3; // P1.3 interrupt flag cleared uAudioSample1 = Audio1[0]; uAudioSample2 = Audio1[1]; lAudioSampleLength = 2012; __bis_SR_register(SCG0); BCSCTL1 = CALBC1_16MHZ; DCOCTL = CALDCO_16MHZ; __delay_cycles(3); __bic_SR_register(SCG0); P1OUT &= ~BIT0; // Initialize Timer //TA0CCTL0 = CCIE; // CCR0 interrupt enabled TA0CCTL1 = CM_0 | OUTMOD_0 | CCIE; // CCR1 Output Mode reset/set //TA0CCTL2 = OUTMOD_7; // CCR2 Output Mode reset/set TA0CCR0 = 256; // Set PWM period to 256 clock ticks TA0CCR1 = 0; TACTL = TASSEL_2 + MC_1 + TACLR + ID_1; __bis_SR_register(GIE); // Mainloop while (1) { P1IE &= ~BIT3; P1OUT |= BIT0; pAudio = (char *) &Audio1; // set pointer to Audio1 data byte *(((char*)(&lAudioSampleLength))+0) = * (pAudio++); *(((char*)(&lAudioSampleLength))+1) = *(pAudio++); *(((char*)(&lAudioSampleLength))+2) = *(pAudio++); *(((char*)(&lAudioSampleLength))+3) = *(pAudio++); uAudioSample1 = *(pAudio++); uAudioSample2 = *(pAudio++); TACCTL1 &= ~(OUTMOD_7 | OUT); // PWM output = LOW P1DIR |= BIT2; // TA1/P1.2 is output P1SEL |= BIT2; // TA1/P1.2 is TA1 output TACCTL1 |= OUTMOD_7; uAvgCntr = 0; TACTL |= MC_1; TACTL |= MC_1; // Start Timer for (lAudioSampleCnt = lAudioSampleLength-1; lAudioSampleCnt > 0; lAudioSampleCnt--) { __bis_SR_register(LPM0_bits + GIE); uAudioSample1 = uAudioSample2; uAudioSample2 = *(pAudio++); } TACTL &= ~MC_0; // Stop Timer TACCTL1 &= ~(OUTMOD_7 | OUT); // and wait until putton pressed P1OUT &= ~BIT2; // PWM GPIO-Pin = LOW P1DIR &= ~BIT2; // TA2/P2.0 is input P1SEL &= ~BIT2; // TA2/P2.0 is P2.0 input P1OUT &= ~BIT0; P1IFG &= ~BIT3; P1IE |= BIT3; __bis_SR_register(LPM4_bits + GIE); } } //****************************************************************************** // Timer A0 interrupt service routine //****************************************************************************** #pragma vector=TIMER0_A1_VECTOR __interrupt void TIMER0_A1_ISR (void) { // Timer interupt (PWM, one sample) switch (__even_in_range(TAIV,10)) { case 2: // Vector 2: TACCR1 __no_operation(); iAudioSampleDifference = (int) uAudioSample2 - (int) uAudioSample1; if (iAudioSampleDifference > 68) { TACTL &= ~TAIFG; // clear overflow flag TAIFG IFG TACTL |= TAIE; // enable overflow interrupt TAIFG TACCTL1 &= ~CCIE; // turn off TACCR1 IFG } switch (__even_in_range(uAvgCntr,6)) { case 0: TACCR1 = (uAudioSample1 + uAudioSample1 + uAudioSample1 + uAudioSample2) >> 2; break; case 2: TACCR1 = (uAudioSample1 + uAudioSample2) >> 1; break; case 4: TACCR1 = (uAudioSample1 + uAudioSample2 + uAudioSample2 + uAudioSample2) >> 2; break; case 6: TACCR1 = uAudioSample2; __bis_SR_register_on_exit(LPM4_bits); break; } uAvgCntr += 2; // increment averaging counter always by 2 uAvgCntr = uAvgCntr & 0x06; // averaging counter range: 0, 2, 4, 6 break; case 4: break; case 10: TACCTL1 &= ~CCIFG; TACCTL1 |= CCIE; TACTL &= ~TAIE; break; } } // __interrupt void TimerA1 (void) //****************************************************************************** // P1 interrupt service routine //****************************************************************************** #pragma vector=PORT1_VECTOR __interrupt void Port_1 (void) { P1IFG = 0x00; // reset all interupt flags P1IE &= ~BIT3; // Disable Port Interrupt _bic_SR_register_on_exit(LPM4_bits); // Clear all LPM bits from 0(SR) // this restarts main loop and // starts next audio playback __no_operation(); }
Audio1.h is the same as in the application note. Can anyone see if there is a mistake with this code or my implementation?