Rev Author Line No. Line
1234 kaklik 1 /*---------------------------------------------------------------*/
2 /* GPS data logger R0.02 (C)ChaN, 2008 */
3 /*---------------------------------------------------------------*/
4  
5 #include <avr/io.h>
6 #include <avr/pgmspace.h>
7 #include <avr/interrupt.h>
8 #include <string.h>
9 #include "tff.h"
10 #include "diskio.h"
11  
12  
13 #define SYSCLK 10000000UL
14  
15 #define BEEP_ON() TCCR0B=0b011
16 #define BEEP_OFF() TCCR0B=0b000
17 #define GPS_ON() PORTB|=0x02
18 #define GPS_OFF() PORTB&=0xFD
19 #define DELAY(dly) for(Timer=dly;Timer;)
20  
21 #define VTH_LOW (WORD)(8000UL*100/3838)
22 #define VTH_HIGH (WORD)(11500UL*100/3838)
23 #define POWER_check 0b01000000 | 1
24 #define ANALOG_IN1 0b01000000 | 2
25  
26  
27 FATFS fatfs; /* File system object for each logical drive */
28 FIL file1; /* File object */
29 BYTE Buff[82]; /* File/Console buffer */
30  
31 BYTE Value1[4]; // logged values
32 BYTE Value2[4];
33  
34 uint16_t battery; // battery voltage
35 uint16_t intensity; // radiation intensity
36  
37 volatile BYTE Timer; /* 100Hz decrement timer */
38 volatile BYTE Stat; /* Status */
39  
40  
41 typedef struct _fifo {
42 uint8_t idx_w;
43 uint8_t idx_r;
44 uint8_t count;
45 uint8_t buff[150];
46 } FIFO;
47 volatile FIFO rxfifo;
48  
49  
50  
51 /*---------------------------------------------------------*/
52 /* ADC interrupt */
53 /*---------------------------------------------------------*/
54  
55 ISR(ADC_vect)
56 {
57 WORD n;
58 static BYTE l, h;
59  
60 n = ADC;
61  
62 if(ADMUX == POWER_check)
63 {
64 if (n < VTH_LOW) {
65 if (l >= 15) {
66 Stat |= 0x01;
67 }
68 else {l++;}
69 }
70 else {l = 0;}
71  
72 if (n > VTH_HIGH) {
73 if (h >= 15) {
74 Stat &= 0xFE;
75 }
76 else {h++;}
77 }
78 else {h = 0;}
79  
80 battery = n;
81 ADMUX = ANALOG_IN1;
82 }
83  
84 if(ADMUX == ANALOG_IN1)
85 {
86 intensity = n;
87 ADMUX = POWER_check;
88 }
89  
90 //!!!!
91 //Stat &= 0xFE;
92  
93 ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
94 }
95  
96  
97 /*---------------------------------------------------------*/
98 /* 100Hz timer interrupt generated by OC1A */
99 /*---------------------------------------------------------*/
100  
101  
102 ISR(TIMER1_COMPA_vect)
103 {
104 BYTE n;
105 static WORD ivt_sync;
106  
107  
108 n = Timer;
109 if (n) Timer = n - 1;
110  
111 if (++ivt_sync >= 180 * 100) {
112 ivt_sync = 0;
113 Stat |= 4;
114 }
115  
116 disk_timerproc(); /* Drive timer procedure of low level disk I/O module */
117  
118 }
119  
120  
121  
122 /*---------------------------------------------------------*/
123 /* User Provided Timer Function for FatFs module */
124 /*---------------------------------------------------------*/
125 /* This is a real time clock service to be called from */
126 /* FatFs module. Any valid time must be returned even if */
127 /* the system does not support a real time clock. */
128  
129  
130 DWORD get_fattime ()
131 {
132 return ((2007UL - 1980) << 25) /* Fixed to 2007.5.1, 00:00:00 */
133 | ((5UL) << 21)
134 | ((1UL) << 16)
135 | (0 << 11)
136 | (0 << 5)
137 | (0 >> 1);
138 }
139  
140  
141 /*--------------------------------------------------------------------------*/
142 /* UART control */
143  
144  
145 static
146 void uart_init (void)
147 {
148 cli();
149 UCSR0B = 0;
150 rxfifo.idx_r = 0;
151 rxfifo.idx_w = 0;
152 rxfifo.count = 0;
153 UBRR0L = SYSCLK/16/9600; // Enable USRAT0 in N81,4800bps
154 UCSR0B = _BV(RXCIE0)|_BV(RXEN0)|_BV(TXEN0);
155 Stat &= 0xFD; // Clear overflow flag
156 sei();
157 }
158  
159  
160 static
161 void uart_stop (void)
162 {
163 UCSR0B = 0;
164 }
165  
166  
167 /* Get a received character */
168 static
169 uint8_t uart_get ()
170 {
171 uint8_t d, i;
172  
173  
174 i = rxfifo.idx_r;
175 if (rxfifo.count == 0) return 0;
176 d = rxfifo.buff[i++];
177 cli();
178 rxfifo.count--;
179 sei();
180 if(i >= sizeof(rxfifo.buff))
181 i = 0;
182 rxfifo.idx_r = i;
183  
184 return d;
1271 kaklik 185 }
1234 kaklik 186  
187 ISR(USART_RX_vect)
188 {
189 uint8_t d, n, i;
190
191  
192  
193 n = rxfifo.count;
194 if(n < sizeof(rxfifo.buff)) {
195 rxfifo.count = ++n;
196 i = rxfifo.idx_w;
197 rxfifo.buff[i++] = d;
198 if(i >= sizeof(rxfifo.buff))
199 i = 0;
200 rxfifo.idx_w = i;
201 } else {
202 Stat |= 2;
203 }
204 }
205
206  
207  
208  
209 /* Get a line received from GPS module */
210 /*----------------------------------------------------*/
211
212  
213 BYTE get_line (void) // 0: Power fail occured, >0: Number of bytes received.
214 {
215 BYTE c, i = 0;
216
217  
218  
219 if (Stat & 1) return 0; // When power fail is detected, return with zero.
220 c = uart_get();
221 if (Stat & 2) { // When buffer overflow has occured, restert to receive line.
222 uart_init();
223 i = 0; c = 0;
224 }
225 if (!c || (i == 0 && c != '$')) continue;
226 Buff[i++] = c;
227 if (c == '\n') break;
228 if (i >= sizeof(Buff)) i = 0;
229 }
230 return i;
231 }
232
233  
234  
235  
236 /* Controls */
237
238  
239 void beep (BYTE len, BYTE cnt)
240 {
241 while (cnt--) {
242 BEEP_ON();
243 DELAY(len);
244 BEEP_OFF();
245 DELAY(len);
246 }
247 }
248
249  
250  
251  
252  
253 static
254 BYTE gp_comp (BYTE *str1, const prog_uint8_t *str2)
255 {
256 BYTE c;
257
258  
259 c = pgm_read_byte(str2++);
260 } while (c && c == *str1++);
261 return c;
262 }
263
264  
265 static
266 BYTE* gp_col ( /* Returns pointer to the item (returns a NULL when not found) */
267 const BYTE* buf, /* Pointer to the sentence */
268 BYTE col /* Column number (0 is the 1st item) */
269 ) {
270 BYTE c;
271
272  
273  
274 do {
275 c = *buf++;
276 if (c <= ' ') return NULL;
277 } while (c != ',');
278 col--;
279 }
280 return (BYTE*)buf;
281 }
282
283  
284  
285  
286 void ioinit (void)
287 {
288 PORTB = 0b00001101; // Port B
289 DDRB = 0b00101110;
290 PORTC = 0b00111111; // Port C
291 DDRC = 0b00000000;
292 PORTD = 0b10101110; // Port D
293 DDRD = 0b01010010;
294
295  
296 SPSR = 0b00000001;
297
298  
299 TCCR1B = 0b00001010;
300 TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt
301
302  
303 TCCR0A = 0b01000010;
304
305  
306 ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADIF)|_BV(ADIE)|0b111;
307
308  
309 }
310
311  
312  
313  
314 /* Main */
315
316  
317  
318 {
319 BYTE b, err, *p = NULL;
320 WORD s;
321
322  
323  
324 f_mount(0, &fatfs); /* Enable file I/O layer */
325
326  
327 uart_stop();
328 GPS_OFF();
329 Timer = 100;
330 do {
331 if (Stat & 1) Timer = 100;
332 } while (Timer);
333
334  
335 Timer = 255;
336 do {
337 if ((Stat & 1) || (disk_status(0) & STA_NODISK)) Timer = 255;
338 } while (Timer);
339
340  
341 uart_init();
342 do { // Wait for valid RMC sentence.
343 b = get_line();
344 if (!b) break;
345 if (gp_comp(Buff, PSTR("$GPRMC"))) continue;
346 p = gp_col(Buff,2);
347 } while (!p || *p != 'A');
348 if (!b) continue;
349 p = gp_col(Buff,9); // Open log file with the name of current date (YYMMDD.log in UTC).
350
351  
352
353  
354 memcpy(&Buff[2], p+2, 2);
355 memcpy(&Buff[4], p+0, 2);
356 strcpy_P(&Buff[6], PSTR(".log"));
357 if (f_open(&file1, Buff, FA_OPEN_ALWAYS | FA_WRITE) || f_lseek(&file1, file1.fsize)) { err = 4; break; }
358
359  
360 err = 0;
361 while ((b = get_line()) > 0) {
362 if ( !gp_comp(Buff, PSTR("$GPGGA")) // Which sentence is logged?
363 || !gp_comp(Buff, PSTR("$GPRMC"))
364 // || !gp_comp(Buff, PSTR("$GPGSA"))
365 // || !gp_comp(Buff, PSTR("$GPGLL"))
366 // || !gp_comp(Buff, PSTR("$GPGSV"))
367 // || !gp_comp(Buff, PSTR("$GPZDA"))
368 // || !gp_comp(Buff, PSTR("$GPVTG"))
369 )
370 {
371 if (f_write(&file1, Buff, b, &s) || b != s) { err = 5; break; };
372 /* itoa(battery,&Value1,10); // convert binary number to character
1271 kaklik 373 itoa(intensity,&Value2,10);
1234 kaklik 374 strcpy(&Buff[0], Value1);
375 strcpy_P(&Buff[4], PSTR(","));
376 strcpy(&Buff[5], Value2);
377 strcpy_P(&Buff[9], PSTR("\r\n"));
378 if (f_write(&file1, Buff, 11, &s) || 11 != s) { err = 8; break; };
1271 kaklik 379 */ }
380 if ((Stat & 4) == 0) continue;
1234 kaklik 381 if (f_sync(&file1)) { err = 6; break; };// Synchronize the file in interval of 300 sec.
382 cli(); Stat &= 0xFB; sei(); // Clear sync request
383 }
384 if (err) break;
385
386  
387 uart_stop();
388 GPS_OFF();
389 if (f_close(&file1)) { err = 7; break; };
390
391  
392 beep(50, 1);
393 }
394
395  
396 uart_stop();
397 GPS_OFF();
398 beep(25, err);
399 for (;;);
400 }
401
402  
403