5d03cca04d33314f26f55b56db6791904824b907
[sensor-light.git] / msp430 / main.c
1 #include <msp430.h> 
2
3 static volatile unsigned int ADC_Result;
4 static volatile unsigned int irq_events = 0;
5 enum {ev_btn1 = 0, ev_btn2, ev_pir1, ev_pir2, ev_tmr, ev_adc, ev_MAX};
6
7 int main(void)
8 {
9         int Duty_Cycle = 1;
10         int Increment = 1;
11         unsigned int Time_Count = 0;
12         unsigned int Time_Left = 5;
13
14         WDTCTL = WDTPW | WDTHOLD;       // stop watchdog timer
15         // Configure GPIO Out
16         P1DIR |= BIT0|BIT1|BIT2;     // Set P1.0&1&2/LEDs to output direction
17         P1OUT &= ~(BIT0|BIT1);       // P1.0&1 LEDs off
18         P1SEL1 |= BIT2;              // P1.2 PWM out
19
20         // Configure GPIO In
21         P2DIR &= ~(BIT3|BIT7);       // Buttons
22         P2OUT |= BIT3|BIT7;          // Pull up
23         P2REN |= BIT3|BIT7;          // Enable pull-up
24         P2IES |= BIT3|BIT7;          // INT on Hi->Lo edge
25         P2IE  |= BIT3|BIT7;          // INT enable
26
27         P2DIR &= ~(BIT2|BIT5);       // PIR Sensors
28         P2OUT &= ~(BIT2|BIT5);       // Pull down
29         P2REN |= BIT2|BIT5;          // Enable pull-down
30         P2IES &= ~(BIT2|BIT5);       // INT on Lo->Hi edge
31         P2IE  |= BIT2|BIT5;          // INT enable
32         P2IFG = 0;                   // ??? Needed?
33
34         // Configure ADC A7 pin
35         SYSCFG2 |= ADCPCTL7;
36
37         // Configure ADC10
38         ADCCTL0 |= ADCSHT_2 | ADCON;        // ADCON, S&H=16 ADC clks
39         ADCCTL1 |= ADCSHP;                  // ADCCLK = MODOSC; sampling timer
40         ADCCTL2 |= ADCRES;                  // 10-bit conversion results
41         ADCMCTL0 |= ADCINCH_7;              // A7 ADC input select; Vref=AVCC
42         ADCIE |= ADCIE0;                    // Enable ADC conv complete interrupt
43
44         // Configure timer A0 for PWM
45         TA0CCR0 = 10000-1;                         // PWM Period
46         TA0CCTL2 = OUTMOD_7;                      // CCR2 reset/set
47         TA0CCR2 = 500;                     // CCR2 PWM duty cycle
48         TA0CTL = TASSEL__SMCLK | MC__UP | TACLR;  // SMCLK, up mode, clear TAR
49
50         //Configure timer A1 for counting time
51         TA1CTL |= TASSEL__SMCLK | MC__CONTINUOUS | TACLR | TAIE;     // SMCLK, no divider, continuous mode
52
53         // Disable the GPIO power-on default high-impedance mode to activate
54         // previously configured port settings
55         PM5CTL0 &= ~LOCKLPM5;
56
57         while(1)
58         {
59                 unsigned int events;
60
61                 _disable_interrupt();
62                 events = irq_events;
63                 irq_events = 0;
64                 _enable_interrupt();
65
66                 // Button 2 or PIR events initiate light measurement and tuns on green led
67                 if (events & (1<<ev_btn2|1<<ev_pir1|1<<ev_pir2)) {
68                         if (Duty_Cycle > 1) {
69                                 Time_Left = 15;
70                                 continue;
71                         }
72                         ADCCTL0 |= ADCENC | ADCSC;                       // Sampling and conversion start
73                         P1OUT |= BIT1;                                   // Set P1.1 LED on
74                 }
75
76                 // End of light measurement, set new Duty_Cycle and zero increment and tuns off green led
77                 if (events & 1<<ev_adc) {
78                         P1OUT &= ~BIT1;                                  // Clear P1.1 LED off
79                         if (Time_Left)
80                                 continue;
81                         if (ADC_Result < 200)
82                                 continue;
83                         Time_Left = 15;
84                         Increment = 1;
85                 }
86
87                 // Button 1 sets non-zero increment (and toggles it)
88                 if (events & 1<<ev_btn1) {
89                         if (Duty_Cycle > 5000) {
90                                 Time_Left = 0;
91                                 Increment = -1;
92                         } else {
93                                 Time_Left = 15;
94                                 Increment = 1;
95                         }
96                 }
97
98                 // Timer event (100 ms) changed duty cycle and flashes red led
99                 if (events & 1<<ev_tmr) {
100                         if (Time_Count++ > 10) {
101                                 Time_Count = 0;
102                                 P1OUT ^= BIT0;
103                                 if (Time_Left)
104                                         Time_Left--;
105                                 else if (Duty_Cycle > 1)
106                                         Increment = -1;
107                         }
108                         if (Increment == 0)
109                                 continue;
110                         else if (Increment > 0)
111                                 Duty_Cycle *= 2;
112                         else if (Increment < 0)
113                                 Duty_Cycle /= 2;
114                         if (Duty_Cycle < 1) {
115                                 Duty_Cycle = 1;
116                                 Increment = 0;
117                         }
118                         if (Duty_Cycle > (10000-1)) {
119                                 Duty_Cycle = 10000-1;
120                                 Increment = 0;
121                         }
122                         TA0CCR2 = Duty_Cycle;
123                 }
124                 __bis_SR_register(LPM0_bits | GIE);
125                 __no_operation();
126         }
127         retun 0; /* not reached */
128 }
129
130 // TIMER interrupt routine
131 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
132 #pragma vector = TIMER1_A1_VECTOR
133 __interrupt void Timer_A (void)
134 #elif defined(__GNUC__)
135 void __attribute__ ((interrupt(TIMER1_A1_VECTOR))) Timer_A (void)
136 #else
137 #error Compiler not supported!
138 #endif
139 {
140         switch(__even_in_range(TA1IV,TA1IV_TAIFG))
141         {
142                 case TA1IV_NONE:
143                         break;                               // No interrupt
144                 case TA1IV_TACCR1:
145                         break;                               // CCR1 not used
146                 case TA1IV_TACCR2:
147                         break;                               // CCR2 not used
148                 case TA1IV_TAIFG:
149                         irq_events |= 1<<ev_tmr;
150                         __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
151                         break;
152                 default:
153                         break;
154         }
155         //if (Time_Count++ > 1000) {
156         //    Time_Count = 0;
157         //    __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
158         //}
159 }
160
161 // ADC interrupt service routine
162 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
163 #pragma vector=ADC_VECTOR
164 __interrupt void ADC_ISR(void)
165 #elif defined(__GNUC__)
166 void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void)
167 #else
168 #error Compiler not supported!
169 #endif
170 {
171         switch(__even_in_range(ADCIV,ADCIV_ADCIFG))
172         {
173                 case ADCIV_NONE:
174                         break;
175                 case ADCIV_ADCOVIFG:
176                         break;
177                 case ADCIV_ADCTOVIFG:
178                         break;
179                 case ADCIV_ADCHIIFG:
180                         break;
181                 case ADCIV_ADCLOIFG:
182                         break;
183                 case ADCIV_ADCINIFG:
184                         break;
185                 case ADCIV_ADCIFG:
186                         ADC_Result = ADCMEM0;
187                         irq_events |= 1<<ev_adc;
188                         __bic_SR_register_on_exit(LPM0_bits);            // Clear CPUOFF bit from LPM0
189                         break;
190                 default:
191                         break;
192         }
193 }
194
195 // GPIO interrupt service routine
196 #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
197 #pragma vector=PORT2_VECTOR
198 __interrupt void Port_2(void)
199 #elif defined(__GNUC__)
200 void __attribute__ ((interrupt(PORT2_VECTOR))) Port_2 (void)
201 #else
202 #error Compiler not supported!
203 #endif
204 {
205         if (P2IFG & BIT3) {
206                 irq_events |= 1<<ev_btn1;
207                 P2IFG &= ~BIT3;                      // Clear P1.3 IFG
208         }
209         if (P2IFG & BIT7) {
210                 irq_events |= 1<<ev_btn2;
211                 P2IFG &= ~BIT7;                      // Clear P1.3 IFG
212         }
213         if (P2IFG & BIT2) {
214                 irq_events |= 1<<ev_pir1;
215                 P2IFG &= ~BIT2;                      // Clear P1.4 IFG
216         }
217         if (P2IFG & BIT5) {
218                 irq_events |= 1<<ev_pir2;
219                 P2IFG &= ~BIT5;                      // Clear P1.7 IFG
220         }
221         __bic_SR_register_on_exit(LPM3_bits);   // Exit LPM3
222 }