#include #include #include "musicdata.h" #define interrupt(x) void __attribute__((interrupt (x))) void delay_ms(uint16_t ms) { while (ms--) __delay_cycles(1000); } int16_t freqs[] = { 0x0eee, 0x0bd9, 0x09f7, 0x0bd9 }; uint16_t wavelen[] = { 0, 0, 0 }; uint16_t count[] = { 0, 0, 0 }; uint8_t duty[] = { 1, 1, 1 }; uint8_t toggle[] = { 0, 0, 0 }; uint16_t next; int main() { // Disable watchdog WDTCTL = WDTPW | WDTHOLD; // 1MHz internal timer BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // P2 (XOUT/XIN) as GPIO P2SEL = 0x00; P1OUT = 0x00; P1DIR = 0x01; // LED P1REN |= 0x08; //while (!(P1IN & 0x08)) ; // TA0 on P1.1, TA1 on P1.2 P1SEL |= 0x02 | 0x04; P1DIR |= 0x02 | 0x04; TACTL = TASSEL1 | TACLR; // SMCLK source for timer TACCTL0 = OUTMOD_4 | CCIE; // Channel 0 (output mode toggle, enable interrupt) TACCTL1 = OUTMOD_4 | CCIE; // Channel 1 TACCTL2 = OUTMOD_4 | CCIE; // Channel 2 __enable_interrupt(); TACTL |= MC1; // Enable timer, continuous mode count[0] = 0; count[1] = 0; for (uint8_t i = 0; i < 5; i++) { wavelen[0] = note_wl[i + 40]; wavelen[1] = note_wl[i + 44]; wavelen[2] = note_wl[i + 47]; delay_ms(200); wavelen[0] = wavelen[1] = 0; delay_ms(100); } TACTL = TACLR; P1OUT = 0; return 0; } #define UPDATE_CHANNEL(n) \ uint16_t wl = wavelen[n]; \ if (toggle[n]) \ count[n] += wl >> duty[n]; \ else \ count[n] += wl - (wl >> duty[n]); \ toggle[n] ^= 1; \ TACCR##n = count[n]; \ TACCTL##n &= ~CCIFG; interrupt(TIMER0_A0_VECTOR) ta0_isr() { UPDATE_CHANNEL(0); } interrupt(TIMER0_A1_VECTOR) ta1_isr() { if (TACCTL1 & CCIFG) { UPDATE_CHANNEL(1); } else if (TACCTL2 & CCIFG) { UPDATE_CHANNEL(2); } } #undef UPDATE_CHANNEL