Statistics
| Revision:

root / trunk / toolbox / main.c @ 204

History | View | Annotate | Download (8.6 KB)

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