root / trunk / toolbox / main.c @ 227
History | View | Annotate | Download (8.89 KB)
1 | 139 | kwoo | /********
|
---|---|---|---|
2 | * This file is part of Tooltron.
|
||
3 | *
|
||
4 | * Tooltron is free software: you can redistribute it and/or modify
|
||
5 | * it under the terms of the Lesser GNU General Public License as published by
|
||
6 | * the Free Software Foundation, either version 3 of the License, or
|
||
7 | * (at your option) any later version.
|
||
8 | *
|
||
9 | * Tooltron is distributed in the hope that it will be useful,
|
||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
12 | * Lesser GNU General Public License for more details.
|
||
13 | * You should have received a copy of the Lesser GNU General Public License
|
||
14 | * along with Tooltron. If not, see <http://www.gnu.org/licenses/>.
|
||
15 | *
|
||
16 | * Copyright 2009 Kevin Woo <kwoo@2ndt.com>
|
||
17 | *
|
||
18 | ********/
|
||
19 | 2 | snidhiry | /** @file main.c
|
20 | * @brief Contains the main function for the toolbox code.
|
||
21 | *
|
||
22 | 191 | kwoo | * @author Suresh Nidhiry (snidhiry@andrew.cmu.edu)
|
23 | * @author Kevin Woo (kwoo@2ndt.com)
|
||
24 | 2 | snidhiry | */
|
25 | |||
26 | 6 | kwoo | //Includes
|
27 | #include <avr/io.h> |
||
28 | 8 | kwoo | #include <avr/interrupt.h> |
29 | 202 | kwoo | #include <avr/eeprom.h> |
30 | 114 | kwoo | #include <stdint.h> |
31 | #include <util/delay.h> |
||
32 | 191 | kwoo | #include <tooltron.h> |
33 | 204 | kwoo | #include <toolbox_pindefs.h> |
34 | 191 | kwoo | #include "jumptable.h" |
35 | 114 | kwoo | |
36 | 143 | bneuman | /***
|
37 | * TWAIT - minutes to wait before green button is pressed to kill power
|
||
38 | * TWARN - minutes until warning (blink yellow, allow more time with green button)
|
||
39 | * TMAX - minutes until power is killed (unless tool is on)
|
||
40 | */
|
||
41 | 129 | kwoo | #define TWAIT 1 |
42 | 123 | kwoo | #define TWARN 1 |
43 | #define TMAX 2 |
||
44 | |||
45 | uint8_t sec; |
||
46 | uint8_t min; |
||
47 | |||
48 | 114 | kwoo | typedef enum { |
49 | 202 | kwoo | wait, // wait for a turn on packet
|
50 | 114 | kwoo | pwron, // poweron
|
51 | 149 | bneuman | idiot, // user tried to hit green with the machine switch on
|
52 | 116 | kwoo | toolon, // tool on
|
53 | 129 | kwoo | warn, // time warning
|
54 | off // tool off
|
||
55 | 114 | kwoo | } state_t; |
56 | |||
57 | 202 | kwoo | /**
|
58 | * @brief Sets the LED to the specified state
|
||
59 | *
|
||
60 | * This sets LED which to the specified state. You can use this to set
|
||
61 | * multiple LEDs if you OR the LEDs desired into the which argument.
|
||
62 | *
|
||
63 | * @param which The LEDs to set
|
||
64 | * @parma state The state ON or OFF to set to the LEDs to
|
||
65 | * @return void
|
||
66 | */
|
||
67 | 115 | kwoo | void toggle_led(uint8_t which, uint8_t state) {
|
68 | 114 | kwoo | if (state == ON) {
|
69 | 202 | kwoo | LED_PORT &= ~(which); |
70 | 114 | kwoo | } else {
|
71 | 202 | kwoo | LED_PORT |= (which); |
72 | 114 | kwoo | } |
73 | } |
||
74 | |||
75 | 202 | kwoo | /**
|
76 | * @brief Sets the relay to a particular state
|
||
77 | *
|
||
78 | * @param state Sets the relay to either ON or OFF
|
||
79 | * @return void
|
||
80 | */
|
||
81 | 117 | kwoo | void toggle_relay(uint8_t state) {
|
82 | if (state == ON) {
|
||
83 | 202 | kwoo | RELAY_PORT |= RELAY; |
84 | 117 | kwoo | } else {
|
85 | 202 | kwoo | RELAY_PORT &= ~RELAY; |
86 | 117 | kwoo | } |
87 | } |
||
88 | |||
89 | 202 | kwoo | /**
|
90 | * @brief Returns the current value of the AC voltage sense
|
||
91 | *
|
||
92 | * @return ON if AC voltage is detected, OFF otherwise
|
||
93 | */
|
||
94 | 129 | kwoo | inline uint8_t read_vac(void) { |
95 | 202 | kwoo | return (!(VAC_PORT & VAC_SENSE));
|
96 | 129 | kwoo | } |
97 | |||
98 | 202 | kwoo | /**
|
99 | * @brief Returns the current value of the buttons
|
||
100 | *
|
||
101 | * You can read multiple buttons at once but it will only return TRUE
|
||
102 | * if all of the buttons are pressed. You should OR the buttons together
|
||
103 | * while passing them into which.
|
||
104 | *
|
||
105 | 227 | bneuman | * Software debounce is written in to protect against vibration
|
106 | * transients, definable by BUTTON_DEBOUNCE. Specifically, for the
|
||
107 | * button to not be pressed it only needs to read 0 once, but needs to
|
||
108 | * read 1 BUTTON_DEBONCE times in a row to return TRUE.
|
||
109 | *
|
||
110 | 202 | kwoo | * @param which The buttons to read
|
111 | * @return TRUE if the buttons are pressed, FALSE otherwise
|
||
112 | */
|
||
113 | 115 | kwoo | inline uint8_t read_button(uint8_t which) {
|
114 | 227 | bneuman | uint8_t count = 0;
|
115 | |||
116 | while(!(BUT_PORT & (which))){
|
||
117 | if(++count > BUTTON_DEBOUNCE) {
|
||
118 | return TRUE;
|
||
119 | } |
||
120 | } |
||
121 | |||
122 | return FALSE;
|
||
123 | 115 | kwoo | } |
124 | |||
125 | 202 | kwoo | /**
|
126 | * @brief Initialize the hardware timer to be a realtime clock
|
||
127 | *
|
||
128 | * This will set timer 1 to cause an interrupt every 1 second assuming
|
||
129 | * you are using a 8MHz clock. The global sec and min counters are
|
||
130 | * reset as well.
|
||
131 | *
|
||
132 | * @return void
|
||
133 | */
|
||
134 | 123 | kwoo | void init_timer(void) { |
135 | // Clear timmer on OCRA1 Compare match
|
||
136 | // No prescale
|
||
137 | TCCR1B |= _BV(WGM12) | _BV(CS12); |
||
138 | |||
139 | // 1 second @ 8MHz clock
|
||
140 | 202 | kwoo | OCR1A = 0x7A12;
|
141 | 123 | kwoo | |
142 | TIMSK = _BV(OCIE1A); |
||
143 | |||
144 | sec = 0;
|
||
145 | min = 0;
|
||
146 | } |
||
147 | |||
148 | 202 | kwoo | /**
|
149 | * @brief Resets the timer
|
||
150 | * @return void
|
||
151 | */
|
||
152 | 123 | kwoo | void reset_timer(void) { |
153 | sec = 0;
|
||
154 | min = 0;
|
||
155 | } |
||
156 | |||
157 | 202 | kwoo | /**
|
158 | * @brief Timer1 interrupt vector
|
||
159 | *
|
||
160 | * This counts the seconds and minute since the last reset. Automatically
|
||
161 | * resets the seconds once it rolls over to 60s and increments minutes.
|
||
162 | *
|
||
163 | * @note minutes may overflow if you let it run long enough. There are no
|
||
164 | * checks against this
|
||
165 | */
|
||
166 | 123 | kwoo | ISR(TIMER1_COMPA_vect) { |
167 | if (sec == 59) { |
||
168 | sec = 0;
|
||
169 | 202 | kwoo | ++min; |
170 | 123 | kwoo | } else {
|
171 | 202 | kwoo | ++sec; |
172 | 123 | kwoo | } |
173 | } |
||
174 | |||
175 | |||
176 | 202 | kwoo | int main(void) { |
177 | state_t state = wait; |
||
178 | // This reads the node addr
|
||
179 | uint8_t addr = eeprom_read_byte((void*)EEPROM_ADDR);
|
||
180 | 148 | bneuman | uint8_t ms_timer=0;
|
181 | 202 | kwoo | uint8_t mbuf[PROGD_PACKET_SIZE]; // For reading messages
|
182 | 218 | bneuman | uint8_t len; |
183 | 2 | snidhiry | |
184 | 6 | kwoo | /***** Start Start-up Sequence *****/
|
185 | 202 | kwoo | // We are initializing the pins and the RS485 in the bootloader
|
186 | 8 | kwoo | sei(); //Enable interrupts
|
187 | 123 | kwoo | init_timer(); //Set registers for timer
|
188 | 6 | kwoo | /***** End Start-up Sequence *****/
|
189 | 3 | kwoo | |
190 | 202 | kwoo | uint8_t resp; |
191 | 114 | kwoo | |
192 | 6 | kwoo | while(1) { |
193 | 114 | kwoo | switch (state) {
|
194 | 202 | kwoo | case wait:
|
195 | // Reset the lights and relay
|
||
196 | 150 | bneuman | toggle_led(LED_RED, ON); |
197 | 202 | kwoo | toggle_led(LED_YELLOW | LED_GREEN, OFF); |
198 | 117 | kwoo | toggle_relay(OFF); |
199 | 114 | kwoo | |
200 | 202 | kwoo | // Wait for a packet
|
201 | 218 | bneuman | resp = parse_packet(mbuf, &len, addr); |
202 | 114 | kwoo | |
203 | 202 | kwoo | // Turn on the tool
|
204 | if (resp == TT_ON) {
|
||
205 | 217 | kwoo | send_packet(TT_ACK, addr, NULL, 0); |
206 | 114 | kwoo | |
207 | 202 | kwoo | toggle_led(LED_RED, OFF); |
208 | toggle_led(LED_YELLOW, ON); |
||
209 | state = pwron; |
||
210 | reset_timer(); |
||
211 | 217 | kwoo | } else if (resp == TT_PING) { |
212 | 223 | kwoo | _delay_ms(50);
|
213 | 217 | kwoo | send_packet(TT_ACK, addr, NULL, 0); |
214 | 114 | kwoo | } |
215 | break;
|
||
216 | 116 | kwoo | case pwron:
|
217 | 202 | kwoo | // Make sure the tool isn't on before we apply power
|
218 | if (read_vac() == ON) {
|
||
219 | ms_timer = 0;
|
||
220 | state = idiot; |
||
221 | break;
|
||
222 | } |
||
223 | 149 | bneuman | |
224 | 202 | kwoo | // Wait for a black button press
|
225 | 149 | bneuman | if (read_button(BUT_BLACK)) {
|
226 | 115 | kwoo | toggle_led(LED_YELLOW, OFF); |
227 | toggle_led(LED_GREEN, ON); |
||
228 | 149 | bneuman | toggle_relay(ON); |
229 | |||
230 | reset_timer(); |
||
231 | state = toolon; |
||
232 | 202 | kwoo | // Timeout waiting for the user
|
233 | 129 | kwoo | } else if ((read_button(BUT_RED)) || (min >= TWAIT)) { |
234 | state = off; |
||
235 | 114 | kwoo | } |
236 | break;
|
||
237 | 202 | kwoo | case idiot:
|
238 | // We can safely exit this state if the tool is switched off
|
||
239 | if (read_vac() == OFF) {
|
||
240 | state = pwron; |
||
241 | toggle_led(LED_RED, OFF); |
||
242 | toggle_led(LED_YELLOW, ON); |
||
243 | break;
|
||
244 | } |
||
245 | 148 | bneuman | |
246 | 202 | kwoo | // The user has cancelled the tooltron request
|
247 | if (read_button(BUT_RED)) {
|
||
248 | state = off; |
||
249 | break;
|
||
250 | } |
||
251 | 149 | bneuman | |
252 | 202 | kwoo | // Blink code
|
253 | if(ms_timer >= 100) { |
||
254 | toggle_led(LED_YELLOW, ON); |
||
255 | toggle_led(LED_RED, OFF); |
||
256 | |||
257 | if(ms_timer >= 200) { |
||
258 | ms_timer = 0;
|
||
259 | } |
||
260 | } else {
|
||
261 | toggle_led(LED_YELLOW, OFF); |
||
262 | toggle_led(LED_RED, ON); |
||
263 | } |
||
264 | 148 | bneuman | |
265 | 202 | kwoo | _delay_ms(2);
|
266 | ms_timer++; |
||
267 | break;
|
||
268 | 148 | bneuman | |
269 | 116 | kwoo | case toolon:
|
270 | 202 | kwoo | // Give the tool power until the red button is pressed
|
271 | 129 | kwoo | if ((read_button(BUT_RED)) && (read_vac() == OFF)) {
|
272 | state = off; |
||
273 | toggle_relay(OFF); |
||
274 | 202 | kwoo | // Time is about to expire
|
275 | 123 | kwoo | } else if (min >= TWARN) { |
276 | toggle_led(LED_GREEN, OFF); |
||
277 | state = warn; |
||
278 | 116 | kwoo | } |
279 | break;
|
||
280 | 123 | kwoo | |
281 | 116 | kwoo | case warn:
|
282 | 202 | kwoo | // Blink the LED
|
283 | if(ms_timer >= 100) { |
||
284 | toggle_led(LED_YELLOW, ON); |
||
285 | 148 | bneuman | |
286 | 202 | kwoo | if(ms_timer >= 200) { |
287 | ms_timer = 0;
|
||
288 | } |
||
289 | } else {
|
||
290 | toggle_led(LED_YELLOW, OFF); |
||
291 | } |
||
292 | 123 | kwoo | |
293 | 202 | kwoo | // User turns off the tool if it's safe
|
294 | 150 | bneuman | if (read_button(BUT_RED) && read_vac() == OFF) {
|
295 | 123 | kwoo | toggle_relay(OFF); |
296 | 129 | kwoo | state = off; |
297 | 202 | kwoo | // Time extension
|
298 | 116 | kwoo | } else if (read_button(BUT_BLACK)) { |
299 | 123 | kwoo | toggle_led(LED_GREEN, ON); |
300 | toggle_led(LED_YELLOW, OFF); |
||
301 | reset_timer(); |
||
302 | 116 | kwoo | state = toolon; |
303 | 202 | kwoo | // Time expired and it's safe to turn off
|
304 | 129 | kwoo | } else if ((min >= TMAX) && (read_vac() == OFF)) { |
305 | toggle_relay(OFF); |
||
306 | state = off; |
||
307 | } |
||
308 | 148 | bneuman | |
309 | 202 | kwoo | _delay_ms(2);
|
310 | ms_timer++; |
||
311 | 148 | bneuman | |
312 | 116 | kwoo | break;
|
313 | 129 | kwoo | case off:
|
314 | 202 | kwoo | toggle_led(LED_GREEN | LED_YELLOW, OFF); |
315 | 129 | kwoo | toggle_led(LED_RED, ON); |
316 | 202 | kwoo | state = wait; |
317 | 129 | kwoo | break;
|
318 | 202 | kwoo | default: state = wait;
|
319 | 123 | kwoo | } |
320 | 6 | kwoo | } |
321 | |||
322 | return 0; |
||
323 | } |