123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- /*---------------------------------------------------------------*
- * Automotive GPS logger (C)ChaN, 2014 *
- * Modified k4be, 2022 *
- *---------------------------------------------------------------*/
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <avr/sleep.h>
- #include <util/delay.h>
- #include <avr/pgmspace.h>
- #include <string.h>
- #include "main.h"
- #include "ff.h"
- #include "diskio.h"
- #include "uart0.h"
- #include "uart1.h"
- #include "xprintf.h"
- #include "stime.h"
- #include "ds18b20.h"
- #include "I2C.h"
- #include "expander.h"
- #include "HD44780-I2C.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. */
- volatile struct system_s System;
- FATFS Fatfs; /* File system object for each logical drive */
- FIL File1; /* File object */
- char Line[100]; /* Line buffer */
- time_t utc; /* current time */
- /*---------------------------------------------------------*/
- /* 100Hz timer interrupt generated by OC1A */
- /*---------------------------------------------------------*/
- ISR(TIMER1_COMPA_vect)
- {
- static WORD ivt_sync;
- static BYTE led;
- unsigned int *volatile ctimer;
- unsigned char i;
-
- for(i=0; i<sizeof(System.timers)/sizeof(unsigned int); i++){ // decrement every variable from timers struct unless it's already zero
- ctimer = ((unsigned int *)&System.timers) + i;
- if(*ctimer)
- (*ctimer)--;
- }
- /* 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;
- set_timer(recv_timeout, 1000);
- for (;;) {
- if (FLAGS & F_LVD)
- return 0; /* A brownout is detected */
- if (timer_expired(recv_timeout))
- return 0; /* timeout; continue the main loop */
- 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();
- set_timer(beep, len);
- while(!timer_expired(beep)) {};
- BEEP_OFF();
- set_timer(beep, len);
- while(!timer_expired(beep)) {};
- }
- }
- /* Compare sentence header string */
- BYTE gp_comp (const char *str1, __flash const 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)
- {
- BUZZER_DDR |= BUZZER;
- GPS_DIS_DDR |= GPS_DIS;
- LEDR_DDR |= LEDR;
- 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(ADATE)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);
-
- /* uart1 (debug) */
- uart1_init();
-
- I2C_init();
- expander_init(0, 0x00, 0x00); /* all as outputs */
- LCD_Initialize();
- LCD_Clear();
- sei();
-
- ADCSRA |= _BV(ADSC);
- }
- /*-----------------------------------------------------------------------*/
- /* Main */
- /*-----------------------------------------------------------------------*/
- int main (void)
- {
- UINT bw, len;
- struct tm *ct;
- time_t tmp_utc;
- FRESULT res;
- unsigned char prev_status;
- ioinit();
- xdev_out(uart1_put);
- for (;;) {
- utc = 0;
- prev_status = System.status;
- System.status = STATUS_NO_POWER;
- beep(250, prev_status); /* Error beep */
- /* Wait for supply voltage stabled */
- while (FLAGS & F_LVD) {};
- _delay_ms(500);
- if (FLAGS & F_LVD)
- continue;
- /* report error here ( prev_status) */
- if (disk_status(0) & STA_NODISK) {
- System.status = STATUS_NO_DISK;
- continue;
- }
- res = f_mount(&Fatfs, "", 1);
- if (res != FR_OK) {
- xprintf(PSTR("FS error %u\r\n"), res);
- System.status = STATUS_DISK_ERROR;
- continue;
- }
- System.status = STATUS_NO_GPS;
- 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) */
- for (;;) { /* main loop */
- gettemp();
- if (!(FLAGS & F_GPSOK))
- xputs_P(PSTR("Waiting for GPS\r\n"));
- len = get_line(Line, sizeof Line); /* Receive a line from GPS receiver */
- if (!len){
- if (FLAGS & F_LVD)
- break; /* brownout */
- continue;
- }
- tmp_utc = gp_rmctime(Line);
- if (tmp_utc)
- utc = tmp_utc + LOCALDIFF * 3600L; /* Local time */
- if (utc && !(FLAGS & F_FILEOPEN)) {
- 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 */
- {
- System.status = STATUS_FILE_OPEN_ERROR;
- break; /* Failed to start logging */
- }
- FLAGS |= F_FILEOPEN;
- System.status = STATUS_OK;
- beep(50, 2);
- continue; /* Two beeps. Start logging. */
- }
- if (FLAGS & F_FILEOPEN) {
- f_write(&File1, Line, len, &bw);
- if (bw != len) {
- System.status = STATUS_FILE_WRITE_ERROR;
- break;
- }
- if (FLAGS & F_SYNC) {
- if (f_sync(&File1)) {
- System.status = STATUS_FILE_SYNC_ERROR;
- break;
- }
- FLAGS &= ~F_SYNC;
- }
- }
- }
- /* Stop GPS receiver */
- uart0_deinit();
- GPS_OFF();
- FLAGS &= ~F_POW;
- /* Close file */
- if (FLAGS & F_FILEOPEN) {
- if (f_close(&File1))
- System.status = STATUS_FILE_CLOSE_ERROR;
- xputs_P(PSTR("File closed\r\n"));
- }
- FLAGS &= ~F_FILEOPEN;
- disk_ioctl(0, CTRL_POWER, 0);
- if (System.status != STATUS_FILE_CLOSE_ERROR)
- beep(500, 1); /* Long beep on file close succeeded */
- }
- }
|