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 }