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