Project

General

Profile

Statistics
| Revision:

root / trunk / toolbox / main.c @ 292

History | View | Annotate | Download (8.79 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

    
36
/***
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
#define TWAIT   1
42
#define TWARN   1
43
#define TMAX    2
44

    
45
uint8_t sec;
46
uint8_t min;
47

    
48
typedef enum {
49
    wait,   // wait for a turn on packet
50
    pwron,  // poweron
51
    idiot,  // user tried to hit green with the machine switch on
52
    toolon, // tool on
53
    warn,   // time warning
54
    off     // tool off
55
} state_t;
56

    
57
/**
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
void toggle_led(uint8_t which, uint8_t state) {
68
    if (state == ON) {
69
        LED_PORT &= ~(which);
70
    } else {
71
        LED_PORT |= (which);
72
    }
73
}
74

    
75
/**
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
void toggle_relay(uint8_t state) {
82
    if (state == ON) {
83
        RELAY_PORT |= RELAY;
84
    } else {
85
        RELAY_PORT &= ~RELAY;
86
    }
87
}
88

    
89
/**
90
 * @brief Returns the current value of the AC voltage sense
91
 *
92
 * @return ON if AC voltage is detected, OFF otherwise
93
 */
94
inline uint8_t read_vac(void) {
95
    return (!(VAC_PORT & VAC_SENSE));
96
}
97

    
98
/**
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
 * 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
 * @param which The buttons to read
111
 * @return TRUE if the buttons are pressed, FALSE otherwise
112
 */
113
inline uint8_t read_button(uint8_t which) {
114
    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
}
124

    
125
/**
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
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
    OCR1A = 0x7A12;
141

    
142
    TIMSK = _BV(OCIE1A);
143

    
144
    sec = 0;
145
    min = 0;
146
}
147

    
148
/**
149
 * @brief Resets the timer
150
 * @return void
151
 */
152
void reset_timer(void) {
153
    sec = 0;
154
    min = 0;
155
}
156

    
157
/**
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
ISR(TIMER1_COMPA_vect) {
167
    if (sec == 59) {
168
        sec = 0;
169
        ++min;
170
    } else {
171
        ++sec;
172
    }
173
}
174

    
175

    
176
int main(void) {
177
    state_t state = wait;
178
    // This reads the node addr
179
    uint8_t addr = read_addr();
180
    uint8_t ms_timer=0;
181
    uint8_t mbuf[PROGD_PACKET_SIZE];    // For reading messages
182
    uint8_t len;
183

    
184
        /***** Start Start-up Sequence *****/
185
    // We are initializing the pins and the RS485 in the bootloader
186
        sei();                                //Enable interrupts
187
        init_timer();                //Set registers for timer
188
        /***** End Start-up Sequence *****/
189

    
190
    uint8_t resp;
191
    
192
        while(1) {
193
        switch (state) {
194
            case wait:
195
                // Reset the lights and relay
196
                toggle_led(LED_RED, ON);
197
                toggle_led(LED_YELLOW | LED_GREEN, OFF);
198
                toggle_relay(OFF);
199

    
200
                // Wait for a packet
201
                resp = parse_packet(mbuf, &len, addr);
202

    
203
                // Turn on the tool
204
                if (resp == TT_GRANT) {
205
                    send_packet(TT_ACK, addr, NULL, 0);
206

    
207
                    toggle_led(LED_RED, OFF);
208
                    toggle_led(LED_YELLOW, ON);
209
                    state = pwron;
210
                    reset_timer();
211
                } else if (resp == TT_PING) {
212
                    _delay_ms(50);
213
                    send_packet(TT_ACK, addr, NULL, 0);
214
                }
215
                break;
216
            case pwron:
217
                // 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

    
224
                // First check for timeout or red button press
225
                if ((read_button(BUT_RED)) || (min >= TWAIT)) {
226
                    state = off;
227
                }
228
                // If time is not expired, give access on green press
229
                else if (read_button(BUT_BLACK)) {
230
                    toggle_led(LED_YELLOW, OFF);
231
                    toggle_led(LED_GREEN, ON);
232
                    toggle_relay(ON);
233

    
234
                    reset_timer();
235
                    state = toolon;
236
                } 
237
                break;
238
            case idiot:
239
                // We can safely exit this state if the tool is switched off
240
                if (read_vac() == OFF) {
241
                    state = pwron;
242
                    toggle_led(LED_RED, OFF);
243
                    toggle_led(LED_YELLOW, ON);
244
                    break;
245
                }
246

    
247
                // The user has cancelled the tooltron request
248
                if (read_button(BUT_RED)) {
249
                    state = off;
250
                    break;
251
                }
252

    
253
                // Blink code
254
                if(ms_timer >= 100) {
255
                    toggle_led(LED_YELLOW, ON);
256
                    toggle_led(LED_RED, OFF);
257
            
258
                    if(ms_timer >= 200) {
259
                        ms_timer = 0;
260
                    }
261
                } else {
262
                    toggle_led(LED_YELLOW, OFF);
263
                    toggle_led(LED_RED, ON);
264
                }
265

    
266
                _delay_ms(2);
267
                ms_timer++;
268
                break;
269

    
270
            case toolon:
271
                // Give the tool power until the red button is pressed
272
                if ((read_button(BUT_RED)) && (read_vac() == OFF)) {
273
                        state = off;
274
                        toggle_relay(OFF);
275
                // Time is about to expire
276
                } else if (min >= TWARN) {
277
                    toggle_led(LED_GREEN, OFF);
278
                    state = warn;
279
                }
280
                break;
281

    
282
            case warn:
283
                // Blink the LED
284
                        if(ms_timer >= 100) {
285
                            toggle_led(LED_YELLOW, ON);
286
                
287
                            if(ms_timer >= 200) {
288
                                ms_timer = 0;
289
                            }
290
                        } else {
291
                            toggle_led(LED_YELLOW, OFF);
292
                        }
293

    
294
                // User turns off the tool if it's safe
295
                if (read_button(BUT_RED) && read_vac() == OFF) {
296
                    toggle_relay(OFF);
297
                    state = off;
298
                // Time extension
299
                } else if (read_button(BUT_BLACK)) {
300
                    toggle_led(LED_GREEN, ON);
301
                    toggle_led(LED_YELLOW, OFF);
302
                    reset_timer();
303
                    state = toolon;
304
                // Time expired and it's safe to turn off
305
                } else if ((min >= TMAX) && (read_vac() == OFF)) {
306
                    toggle_relay(OFF);
307
                    state = off;
308
                }
309

    
310
                        _delay_ms(2);
311
                        ms_timer++;
312

    
313
                break;
314
            case off:
315
                toggle_led(LED_GREEN | LED_YELLOW, OFF);
316
                toggle_led(LED_RED, ON);
317
                state = wait;
318
                break;
319
            default: state = wait;
320
        }     
321
        }
322
        
323
        return 0;
324
}