comparison main.c @ 2:0a6cbbb8c2b7

mostly there
author Matt Johnston <matt@ucc.asn.au>
date Mon, 03 Jun 2013 23:29:13 +0800
parents e23c1b6f6080
children fd28c7358ce8
comparison
equal deleted inserted replaced
1:e23c1b6f6080 2:0a6cbbb8c2b7
11 #include <avr/eeprom.h> 11 #include <avr/eeprom.h>
12 #include <avr/wdt.h> 12 #include <avr/wdt.h>
13 #include <util/atomic.h> 13 #include <util/atomic.h>
14 #include <util/crc16.h> 14 #include <util/crc16.h>
15 15
16 #include "hmac-sha1.h"
17
16 //#include "simple_ds18b20.h" 18 //#include "simple_ds18b20.h"
17 //#include "onewire.h" 19 //#include "onewire.h"
18 20
19 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) 21 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
20 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) 22 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
21 23
22 // TICK should be 8 or less (8 untested). all timers need 24 // TICK should be 8 or less (8 untested). all timers need
23 // to be a multiple. 25 // to be a multiple.
24 26
25 #define TICK 1 27 #define TICK 1
26 // we have 1024 prescaler, 32768 crystal. 28 #define SLEEP_COMPARE (2000000/64) // == 31250 exactly
27 #define SLEEP_COMPARE (32*TICK-1) 29 #define NKEYS 6
28
29 #define KEYLEN 20 30 #define KEYLEN 20
30
31 #define VALUE_NOSENSOR 0x07D0 // 125 degrees
32 #define VALUE_BROKEN 0x07D1 // 125.0625
33
34 #define OVERSHOOT_MAX_DIV 1800.0 // 30 mins
35 #define WORT_INVALID_TIME 900 // 15 mins
36 // fridge min/max are only used if the wort sensor is invalid
37 #define FRIDGE_AIR_MIN_RANGE 40 // 4º
38 #define FRIDGE_AIR_MAX_RANGE 40 // 4º
39 31
40 #define BAUD 19200 32 #define BAUD 19200
41 #define UBRR ((F_CPU)/8/(BAUD)-1) 33 #define UBRR ((F_CPU)/8/(BAUD)-1)
34
35 // XXX
36 #define PORT_PI_BOOT PORTD
37 #define DDR_PI_BOOT DDRD
38 #define PIN_PI_BOOT PD7
39
40 // XXX
41 #define PORT_PI_RESET PORTD
42 #define DDR_PI_RESET DDRD
43 #define PIN_PI_RESET PD6
44
42 45
43 #define PORT_LED PORTC 46 #define PORT_LED PORTC
44 #define DDR_LED DDRC 47 #define DDR_LED DDRC
45 #define PIN_LED PC4 48 #define PIN_LED PC4
46
47 #define PORT_SHDN PORTD
48 #define DDR_SHDN DDRD
49 #define PIN_SHDN PD7
50
51 #define PORT_FRIDGE PORTD
52 #define DDR_FRIDGE DDRD
53 #define PIN_FRIDGE PD6
54
55 // total amount of 16bit values available for measurements.
56 // adjust emperically, be sure to allow enough stack space too
57 #define TOTAL_MEASUREMENTS 800
58
59 // each sensor slot uses 8 bytes
60 #define MAX_SENSORS 6
61
62 // fixed at 8, have a shorter name
63 #define ID_LEN OW_ROMCODE_SIZE
64 49
65 // #define HAVE_UART_ECHO 50 // #define HAVE_UART_ECHO
66 51
67 // stores a value of clock_epoch combined with the remainder of TCNT2, 52 // stores a value of clock_epoch combined with the remainder of TCNT2,
68 // for 1/32 second accuracy 53 // for 1/32 second accuracy
73 uint8_t rem; 58 uint8_t rem;
74 }; 59 };
75 60
76 // eeprom-settable parameters, default values defined here. 61 // eeprom-settable parameters, default values defined here.
77 // all timeouts should be a multiple of TICK 62 // all timeouts should be a multiple of TICK
78 static uint32_t watchdog_long_limit = 60*60*24; 63 static uint32_t watchdog_long_limit = (60L*60*24);
79 static uint32_t watchdog_short_limit = 0; 64 static uint32_t watchdog_short_limit = 0;
80 static uint32_t newboot_limit = 60*10; 65 static uint32_t newboot_limit = 60*10;
81 66
82 // avr proves itself 67 // avr proves itself
83 static uint8_t avr_keys[NKEYS][KEYLEN] = {0}; 68 static uint8_t avr_keys[NKEYS][KEYLEN] = {{0}};
84
85 69
86 // ---- Atomic guards required accessing these variables 70 // ---- Atomic guards required accessing these variables
87 // clock_epoch in seconds 71 // clock_epoch in seconds
88 static uint32_t clock_epoch; 72 static uint32_t clock_epoch;
89 // watchdog counts up 73 // watchdog counts up
90 static uint32_t watchdog_long_count; 74 static uint32_t watchdog_long_count;
91 static uint32_t watchdog_short_count; 75 static uint32_t watchdog_short_count;
92 // newboot counts down - it's a one-shot 76 // newboot counts down
93 static uint32_t newboot_count; 77 static uint32_t newboot_count;
78 // oneshot counts down
79 static uint32_t oneshot_count;
80
94 // ---- End atomic guards required 81 // ---- End atomic guards required
95 82
96 // boolean flags 83 // boolean flags
97 static uint8_t watchdog_long_hit; 84 static uint8_t watchdog_long_hit;
98 static uint8_t watchdog_short_hit; 85 static uint8_t watchdog_short_hit;
99 static uint8_t newboot_hit; 86 static uint8_t newboot_hit;
87 static uint8_t oneshot_hit;
100 88
101 static uint8_t readpos; 89 static uint8_t readpos;
102 static char readbuf[50]; 90 static char readbuf[50];
103 static uint8_t have_cmd; 91 static uint8_t have_cmd;
104 92
105 int uart_putchar(char c, FILE *stream); 93 int uart_putchar(char c, FILE *stream);
106 static void long_delay(int ms); 94 static void long_delay(int ms);
107 static void blink(); 95 static void blink();
108 static uint16_t adc_vcc(); 96 static uint16_t adc_vcc();
97 static void set_pi_boot_normal(uint8_t normal);
109 98
110 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, 99 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
111 _FDEV_SETUP_WRITE); 100 _FDEV_SETUP_WRITE);
112 101
113 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/ 102 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/
121 struct __attribute__ ((__packed__)) __eeprom_data { 110 struct __attribute__ ((__packed__)) __eeprom_data {
122 uint32_t watchdog_long_limit; 111 uint32_t watchdog_long_limit;
123 uint32_t watchdog_short_limit; 112 uint32_t watchdog_short_limit;
124 uint32_t newboot_limit; 113 uint32_t newboot_limit;
125 114
126 uint8_t avr_key[NKEYS][KEYLEN]; 115 uint8_t avr_keys[NKEYS][KEYLEN];
127 116
128 uint16_t magic; 117 uint16_t magic;
129 }; 118 };
130
131 static void deep_sleep();
132 119
133 // Very first setup 120 // Very first setup
134 static void 121 static void
135 setup_chip() 122 setup_chip()
136 { 123 {
145 // set to 8S, in case sha1 is slow etc. 132 // set to 8S, in case sha1 is slow etc.
146 wdt_enable(WDTO_8S); 133 wdt_enable(WDTO_8S);
147 134
148 // Set clock to 2mhz 135 // Set clock to 2mhz
149 CLKPR = _BV(CLKPCE); 136 CLKPR = _BV(CLKPCE);
150 // divide by 4
151 CLKPR = _BV(CLKPS1); 137 CLKPR = _BV(CLKPS1);
152 138
153 // enable pullups 139 // enable pullups
154 // XXX matt pihelp 140 // XXX matt pihelp
155 PORTB = 0xff; // XXX change when using SPI 141 PORTB = 0xff; // XXX change when using SPI
186 } 172 }
187 173
188 static void 174 static void
189 setup_tick_counter() 175 setup_tick_counter()
190 { 176 {
177 // set up counter1
178
191 // set up counter2. 179 // set up counter2.
192 // COM21 COM20 Set OC2 on Compare Match (p116) 180 // COM21 COM20 Set OC2 on Compare Match (p116)
193 // WGM21 Clear counter on compare 181 // WGM21 Clear counter on compare
194 //TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); 182 //TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21);
195 // toggle on match 183 // toggle on match
196 TCCR2A = _BV(COM2A0); 184 TCCR1A = _BV(COM1A0);
197 // CS22 CS21 CS20 clk/1024 185 // systemclock/1024
198 TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); 186 TCCR1B = _BV(CS12) | _BV(CS10);
199 // set async mode 187 TCNT1 = 0;
200 ASSR |= _BV(AS2); 188 OCR1A = SLEEP_COMPARE;
201 TCNT2 = 0;
202 OCR2A = SLEEP_COMPARE;
203 // interrupt 189 // interrupt
204 TIMSK2 = _BV(OCIE2A); 190 TIMSK1 = _BV(OCIE1A);
205 } 191 }
206 192
207 static void 193 static void
208 uart_on() 194 uart_on()
209 { 195 {
217 // set 2x clock, improves accuracy of UBRR 203 // set 2x clock, improves accuracy of UBRR
218 UCSR0A |= _BV(U2X0); 204 UCSR0A |= _BV(U2X0);
219 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); 205 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0);
220 //8N1 206 //8N1
221 UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); 207 UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);
222 uart_enabled = 1;
223 } 208 }
224 209
225 static void 210 static void
226 uart_off() 211 uart_off()
227 { 212 {
228 // Turn off interrupts and disable tx/rx 213 // Turn off interrupts and disable tx/rx
229 UCSR0B = 0; 214 UCSR0B = 0;
230 uart_enabled = 0;
231 215
232 // Power reduction register 216 // Power reduction register
233 PRR |= _BV(PRUSART0); 217 PRR |= _BV(PRUSART0);
234 } 218 }
235 219
236 int 220 int
237 uart_putchar(char c, FILE *stream) 221 uart_putchar(char c, FILE *stream)
238 { 222 {
239 if (!uart_enabled)
240 {
241 return EOF;
242 }
243 // XXX could perhaps sleep in the loop for power. 223 // XXX could perhaps sleep in the loop for power.
244 if (c == '\n') 224 if (c == '\n')
245 { 225 {
246 loop_until_bit_is_set(UCSR0A, UDRE0); 226 loop_until_bit_is_set(UCSR0A, UDRE0);
247 UDR0 = '\r'; 227 UDR0 = '\r';
248 } 228 }
249 loop_until_bit_is_set(UCSR0A, UDRE0); 229 loop_until_bit_is_set(UCSR0A, UDRE0);
250 UDR0 = c; 230 UDR0 = c;
251 if (stream == crc_stdout)
252 {
253 crc_out = _crc_ccitt_update(crc_out, c);
254 }
255 if (c == '\r') 231 if (c == '\r')
256 { 232 {
257 loop_until_bit_is_set(UCSR0A, UDRE0); 233 loop_until_bit_is_set(UCSR0A, UDRE0);
258 UDR0 = '\n'; 234 UDR0 = '\n';
259 if (stream == crc_stdout)
260 {
261 crc_out = _crc_ccitt_update(crc_out, '\n');
262 }
263 } 235 }
264 return (unsigned char)c; 236 return (unsigned char)c;
265 } 237 }
266 238
267 static void 239 static void
272 cli(); // disable interrupts 244 cli(); // disable interrupts
273 wdt_enable(WDTO_15MS); // enable watchdog 245 wdt_enable(WDTO_15MS); // enable watchdog
274 while(1); // wait for watchdog to reset processor 246 while(1); // wait for watchdog to reset processor
275 } 247 }
276 248
249 static void
250 cmd_newboot()
251 {
252 set_pi_boot_normal(1);
253 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
254 {
255 newboot_count = newboot_limit;
256 }
257 printf_P(PSTR("newboot for %d secs"), newboot_limit);
258 }
259
277 260
278 261
279 static void 262 static void
280 cmd_get_params() 263 cmd_get_params()
281 { 264 {
282 uint32_t cur_watchdog_long, cur_watchdog_short, cur_newboot; 265 uint32_t cur_watchdog_long, cur_watchdog_short, cur_newboot, cur_oneshot;
283 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 266 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
284 { 267 {
285 cur_watchdog_long = watchdot_long_count; 268 cur_watchdog_long = watchdog_long_count;
286 cur_watchdog_short = watchdot_short_count; 269 cur_watchdog_short = watchdog_short_count;
287 cur_newboot = newboot_limit_count; 270 cur_newboot = newboot_count;
288 } 271 cur_oneshot = oneshot_count;
289 272 }
290 printf_P(PSTR("limit (count) : watchdog_long %lu (%lu) watchdog_short %lu (%lu) newboot %lu (%lu)\n"), 273
274 printf_P(PSTR("limit (count) : watchdog_long %lu (%lu) watchdog_short %lu (%lu) newboot %lu (%lu) oneshot (%lu)\n"),
291 watchdog_long_limit, 275 watchdog_long_limit,
292 watchdog_long_count, 276 cur_watchdog_long,
293 watchdog_short_limit, 277 watchdog_short_limit,
294 watchdog_short_count, 278 cur_watchdog_short,
295 newboot_limit, 279 newboot_limit,
296 newboot_count); 280 cur_newboot,
281 cur_oneshot);
297 } 282 }
298 283
299 static void 284 static void
300 cmd_set_params(const char *params) 285 cmd_set_params(const char *params)
301 { 286 {
344 return c-'A' + 0xa; 329 return c-'A' + 0xa;
345 } 330 }
346 return 0; 331 return 0;
347 } 332 }
348 333
334 static void
335 printhex_nibble(const unsigned char b, FILE *stream)
336 {
337 unsigned char c = b & 0x0f;
338 if ( c > 9 ) {
339 c += 'A'-10;
340 }
341 else {
342 c += '0';
343 }
344 fputc(c, stream);
345 }
346
347 void
348 printhex_byte(const unsigned char b, FILE *stream)
349 {
350 printhex_nibble( b >> 4, stream);
351 printhex_nibble( b, stream);
352 }
353
354 void
355 printhex(uint8_t *id, uint8_t n, FILE *stream)
356 {
357 for (uint8_t i = 0; i < n; i++)
358 {
359 if (i > 0)
360 {
361 fputc(' ', stream);
362 }
363 printhex_byte(id[i], stream);
364 }
365 }
366
367 static int8_t
368 parse_key(const char *params, uint8_t *key_index, uint8_t bytes[KEYLEN])
369 {
370 // "N HEXKEY"
371 if (strlen(params) != KEYLEN*2+2) {
372 printf_P(PSTR("Wrong length key\n"));
373 return -1;
374 }
375
376 if (params[1] != ' ')
377 {
378 printf_P(PSTR("Missing space\n"));
379 return -1;
380 }
381
382 *key_index = from_hex(params[0]);
383 if (*key_index >= NKEYS)
384 {
385 printf_P(PSTR("Bad key index %d, max %d\n"), *key_index, NKEYS);
386 return -1;
387 }
388
389 for (int i = 0, p = 0; i < KEYLEN; i++, p += 2)
390 {
391 bytes[i] = (from_hex(params[p+2]) << 4) | from_hex(params[p+3]);
392 }
393 return 0;
394 }
395
349 static void 396 static void
350 cmd_set_avr_key(const char *params) 397 cmd_set_avr_key(const char *params)
351 { 398 {
352 // "N HEXKEY" 399 uint8_t new_key[KEYLEN];
353 if (strlen(params)) != KEYLEN*2+2) { 400 uint8_t key_index;
354 printf_P(PSTR("Wrong length key\n")); 401 if (parse_key(params, &key_index, new_key) != 0)
402 {
355 return; 403 return;
356 } 404 }
357 405 memcpy(avr_keys[key_index], new_key, sizeof(new_key));
358 uint8_t new_key[KEYLEN]; 406 eeprom_write(avr_keys, avr_keys);
359 for (int i = 0, p = 0; i < KEYLEN; i++, p += 2) 407 }
360 { 408
361 new_key[i] = (fromhex(params[p]) << 4) | fromhex(params[p+1]); 409 static void
362 } 410 cmd_hmac(const char *params)
411 {
412 uint8_t data[KEYLEN];
413 uint8_t key_index;
414 if (parse_key(params, &key_index, data) != 0)
415 {
416 printf_P(PSTR("FAIL: Bad input\n"));
417 }
418
419 hmac_sha1_ctx_t ctx;
420 hmac_sha1_init(&ctx, avr_keys[key_index], KEYLEN);
421 hmac_sha1_lastBlock(&ctx, data, KEYLEN);
422 hmac_sha1_final(data, &ctx);
423
424 printf_P(PSTR("HMAC: "));
425 printhex(data, KEYLEN, stdout);
426 fputc('\n', stdout);
427 }
428
429 static void
430 cmd_oneshot_reboot(const char *params)
431 {
432 uint32_t new_delay = strtoul(params, NULL, 10);
433 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
434 {
435 oneshot_count = new_delay;
436 }
437 printf_P(PSTR("oneshot delay %lu\n"), new_delay);
363 } 438 }
364 439
365 static void 440 static void
366 load_params() 441 load_params()
367 { 442 {
369 eeprom_read(magic, magic); 444 eeprom_read(magic, magic);
370 if (magic == EXPECT_MAGIC) 445 if (magic == EXPECT_MAGIC)
371 { 446 {
372 eeprom_read(watchdog_long_limit, watchdog_long_limit); 447 eeprom_read(watchdog_long_limit, watchdog_long_limit);
373 eeprom_read(watchdog_short_limit, watchdog_short_limit); 448 eeprom_read(watchdog_short_limit, watchdog_short_limit);
374 eeprom_read(netboot_limit); 449 eeprom_read(newboot_limit, newboot_limit);
375 eeprom_read(avr_key);
376 } 450 }
377 } 451
378 452 eeprom_read(avr_keys, avr_keys);
379 // returns true if eeprom was written 453 }
380 static bool 454
381 set_initial_eeprom() 455 static void
382 { 456 cmd_vcc()
383 uint16_t magic; 457 {
384 eeprom_read(magic, magic); 458 uint16_t vcc = adc_vcc();
385 if (magic == EXPECT_MAGIC) 459 printf_P("vcc: %u mV\n", vcc);
386 {
387 return false;
388 }
389
390 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
391 {
392 eeprom_write(measure_wake, measure_wake);
393 eeprom_write(comms_wake, comms_wake);
394 eeprom_write(wake_secs, wake_secs);
395 eeprom_write(fridge_setpoint, fridge_setpoint);
396 eeprom_write(fridge_difference, fridge_difference);
397 eeprom_write(fridge_delay, fridge_delay);
398 eeprom_write(overshoot_delay, overshoot_delay);
399 eeprom_write(overshoot_factor, overshoot_factor);
400 magic = EXPECT_MAGIC;
401 eeprom_write(magic, magic);
402 }
403
404 return true;
405 } 460 }
406 461
407 static void 462 static void
408 read_handler() 463 read_handler()
409 { 464 {
410 if (strcmp_P(readbuf, PSTR("fetch")) == 0) 465 if (strcmp_P(readbuf, PSTR("get_params")) == 0)
411 {
412 cmd_fetch();
413 }
414 else if (strcmp_P(readbuf, PSTR("clear")) == 0)
415 {
416 cmd_clear();
417 }
418 else if (strcmp_P(readbuf, PSTR("btoff")) == 0)
419 {
420 cmd_btoff();
421 }
422 else if (strcmp_P(readbuf, PSTR("measure")) == 0)
423 {
424 cmd_measure();
425 }
426 else if (strcmp_P(readbuf, PSTR("sensors")) == 0)
427 {
428 cmd_sensors();
429 }
430 else if (strcmp_P(readbuf, PSTR("get_params")) == 0)
431 { 466 {
432 cmd_get_params(); 467 cmd_get_params();
433 } 468 }
434 else if (strncmp_P(readbuf, PSTR("set_params "), 11) == 0) 469 else if (strncmp_P(readbuf, PSTR("set_params "), 11) == 0)
435 { 470 {
436 cmd_set_params(&readbuf[11]); 471 cmd_set_params(&readbuf[11]);
437 } 472 }
438 else if (strcmp_P(readbuf, PSTR("awake")) == 0) 473 else if (strncmp_P(readbuf, PSTR("set_key "), 8) == 0)
439 { 474 {
440 cmd_awake(); 475 cmd_set_avr_key(&readbuf[8]);
441 } 476 }
442 else if (strncmp_P(readbuf, PSTR("fridge_setpoint "), 16) == 0) 477 else if (strncmp_P(readbuf, PSTR("oneshot "), 8) == 0)
443 { 478 {
444 cmd_set_fridge_setpoint(&readbuf[16]); 479 cmd_oneshot_reboot(&readbuf[8]);
445 } 480 }
446 else if (strncmp_P(readbuf, PSTR("fridge_diff "), 12) == 0) 481 else if (strncmp_P(readbuf, PSTR("hmac "), 5) == 0)
447 { 482 {
448 cmd_set_fridge_difference(&readbuf[12]); 483 cmd_hmac(&readbuf[5]);
449 } 484 }
450 else if (strncmp_P(readbuf, PSTR("fridge_delay "), 13) == 0) 485 else if (strcmp_P(readbuf, PSTR("vcc")) == 0)
451 { 486 {
452 cmd_set_fridge_delay(&readbuf[13]); 487 cmd_vcc();
453 }
454 else if (strncmp_P(readbuf, PSTR("overshoot_delay "), 16) == 0)
455 {
456 cmd_set_overshoot_delay(&readbuf[16]);
457 }
458 else if (strncmp_P(readbuf, PSTR("overshoot_factor "), 17) == 0)
459 {
460 cmd_set_overshoot_factor(&readbuf[17]);
461 } 488 }
462 else if (strcmp_P(readbuf, PSTR("reset")) == 0) 489 else if (strcmp_P(readbuf, PSTR("reset")) == 0)
463 { 490 {
464 cmd_reset(); 491 cmd_reset();
465 } 492 }
469 } 496 }
470 } 497 }
471 498
472 ISR(INT0_vect) 499 ISR(INT0_vect)
473 { 500 {
474 button_pressed = 1;
475 blink(); 501 blink();
476 _delay_ms(100); 502 _delay_ms(100);
477 blink(); 503 blink();
478 } 504 }
479 505
502 readpos = 0; 528 readpos = 0;
503 } 529 }
504 } 530 }
505 } 531 }
506 532
507 ISR(TIMER2_COMPA_vect) 533 ISR(TIMER1_COMPA_vect)
508 { 534 {
509 TCNT2 = 0; 535 TCNT1 = 0;
510 536
511 clock_epoch += TICK; 537 clock_epoch += TICK;
512 538
513 // watchdogs count up, continuous 539 // watchdogs count up, continuous
514 if (watchdog_long_limit > 0) { 540 if (watchdog_long_limit > 0) {
515 watchdog_count += TICK; 541 watchdog_long_count += TICK;
516 if (watchdog_long_count >= watchdog_long_limit) 542 if (watchdog_long_count >= watchdog_long_limit)
517 { 543 {
518 watchdog_long_count = 0; 544 watchdog_long_count = 0;
519 watchdog_long_hit = 1; 545 watchdog_long_hit = 1;
520 } 546 }
521 } 547 }
522 548
523 if (watchdog_short_limit > 0) { 549 if (watchdog_short_limit > 0) {
524 watchdog_count += TICK; 550 watchdog_short_count += TICK;
525 if (watchdog_short_count >= watchdog_short_limit) 551 if (watchdog_short_count >= watchdog_short_limit)
526 { 552 {
527 watchdog_short_count = 0; 553 watchdog_short_count = 0;
528 watchdog_short_hit = 1; 554 watchdog_short_hit = 1;
529 } 555 }
530 } 556 }
531 557
532 // newboot counts down, oneshot. 558 // newboot counts down
533 if (newboot_count > 0) 559 if (newboot_count > 0)
534 { 560 {
535 newboot_count--; 561 newboot_count-=TICK;
536 if (newboot_count == 0) 562 if (newboot_count <= 0)
537 { 563 {
538 newboot_hit = 1; 564 newboot_hit = 1;
539 } 565 newboot_count = 0;
540 } 566 }
541 567 }
542 } 568
543 569 if (oneshot_count > 0)
544 static void 570 {
545 deep_sleep() 571 oneshot_count-=TICK;
546 { 572 if (oneshot_count <= 0)
547 // p119 of manual 573 {
548 OCR2A = SLEEP_COMPARE; 574 oneshot_hit = 1;
549 loop_until_bit_is_clear(ASSR, OCR2AUB); 575 oneshot_count = 0;
550 576 }
551 set_sleep_mode(SLEEP_MODE_PWR_SAVE); 577 }
552 sleep_mode(); 578
579
553 } 580 }
554 581
555 static void 582 static void
556 idle_sleep() 583 idle_sleep()
557 { 584 {
594 //return 1000 * res_volts; 621 //return 1000 * res_volts;
595 return ((uint32_t)1100*1024*num) / sum; 622 return ((uint32_t)1100*1024*num) / sum;
596 } 623 }
597 624
598 static void 625 static void
626 reboot_pi()
627 {
628 // pull it low for 30ms
629 PORT_PI_RESET &= ~_BV(PIN_PI_RESET);
630 DDR_PI_RESET |= _BV(PIN_PI_RESET);
631 _delay_ms(30);
632 DDR_PI_RESET &= ~_BV(PIN_PI_RESET);
633 }
634
635 static void
636 set_pi_boot_normal(uint8_t normal)
637 {
638 PORT_PI_BOOT &= ~_BV(PIN_PI_BOOT);
639 if (normal)
640 {
641 // tristate
642 DDR_PI_BOOT &= ~_BV(PIN_PI_BOOT);
643 }
644 else
645 {
646 // pull it low
647 DDR_PI_RESET |= _BV(PIN_PI_BOOT);
648
649 }
650 }
651
652 static void
653 check_flags()
654 {
655 if (watchdog_long_hit
656 || watchdog_short_hit
657 || oneshot_hit)
658 {
659 reboot_pi();
660 }
661
662 if (newboot_hit) {
663 set_pi_boot_normal(0);
664 }
665
666 watchdog_long_hit = 0;
667 watchdog_short_hit = 0;
668 newboot_hit = 0;
669 oneshot_hit = 0;
670 }
671
672 static void
599 do_comms() 673 do_comms()
600 { 674 {
601 // avoid receiving rubbish, perhaps 675 // avoid receiving rubbish, perhaps
602 uart_on(); 676 uart_on();
603 677
604 // write sd card here? same 3.3v regulator... 678 // write sd card here? same 3.3v regulator...
605 679
606 while (1) 680 while (1)
607 { 681 {
608 wdt_reset(); 682 wdt_reset();
683
684 check_flags();
685
609 if (have_cmd) 686 if (have_cmd)
610 { 687 {
611 have_cmd = 0; 688 have_cmd = 0;
612 read_handler(); 689 read_handler();
613 continue; 690 continue;
651 stdout = &mystdout; 728 stdout = &mystdout;
652 uart_on(); 729 uart_on();
653 730
654 printf(PSTR("Started.\n")); 731 printf(PSTR("Started.\n"));
655 732
733 set_pi_boot_normal(0);
734
656 load_params(); 735 load_params();
657 736
658 setup_tick_counter(); 737 setup_tick_counter();
659 738
660 sei(); 739 sei();