By first doing a: typedef int (*IntFunc)(void) simplifies it a little.
unlike case, functions can be repeated as you can see that red_off is there twice.
This is for a G2553 Launchpad done with IAR C99
No need for a 32K crystal as I slow down smlk/8 and TA /8 just for this example.
With more complicated states you of course don't have just to go to next state, maybe repeat same state or jump to any state.
if jumping states, best to use enum so to give each state a name.
Each state has it's own delay setting before next state is coming up, if they all have same delay move that up to single point by flag &= ~BIT0;
This is my first C code as I just started to learn it last week, been an assembler programmer for decades.
This is the correct way to program the msp430 to save power, sleep as much as possible wake up and do thing fast and come back later after a nap.
32K crystal for ACLK TA and LPM3 for best power saving of course.
#include <msp430.h> // bitfield version is io430.h
int unsigned m1state=0;
int unsigned flag=0;
int red_on(); // declaration of functions
int red_off();
int green_off();
int red_green_on();
int red_green_off();
typedef int (*IntFunc)(void);
IntFunc const DoState[6] = { red_green_off, red_on, red_off, red_green_on, red_off, green_off};
int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1OUT = 0;
P1DIR = BIT0+BIT6; // P1.0 & P1.6 output, rest is input
P1OUT |= BIT3; // prepare button
P1REN |= BIT3;
P1IES |= BIT3;
P1IFG &= ~BIT3;
P1IE |= BIT3;
P2OUT =0;
P2REN =0x3f;
P3OUT =0;
P3REN =0xff;
BCSCTL2 |= DIVS_3; // SMCLK div by 8
TACTL = TASSEL_2 + ID_3 + MC_2; // SMCLK /8, contmode
while(1)
{
__bic_SR_register(GIE); // we don't want a IRQ to happen between if and __bis
if (!flag) // only go back to sleep if non pending
{
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt
__no_operation();
}
__bis_SR_register(GIE); // enable irq again
if (flag & BIT0) // one of them that woke us up wanted us
{
flag &= ~BIT0;
m1state= DoState[m1state](); // do the state and set the state-number for next time
}
}
}
int red_green_off(void) // our entry init state
{
P1OUT &= ~(BIT0+BIT6); // turn off both led's
CCR0 = TA0R + 4000; // come back soon
CCTL0 = CCIE; // enable irq
return ++m1state;
}
int red_on(void)
{
P1IFG &= ~BIT3; // Clear Interrupt Flag just in case
P1IE |= BIT3; // turn button irq back on
P1OUT |= BIT0;
CCR0 += 12000;
return ++m1state;
}
int red_off(void)
{
P1OUT &= ~BIT0;
CCR0 += 15000;
return ++m1state;
}
int red_green_on(void)
{
P1OUT |=BIT0+BIT6;
CCR0 += 22000;
return ++m1state;
}
int green_off(void) // it's also our exit state
{
P1OUT &= ~BIT6;
CCTL0 = 0;
return 0;
}
//\\//\\////\\//\\////\\//\\////\\//\\////\\//\\////\\//\\////\\//\\//
#pragma vector=PORT1_VECTOR
__interrupt void PORT1(void) // only one IRQ on P1 no need to search IFG register
{
P1IE &= ~BIT3; // turn off button irq as a way of debounce
P1IFG &= ~BIT3; // Clear Interrupt Flag
m1state = 0;
flag |= BIT0;
__bic_SR_register_on_exit(LPM0_bits);
}
//\\//\\////\\//\\////\\//\\////\\//\\////\\//\\////\\//\\////\\//\\//
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A (void)
{
flag |= BIT0;
__bic_SR_register_on_exit(LPM0_bits);
}
//\\//\\////\\//\\////\\//\\////\\//\\////\\//\\////\\//\\////\\//\\//