Mercurial > templog
comparison main.c @ 312:ef64a178092f
- Some basic ADC code
- Turn on -mcall-prologues
- Put strings in program space, saves RAM
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 14 May 2012 00:22:57 +0800 |
parents | fc96a51bdce6 |
children | 52cb08a01171 |
comparison
equal
deleted
inserted
replaced
311:fc96a51bdce6 | 312:ef64a178092f |
---|---|
7 #include <stdio.h> | 7 #include <stdio.h> |
8 #include <string.h> | 8 #include <string.h> |
9 #include <avr/io.h> | 9 #include <avr/io.h> |
10 #include <avr/interrupt.h> | 10 #include <avr/interrupt.h> |
11 #include <avr/sleep.h> | 11 #include <avr/sleep.h> |
12 #include <avr/pgmspace.h> | |
12 #include <util/crc16.h> | 13 #include <util/crc16.h> |
13 | 14 |
14 #include "integer.h" | 15 #include "integer.h" |
15 | 16 |
16 // configuration params | 17 // configuration params |
26 #define COMMS_WAKE 3600 | 27 #define COMMS_WAKE 3600 |
27 | 28 |
28 #define BAUD 9600 | 29 #define BAUD 9600 |
29 #define UBRR ((F_CPU)/16/(BAUD)-1) | 30 #define UBRR ((F_CPU)/16/(BAUD)-1) |
30 | 31 |
32 #define NUM_MEASUREMENTS 300 | |
33 | |
31 static int uart_putchar(char c, FILE *stream); | 34 static int uart_putchar(char c, FILE *stream); |
32 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, | 35 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, |
33 _FDEV_SETUP_WRITE); | 36 _FDEV_SETUP_WRITE); |
34 | 37 |
35 static uint8_t n_measurements; | 38 static uint8_t n_measurements; |
36 static uint8_t measurements[500]; | 39 // stored as 1/5 degree above 0 |
40 static uint8_t measurements[NUM_MEASUREMENTS]; | |
41 static uint8_t internal_measurements[NUM_MEASUREMENTS]; | |
37 | 42 |
38 // boolean flags | 43 // boolean flags |
39 static uint8_t need_measurement; | 44 static uint8_t need_measurement; |
40 static uint8_t need_comms; | 45 static uint8_t need_comms; |
41 static uint8_t comms_done; | 46 static uint8_t comms_done; |
47 static uint16_t comms_count; | 52 static uint16_t comms_count; |
48 | 53 |
49 static void deep_sleep(); | 54 static void deep_sleep(); |
50 | 55 |
51 static void | 56 static void |
52 uart_init(unsigned int ubrr) | 57 uart_on(unsigned int ubrr) |
53 { | 58 { |
54 // baud rate | 59 // baud rate |
55 UBRR0H = (unsigned char)(ubrr >> 8); | 60 UBRR0H = (unsigned char)(ubrr >> 8); |
56 UBRR0L = (unsigned char)ubrr; | 61 UBRR0L = (unsigned char)ubrr; |
57 UCSR0B = (1<<RXEN0)|(1<<TXEN0); | 62 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); |
58 //8N1 | 63 //8N1 |
59 UCSR0C = (1<<UMSEL00)|(3<<UCSZ00); | 64 UCSR0C = _BV(UMSEL00) | _BV(UCSZ00); |
65 | |
66 // Power reduction register | |
67 PRR &= ~_BV(PRUSART0); | |
68 } | |
69 | |
70 static void | |
71 uart_off() | |
72 { | |
73 // Turn of interrupts and disable tx/rx | |
74 UCSR0B = 0; | |
75 | |
76 // Power reduction register | |
77 PRR |= _BV(PRUSART0); | |
60 } | 78 } |
61 | 79 |
62 static int | 80 static int |
63 uart_putchar(char c, FILE *stream) | 81 uart_putchar(char c, FILE *stream) |
64 { | 82 { |
71 static void | 89 static void |
72 cmd_fetch() | 90 cmd_fetch() |
73 { | 91 { |
74 uint16_t crc = 0; | 92 uint16_t crc = 0; |
75 int i; | 93 int i; |
76 printf("%d measurements\n", n_measurements); | 94 printf_P(PSTR("%d measurements\n"), n_measurements); |
77 for (i = 0; i < n_measurements; i++) | 95 for (i = 0; i < n_measurements; i++) |
78 { | 96 { |
79 printf("%3d : %d\n", i, measurements[i]); | 97 printf_P(PSTR("%3d : %d\n"), i, measurements[i]); |
80 crc = _crc_ccitt_update(crc, measurements[i]); | 98 crc = _crc_ccitt_update(crc, measurements[i]); |
81 } | 99 } |
82 printf("CRC : %d\n", crc); | 100 printf_P(PSTR("CRC : %d\n"), crc); |
83 } | 101 } |
84 | 102 |
85 static void | 103 static void |
86 cmd_clear() | 104 cmd_clear() |
87 { | 105 { |
94 } | 112 } |
95 | 113 |
96 static void | 114 static void |
97 read_handler() | 115 read_handler() |
98 { | 116 { |
99 if (strcmp(readbuf, "fetch") == 0) | 117 if (strcmp_P(readbuf, PSTR("fetch")) == 0) |
100 { | 118 { |
101 cmd_fetch(); | 119 cmd_fetch(); |
102 } | 120 } |
103 else if (strcmp(readbuf, "clear") == 0) | 121 else if (strcmp_P(readbuf, PSTR("clear")) == 0) |
104 { | 122 { |
105 cmd_clear(); | 123 cmd_clear(); |
106 } | 124 } |
107 else if (strcmp(readbuf, "btoff") == 0) | 125 else if (strcmp_P(readbuf, PSTR("btoff")) == 0) |
108 { | 126 { |
109 cmd_btoff(); | 127 cmd_btoff(); |
110 } | 128 } |
111 else | 129 else |
112 { | 130 { |
113 printf("Bad command\n"); | 131 printf_P(PSTR("Bad command\n")); |
114 } | 132 } |
115 } | 133 } |
116 | 134 |
117 ISR(USART_RX_vect) | 135 ISR(USART_RX_vect) |
118 { | 136 { |
172 { | 190 { |
173 set_sleep_mode(SLEEP_MODE_IDLE); | 191 set_sleep_mode(SLEEP_MODE_IDLE); |
174 sleep_mode(); | 192 sleep_mode(); |
175 } | 193 } |
176 | 194 |
195 static void | |
196 do_adc_335() | |
197 { | |
198 PRR &= ~_BV(PRADC); | |
199 | |
200 ADMUX = _BV(ADLAR); | |
201 | |
202 // ADPS2 = /16 prescaler, 62khz at 1mhz clock | |
203 ADCSRA = _BV(ADEN) | _BV(ADPS2); | |
204 | |
205 // measure value | |
206 ADCSRA |= _BV(ADSC); | |
207 loop_until_bit_is_clear(ADCSRA, ADSC); | |
208 uint8_t low = ADCL; | |
209 uint8_t high = ADCH; | |
210 uint16_t f_measure = low + (high << 8); | |
211 | |
212 // set to measure 1.1 reference | |
213 ADMUX = _BV(ADLAR) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
214 ADCSRA |= _BV(ADSC); | |
215 loop_until_bit_is_clear(ADCSRA, ADSC); | |
216 uint8_t low_11 = ADCL; | |
217 uint8_t high_11 = ADCH; | |
218 uint16_t f_11 = low_11 + (high_11 << 8); | |
219 | |
220 float res_volts = 1.1 * f_measure / f_11; | |
221 | |
222 // 10mV/degree | |
223 // scale to 1/5 degree units above 0C | |
224 int temp = (res_volts - 2.73) * 500; | |
225 measurements[n_measurements] = temp; | |
226 // XXX something if it hits the limit | |
227 | |
228 // measure AVR internal temperature against 1.1 ref. | |
229 ADMUX = _BV(ADLAR) | _BV(MUX3) | _BV(REFS1) | _BV(REFS0); | |
230 ADCSRA |= _BV(ADSC); | |
231 loop_until_bit_is_clear(ADCSRA, ADSC); | |
232 uint16_t res_internal = ADCL; | |
233 res_internal |= ADCH << 8; | |
234 | |
235 float internal_volts = res_internal * (1.1 / 1024.0); | |
236 | |
237 // 1mV/degree | |
238 int internal_temp = (internal_volts - 2.73) * 5000; | |
239 internal_measurements[n_measurements] = internal_temp; | |
240 | |
241 printf_P("measure %d: external %d, internal %d, 1.1 %d\n", | |
242 n_measurements, temp, internal_temp, f_11); | |
243 | |
244 n_measurements++; | |
245 PRR |= _BV(PRADC); | |
246 } | |
247 | |
177 static void | 248 static void |
178 do_measurement() | 249 do_measurement() |
179 { | 250 { |
180 need_measurement = 0; | 251 need_measurement = 0; |
252 | |
253 do_adc_335(); | |
181 } | 254 } |
182 | 255 |
183 static void | 256 static void |
184 do_comms() | 257 do_comms() |
185 { | 258 { |
186 need_comms = 0; | 259 need_comms = 0; |
187 | 260 |
188 // turn on bluetooth | 261 // turn on bluetooth |
189 // turn on serial (interrupts) | 262 uart_on(UBRR); |
190 | 263 |
191 // write sd card here? same 3.3v regulator... | 264 // write sd card here? same 3.3v regulator... |
192 | 265 |
193 comms_done = 0; | 266 comms_done = 0; |
194 for (;;) | 267 for (;;) |
195 { | 268 { |
196 if (comms_done) | 269 if (comms_done) |
197 { | 270 { |
198 break; | 271 break; |
199 } | 272 } |
273 | |
274 if (need_measurement) | |
275 { | |
276 do_measurement(); | |
277 } | |
278 | |
200 idle_sleep(); | 279 idle_sleep(); |
201 } | 280 } |
202 | 281 |
282 uart_off(); | |
283 | |
203 // turn off bluetooth | 284 // turn off bluetooth |
204 // turn off serial (interrupts) | |
205 } | 285 } |
206 | 286 |
207 int main(void) | 287 int main(void) |
208 { | 288 { |
209 uart_init(UBRR); | 289 stdout = &mystdout; |
210 | 290 uart_on(UBRR); |
211 fprintf(&mystdout, "hello %d\n", 12); | 291 fprintf_P(&mystdout, PSTR("hello %d\n"), 12); |
292 uart_off(); | |
293 | |
294 // turn off everything except timer2 | |
295 PRR = _BV(PRTWI) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC); | |
212 | 296 |
213 // set up counter2. | 297 // set up counter2. |
214 // COM21 COM20 Set OC2 on Compare Match (p116) | 298 // COM21 COM20 Set OC2 on Compare Match (p116) |
215 // WGM21 Clear counter on compare | 299 // WGM21 Clear counter on compare |
216 // CS22 CS21 CS20 clk/1024 | 300 // CS22 CS21 CS20 clk/1024 |
217 TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); | 301 TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); |
218 TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); | 302 TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); |
219 // set async mode | 303 // set async mode |
220 ASSR |= _BV(AS2); | 304 ASSR |= _BV(AS2); |
221 | 305 |
306 #ifdef TEST_MODE | |
307 for (;;) | |
308 { | |
309 do_comms() | |
310 } | |
311 #else | |
222 for(;;){ | 312 for(;;){ |
223 /* insert your main loop code here */ | 313 /* insert your main loop code here */ |
224 if (need_measurement) | 314 if (need_measurement) |
225 { | 315 { |
226 do_measurement(); | 316 do_measurement(); |
233 continue; | 323 continue; |
234 } | 324 } |
235 | 325 |
236 deep_sleep(); | 326 deep_sleep(); |
237 } | 327 } |
328 #endif | |
238 return 0; /* never reached */ | 329 return 0; /* never reached */ |
239 } | 330 } |