123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /*---------------------------------------------------------------*
- * Automotive GPS logger (C)ChaN, 2014 *
- * Modified k4be, 2022 *
- *---------------------------------------------------------------*/
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- #include <string.h>
- #include "main.h"
- #include "ff.h"
- #include "diskio.h"
- #include "uart0.h"
- #include "uart1.h"
- #include "xitoa.h"
- #include "stime.h"
- FUSES = {0xFF, 0x11, 0xFE}; /* ATmega644PA fuses: Low, High, Extended.
- This is the fuse settings for this project. The fuse bits will be included
- in the output hex file with program code. However some old flash programmers
- cannot load the fuse bits from hex file. If it is the case, remove this line
- and use these values to program the fuse bits. */
- FATFS Fatfs; /* File system object for each logical drive */
- FIL File1; /* File object */
- char Line[100]; /* Line buffer */
- volatile BYTE Timer; /* 100Hz decrement timer */
- /*---------------------------------------------------------*/
- /* 100Hz timer interrupt generated by OC1A */
- /*---------------------------------------------------------*/
- ISR(TIMER1_COMPA_vect)
- {
- BYTE n;
- static WORD ivt_sync;
- static BYTE led;
- n = Timer;
- if (n) Timer = --n;;
- /* Sync interval */
- if (IVT_SYNC && ++ivt_sync >= IVT_SYNC * 100) {
- ivt_sync = 0;
- FLAGS |= F_SYNC;
- }
- /* Green LED drive */
- if (FLAGS & F_POW) {
- if ((FLAGS & F_GPSOK) || (++led & 0x20)) {
- LEDG_ON();
- } else {
- LEDG_OFF();
- }
- } else {
- LEDG_OFF();
- }
- /* MMC/SD timer procedure */
- disk_timerproc();
- }
- /* Power supply monitor */
- ISR(ADC_vect)
- {
- WORD ad;
- static BYTE lvt;
- ad = ADC * 100;
- if (FLAGS & F_LVD) {
- if (ad > (WORD)(VI_LVH * VI_MULT) * 100) {
- FLAGS &= ~F_LVD;
- lvt = 0;
- }
- } else {
- if (ad < (WORD)(VI_LVL * VI_MULT) * 100) {
- if (++lvt >= 10)
- FLAGS |= F_LVD;
- } else {
- lvt = 0;
- }
- }
- }
- /*---------------------------------------------------------*/
- /* User Provided Timer Function for FatFs module */
- /*---------------------------------------------------------*/
- DWORD get_fattime (void)
- {
- return 0;
- }
- /*----------------------------------------------------*/
- /* Get a line received from GPS module */
- /*----------------------------------------------------*/
- UINT get_line ( /* 0:Brownout, >0: Number of bytes received. */
- char *buff,
- UINT sz_buf
- )
- {
- char c;
- UINT i = 0;
- for (;;) {
- if (FLAGS & F_LVD) return 0; /* A brownout is detected */
- if (!uart0_test()) continue;
- c = (char)uart0_get();
- xputc(c);
- if (i == 0 && c != '$') continue; /* Find start of line */
- buff[i++] = c;
- if (c == '\n') break; /* EOL */
- if (i >= sz_buf) i = 0; /* Buffer overflow (abort this line) */
- }
- return i;
- }
- /*--------------------------------------------------------------------------*/
- /* Controls */
- void beep (UINT len, BYTE cnt)
- {
- while (cnt--) {
- BEEP_ON();
- DELAY_MS(len);
- BEEP_OFF();
- DELAY_MS(len);
- }
- }
- /* Compare sentence header string */
- BYTE gp_comp (const char *str1, const prog_char *str2)
- {
- char c;
- do {
- c = pgm_read_byte(str2++);
- } while (c && c == *str1++);
- return c;
- }
- /* Get a column item */
- static
- BYTE* gp_col ( /* Returns pointer to the item (returns a NULL when not found) */
- const char* buf, /* Pointer to the sentence */
- BYTE col /* Column number (0 is the 1st item) */
- ) {
- BYTE c;
- while (col) {
- do {
- c = *buf++;
- if (c <= ' ') return NULL;
- } while (c != ',');
- col--;
- }
- return (BYTE*)buf;
- }
- static
- BYTE gp_val2 (
- const BYTE *db
- )
- {
- BYTE n, m;
- n = db[0] - '0';
- if (n >= 10) return 0;
- m = db[1] - '0';
- if (m >= 10) return 0;
- return n * 10 + m;
- }
- static
- time_t gp_rmctime ( /* Get GPS status from RMC sentence */
- const char *str
- )
- {
- const BYTE *p;
- struct tm tmc;
- time_t utc;
- if (gp_comp(str, PSTR("$GPRMC"))) return 0; /* Not the RMC */
- p = gp_col(str, 2); /* Get status */
- if (!p || *p != 'A') {
- FLAGS &= ~F_GPSOK;
- return 0;
- }
- p = gp_col(str, 1); /* Get h:m:s */
- if (!p) return 0;
- tmc.tm_hour = gp_val2(p);
- tmc.tm_min = gp_val2(p+2);
- tmc.tm_sec = gp_val2(p+4);
- p = gp_col(str, 9); /* Get y:m:d */
- if (!p) return 0;
- tmc.tm_mday = gp_val2(p);
- tmc.tm_mon = gp_val2(p+2) - 1;
- tmc.tm_year = gp_val2(p+4) + 100;
- utc = mktime(&tmc); /* Check time validity */
- if (utc == -1) return 0;
- FLAGS |= F_GPSOK;
- return utc;
- }
- static
- void ioinit (void)
- {
- PORTB = 0b00000011; /* --zzzzHH */
- DDRB = 0b00000011;
- PORTC = 0b00111101; /* --uuuuLH */
- DDRC = 0b00000011;
- PORTD = 0b10111110; /* uLuuuuHz */
- DDRD = 0b01000010;
- OCR1A = F_CPU/8/100-1; /* Timer1: 100Hz interval (OC1A) */
- TCCR1B = _BV(WGM12) | _BV(CS11);
- TIMSK1 = _BV(OCIE1A); /* Enable TC1.oca interrupt */
- ACSR = _BV(ACD); /* Disable analog comp */
- /* ADC */
- ADMUX = 0;
- ADCSRA = _BV(ADEN)|_BV(ADSC)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);
-
- /* uart1 (debug) */
- uart1_init();
- sei();
- }
- /*-----------------------------------------------------------------------*/
- /* Main */
- /*-----------------------------------------------------------------------*/
- int main (void)
- {
- UINT bw, len, err;
- struct tm *ct;
- time_t utc;
- FRESULT res;
- ioinit();
- xdev_out(uart1_put);
- err = 0;
- for (;;) {
- beep(250, err); /* Error beep */
- err = 0;
- /* Wait for supply voltage stabled */
- while (FLAGS & F_LVD) {};
- DELAY_MS(500);
- if (FLAGS & F_LVD) continue;
- if (disk_status(0) & STA_NODISK) continue;
- res = f_mount(&Fatfs, "", 1);
- if (res != FR_OK) {
- xprintf(PSTR("FS error %u\r\n"), res);
- err = 2; continue;
- }
- xputs(PSTR("FS Ok\r\n"));
- beep(50, 1); /* 1 beep */
- /* Initialize GPS receiver */
- GPS_ON(); /* GPS power on */
- FLAGS |= F_POW;
- DELAY_MS(300); /* Delay */
- uart0_init(); /* Enable UART */
- // xfprintf(uart0_put, PSTR("$PSRF106,21*0F\r\n")); /* Send initialization command (depends on the receiver) */
- utc = 0;
- for (;;) {
- len = get_line(Line, sizeof Line); /* Receive a line from GPS receiver */
- if (!len) break; /* Brownout? */
- if (!utc) {
- utc = gp_rmctime(Line); /* Get time in UTC from a valid RMC sentence */
- if (utc) {
- utc += LOCALDIFF * 3600L; /* Local time */
- ct = gmtime(&utc);
- xsprintf(Line, PSTR("%02u%02u%02u.LOG"), ct->tm_year % 100, ct->tm_mon + 1, ct->tm_mday);
- xprintf(PSTR("Open %s\r\n"), Line);
- if (f_open(&File1, Line, FA_WRITE | FA_OPEN_ALWAYS) /* Open log file */
- || f_lseek(&File1, f_size(&File1)) /* Append mode */
- || f_write(&File1, "\r\n", 2, &bw)) /* Put a blank line as start marker */
- {
- utc = 0; err = 2; break; /* Failed to start logging */
- }
- beep(50, 2); /* Two beeps. Start logging. */
- }
- } else {
- gp_rmctime(Line);
- f_write(&File1, Line, len, &bw);
- if (bw != len) {
- err = 3; break;
- }
- if (FLAGS & F_SYNC) {
- if (f_sync(&File1)) {
- err = 2; break;
- }
- FLAGS &= ~F_SYNC;
- }
- }
- }
- /* Stop GPS receiver */
- uart0_deinit();
- GPS_OFF();
- FLAGS &= ~F_POW;
- /* Close file */
- if (utc && f_close(&File1)) err = 2;
- disk_ioctl(0, CTRL_POWER_OFF, 0);
- if (!err) beep(500, 1); /* Long beep on file close succeeded */
- }
- }
|