X-Git-Url: http://www.average.org/gitweb/?p=sensor-light.git;a=blobdiff_plain;f=msp430%2Fmain.c;h=6b075ad91d6b9753f86cb258216d88227842d174;hp=914b865dc119e5394d2e01458b097a8268c1950e;hb=68eddb43a02efafa7d42778a58659313199c8228;hpb=15874ff8800f58c60d220721f3625761b1fa922c diff --git a/msp430/main.c b/msp430/main.c index 914b865..6b075ad 100644 --- a/msp430/main.c +++ b/msp430/main.c @@ -1,222 +1,305 @@ -#include - -static volatile unsigned int ADC_Result; -static volatile unsigned int irq_events = 0; -enum {ev_btn1 = 0, ev_btn2, ev_pir1, ev_pir2, ev_tmr, ev_adc, ev_MAX}; - -int main(void) -{ - int Duty_Cycle = 1; - int Increment = 1; - unsigned int Time_Count = 0; - unsigned int Time_Left = 5; - - WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer - // Configure GPIO Out - P1DIR |= BIT0|BIT1|BIT2; // Set P1.0&1&2/LEDs to output direction - P1OUT &= ~(BIT0|BIT1); // P1.0&1 LEDs off - P1SEL1 |= BIT2; // P1.2 PWM out - - // Configure GPIO In - P2DIR &= ~(BIT3|BIT7); // Buttons - P2OUT |= BIT3|BIT7; // Pull up - P2REN |= BIT3|BIT7; // Enable pull-up - P2IES |= BIT3|BIT7; // INT on Hi->Lo edge - P2IE |= BIT3|BIT7; // INT enable - - P2DIR &= ~(BIT2|BIT5); // PIR Sensors - P2OUT &= ~(BIT2|BIT5); // Pull down - P2REN |= BIT2|BIT5; // Enable pull-down - P2IES &= ~(BIT2|BIT5); // INT on Lo->Hi edge - P2IE |= BIT2|BIT5; // INT enable - P2IFG = 0; // ??? Needed? - - // Configure ADC A7 pin - SYSCFG2 |= ADCPCTL7; - - // Configure ADC10 - ADCCTL0 |= ADCSHT_2 | ADCON; // ADCON, S&H=16 ADC clks - ADCCTL1 |= ADCSHP; // ADCCLK = MODOSC; sampling timer - ADCCTL2 |= ADCRES; // 10-bit conversion results - ADCMCTL0 |= ADCINCH_7; // A7 ADC input select; Vref=AVCC - ADCIE |= ADCIE0; // Enable ADC conv complete interrupt - - // Configure timer A0 for PWM - TA0CCR0 = 10000-1; // PWM Period - TA0CCTL2 = OUTMOD_7; // CCR2 reset/set - TA0CCR2 = 500; // CCR2 PWM duty cycle - TA0CTL = TASSEL__SMCLK | MC__UP | TACLR; // SMCLK, up mode, clear TAR - - //Configure timer A1 for counting time - TA1CTL |= TASSEL__SMCLK | MC__CONTINUOUS | TACLR | TAIE; // SMCLK, no divider, continuous mode - - // Disable the GPIO power-on default high-impedance mode to activate - // previously configured port settings - PM5CTL0 &= ~LOCKLPM5; - - while(1) - { - unsigned int events; - - _disable_interrupt(); - events = irq_events; - irq_events = 0; - _enable_interrupt(); - - // Button 2 or PIR events initiate light measurement and turns on green led - if (events & (1< 1) { - Time_Left = 15; - continue; - } - ADCCTL0 |= ADCENC | ADCSC; // Sampling and conversion start - P1OUT |= BIT1; // Set P1.1 LED on - } - - // End of light measurement, set new Duty_Cycle and zero increment and turns off green led - if (events & 1< 5000) { - Time_Left = 0; - Increment = -1; - } else { - Time_Left = 15; - Increment = 1; - } - } - - // Timer event (100 ms) changed duty cycle and flashes red led - if (events & 1< 10) { - Time_Count = 0; - P1OUT ^= BIT0; - if (Time_Left) - Time_Left--; - else if (Duty_Cycle > 1) - Increment = -1; - } - if (Increment == 0) - continue; - else if (Increment > 0) - Duty_Cycle *= 2; - else if (Increment < 0) - Duty_Cycle /= 2; - if (Duty_Cycle < 1) { - Duty_Cycle = 1; - Increment = 0; - } - if (Duty_Cycle > (10000-1)) { - Duty_Cycle = 10000-1; - Increment = 0; - } - TA0CCR2 = Duty_Cycle; - } - __bis_SR_register(LPM0_bits | GIE); - __no_operation(); - } - return 0; /* not reached */ -} - -// TIMER interrupt routine -#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) -#pragma vector = TIMER1_A1_VECTOR -__interrupt void Timer_A (void) -#elif defined(__GNUC__) -void __attribute__ ((interrupt(TIMER1_A1_VECTOR))) Timer_A (void) -#else -#error Compiler not supported! -#endif -{ - switch(__even_in_range(TA1IV,TA1IV_TAIFG)) - { - case TA1IV_NONE: - break; // No interrupt - case TA1IV_TACCR1: - break; // CCR1 not used - case TA1IV_TACCR2: - break; // CCR2 not used - case TA1IV_TAIFG: - irq_events |= 1< 1000) { - // Time_Count = 0; - // __bic_SR_register_on_exit(LPM0_bits); // Clear CPUOFF bit from LPM0 - //} -} - -// ADC interrupt service routine -#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) -#pragma vector=ADC_VECTOR -__interrupt void ADC_ISR(void) -#elif defined(__GNUC__) -void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void) -#else -#error Compiler not supported! -#endif -{ - switch(__even_in_range(ADCIV,ADCIV_ADCIFG)) - { - case ADCIV_NONE: - break; - case ADCIV_ADCOVIFG: - break; - case ADCIV_ADCTOVIFG: - break; - case ADCIV_ADCHIIFG: - break; - case ADCIV_ADCLOIFG: - break; - case ADCIV_ADCINIFG: - break; - case ADCIV_ADCIFG: - ADC_Result = ADCMEM0; - irq_events |= 1< + +static volatile unsigned int ADC_Result; +static volatile unsigned int irq_events = 0; +enum {ev_btn1 = 0, ev_btn2, ev_pir1, ev_pir2, ev_tmr, ev_adc, ev_MAX}; + +#define PWM_ORDER 10 +#define PWM_HALF 5 +#define LIGHT_THRESHOLD 600 +#define TIME_ON 16 + +#ifdef ADCSC /* Let us hope that this is a "new" model */ +# define BIT_RL BIT0 +# define BIT_GL BIT1 +# define PBTN(x) P2##x +# define BIT_BTN BIT3 +# define HAVE_BTN2 +# define BIT_BTN2 BIT7 +#else +# define BIT_RL BIT0 +# define BIT_GL BIT6 +# define PBTN(x) P1##x +# define BIT_BTN BIT3 +# define BIT_BTN2 0 +#endif + +static int expon2(int duty) +{ + int shift = duty>>1; + int comp = 1<>1 : 0; + return (duty ? comp|extra : 0); +} + +int main(void) +{ + int Duty_Cycle = 0; + int Increment = 1; + unsigned int Time_Count = 0; + unsigned int Time_Left = 5; + unsigned int Time_Indicate = 2; + + WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer + // Configure GPIO Out + P1DIR |= BIT_RL|BIT_GL|BIT2; // Set LEDs & PWM to output direction + P1OUT &= ~(BIT_RL|BIT_GL); // LEDs off +#ifdef P1SEL1 + P1SEL1 |= BIT2; // PWM out +#else + P1SEL |= BIT2; // PWM out +#endif + + // Configure GPIO In + PBTN(DIR) &= ~(BIT_BTN|BIT_BTN2); // Buttons + PBTN(OUT) |= BIT_BTN|BIT_BTN2; // Pull up + PBTN(REN) |= BIT_BTN|BIT_BTN2; // Enable pull-up + PBTN(IES) |= BIT_BTN|BIT_BTN2; // INT on Hi->Lo edge + PBTN(IE) |= BIT_BTN|BIT_BTN2; // INT enable + + P2DIR &= ~(BIT4|BIT5); // PIR Sensors + P2OUT &= ~(BIT4|BIT5); // Pull down + P2REN |= BIT4|BIT5; // Enable pull-down + P2IES &= ~(BIT4|BIT5); // INT on Lo->Hi edge + P2IE |= BIT4|BIT5; // INT enable + + // Configure ADC10 + +#ifdef ADCPCTL4 /* Newer model */ + SYSCFG2 |= ADCPCTL4|ADCPCTL5; // disconnect pin 4 and 5 from GPIO + ADCCTL0 |= ADCSHT_2 | ADCON; // ADCON, S&H=16 ADC clks + ADCCTL1 |= ADCSHP; // ADCCLK = MODOSC; sampling timer + ADCCTL2 |= ADCRES; // 10-bit conversion results + ADCMCTL0 |= ADCINCH_4; // A4 ADC input select; Vref=AVCC + ADCIE |= ADCIE0; // Enable ADC conv complete interrupt + // channel 5 is unused, reserved for measuring current +#else + ADC10CTL0 = ADC10SHT_2 + ADC10ON + ADC10IE; // ADCON, S&H=16 ADC clks + ADC10CTL1 = INCH_4; // A4 ADC input select + // channel 5 is unused, reserved for measuring current +#endif + + // Timer and PWM + +#ifndef TASSEL__SMCLK +# define TASSEL__SMCLK TASSEL_2 +# define MC__UP MC_1 +# define MC__CONTINUOUS MC_2 +# define TA0CCR2 TA0CCR1 +# define TA0CCTL2 TA0CCTL1 +#endif + + // Configure timer A0 for PWM + TA0CCR0 = 1 << PWM_ORDER; // PWM Period 2^10 ca. 1 kHz + TA0CCR2 = 0; // CCR1 PWM duty cycle + TA0CCTL2 = OUTMOD_7; // CCR1 reset/set + TA0CTL = TASSEL__SMCLK | MC__UP | TACLR;// SMCLK, up mode + // SMCLK, no divider, up mode, no interrupt, clear TAR + + //Configure timer A1 for counting time + TA1CTL |= TASSEL__SMCLK | MC__CONTINUOUS | TACLR | TAIE; + // SMCLK, no divider, continuous mode, interrupt enable + +#ifdef LOCKLPM5 + // Disable the GPIO power-on default high-impedance mode to activate + // previously configured port settings + PM5CTL0 &= ~LOCKLPM5; +#endif + + while(1) + { + unsigned int events; + + _disable_interrupts(); + events = irq_events; + irq_events = 0; + _enable_interrupts(); + + // Button 2 or PIR events initiate light measurement + // and tuns on green or red led + if (events & (1< PWM_HALF) { + Time_Left = 0; + Increment = -1; + } else { + Time_Left = TIME_ON; + Increment = 1; + } + } + + // Timer event (100 ms) changed duty cycle and flashes red led + if (events & 1< 10) { + Time_Count = 0; + if (Time_Left) + Time_Left--; + else if (Duty_Cycle > 1) + Increment = -1; + } + if (Increment > 0) { + if (++Duty_Cycle >= (PWM_ORDER<<1)) { + Duty_Cycle = PWM_ORDER<<1; + Increment = 0; + } + } else if (Increment < 0) { + if (--Duty_Cycle < 1) { + Duty_Cycle = 0; + Increment = 0; + } + } else + continue; + + TA0CCR2 = expon2(Duty_Cycle); + } + __bis_SR_register(LPM0_bits | GIE); + __no_operation(); + } + return 0; /* not reached */ +} + +// TIMER interrupt routine +#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) +#pragma vector = TIMER1_A1_VECTOR +__interrupt void Timer_A (void) +#elif defined(__GNUC__) +void __attribute__ ((interrupt(TIMER1_A1_VECTOR))) Timer_A (void) +#else +#error Compiler not supported! +#endif +{ + switch(__even_in_range(TA1IV,TA1IV_TAIFG)) + { + case TA1IV_NONE: + break; // No interrupt + case TA1IV_TACCR1: + break; // CCR1 not used + case TA1IV_TACCR2: + break; // CCR2 not used + case TA1IV_TAIFG: + irq_events |= 1<