Project

General

Profile

Statistics
| Revision:

root / trunk / toolbox / main.c @ 207

History | View | Annotate | Download (8.37 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
 * @param which The buttons to read
106
 * @return TRUE if the buttons are pressed, FALSE otherwise
107
 */
108
inline uint8_t read_button(uint8_t which) {
109
    return (!(BUT_PORT & (which)));
110
}
111

    
112
/**
113
 * @brief Initialize the hardware timer to be a realtime clock
114
 *
115
 * This will set timer 1 to cause an interrupt every 1 second assuming
116
 * you are using a 8MHz clock. The global sec and min counters are 
117
 * reset as well.
118
 *
119
 * @return void
120
 */
121
void init_timer(void) {
122
    // Clear timmer on OCRA1 Compare match
123
    // No prescale
124
    TCCR1B |= _BV(WGM12) | _BV(CS12);
125
    
126
    // 1 second @ 8MHz clock
127
    OCR1A = 0x7A12;
128

    
129
    TIMSK = _BV(OCIE1A);
130

    
131
    sec = 0;
132
    min = 0;
133
}
134

    
135
/**
136
 * @brief Resets the timer
137
 * @return void
138
 */
139
void reset_timer(void) {
140
    sec = 0;
141
    min = 0;
142
}
143

    
144
/**
145
 * @brief Timer1 interrupt vector
146
 *
147
 * This counts the seconds and minute since the last reset. Automatically
148
 * resets the seconds once it rolls over to 60s and increments minutes.
149
 *
150
 * @note minutes may overflow if you let it run long enough. There are no
151
 * checks against this
152
 */
153
ISR(TIMER1_COMPA_vect) {
154
    if (sec == 59) {
155
        sec = 0;
156
        ++min;
157
    } else {
158
        ++sec;
159
    }
160
}
161

    
162

    
163
int main(void) {
164
    state_t state = wait;
165
    // This reads the node addr
166
    uint8_t addr = eeprom_read_byte((void*)EEPROM_ADDR);    
167
    uint8_t ms_timer=0;
168
    uint8_t mbuf[PROGD_PACKET_SIZE];    // For reading messages
169

    
170
        /***** Start Start-up Sequence *****/
171
    // We are initializing the pins and the RS485 in the bootloader
172
        sei();                                //Enable interrupts
173
        init_timer();                //Set registers for timer
174
        /***** End Start-up Sequence *****/
175

    
176
    uint8_t resp;
177
    
178
        while(1) {
179
        switch (state) {
180
            case wait:
181
                // Reset the lights and relay
182
                toggle_led(LED_RED, ON);
183
                toggle_led(LED_YELLOW | LED_GREEN, OFF);
184
                toggle_relay(OFF);
185

    
186
                // Wait for a packet
187
                resp = parse_packet(mbuf, addr);
188

    
189
                // Turn on the tool
190
                if (resp == TT_ON) {
191
                    send_packet(TT_ACK, addr);
192

    
193
                    toggle_led(LED_RED, OFF);
194
                    toggle_led(LED_YELLOW, ON);
195
                    state = pwron;
196
                    reset_timer();
197
                }
198
                break;
199
            case pwron:
200
                // Make sure the tool isn't on before we apply power
201
                    if (read_vac() == ON) {
202
                            ms_timer = 0;
203
                            state = idiot;
204
                            break;
205
                    }
206

    
207
                // Wait for a black button press
208
                if (read_button(BUT_BLACK)) {
209
                    toggle_led(LED_YELLOW, OFF);
210
                    toggle_led(LED_GREEN, ON);
211
                    toggle_relay(ON);
212

    
213
                    reset_timer();
214
                    state = toolon;
215
                // Timeout waiting for the user
216
                } else if ((read_button(BUT_RED)) || (min >= TWAIT)) {
217
                    state = off;
218
                }
219
                break;
220
            case idiot:
221
                // We can safely exit this state if the tool is switched off
222
                if (read_vac() == OFF) {
223
                    state = pwron;
224
                    toggle_led(LED_RED, OFF);
225
                    toggle_led(LED_YELLOW, ON);
226
                    break;
227
                }
228

    
229
                // The user has cancelled the tooltron request
230
                if (read_button(BUT_RED)) {
231
                    state = off;
232
                    break;
233
                }
234

    
235
                // Blink code
236
                if(ms_timer >= 100) {
237
                    toggle_led(LED_YELLOW, ON);
238
                    toggle_led(LED_RED, OFF);
239
            
240
                    if(ms_timer >= 200) {
241
                        ms_timer = 0;
242
                    }
243
                } else {
244
                    toggle_led(LED_YELLOW, OFF);
245
                    toggle_led(LED_RED, ON);
246
                }
247

    
248
                _delay_ms(2);
249
                ms_timer++;
250
                break;
251

    
252
            case toolon:
253
                // Give the tool power until the red button is pressed
254
                if ((read_button(BUT_RED)) && (read_vac() == OFF)) {
255
                        state = off;
256
                        toggle_relay(OFF);
257
                // Time is about to expire
258
                } else if (min >= TWARN) {
259
                    toggle_led(LED_GREEN, OFF);
260
                    state = warn;
261
                }
262
                break;
263

    
264
            case warn:
265
                // Blink the LED
266
                        if(ms_timer >= 100) {
267
                            toggle_led(LED_YELLOW, ON);
268
                
269
                            if(ms_timer >= 200) {
270
                                ms_timer = 0;
271
                            }
272
                        } else {
273
                            toggle_led(LED_YELLOW, OFF);
274
                        }
275

    
276
                // User turns off the tool if it's safe
277
                if (read_button(BUT_RED) && read_vac() == OFF) {
278
                    toggle_relay(OFF);
279
                    state = off;
280
                // Time extension
281
                } else if (read_button(BUT_BLACK)) {
282
                    toggle_led(LED_GREEN, ON);
283
                    toggle_led(LED_YELLOW, OFF);
284
                    reset_timer();
285
                    state = toolon;
286
                // Time expired and it's safe to turn off
287
                } else if ((min >= TMAX) && (read_vac() == OFF)) {
288
                    toggle_relay(OFF);
289
                    state = off;
290
                }
291

    
292
                        _delay_ms(2);
293
                        ms_timer++;
294

    
295
                break;
296
            case off:
297
                toggle_led(LED_GREEN | LED_YELLOW, OFF);
298
                toggle_led(LED_RED, ON);
299
                state = wait;
300
                break;
301
            default: state = wait;
302
        }     
303
        }
304
        
305
        return 0;
306
}