Mercurial > templog
annotate main.c @ 9:7da9a3f23592
Import ds18x20 code
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Fri, 18 May 2012 23:57:08 +0800 |
parents | c55321727d02 |
children | 1bfe28c348dd |
rev | line source |
---|---|
0 | 1 /* Name: main.c |
2 * Author: <insert your name here> | |
3 * Copyright: <insert your copyright message here> | |
4 * License: <insert your license reference here> | |
5 */ | |
6 | |
7 #include <stdio.h> | |
8 #include <string.h> | |
1 | 9 #include <avr/io.h> |
10 #include <avr/interrupt.h> | |
11 #include <avr/sleep.h> | |
7 | 12 #include <util/delay.h> |
6 | 13 #include <avr/pgmspace.h> |
0 | 14 #include <util/crc16.h> |
15 | |
3 | 16 #include "integer.h" |
9 | 17 #include "onewire.h" |
3 | 18 |
0 | 19 // configuration params |
20 // - measurement interval | |
21 // - transmit interval | |
22 // - bluetooth params | |
23 // - number of sensors (and range?) | |
24 | |
1 | 25 // 1 second. we have 1024 prescaler, 32768 crystal. |
2 | 26 #define SLEEP_COMPARE 32 |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
27 #define MEASURE_WAKE 60 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
28 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
29 #define COMMS_WAKE 3600 |
2 | 30 |
31 #define BAUD 9600 | |
7 | 32 #define UBRR ((F_CPU)/8/(BAUD)-1) |
33 | |
34 #define PORT_LED PORTC | |
35 #define DDR_LED DDRC | |
36 #define PIN_LED PC4 | |
1 | 37 |
6 | 38 #define NUM_MEASUREMENTS 300 |
39 | |
0 | 40 static int uart_putchar(char c, FILE *stream); |
41 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, | |
42 _FDEV_SETUP_WRITE); | |
43 | |
7 | 44 static uint8_t n_measurements = 0; |
6 | 45 // stored as 1/5 degree above 0 |
46 static uint8_t measurements[NUM_MEASUREMENTS]; | |
47 static uint8_t internal_measurements[NUM_MEASUREMENTS]; | |
0 | 48 |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
49 // boolean flags |
7 | 50 static uint8_t need_measurement = 0; |
51 static uint8_t need_comms = 0; | |
52 static uint8_t comms_done = 0; | |
1 | 53 |
7 | 54 static uint8_t readpos = 0; |
0 | 55 static char readbuf[30]; |
56 | |
7 | 57 static uint8_t measure_count = 0; |
58 static uint16_t comms_count = 0; | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
59 |
8 | 60 #define DEBUG(str) printf_P(PSTR(str)) |
61 | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
62 static void deep_sleep(); |
1 | 63 |
0 | 64 static void |
7 | 65 uart_on() |
0 | 66 { |
8 | 67 // Power reduction register |
68 //PRR &= ~_BV(PRUSART0); | |
69 | |
0 | 70 // baud rate |
7 | 71 UBRR0H = (unsigned char)(UBRR >> 8); |
72 UBRR0L = (unsigned char)UBRR; | |
73 // set 2x clock, improves accuracy of UBRR | |
74 UCSR0A |= _BV(U2X0); | |
6 | 75 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); |
0 | 76 //8N1 |
7 | 77 UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); |
6 | 78 } |
79 | |
80 static void | |
81 uart_off() | |
82 { | |
83 // Turn of interrupts and disable tx/rx | |
84 UCSR0B = 0; | |
85 | |
86 // Power reduction register | |
8 | 87 //PRR |= _BV(PRUSART0); |
0 | 88 } |
89 | |
90 static int | |
91 uart_putchar(char c, FILE *stream) | |
92 { | |
8 | 93 if (c == '\n') |
94 { | |
95 uart_putchar('\r', stream); | |
96 } | |
0 | 97 // XXX should sleep in the loop for power. |
2 | 98 loop_until_bit_is_set(UCSR0A, UDRE0); |
99 UDR0 = c; | |
0 | 100 return 0; |
101 } | |
102 | |
103 static void | |
104 cmd_fetch() | |
105 { | |
106 uint16_t crc = 0; | |
107 int i; | |
6 | 108 printf_P(PSTR("%d measurements\n"), n_measurements); |
0 | 109 for (i = 0; i < n_measurements; i++) |
110 { | |
6 | 111 printf_P(PSTR("%3d : %d\n"), i, measurements[i]); |
1 | 112 crc = _crc_ccitt_update(crc, measurements[i]); |
0 | 113 } |
6 | 114 printf_P(PSTR("CRC : %d\n"), crc); |
0 | 115 } |
116 | |
117 static void | |
118 cmd_clear() | |
119 { | |
7 | 120 n_measurements = 0; |
121 printf_P(PSTR("Cleared\n")); | |
0 | 122 } |
123 | |
124 static void | |
125 cmd_btoff() | |
126 { | |
7 | 127 printf_P(PSTR("Turning off\n")); |
128 _delay_ms(50); | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
129 comms_done = 1; |
0 | 130 } |
131 | |
132 static void | |
133 read_handler() | |
134 { | |
6 | 135 if (strcmp_P(readbuf, PSTR("fetch")) == 0) |
0 | 136 { |
137 cmd_fetch(); | |
138 } | |
6 | 139 else if (strcmp_P(readbuf, PSTR("clear")) == 0) |
0 | 140 { |
141 cmd_clear(); | |
142 } | |
6 | 143 else if (strcmp_P(readbuf, PSTR("btoff")) == 0) |
0 | 144 { |
145 cmd_btoff(); | |
146 } | |
147 else | |
148 { | |
6 | 149 printf_P(PSTR("Bad command\n")); |
0 | 150 } |
151 } | |
152 | |
2 | 153 ISR(USART_RX_vect) |
0 | 154 { |
2 | 155 char c = UDR0; |
8 | 156 printf_P(PSTR("wake up '%c'\n"), c); |
0 | 157 if (c == '\n') |
158 { | |
159 readbuf[readpos] = '\0'; | |
160 read_handler(); | |
161 readpos = 0; | |
162 } | |
163 else | |
164 { | |
165 readbuf[readpos] = c; | |
166 readpos++; | |
167 if (readpos >= sizeof(readbuf)) | |
168 { | |
169 readpos = 0; | |
170 } | |
171 } | |
172 } | |
173 | |
2 | 174 ISR(TIMER2_COMPA_vect) |
1 | 175 { |
8 | 176 DEBUG("wake up\n"); |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
177 measure_count ++; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
178 comms_count ++; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
179 if (measure_count == MEASURE_WAKE) |
1 | 180 { |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
181 measure_count = 0; |
1 | 182 need_measurement = 1; |
183 } | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
184 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
185 if (comms_count == COMMS_WAKE) |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
186 { |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
187 comms_count = 0; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
188 need_comms = 1; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
189 } |
1 | 190 } |
191 | |
3 | 192 DWORD get_fattime (void) |
193 { | |
194 return 0; | |
195 } | |
196 | |
1 | 197 static void |
198 deep_sleep() | |
199 { | |
8 | 200 DEBUG("deep sleep\n"); |
1 | 201 // p119 of manual |
2 | 202 OCR2A = SLEEP_COMPARE; |
203 loop_until_bit_is_clear(ASSR, OCR2AUB); | |
1 | 204 |
8 | 205 DEBUG("really about to\n"); |
206 | |
1 | 207 set_sleep_mode(SLEEP_MODE_PWR_SAVE); |
8 | 208 DEBUG("done.\n"); |
1 | 209 sleep_mode(); |
210 } | |
211 | |
212 static void | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
213 idle_sleep() |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
214 { |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
215 set_sleep_mode(SLEEP_MODE_IDLE); |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
216 sleep_mode(); |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
217 } |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
218 |
6 | 219 static void |
220 do_adc_335() | |
221 { | |
8 | 222 //PRR &= ~_BV(PRADC); |
6 | 223 |
224 ADMUX = _BV(ADLAR); | |
225 | |
226 // ADPS2 = /16 prescaler, 62khz at 1mhz clock | |
227 ADCSRA = _BV(ADEN) | _BV(ADPS2); | |
228 | |
229 // measure value | |
230 ADCSRA |= _BV(ADSC); | |
231 loop_until_bit_is_clear(ADCSRA, ADSC); | |
232 uint8_t low = ADCL; | |
233 uint8_t high = ADCH; | |
234 uint16_t f_measure = low + (high << 8); | |
235 | |
236 // set to measure 1.1 reference | |
237 ADMUX = _BV(ADLAR) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
238 ADCSRA |= _BV(ADSC); | |
239 loop_until_bit_is_clear(ADCSRA, ADSC); | |
240 uint8_t low_11 = ADCL; | |
241 uint8_t high_11 = ADCH; | |
242 uint16_t f_11 = low_11 + (high_11 << 8); | |
243 | |
244 float res_volts = 1.1 * f_measure / f_11; | |
245 | |
246 // 10mV/degree | |
247 // scale to 1/5 degree units above 0C | |
248 int temp = (res_volts - 2.73) * 500; | |
249 measurements[n_measurements] = temp; | |
250 // XXX something if it hits the limit | |
251 | |
252 // measure AVR internal temperature against 1.1 ref. | |
253 ADMUX = _BV(ADLAR) | _BV(MUX3) | _BV(REFS1) | _BV(REFS0); | |
254 ADCSRA |= _BV(ADSC); | |
255 loop_until_bit_is_clear(ADCSRA, ADSC); | |
256 uint16_t res_internal = ADCL; | |
257 res_internal |= ADCH << 8; | |
258 | |
259 float internal_volts = res_internal * (1.1 / 1024.0); | |
260 | |
261 // 1mV/degree | |
262 int internal_temp = (internal_volts - 2.73) * 5000; | |
263 internal_measurements[n_measurements] = internal_temp; | |
264 | |
265 printf_P("measure %d: external %d, internal %d, 1.1 %d\n", | |
266 n_measurements, temp, internal_temp, f_11); | |
267 | |
268 n_measurements++; | |
8 | 269 //PRR |= _BV(PRADC); |
6 | 270 } |
271 | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
272 static void |
1 | 273 do_measurement() |
274 { | |
275 need_measurement = 0; | |
6 | 276 |
277 do_adc_335(); | |
1 | 278 } |
279 | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
280 static void |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
281 do_comms() |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
282 { |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
283 need_comms = 0; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
284 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
285 // turn on bluetooth |
7 | 286 uart_on(); |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
287 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
288 // write sd card here? same 3.3v regulator... |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
289 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
290 comms_done = 0; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
291 for (;;) |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
292 { |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
293 if (comms_done) |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
294 { |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
295 break; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
296 } |
6 | 297 |
298 if (need_measurement) | |
299 { | |
300 do_measurement(); | |
301 } | |
302 | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
303 idle_sleep(); |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
304 } |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
305 |
6 | 306 uart_off(); |
307 | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
308 // turn off bluetooth |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
309 } |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
310 |
7 | 311 static void |
312 blink() | |
313 { | |
314 PORT_LED &= ~_BV(PIN_LED); | |
9 | 315 _delay_ms(1); |
7 | 316 PORT_LED |= _BV(PIN_LED); |
317 } | |
318 | |
319 static void | |
320 long_delay(int ms) | |
321 { | |
322 int iter = ms / 100; | |
323 | |
324 for (int i = 0; i < iter; i++) | |
325 { | |
326 _delay_ms(100); | |
327 } | |
328 } | |
329 | |
8 | 330 ISR(BADISR_vect) |
331 { | |
332 uart_on(); | |
333 printf_P(PSTR("Bad interrupt\n")); | |
334 } | |
335 | |
9 | 336 static void |
337 set_2mhz() | |
338 { | |
339 cli(); | |
340 CLKPR = _BV(CLKPCE); | |
341 // divide by 4 | |
342 CLKPR = _BV(CLKPS1); | |
343 sei(); | |
344 } | |
345 | |
346 static void | |
347 test1wire() | |
348 { | |
349 ow_reset(); | |
350 } | |
351 | |
0 | 352 int main(void) |
353 { | |
9 | 354 set_2mhz(); |
355 | |
7 | 356 DDR_LED |= _BV(PIN_LED); |
8 | 357 blink(); |
7 | 358 |
6 | 359 stdout = &mystdout; |
7 | 360 uart_on(); |
361 | |
6 | 362 fprintf_P(&mystdout, PSTR("hello %d\n"), 12); |
8 | 363 uart_off(); |
0 | 364 |
6 | 365 // turn off everything except timer2 |
8 | 366 //PRR = _BV(PRTWI) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC); |
367 | |
368 // for testing | |
369 uart_on(); | |
370 | |
371 DEBUG("power off\n"); | |
372 sei(); | |
373 DEBUG("sei done\n"); | |
374 | |
0 | 375 |
1 | 376 // set up counter2. |
377 // COM21 COM20 Set OC2 on Compare Match (p116) | |
378 // WGM21 Clear counter on compare | |
8 | 379 TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); |
1 | 380 // CS22 CS21 CS20 clk/1024 |
2 | 381 TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); |
1 | 382 // set async mode |
383 ASSR |= _BV(AS2); | |
8 | 384 // interrupt |
385 TIMSK2 = _BV(OCIE2A); | |
0 | 386 |
8 | 387 DEBUG("async setup\n"); |
7 | 388 |
6 | 389 #ifdef TEST_MODE |
390 for (;;) | |
391 { | |
392 do_comms() | |
393 } | |
394 #else | |
0 | 395 for(;;){ |
9 | 396 |
397 test1wire(); | |
398 | |
0 | 399 /* insert your main loop code here */ |
1 | 400 if (need_measurement) |
401 { | |
402 do_measurement(); | |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
403 continue; |
1 | 404 } |
4
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
405 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
406 if (need_comms) |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
407 { |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
408 do_comms(); |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
409 continue; |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
410 } |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
411 |
54d369e3d689
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
3
diff
changeset
|
412 deep_sleep(); |
9 | 413 blink(); |
0 | 414 } |
6 | 415 #endif |
0 | 416 return 0; /* never reached */ |
417 } |