main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*---------------------------------------------------------------*
  2. * Automotive GPS logger (C)ChaN, 2014 *
  3. * Modified k4be, 2022 *
  4. *---------------------------------------------------------------*/
  5. #include <avr/io.h>
  6. #include <avr/interrupt.h>
  7. #include <avr/sleep.h>
  8. #include <util/delay.h>
  9. #include <avr/pgmspace.h>
  10. #include <avr/wdt.h>
  11. #include <string.h>
  12. #include "main.h"
  13. #include "ff.h"
  14. #include "diskio.h"
  15. #include "uart0.h"
  16. #include "uart1.h"
  17. #include "xprintf.h"
  18. #include "stime.h"
  19. #include "ds18b20.h"
  20. #include "I2C.h"
  21. #include "expander.h"
  22. #include "HD44780-I2C.h"
  23. #include "gpx.h"
  24. /*FUSES = {0xFF, 0x11, 0xFE};*/ /* ATmega644PA fuses: Low, High, Extended.
  25. This is the fuse settings for this project. The fuse bits will be included
  26. in the output hex file with program code. However some old flash programmers
  27. cannot load the fuse bits from hex file. If it is the case, remove this line
  28. and use these values to program the fuse bits. */
  29. volatile struct system_s System;
  30. FATFS Fatfs; /* File system object for each logical drive */
  31. FIL gps_log; /* File object */
  32. FIL system_log; /* System log file */
  33. char Line[100]; /* Line buffer */
  34. time_t utc; /* current time */
  35. struct location_s location;
  36. void start_bootloader(void) {
  37. typedef void (*do_reboot_t)(void);
  38. const do_reboot_t do_reboot = (do_reboot_t)((FLASHEND - 1023) >> 1);
  39. cli();
  40. LCD_Clear();
  41. LCD_GoTo(0,0);
  42. LCD_WriteTextP(PSTR("Aktualizacja"));
  43. LCD_GoTo(8,1);
  44. LCD_WriteTextP(PSTR("softu..."));
  45. TCCR0A = TCCR1A = TCCR2A = 0; // make sure interrupts are off and timers are reset.
  46. do_reboot();
  47. wdt_enable(WDTO_15MS);
  48. while(1);
  49. }
  50. /*---------------------------------------------------------*/
  51. /* 100Hz timer interrupt generated by OC1A */
  52. /*---------------------------------------------------------*/
  53. ISR(TIMER1_COMPA_vect)
  54. {
  55. static WORD ivt_sync;
  56. // static BYTE led;
  57. static unsigned int power_sw;
  58. unsigned int *volatile ctimer;
  59. unsigned char i;
  60. for(i=0; i<sizeof(System.timers)/sizeof(unsigned int); i++){ // decrement every variable from timers struct unless it's already zero
  61. ctimer = ((unsigned int *)&System.timers) + i;
  62. if(*ctimer)
  63. (*ctimer)--;
  64. }
  65. /* Sync interval */
  66. if (IVT_SYNC && ++ivt_sync >= IVT_SYNC * 100) {
  67. ivt_sync = 0;
  68. FLAGS |= F_SYNC;
  69. }
  70. /* Green LED drive */
  71. /* if (FLAGS & F_POW) {
  72. if ((FLAGS & F_GPSOK) || (++led & 0x20)) {
  73. LEDG_ON();
  74. } else {
  75. LEDG_OFF();
  76. }
  77. } else {
  78. LEDG_OFF();
  79. }*/
  80. /* MMC/SD timer procedure */
  81. disk_timerproc();
  82. /* Switch off */
  83. if (POWER_SW_PRESSED()) {
  84. if (++power_sw == POWER_SW_TIME){
  85. FLAGS |= F_POWEROFF;
  86. power_sw++;
  87. }
  88. } else {
  89. power_sw = 0;
  90. }
  91. if (uart1_test() && uart1_get() == '0' && uart1_get() == ' '){
  92. LEDB_ON();
  93. start_bootloader();
  94. LEDR_ON();
  95. }
  96. }
  97. /* Power supply monitor */
  98. ISR(ADC_vect)
  99. {
  100. float bat_volt;
  101. static unsigned int adc_buf;
  102. static unsigned char adc_cnt;
  103. static BYTE lvt;
  104. adc_buf += ADC;
  105. if(++adc_cnt < 15)
  106. return;
  107. bat_volt = (float)adc_buf/(float)(adc_cnt)/VI_MULT;
  108. adc_buf = 0;
  109. adc_cnt = 0;
  110. System.bat_volt = bat_volt;
  111. if (FLAGS & F_LVD) {
  112. if (bat_volt > VI_LVH) {
  113. FLAGS &= ~F_LVD;
  114. lvt = 0;
  115. }
  116. } else {
  117. if (bat_volt < VI_LVL) {
  118. if (++lvt >= 3)
  119. FLAGS |= F_LVD;
  120. } else {
  121. lvt = 0;
  122. }
  123. }
  124. }
  125. /*---------------------------------------------------------*/
  126. /* User Provided Timer Function for FatFs module */
  127. /*---------------------------------------------------------*/
  128. DWORD get_fattime (void)
  129. {
  130. struct tm *stm;
  131. time_t localtime = utc + LOCALDIFF;
  132. stm = gmtime(&localtime);
  133. return (DWORD)(stm->tm_year - 80) << 25 |
  134. (DWORD)(stm->tm_mon + 1) << 21 |
  135. (DWORD)stm->tm_mday << 16 |
  136. (DWORD)stm->tm_hour << 11 |
  137. (DWORD)stm->tm_min << 5 |
  138. (DWORD)stm->tm_sec >> 1;
  139. }
  140. static void sleep(void) {
  141. set_sleep_mode(SLEEP_MODE_IDLE);
  142. sleep_enable();
  143. sleep_cpu();
  144. sleep_disable();
  145. }
  146. /*----------------------------------------------------*/
  147. /* Get a line received from GPS module */
  148. /*----------------------------------------------------*/
  149. UINT get_line ( /* 0:Brownout or timeout, >0: Number of bytes received. */
  150. char *buff,
  151. UINT sz_buf
  152. )
  153. {
  154. char c;
  155. UINT i = 0;
  156. set_timer(recv_timeout, 1000);
  157. for (;;) {
  158. wdt_reset();
  159. if (FLAGS & (F_LVD | F_POWEROFF))
  160. return 0; /* A brownout is detected */
  161. if (timer_expired(recv_timeout))
  162. return 0; /* timeout; continue the main loop */
  163. if (!uart0_test()) {
  164. sleep();
  165. continue;
  166. }
  167. c = (char)uart0_get();
  168. uart1_put(c);
  169. if (i == 0 && c != '$')
  170. continue; /* Find start of line */
  171. buff[i++] = c;
  172. if (c == '\n')
  173. break; /* EOL */
  174. if (i >= sz_buf)
  175. i = 0; /* Buffer overflow (abort this line) */
  176. }
  177. return i;
  178. }
  179. /*--------------------------------------------------------------------------*/
  180. /* Controls */
  181. void beep (UINT len, BYTE cnt)
  182. {
  183. while (cnt--) {
  184. BEEP_ON();
  185. set_timer(beep, len);
  186. while(!timer_expired(beep)) {};
  187. BEEP_OFF();
  188. set_timer(beep, len);
  189. while(!timer_expired(beep)) {};
  190. }
  191. }
  192. /* Make ISO time string */
  193. const char *get_iso_time(time_t time) {
  194. static char output[32];
  195. struct tm *ct = gmtime(&time);
  196. xsprintf(output, PSTR("%4u-%02u-%02uT%02u:%02u:%02u.000Z"), ct->tm_year+1900, ct->tm_mon+1, ct->tm_mday, ct->tm_hour, ct->tm_min, ct->tm_sec);
  197. return output;
  198. }
  199. /* Compare sentence header string */
  200. BYTE gp_comp (const char *str1, __flash const char *str2)
  201. {
  202. char c;
  203. do {
  204. c = pgm_read_byte(str2++);
  205. } while (c && c == *str1++);
  206. return c;
  207. }
  208. #define FIELD_BUF_LEN 32
  209. /* Get a column item */
  210. static
  211. const char* gp_col ( /* Returns pointer to the item (returns a NULL when not found) */
  212. const char* buf, /* Pointer to the sentence */
  213. BYTE col /* Column number (0 is the 1st item) */
  214. ) {
  215. BYTE c;
  216. static char field_buf[FIELD_BUF_LEN];
  217. unsigned char length = 0;
  218. while (col) {
  219. do {
  220. c = *buf++;
  221. if (c <= ' ') return NULL;
  222. } while (c != ',');
  223. col--;
  224. }
  225. while (*buf && *buf != ',' && length < FIELD_BUF_LEN-1) {
  226. field_buf[length++] = *buf++;
  227. }
  228. field_buf[length] = '\0';
  229. return field_buf;
  230. }
  231. static
  232. BYTE gp_val2 (
  233. const char *db
  234. )
  235. {
  236. BYTE n, m;
  237. n = db[0] - '0';
  238. if (n >= 10)
  239. return 0;
  240. m = db[1] - '0';
  241. if (m >= 10)
  242. return 0;
  243. return n * 10 + m;
  244. }
  245. static
  246. UINT gp_val3 (
  247. const char *db
  248. )
  249. {
  250. BYTE n, m, l;
  251. n = db[0] - '0';
  252. if (n >= 10)
  253. return 0;
  254. m = db[1] - '0';
  255. if (m >= 10)
  256. return 0;
  257. l = db[2] - '0';
  258. if (l >= 10)
  259. return 0;
  260. return n * 100 + m * 10 + l;
  261. }
  262. static
  263. time_t gp_rmctime ( /* Get GPS status from RMC sentence */
  264. const char *str
  265. )
  266. {
  267. const char *p;
  268. struct tm tmc;
  269. double tmp;
  270. if (gp_comp(str, PSTR("$GPRMC")))
  271. return 0; /* Not the RMC */
  272. p = gp_col(str, 1); /* Get h:m:s */
  273. if (!p)
  274. return 0;
  275. tmc.tm_hour = gp_val2(p);
  276. tmc.tm_min = gp_val2(p+2);
  277. tmc.tm_sec = gp_val2(p+4);
  278. p = gp_col(str, 9); /* Get y:m:d */
  279. if (!p)
  280. return 0;
  281. tmc.tm_mday = gp_val2(p);
  282. tmc.tm_mon = gp_val2(p+2) - 1;
  283. tmc.tm_year = gp_val2(p+4) + 100;
  284. utc = mktime(&tmc); /* Check time validity */
  285. if (utc == -1)
  286. return 0;
  287. p = gp_col(str, 2); /* Get status */
  288. if (!p || *p != 'A') {
  289. FLAGS &= ~F_GPSOK;
  290. return 0; /* Return 0 even is time is valid (comes from module's internal RTC) */
  291. }
  292. FLAGS |= F_GPSOK;
  293. /* parse location */
  294. p = gp_col(str, 3); /* latitude */
  295. location.lat = gp_val2(p); /* degrees */
  296. p += 2;
  297. xatof(&p, &tmp); /* minutes */
  298. tmp /= 60; /* convert minutes to degrees */
  299. location.lat += tmp;
  300. p = gp_col(str, 4); /* N/S */
  301. if (*p != 'N')
  302. location.lat = -location.lat;
  303. p = gp_col(str, 5); /* longitude */
  304. location.lon = gp_val3(p); /* degrees */
  305. p += 3;
  306. xatof(&p, &tmp); /* minutes */
  307. tmp /= 60; /* convert minutes to degrees */
  308. location.lon += tmp;
  309. p = gp_col(str, 6); /* E/W */
  310. if (*p != 'E')
  311. location.lon = -location.lon;
  312. location.time = utc;
  313. return utc;
  314. }
  315. #define LOG_SIZE 300
  316. struct {
  317. char buf[LOG_SIZE+1];
  318. unsigned int len;
  319. } logbuf;
  320. void log_put(char c){
  321. UINT bw;
  322. uart1_put(c);
  323. logbuf.buf[logbuf.len++] = c;
  324. if (logbuf.len >= LOG_SIZE && (FLAGS & F_FILEOPEN)) {
  325. if(!f_write(&system_log, logbuf.buf, logbuf.len, &bw))
  326. logbuf.len = 0;
  327. }
  328. if (logbuf.len > LOG_SIZE) {
  329. logbuf.len--;
  330. }
  331. }
  332. static
  333. void ioinit (void)
  334. {
  335. wdt_enable(WDTO_4S);
  336. MCUSR = 0;
  337. POWER_ON_DDR |= POWER_ON;
  338. PORTA |= POWER_ON;
  339. BUZZER_DDR |= BUZZER;
  340. GPS_DIS_DDR |= GPS_DIS;
  341. LEDR_DDR |= LEDR;
  342. OCR1A = F_CPU/8/100-1; /* Timer1: 100Hz interval (OC1A) */
  343. TCCR1B = _BV(WGM12) | _BV(CS11);
  344. TIMSK1 = _BV(OCIE1A); /* Enable TC1.oca interrupt */
  345. /* ADC */
  346. // ADMUX = 0;
  347. ADMUX = 1; // FIXME only testing battery voltage
  348. ADCSRA = _BV(ADEN)|_BV(ADATE)|_BV(ADIE)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);
  349. /* uart1 (debug) */
  350. uart1_init();
  351. I2C_init();
  352. expander_init(0, 0x00, 0x00); /* all as outputs */
  353. LCD_Initialize();
  354. LCD_Clear();
  355. sei();
  356. ADCSRA |= _BV(ADSC);
  357. /* unused pins */
  358. DDRA |= _BV(PA2) | _BV(PA4) | _BV(PA5);
  359. PRR0 |= _BV(PRTIM2) | _BV(PRTIM0);
  360. ACSR = _BV(ACD); /* Disable analog comp */
  361. }
  362. __flash const unsigned char battery_states[][8] = {
  363. {
  364. 0b01110,
  365. 0b11111,
  366. 0b11111,
  367. 0b11111,
  368. 0b11111,
  369. 0b11111,
  370. 0b11111,
  371. 0b11111,
  372. },
  373. {
  374. 0b01110,
  375. 0b11111,
  376. 0b10001,
  377. 0b11111,
  378. 0b11111,
  379. 0b11111,
  380. 0b11111,
  381. 0b11111,
  382. },
  383. {
  384. 0b01110,
  385. 0b11111,
  386. 0b10001,
  387. 0b10001,
  388. 0b10001,
  389. 0b11111,
  390. 0b11111,
  391. 0b11111,
  392. },
  393. {
  394. 0b01110,
  395. 0b11111,
  396. 0b10001,
  397. 0b10001,
  398. 0b10001,
  399. 0b10001,
  400. 0b10001,
  401. 0b11111,
  402. },
  403. };
  404. void battery_state_display(void) {
  405. unsigned char i;
  406. unsigned char index;
  407. if (System.bat_volt > 4.0)
  408. index = 0;
  409. else if (System.bat_volt > 3.7)
  410. index = 1;
  411. else if (System.bat_volt > 3.4)
  412. index = 2;
  413. else
  414. index = 3;
  415. LCD_WriteCommand(0x40 + 0); // 0x00
  416. for(i=0; i<8; i++){
  417. LCD_WriteData(battery_states[index][i]);
  418. };
  419. }
  420. __flash const char __open_msg[] = "Open %s\r\n";
  421. /*-----------------------------------------------------------------------*/
  422. /* Main */
  423. /*-----------------------------------------------------------------------*/
  424. int main (void)
  425. {
  426. UINT bw, len;
  427. static struct tm ct;
  428. time_t tmp_utc, localtime;
  429. FRESULT res;
  430. unsigned char prev_status;
  431. ioinit();
  432. xdev_out(log_put);
  433. xputs_P(PSTR("STARTUP\r\n"));
  434. LCD_GoTo(0,0);
  435. LCD_WriteTextP(PSTR("Uruchamianie... "));
  436. for (;;) {
  437. wdt_reset();
  438. if (FLAGS & (F_POWEROFF | F_LVD)) {
  439. xputs_P(PSTR("POWEROFF\r\n"));
  440. LCD_GoTo(0,0);
  441. LCD_WriteTextP(PSTR("Wylaczanie... "));
  442. if (FLAGS & F_LVD) {
  443. LCD_GoTo(0,1);
  444. LCD_WriteTextP(PSTR("Bateria slaba! "));
  445. _delay_ms(500);
  446. }
  447. POWEROFF();
  448. while (POWER_SW_PRESSED());
  449. _delay_ms(2000); /* wait for switch off */
  450. FLAGS &= ~F_POWEROFF; /* restart if power is not lost */
  451. POWERON();
  452. xputs_P(PSTR("RESTART\r\n"));
  453. }
  454. LCD_GoTo(0,0);
  455. LCD_WriteTextP(PSTR("Start "));
  456. LCD_GoTo(0,1);
  457. switch(System.status){
  458. case STATUS_NO_POWER: case STATUS_OK: case STATUS_NO_GPS: LCD_WriteTextP(PSTR(" ")); break;
  459. case STATUS_NO_DISK: LCD_WriteTextP(PSTR("Brak karty! ")); break;
  460. case STATUS_DISK_ERROR: LCD_WriteTextP(PSTR("Blad karty! ")); break;
  461. case STATUS_FILE_WRITE_ERROR: LCD_WriteTextP(PSTR("Blad zapisu! ")); break;
  462. case STATUS_FILE_SYNC_ERROR: LCD_WriteTextP(PSTR("Blad zapisu FAT!")); break;
  463. case STATUS_FILE_CLOSE_ERROR: LCD_WriteTextP(PSTR("Blad zamk.pliku!")); break;
  464. case STATUS_FILE_OPEN_ERROR: LCD_WriteTextP(PSTR("Blad otw. pliku!")); break;
  465. }
  466. xprintf(PSTR("LOOP err=%u\r\n"), (unsigned int)System.status);
  467. utc = 0;
  468. localtime = 0;
  469. prev_status = System.status;
  470. System.status = STATUS_NO_POWER;
  471. beep(250, prev_status); /* Error beep */
  472. /* Wait for supply voltage stabled */
  473. _delay_ms(500);
  474. if (FLAGS & F_LVD)
  475. continue;
  476. /* report error here ( prev_status) */
  477. if (disk_status(0) & STA_NODISK) {
  478. System.status = STATUS_NO_DISK;
  479. continue;
  480. }
  481. res = f_mount(&Fatfs, "", 1);
  482. if (res != FR_OK) {
  483. xprintf(PSTR("FS error %u\r\n"), res);
  484. System.status = STATUS_DISK_ERROR;
  485. continue;
  486. }
  487. System.status = STATUS_NO_GPS;
  488. xputs(PSTR("FS Ok\r\n"));
  489. LCD_GoTo(0,0);
  490. LCD_WriteTextP(PSTR("Karta OK! "));
  491. LCD_WriteData(0); /* battery symbol */
  492. LCD_GoTo(0,1);
  493. LCD_WriteTextP(PSTR("Czekam na GPS..."));
  494. beep(50, 1); /* 1 beep */
  495. /* Initialize GPS receiver */
  496. GPS_ON(); /* GPS power on */
  497. FLAGS |= F_POW;
  498. _delay_ms(300); /* Delay */
  499. uart0_init(); /* Enable UART */
  500. // xfprintf(uart0_put, PSTR("$PSRF106,21*0F\r\n")); /* Send initialization command (depends on the receiver) */
  501. for (;;) { /* main loop */
  502. wdt_reset();
  503. battery_state_display();
  504. gettemp();
  505. if (!(FLAGS & F_GPSOK))
  506. xputs_P(PSTR("Waiting for GPS\r\n"));
  507. len = get_line(Line, sizeof Line); /* Receive a line from GPS receiver */
  508. if (!len){
  509. if (FLAGS & (F_LVD | F_POWEROFF))
  510. break; /* brownout */
  511. continue;
  512. }
  513. tmp_utc = gp_rmctime(Line);
  514. if (tmp_utc) {
  515. localtime = tmp_utc + LOCALDIFF * 3600L; /* Local time */
  516. ct = *gmtime(&localtime);
  517. if (timer_expired(system_log)) {
  518. set_timer(system_log, 5000);
  519. xprintf(PSTR("Time: %u.%02u.%04u %u:%02u:%02u\r\n"), ct.tm_mday, ct.tm_mon + 1, ct.tm_year+1900, ct.tm_hour, ct.tm_min, ct.tm_sec);
  520. xprintf(PSTR("Bat volt: %.3f\r\n"), System.bat_volt);
  521. if (System.temperature_ok)
  522. xprintf(PSTR("Temp: %.2f\r\n"), System.temperature);
  523. else
  524. xputs_P(PSTR("Temperature unknown\r\n"));
  525. }
  526. LEDG_ON();
  527. _delay_ms(2);
  528. LEDG_OFF();
  529. }
  530. if (localtime && !(FLAGS & F_FILEOPEN)) {
  531. xsprintf(Line, PSTR("%04u-%02u-%02u_%02u-%02u-%02u.LOG"), ct.tm_year+1900, ct.tm_mon + 1, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec);
  532. xprintf(__open_msg, Line);
  533. if (f_open(&gps_log, Line, FA_WRITE | FA_OPEN_ALWAYS) /* Open log file */
  534. || f_lseek(&gps_log, f_size(&gps_log)) /* Append mode */
  535. || f_write(&gps_log, "\r\n", 2, &bw)) /* Put a blank line as start marker */
  536. {
  537. System.status = STATUS_FILE_OPEN_ERROR;
  538. break; /* Failed to start logging */
  539. }
  540. xsprintf(Line, PSTR("%04u-%02u-%02u_%02u-%02u-%02u.GPX"), ct.tm_year+1900, ct.tm_mon + 1, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec);
  541. xprintf(__open_msg, Line);
  542. if (f_open(&gpx_file, Line, FA_WRITE | FA_OPEN_ALWAYS) /* Open log file */
  543. || f_lseek(&gpx_file, f_size(&gpx_file)) /* Append mode */
  544. || gpx_init(&gpx_file)) /* Put a blank line as start marker */
  545. {
  546. f_close(&gpx_file);
  547. System.status = STATUS_FILE_OPEN_ERROR;
  548. break; /* Failed to start logging */
  549. }
  550. xsprintf(Line, PSTR("%04u-%02u-%02u_%02u-%02u-%02u-SYSTEM.LOG"), ct.tm_year+1900, ct.tm_mon + 1, ct.tm_mday, ct.tm_hour, ct.tm_min, ct.tm_sec);
  551. xprintf(__open_msg, Line);
  552. if (f_open(&system_log, Line, FA_WRITE | FA_OPEN_ALWAYS) /* Open log file */
  553. || f_lseek(&system_log, f_size(&system_log)) /* Append mode */
  554. || f_write(&system_log, "\r\n", 2, &bw)) /* Put a blank line as start marker */
  555. {
  556. f_close(&gpx_file);
  557. f_close(&gps_log);
  558. System.status = STATUS_FILE_OPEN_ERROR;
  559. break; /* Failed to start logging */
  560. }
  561. FLAGS |= F_FILEOPEN;
  562. System.status = STATUS_OK;
  563. beep(50, 2); /* Two beeps. Start logging. */
  564. LCD_GoTo(0,1);
  565. LCD_WriteTextP(PSTR("Zapis aktywny "));
  566. continue;
  567. }
  568. if (FLAGS & F_FILEOPEN) {
  569. f_write(&gps_log, Line, len, &bw);
  570. if (bw != len) {
  571. System.status = STATUS_FILE_WRITE_ERROR;
  572. break;
  573. }
  574. if(tmp_utc) /* a new point */
  575. gpx_process_point(&location, &gpx_file);
  576. if (FLAGS & F_SYNC) {
  577. if (f_sync(&gps_log)) {
  578. System.status = STATUS_FILE_SYNC_ERROR;
  579. break;
  580. }
  581. FLAGS &= ~F_SYNC;
  582. }
  583. }
  584. }
  585. /* Stop GPS receiver */
  586. uart0_deinit();
  587. GPS_OFF();
  588. FLAGS &= ~F_POW;
  589. /* Close file */
  590. if (FLAGS & F_FILEOPEN) {
  591. if (f_close(&gps_log))
  592. System.status = STATUS_FILE_CLOSE_ERROR;
  593. if (gpx_close(&gpx_file))
  594. System.status = STATUS_FILE_CLOSE_ERROR;
  595. if (logbuf.len && !f_write(&system_log, logbuf.buf, logbuf.len, &bw)) {
  596. logbuf.len = 0;
  597. }
  598. if (f_close(&system_log))
  599. System.status = STATUS_FILE_CLOSE_ERROR;
  600. xputs_P(PSTR("File closed\r\n"));
  601. LCD_GoTo(0,1);
  602. LCD_WriteTextP(PSTR("Pliki zamkniete "));
  603. }
  604. FLAGS &= ~F_FILEOPEN;
  605. disk_ioctl(0, CTRL_POWER, 0);
  606. if (System.status != STATUS_FILE_CLOSE_ERROR)
  607. beep(500, 1); /* Long beep on file close succeeded */
  608. }
  609. }