Created
March 3, 2018 18:34
-
-
Save sdp8483/6f7a660d7b661386fb9b845732abdf86 to your computer and use it in GitHub Desktop.
train horn project code for embedding into website. See github repo for up to date code.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//****************************************************************************** | |
// MSP430FR2000 - Train Horn Hold To Play | |
// | |
// Description: Toggle pins at multiple frequencies using only TimerB, | |
// mimic train horn for silly reasons. | |
// P1.5 toggles using CRR0 and software. P2.0 and P2.1 toggle using CCR1 and CCR2 | |
// Button on P1.1 enables frequency generation while held low | |
// 1.2 VREF+ output on pin 1.7 to connect to external comparator for LiPo voltage monitor, | |
// could not get MSP430 internal comparator to work | |
// | |
// ACLK = TBCLK = 32768Hz, MCLK = SMCLK = default DCODIV ~1MHz | |
// P1.5 = CCR0 ~ 32KHz/(2*64) = ~256.00Hz -> target frequency: 255Hz (~C4) | |
// P2.0 = CCR1 ~ 32KHz/(2*53) = ~309.13Hz -> target frequency: 311Hz (~D#4) | |
// P2.1 = CCR2 ~ 32KHz/(2*37) = ~442.81Hz -> target frequency: 440Hz (A4) | |
// | |
// MSP430FR2000 | |
// ----------------- | |
// | P1.0|--> LED for timer status | |
// | P1.2|--> Audio Amp Shutdown | |
// | P1.3|<-- Play Button to gnd | |
// | | | |
// | P1.7/VREF+|--> 1.2VREF Output | |
// | | | |
// | P1.5|--> ~248.24Hz | |
// | P2.0/TB0.1|--> ~309.13Hz | |
// | P2.1/TB0.2|--> ~442.81Hz | |
// | | | |
// | |
// | |
// TimerB multi frequency based on TI app note SLAA513A and accompanying code | |
//****************************************************************************** | |
#include <msp430.h> | |
// Port1 Pin Defines | |
#define PLAY_BTN BIT3 // Play button port 1 input | |
#define PLAY_LED BIT0 // Play LED port 1 output | |
#define AMP_EN BIT2 // Amplifier enable port 1 output | |
int main(void) | |
{ | |
WDTCTL = WDTPW | WDTHOLD; // Stop WDT | |
// Configure reset | |
SFRRPCR |= SYSRSTRE | SYSRSTUP; // Enable internal pullup resistor on reset pin | |
// Configure Interrupt Button | |
P1IES |= PLAY_BTN; // play button interrupts on high-to-low transition | |
P1REN |= PLAY_BTN; // enable internal resistor | |
P1OUT |= PLAY_BTN; // set resistor to pullup | |
// Configure Audio Amp Shutdown | |
P1DIR |= AMP_EN; // set as output | |
P1OUT &= ~AMP_EN; // Pull low to turn off audio amp | |
// Configure Play LED indicator | |
P1DIR |= PLAY_LED; // set as output | |
P1OUT &= ~PLAY_LED; // turn off LED | |
// Configure Timer_B Outputs | |
P2SEL0 |= BIT0 | BIT1; // Select TB0.1 and TB0.2 pin functions for P2.0 and P2.1 | |
P2DIR |= BIT0 | BIT1; | |
P1DIR |= BIT5; // P1.5 is an output | |
// Configure Voltage Reference Output | |
P1SEL0 |= BIT7; // Select VREF+ pin function for P1.7 | |
P1SEL1 |= BIT7; | |
// Configure Unused GPIO as outputs per ULP advice | |
P1DIR |= BIT1 | BIT4 | BIT6; | |
P2DIR |= BIT6 | BIT7; | |
PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode to activate | |
// previously configured port settings | |
// Configure reference | |
PMMCTL0_H = PMMPW_H; // Unlock the PMM registers | |
PMMCTL2 |= EXTREFEN; // Enable external reference | |
while(!(PMMCTL2 & REFGENRDY)); // Poll until internal reference settles | |
P1IFG &= ~PLAY_BTN; // clear any pending interrupts | |
P1IE |= PLAY_BTN; // enable interrupts on P1.1 | |
// setup timerB | |
TB0CCTL0 = OUTMOD_4 + CCIE; // TBCCR0 toggle, interrupt enabled | |
TB0CCTL1 = OUTMOD_4 + CCIE; // TBCCR1 toggle, interrupt enabled | |
TB0CCTL2 = OUTMOD_4 + CCIE; // TBCCR2 toggle, interrupt enabled | |
TB0CTL = TBSSEL_1 | TBCLR | TBIE; // ACLK, clear TBR, enable interrupts | |
TB0R = 0xFFFF; // Set initial count of Timer_B | |
// removes pause before initial sound generation | |
for(;;) { | |
__bis_SR_register(LPM3_bits | GIE); // Enter LPM3, enable interrupts | |
TB0CTL |= MC_2 | TBIE; // enable timer | |
while (!(P1IN & PLAY_BTN)); // Poll until play button is released | |
P1OUT ^= PLAY_LED | AMP_EN; // toggle play LED for status indicator | |
// turn off audio amp | |
TB0CTL &= ~MC_2; // disable Timer_B | |
P1OUT &= ~(BIT5 | BIT6 | BIT7); // set pins low since they could have been high during interrupt | |
// delay to prvent fast button presses from locking up system | |
__delay_cycles(20000); | |
// enable play button again | |
P1IFG &= ~PLAY_BTN; // acknowledge all interrupts | |
P1IE |= PLAY_BTN; // enable interrupt on play button | |
} | |
} | |
// Port1 Interrupt Vector handler | |
#pragma vector=PORT1_VECTOR | |
__interrupt void PORT1_ISR(void) | |
{ | |
P1IE &= ~PLAY_BTN; // disable any further interrupts | |
P1OUT ^= PLAY_LED | AMP_EN; // toggle play LED for status indicator | |
// toggle audio amp on | |
__bic_SR_register_on_exit(LPM3_bits); // Exit LPM3 | |
} | |
// Timer0_B3 Interrupt Vector (TBIV) handler | |
#pragma vector=TIMER0_B0_VECTOR | |
__interrupt void TIMER0_B0_ISR(void) | |
{ | |
TBCCR0 += 64; | |
P1OUT ^= BIT5; // ~256Hz frequency generation on P1.5 | |
} | |
// Timer0_B3 Interrupt Vector (TBIV) handler | |
#pragma vector=TIMER0_B1_VECTOR | |
__interrupt void TIMER0_B1_ISR(void) | |
{ | |
switch(__even_in_range(TB0IV,TB0IV_TBIFG)) | |
{ | |
case TB0IV_NONE: | |
break; // No interrupt | |
case TB0IV_TBCCR1: // CCR1 | |
TBCCR1 += 53; // ~309.13Hz frequency generation on P1.6 | |
break; | |
case TB0IV_TBCCR2: // CCR2 | |
TBCCR2 += 37; // ~442.81Hz frequency generation on P1.7 | |
break; | |
case TB0IV_TBIFG: // overflow | |
break; | |
default: | |
break; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment