Mercurial > templog
annotate 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 |
rev | line source |
---|---|
306 | 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> | |
307 | 9 #include <avr/io.h> |
10 #include <avr/interrupt.h> | |
11 #include <avr/sleep.h> | |
312 | 12 #include <avr/pgmspace.h> |
306 | 13 #include <util/crc16.h> |
14 | |
309 | 15 #include "integer.h" |
16 | |
306 | 17 // configuration params |
18 // - measurement interval | |
19 // - transmit interval | |
20 // - bluetooth params | |
21 // - number of sensors (and range?) | |
22 | |
307 | 23 // 1 second. we have 1024 prescaler, 32768 crystal. |
308 | 24 #define SLEEP_COMPARE 32 |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
25 #define MEASURE_WAKE 60 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
26 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
27 #define COMMS_WAKE 3600 |
308 | 28 |
29 #define BAUD 9600 | |
30 #define UBRR ((F_CPU)/16/(BAUD)-1) | |
307 | 31 |
312 | 32 #define NUM_MEASUREMENTS 300 |
33 | |
306 | 34 static int uart_putchar(char c, FILE *stream); |
35 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, | |
36 _FDEV_SETUP_WRITE); | |
37 | |
38 static uint8_t n_measurements; | |
312 | 39 // stored as 1/5 degree above 0 |
40 static uint8_t measurements[NUM_MEASUREMENTS]; | |
41 static uint8_t internal_measurements[NUM_MEASUREMENTS]; | |
306 | 42 |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
43 // boolean flags |
307 | 44 static uint8_t need_measurement; |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
45 static uint8_t need_comms; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
46 static uint8_t comms_done; |
307 | 47 |
306 | 48 static uint8_t readpos; |
49 static char readbuf[30]; | |
50 | |
311 | 51 static uint8_t measure_count; |
52 static uint16_t comms_count; | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
53 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
54 static void deep_sleep(); |
307 | 55 |
306 | 56 static void |
312 | 57 uart_on(unsigned int ubrr) |
306 | 58 { |
59 // baud rate | |
308 | 60 UBRR0H = (unsigned char)(ubrr >> 8); |
61 UBRR0L = (unsigned char)ubrr; | |
312 | 62 UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); |
306 | 63 //8N1 |
312 | 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); | |
306 | 78 } |
79 | |
80 static int | |
81 uart_putchar(char c, FILE *stream) | |
82 { | |
83 // XXX should sleep in the loop for power. | |
308 | 84 loop_until_bit_is_set(UCSR0A, UDRE0); |
85 UDR0 = c; | |
306 | 86 return 0; |
87 } | |
88 | |
89 static void | |
90 cmd_fetch() | |
91 { | |
92 uint16_t crc = 0; | |
93 int i; | |
312 | 94 printf_P(PSTR("%d measurements\n"), n_measurements); |
306 | 95 for (i = 0; i < n_measurements; i++) |
96 { | |
312 | 97 printf_P(PSTR("%3d : %d\n"), i, measurements[i]); |
307 | 98 crc = _crc_ccitt_update(crc, measurements[i]); |
306 | 99 } |
312 | 100 printf_P(PSTR("CRC : %d\n"), crc); |
306 | 101 } |
102 | |
103 static void | |
104 cmd_clear() | |
105 { | |
106 } | |
107 | |
108 static void | |
109 cmd_btoff() | |
110 { | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
111 comms_done = 1; |
306 | 112 } |
113 | |
114 static void | |
115 read_handler() | |
116 { | |
312 | 117 if (strcmp_P(readbuf, PSTR("fetch")) == 0) |
306 | 118 { |
119 cmd_fetch(); | |
120 } | |
312 | 121 else if (strcmp_P(readbuf, PSTR("clear")) == 0) |
306 | 122 { |
123 cmd_clear(); | |
124 } | |
312 | 125 else if (strcmp_P(readbuf, PSTR("btoff")) == 0) |
306 | 126 { |
127 cmd_btoff(); | |
128 } | |
129 else | |
130 { | |
312 | 131 printf_P(PSTR("Bad command\n")); |
306 | 132 } |
133 } | |
134 | |
308 | 135 ISR(USART_RX_vect) |
306 | 136 { |
308 | 137 char c = UDR0; |
306 | 138 if (c == '\n') |
139 { | |
140 readbuf[readpos] = '\0'; | |
141 read_handler(); | |
142 readpos = 0; | |
143 } | |
144 else | |
145 { | |
146 readbuf[readpos] = c; | |
147 readpos++; | |
148 if (readpos >= sizeof(readbuf)) | |
149 { | |
150 readpos = 0; | |
151 } | |
152 } | |
153 } | |
154 | |
308 | 155 ISR(TIMER2_COMPA_vect) |
307 | 156 { |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
157 measure_count ++; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
158 comms_count ++; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
159 if (measure_count == MEASURE_WAKE) |
307 | 160 { |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
161 measure_count = 0; |
307 | 162 need_measurement = 1; |
163 } | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
164 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
165 if (comms_count == COMMS_WAKE) |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
166 { |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
167 comms_count = 0; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
168 need_comms = 1; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
169 } |
307 | 170 } |
171 | |
309 | 172 DWORD get_fattime (void) |
173 { | |
174 return 0; | |
175 } | |
176 | |
307 | 177 static void |
178 deep_sleep() | |
179 { | |
180 // p119 of manual | |
308 | 181 OCR2A = SLEEP_COMPARE; |
182 loop_until_bit_is_clear(ASSR, OCR2AUB); | |
307 | 183 |
184 set_sleep_mode(SLEEP_MODE_PWR_SAVE); | |
185 sleep_mode(); | |
186 } | |
187 | |
188 static void | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
189 idle_sleep() |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
190 { |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
191 set_sleep_mode(SLEEP_MODE_IDLE); |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
192 sleep_mode(); |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
193 } |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
194 |
312 | 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 | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
248 static void |
307 | 249 do_measurement() |
250 { | |
251 need_measurement = 0; | |
312 | 252 |
253 do_adc_335(); | |
307 | 254 } |
255 | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
256 static void |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
257 do_comms() |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
258 { |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
259 need_comms = 0; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
260 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
261 // turn on bluetooth |
312 | 262 uart_on(UBRR); |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
263 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
264 // write sd card here? same 3.3v regulator... |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
265 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
266 comms_done = 0; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
267 for (;;) |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
268 { |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
269 if (comms_done) |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
270 { |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
271 break; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
272 } |
312 | 273 |
274 if (need_measurement) | |
275 { | |
276 do_measurement(); | |
277 } | |
278 | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
279 idle_sleep(); |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
280 } |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
281 |
312 | 282 uart_off(); |
283 | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
284 // turn off bluetooth |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
285 } |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
286 |
306 | 287 int main(void) |
288 { | |
312 | 289 stdout = &mystdout; |
290 uart_on(UBRR); | |
291 fprintf_P(&mystdout, PSTR("hello %d\n"), 12); | |
292 uart_off(); | |
306 | 293 |
312 | 294 // turn off everything except timer2 |
295 PRR = _BV(PRTWI) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC); | |
306 | 296 |
307 | 297 // set up counter2. |
298 // COM21 COM20 Set OC2 on Compare Match (p116) | |
299 // WGM21 Clear counter on compare | |
300 // CS22 CS21 CS20 clk/1024 | |
308 | 301 TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); |
302 TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); | |
307 | 303 // set async mode |
304 ASSR |= _BV(AS2); | |
306 | 305 |
312 | 306 #ifdef TEST_MODE |
307 for (;;) | |
308 { | |
309 do_comms() | |
310 } | |
311 #else | |
306 | 312 for(;;){ |
313 /* insert your main loop code here */ | |
307 | 314 if (need_measurement) |
315 { | |
316 do_measurement(); | |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
317 continue; |
307 | 318 } |
310
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
319 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
320 if (need_comms) |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
321 { |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
322 do_comms(); |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
323 continue; |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
324 } |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
325 |
0a64532c1de1
Fill out more main.c structure
Matt Johnston <matt@ucc.asn.au>
parents:
309
diff
changeset
|
326 deep_sleep(); |
306 | 327 } |
312 | 328 #endif |
306 | 329 return 0; /* never reached */ |
330 } |