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