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