Mercurial > templog
comparison main.c @ 59:d5b269352ba0
- add some atomic guards
- get rid of avrtemp
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 25 Jun 2012 22:06:03 +0800 |
parents | 5100e0bdadad |
children | 2ebe33714989 |
comparison
equal
deleted
inserted
replaced
58:5100e0bdadad | 59:d5b269352ba0 |
---|---|
6 #include <avr/sleep.h> | 6 #include <avr/sleep.h> |
7 #include <util/delay.h> | 7 #include <util/delay.h> |
8 #include <avr/pgmspace.h> | 8 #include <avr/pgmspace.h> |
9 #include <avr/eeprom.h> | 9 #include <avr/eeprom.h> |
10 #include <avr/wdt.h> | 10 #include <avr/wdt.h> |
11 #include <util/atomic.h> | |
11 #include <util/crc16.h> | 12 #include <util/crc16.h> |
12 | 13 |
13 // for DWORD of get_fattime() | 14 // for DWORD of get_fattime() |
14 #include "integer.h" | 15 #include "integer.h" |
15 | 16 |
59 // #define HAVE_UART_ECHO | 60 // #define HAVE_UART_ECHO |
60 | 61 |
61 int uart_putchar(char c, FILE *stream); | 62 int uart_putchar(char c, FILE *stream); |
62 static void long_delay(int ms); | 63 static void long_delay(int ms); |
63 static void blink(); | 64 static void blink(); |
64 static void adc_internal(uint16_t *millivolt_vcc, uint16_t *int_temp); | 65 static uint16_t adc_vcc(); |
65 | 66 |
66 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, | 67 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, |
67 _FDEV_SETUP_WRITE); | 68 _FDEV_SETUP_WRITE); |
68 | 69 |
69 uint16_t crc_out; | 70 uint16_t crc_out; |
70 static FILE _crc_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, | 71 static FILE _crc_stdout = FDEV_SETUP_STREAM(uart_putchar, NULL, |
71 _FDEV_SETUP_WRITE); | 72 _FDEV_SETUP_WRITE); |
72 // convenience | 73 // convenience |
73 static FILE *crc_stdout = &_crc_stdout; | 74 static FILE *crc_stdout = &_crc_stdout; |
74 | 75 |
76 // ---- Atomic guards required accessing these variables | |
77 static uint32_t clock_epoch; | |
78 static uint16_t comms_count; | |
79 static uint16_t measure_count; | |
80 // ---- End atomic guards required | |
81 | |
75 static uint16_t n_measurements; | 82 static uint16_t n_measurements; |
83 | |
76 // stored as decidegrees | 84 // stored as decidegrees |
77 static int16_t measurements[NUM_MEASUREMENTS][MAX_SENSORS]; | 85 static int16_t measurements[NUM_MEASUREMENTS][MAX_SENSORS]; |
78 static uint32_t first_measurement_clock; | 86 static uint32_t first_measurement_clock; |
79 // last_measurement_clock is redundant but checks that we're not missing | 87 // last_measurement_clock is redundant but checks that we're not missing |
80 // samples | 88 // samples |
81 static uint32_t last_measurement_clock; | 89 static uint32_t last_measurement_clock; |
82 | 90 |
91 static uint32_t last_comms_clock; | |
92 | |
83 // boolean flags | 93 // boolean flags |
84 static uint8_t need_measurement; | 94 static uint8_t need_measurement; |
85 static uint8_t need_comms; | 95 static uint8_t need_comms; |
86 static uint8_t uart_enabled; | 96 static uint8_t uart_enabled; |
87 | 97 |
90 | 100 |
91 static uint8_t readpos; | 101 static uint8_t readpos; |
92 static char readbuf[30]; | 102 static char readbuf[30]; |
93 static uint8_t have_cmd; | 103 static uint8_t have_cmd; |
94 | 104 |
95 static uint16_t measure_count; | |
96 static uint16_t comms_count; | |
97 | |
98 static uint32_t clock_epoch; | |
99 | 105 |
100 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/ | 106 // thanks to http://projectgus.com/2010/07/eeprom-access-with-arduino/ |
101 #define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size)) | 107 #define eeprom_read_to(dst_p, eeprom_field, dst_size) eeprom_read_block((dst_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (dst_size)) |
102 #define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst)) | 108 #define eeprom_read(dst, eeprom_field) eeprom_read_to((&dst), eeprom_field, sizeof(dst)) |
103 #define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size)) | 109 #define eeprom_write_from(src_p, eeprom_field, src_size) eeprom_write_block((src_p), (void *)offsetof(struct __eeprom_data, eeprom_field), (src_size)) |
254 { | 260 { |
255 crc_out = 0; | 261 crc_out = 0; |
256 uint8_t n_sensors; | 262 uint8_t n_sensors; |
257 eeprom_read(n_sensors, n_sensors); | 263 eeprom_read(n_sensors, n_sensors); |
258 | 264 |
259 uint16_t millivolt_vcc, int_temp; | 265 uint16_t millivolt_vcc = adc_vcc(); |
260 | 266 |
261 adc_internal(&millivolt_vcc, &int_temp); | 267 uint32_t epoch_copy; |
268 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) | |
269 { | |
270 epoch_copy = clock_epoch; | |
271 } | |
262 | 272 |
263 fprintf_P(crc_stdout, PSTR("START\n")); | 273 fprintf_P(crc_stdout, PSTR("START\n")); |
264 fprintf_P(crc_stdout, PSTR("now=%lu\n" | 274 fprintf_P(crc_stdout, PSTR("now=%lu\n" |
265 "time_step=%hu\n" | 275 "time_step=%hu\n" |
266 "first_time=%lu\n" | 276 "first_time=%lu\n" |
267 "last_time=%lu\n" | 277 "last_time=%lu\n" |
278 "comms_time=%lu\n" | |
268 "voltage=%hu\n" | 279 "voltage=%hu\n" |
269 "avrtemp=%hu\n"), | 280 "avrtemp=%hu\n"), |
270 clock_epoch, | 281 epoch_copy, |
271 (uint16_t)MEASURE_WAKE, | 282 (uint16_t)MEASURE_WAKE, |
272 first_measurement_clock, | 283 first_measurement_clock, |
273 last_measurement_clock, | 284 last_measurement_clock, |
274 millivolt_vcc, | 285 last_comms_clock, |
275 int_temp | 286 millivolt_vcc |
276 ); | 287 ); |
277 fprintf_P(crc_stdout, PSTR("sensors=%u\n"), n_sensors); | 288 fprintf_P(crc_stdout, PSTR("sensors=%u\n"), n_sensors); |
278 for (uint8_t s = 0; s < n_sensors; s++) | 289 for (uint8_t s = 0; s < n_sensors; s++) |
279 { | 290 { |
280 uint8_t id[ID_LEN]; | 291 uint8_t id[ID_LEN]; |
305 } | 316 } |
306 | 317 |
307 static void | 318 static void |
308 cmd_btoff() | 319 cmd_btoff() |
309 { | 320 { |
310 comms_count = 0; | 321 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) |
322 { | |
323 comms_count = 0; | |
324 } | |
311 printf_P(PSTR("off:%hu\n"), COMMS_WAKE); | 325 printf_P(PSTR("off:%hu\n"), COMMS_WAKE); |
312 _delay_ms(100); | 326 _delay_ms(100); |
313 comms_timeout = 0; | 327 comms_timeout = 0; |
314 } | 328 } |
315 | 329 |
579 if (comms_count >= COMMS_WAKE) | 593 if (comms_count >= COMMS_WAKE) |
580 { | 594 { |
581 comms_count = 0; | 595 comms_count = 0; |
582 need_comms = 1; | 596 need_comms = 1; |
583 } | 597 } |
584 | |
585 } | 598 } |
586 | 599 |
587 DWORD get_fattime (void) | 600 DWORD get_fattime (void) |
588 { | 601 { |
589 return 0; | 602 return 0; |
605 { | 618 { |
606 set_sleep_mode(SLEEP_MODE_IDLE); | 619 set_sleep_mode(SLEEP_MODE_IDLE); |
607 sleep_mode(); | 620 sleep_mode(); |
608 } | 621 } |
609 | 622 |
610 static void | 623 static uint16_t |
611 adc_internal(uint16_t *millivolt_vcc, uint16_t *int_temp) | 624 adc_vcc() |
612 { | 625 { |
613 PRR &= ~_BV(PRADC); | 626 PRR &= ~_BV(PRADC); |
614 | 627 |
615 // left adjust | 628 // left adjust |
616 ADMUX = _BV(ADLAR); | 629 ADMUX = _BV(ADLAR); |
618 // ADPS2 = /16 prescaler, 62khz at 1mhz clock | 631 // ADPS2 = /16 prescaler, 62khz at 1mhz clock |
619 ADCSRA = _BV(ADEN) | _BV(ADPS2); | 632 ADCSRA = _BV(ADEN) | _BV(ADPS2); |
620 | 633 |
621 // set to measure 1.1 reference | 634 // set to measure 1.1 reference |
622 ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | 635 ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); |
623 ADCSRA |= _BV(ADSC); | 636 _delay_ms(30); |
624 loop_until_bit_is_clear(ADCSRA, ADSC); | 637 // try a few times so it can stabilise |
638 for (uint16_t n = 0; n < 20; n++) | |
639 { | |
640 ADCSRA |= _BV(ADSC); | |
641 loop_until_bit_is_clear(ADCSRA, ADSC); | |
642 } | |
625 uint8_t low_11 = ADCL; | 643 uint8_t low_11 = ADCL; |
626 uint8_t high_11 = ADCH; | 644 uint8_t high_11 = ADCH; |
627 uint16_t f_11 = low_11 + (high_11 << 8); | 645 uint16_t f_11 = low_11 + (high_11 << 8); |
628 | 646 |
629 float res_volts = 1.1 * 1024 / f_11; | 647 float res_volts = 1.1 * 1024 / f_11; |
630 *millivolt_vcc = 1000 * res_volts; | |
631 | |
632 // measure AVR internal temperature against 1.1 ref. | |
633 ADMUX = _BV(MUX3) | _BV(REFS1) | _BV(REFS0); | |
634 ADCSRA |= _BV(ADSC); | |
635 loop_until_bit_is_clear(ADCSRA, ADSC); | |
636 uint8_t low_temp = ADCL; | |
637 uint8_t high_temp = ADCH; | |
638 uint16_t res_internal = low_temp + (high_temp << 8); | |
639 float internal_volts = res_internal * (1.1 / 1024.0); | |
640 // millivolts | |
641 *int_temp = internal_volts * 1000; | |
642 | 648 |
643 PRR |= _BV(PRADC); | 649 PRR |= _BV(PRADC); |
644 ADCSRA = 0; | 650 ADCSRA = 0; |
651 | |
652 return 1000 * res_volts; | |
645 } | 653 } |
646 | 654 |
647 #if 0 | 655 #if 0 |
648 // untested | 656 // untested |
649 static void | 657 static void |
707 { | 715 { |
708 uint8_t n_sensors; | 716 uint8_t n_sensors; |
709 eeprom_read(n_sensors, n_sensors); | 717 eeprom_read(n_sensors, n_sensors); |
710 | 718 |
711 simple_ds18b20_start_meas(NULL); | 719 simple_ds18b20_start_meas(NULL); |
712 _delay_ms(DS18B20_TCONV_12BIT); | 720 // sleep rather than using a long delay |
721 deep_sleep(); | |
722 //_delay_ms(DS18B20_TCONV_12BIT); | |
713 | 723 |
714 if (n_measurements == NUM_MEASUREMENTS) | 724 if (n_measurements == NUM_MEASUREMENTS) |
715 { | 725 { |
716 n_measurements = 0; | 726 n_measurements = 0; |
717 } | 727 } |
735 } | 745 } |
736 } | 746 } |
737 measurements[n_measurements][s] = decicelsius; | 747 measurements[n_measurements][s] = decicelsius; |
738 } | 748 } |
739 | 749 |
740 if (n_measurements == 0) | 750 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) |
741 { | 751 { |
742 first_measurement_clock = clock_epoch; | 752 if (n_measurements == 0) |
743 } | 753 { |
744 last_measurement_clock = clock_epoch; | 754 first_measurement_clock = clock_epoch; |
755 } | |
756 last_measurement_clock = clock_epoch; | |
757 } | |
745 | 758 |
746 n_measurements++; | 759 n_measurements++; |
747 //do_adc_335(); | 760 //do_adc_335(); |
748 } | 761 } |
749 | 762 |
750 static void | 763 static void |
751 do_comms() | 764 do_comms() |
752 { | 765 { |
753 // turn on bluetooth | 766 // turn on bluetooth |
767 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) | |
768 { | |
769 last_comms_clock = clock_epoch; | |
770 } | |
754 set_aux_power(1); | 771 set_aux_power(1); |
755 uart_on(); | 772 uart_on(); |
756 | 773 |
757 // write sd card here? same 3.3v regulator... | 774 // write sd card here? same 3.3v regulator... |
758 | 775 |