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?