display.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include "main.h"
  2. #ifndef LCD_GRAPHIC
  3. __flash const unsigned char battery_states[][8] = {
  4. {
  5. 0b01110,
  6. 0b11111,
  7. 0b11111,
  8. 0b11111,
  9. 0b11111,
  10. 0b11111,
  11. 0b11111,
  12. 0b11111,
  13. },
  14. {
  15. 0b01110,
  16. 0b11111,
  17. 0b10001,
  18. 0b11111,
  19. 0b11111,
  20. 0b11111,
  21. 0b11111,
  22. 0b11111,
  23. },
  24. {
  25. 0b01110,
  26. 0b11111,
  27. 0b10001,
  28. 0b10001,
  29. 0b10001,
  30. 0b11111,
  31. 0b11111,
  32. 0b11111,
  33. },
  34. {
  35. 0b01110,
  36. 0b11111,
  37. 0b10001,
  38. 0b10001,
  39. 0b10001,
  40. 0b10001,
  41. 0b10001,
  42. 0b11111,
  43. },
  44. };
  45. __flash const unsigned char custom_chars[] = {
  46. 0b00000, /* 0x01 down arrow */
  47. 0b00100,
  48. 0b00100,
  49. 0b00100,
  50. 0b10101,
  51. 0b01110,
  52. 0b00100,
  53. 0b00000,
  54. 0b00000, /* 0x02 up arrow */
  55. 0b00100,
  56. 0b01110,
  57. 0b10101,
  58. 0b00100,
  59. 0b00100,
  60. 0b00100,
  61. 0b00000,
  62. };
  63. #endif /* LCD_GRAPHIC */
  64. struct disp_s disp;
  65. void disp_init(void) { /* send custom characters starting with 0x01 */
  66. #ifndef LCD_GRAPHIC
  67. unsigned char i;
  68. LCD_WriteCommand(0x40 + 8); // 0x01
  69. for(i=0; i<sizeof(custom_chars); i++){
  70. LCD_WriteData(custom_chars[i]);
  71. };
  72. #endif /* LCD_GRAPHIC */
  73. }
  74. void battery_state_display(void) {
  75. unsigned char index;
  76. if (System.bat_volt > 4.0)
  77. index = 0;
  78. else if (System.bat_volt > 3.7)
  79. index = 1;
  80. else if (System.bat_volt > 3.4)
  81. index = 2;
  82. else
  83. index = 3;
  84. #ifdef LCD_GRAPHIC
  85. LCD_GoTo(15,0);
  86. LCD_WriteChar(0x82 + index);
  87. #else
  88. unsigned char i;
  89. LCD_WriteCommand(0x40 + 0); // 0x00
  90. for(i=0; i<8; i++){
  91. LCD_WriteData(battery_states[index][i]);
  92. };
  93. #endif /* LCD_GRAPHIC */
  94. }
  95. static inline void disp_line(unsigned char i, __flash const char *text) {
  96. switch(i) {
  97. case 2: strcpy_P(disp.line2, text); break;
  98. case 1: strcpy_P(disp.line1, text); break;
  99. }
  100. }
  101. void disp_line1(__flash const char *text) {
  102. disp_line(1, text);
  103. }
  104. void disp_line2(__flash const char *text) {
  105. disp_line(2, text);
  106. }
  107. __flash const char _gps_wait[] = "Czekam na GPS...";
  108. __flash const char _gps_ok[] = "GPS OK!";
  109. __flash const char _card_ok[] = "Karta OK!";
  110. __flash const char _logging_active[] = "Zapis aktywny";
  111. __flash const char _logging_paused[] = "Zapis wstrzymany";
  112. __flash const char _starting[] = "Uruchamianie...";
  113. __flash const char _battery_low[] = "Bateria slaba!";
  114. __flash const char _shutting_down[] = "Wylaczanie...";
  115. __flash const char _no_card[] = "Brak karty!";
  116. __flash const char _card_error[] = "Blad karty!";
  117. __flash const char _write_error[] = "Blad zapisu!";
  118. __flash const char _fat_write_error[] = "Blad zapisu FAT!";
  119. __flash const char _file_close_error[] = "Blad zamk.pliku!";
  120. __flash const char _file_open_error[] = "Blad otw. pliku!";
  121. __flash const char _files_closed[] = "Pliki zamkniete";
  122. __flash const char _files_open[] = "Pliki otwarte";
  123. __flash const char _tracking_paused[] = "Wstrzymano!";
  124. __flash const char _tracking_resumed[] = "Wznowiono!";
  125. __flash const char _point_saved[] = "Zapisano!";
  126. __flash const char _point_not_saved[] = "Nie zapisano!";
  127. __flash const char _logging_auto_paused[] = "Autom. wstrzym.";
  128. __flash const char _sat_count_low[] = "Za malo satelit";
  129. void display_event(unsigned char event) { /* overrides display with current messages */
  130. switch (event) {
  131. case DISPLAY_EVENT_STARTUP:
  132. disp_line1(_starting);
  133. break;
  134. case DISPLAY_EVENT_LOW_BATTERY:
  135. disp_line2(_battery_low);
  136. /* fall through */
  137. case DISPLAY_EVENT_POWEROFF:
  138. disp_line1(_shutting_down);
  139. break;
  140. case DISPLAY_EVENT_INITIALIZED:
  141. disp_line1(PSTR("Start"));
  142. switch(System.status){
  143. case STATUS_NO_POWER: case STATUS_OK: case STATUS_NO_GPS: disp.line2[0] = '\0'; break;
  144. case STATUS_NO_DISK: disp_line2(_no_card); break;
  145. case STATUS_DISK_ERROR: disp_line2(_card_error); break;
  146. case STATUS_FILE_WRITE_ERROR: disp_line2(_write_error); break;
  147. case STATUS_FILE_SYNC_ERROR: disp_line2(_fat_write_error); break;
  148. case STATUS_FILE_CLOSE_ERROR: disp_line2(_file_close_error); break;
  149. case STATUS_FILE_OPEN_ERROR: disp_line2(_file_open_error); break;
  150. }
  151. break;
  152. case DISPLAY_EVENT_CARD_INITIALIZED:
  153. disp_line1(_card_ok);
  154. disp_line2(_gps_wait);
  155. break;
  156. case DISPLAY_EVENT_FILE_CLOSED:
  157. disp_line2(_files_closed);
  158. break;
  159. case DISPLAY_EVENT_FILE_OPEN:
  160. disp_line2(_files_open);
  161. break;
  162. case DISPLAY_EVENT_TRACKING_PAUSED:
  163. disp_line2(_tracking_paused);
  164. break;
  165. case DISPLAY_EVENT_TRACKING_RESUMED:
  166. disp_line2(_tracking_resumed);
  167. break;
  168. case DISPLAY_EVENT_POINT_SAVED:
  169. disp_line2(_point_saved);
  170. break;
  171. case DISPLAY_EVENT_POINT_NOT_SAVED:
  172. disp_line2(_point_not_saved);
  173. break;
  174. }
  175. display_refresh(1);
  176. }
  177. void disp_func_main_default(void) {
  178. if (FLAGS & F_FILEOPEN) {
  179. if (System.tracking_paused) {
  180. disp_line1(_logging_paused);
  181. } else if (System.tracking_auto_paused) {
  182. disp_line1(_logging_auto_paused);
  183. } else {
  184. disp_line1(_logging_active);
  185. }
  186. } else
  187. disp_line1(_card_ok);
  188. if (FLAGS & F_GPSOK) {
  189. if (System.sat_count_low)
  190. disp_line2(_sat_count_low);
  191. else
  192. disp_line2(_gps_ok);
  193. } else {
  194. disp_line2(_gps_wait);
  195. }
  196. }
  197. void disp_func_coord(void) {
  198. if (System.location_valid == LOC_INVALID) {
  199. disp_line1(PSTR("??? N/S"));
  200. disp_line2(PSTR("??? E/W"));
  201. return;
  202. }
  203. xsprintf(disp.line1, PSTR("%2.6f%c"), (location.lat < 0)?(-location.lat):location.lat, (location.lat < 0)?'S':'N');
  204. xsprintf(disp.line2, PSTR("%3.6f%c"), (location.lon < 0)?(-location.lon):location.lon, (location.lon < 0)?'W':'E');
  205. }
  206. void disp_func_ele_sat(void) {
  207. if (System.location_valid == LOC_INVALID) {
  208. disp_line1(PSTR("ele = ???"));
  209. } else {
  210. xsprintf(disp.line1, PSTR("ele = %.1fm"), location.alt);
  211. }
  212. xsprintf(disp.line2, PSTR("%2d satelit"), System.satellites_used);
  213. if (System.sbas)
  214. strcat_P(disp.line2, PSTR(", DGPS"));
  215. }
  216. static void format_time(char *buf, unsigned int seconds) {
  217. unsigned int hours;
  218. unsigned char mins, secs;
  219. hours = seconds / 3600;
  220. mins = (seconds % 3600) / 60;
  221. secs = seconds % 60;
  222. if (seconds < 60) {
  223. /* Under 1 minute: show seconds only */
  224. xsprintf(buf, PSTR("%us"), secs);
  225. } else if (seconds < 3600) {
  226. /* Under 1 hour: show minutes and seconds */
  227. xsprintf(buf, PSTR("%um%02us"), mins, secs);
  228. } else if (hours < 10) {
  229. /* Under 10 hours: show full format */
  230. xsprintf(buf, PSTR("%uh%02um%02us"), hours, mins, secs);
  231. } else {
  232. /* 10 hours or more: drop seconds to save space */
  233. xsprintf(buf, PSTR("%uh%02um"), hours, mins);
  234. }
  235. }
  236. void disp_distance_and_time(void) {
  237. unsigned int time = get_logging_time();
  238. xsprintf(disp.line1, PSTR("%.2f km"), (float)System.distance / 100000.0);
  239. if (time) {
  240. strcpy(disp.line2, "t=");
  241. format_time(disp.line2 + 2, time);
  242. } else {
  243. disp_line2(PSTR("Czas nieznany"));
  244. }
  245. }
  246. void disp_pause_time(void) {
  247. strcpy_P(disp.line1, PSTR("Pauza: "));
  248. format_time(disp.line1 + 7, get_pause_time());
  249. disp.line2[0] = '\0';
  250. }
  251. void disp_speed(void) {
  252. unsigned int time = get_logging_time();
  253. disp_line1(PSTR("Predkosc:"));
  254. if (time) {
  255. xsprintf(disp.line2, PSTR("%.2f km/h"), (float)System.distance / (float)(time) * 0.036); /* convert seconds to hours */
  256. } else {
  257. disp_line2(PSTR("nieznana"));
  258. }
  259. }
  260. void disp_time(void) {
  261. if (utc == 0) {
  262. disp_line1(PSTR("?"));
  263. disp_line2(PSTR("?"));
  264. return;
  265. }
  266. time_t time = utc;
  267. time += local_time_diff(time) * (signed int)3600;
  268. struct tm *ct = gmtime(&time);
  269. xsprintf(disp.line1, PSTR("%d.%02d.%4d"), ct->tm_mday, ct->tm_mon+1, ct->tm_year+1900);
  270. xsprintf(disp.line2, PSTR("%d:%02d:%02d"), ct->tm_hour, ct->tm_min, ct->tm_sec);
  271. }
  272. void disp_func_temperature(void) {
  273. disp_line1(PSTR("Temperatura"));
  274. if (System.temperature_ok) {
  275. xsprintf(disp.line2, PSTR("%.1f stC"), System.temperature);
  276. } else {
  277. disp_line2(PSTR("Blad!"));
  278. }
  279. }
  280. static struct {
  281. unsigned char index;
  282. unsigned char count;
  283. } error_browser;
  284. __flash const char _error_temp[] = "Czujnik temp.";
  285. __flash const char _error_i2c[] = "I2C";
  286. __flash const char _error_i2c_timeout[] = "I2C timeout";
  287. __flash const char _error_disk[] = "Blad karty";
  288. __flash const char _error_file_write[] = "Blad zapisu";
  289. __flash const char _error_file_sync[] = "Blad zapisu FAT";
  290. __flash const char _error_file_close[] = "Blad zamk.pliku";
  291. __flash const char _error_file_open[] = "Blad otw. pliku";
  292. static __flash const struct {
  293. unsigned int flag;
  294. __flash const char *name;
  295. } error_list[] = {
  296. {ERROR_TEMPERATURE, _error_temp},
  297. {ERROR_I2C, _error_i2c},
  298. {ERROR_I2C_TIMEOUT, _error_i2c_timeout},
  299. {ERROR_DISK, _error_disk},
  300. {ERROR_FILE_WRITE, _error_file_write},
  301. {ERROR_FILE_SYNC, _error_file_sync},
  302. {ERROR_FILE_CLOSE, _error_file_close},
  303. {ERROR_FILE_OPEN, _error_file_open},
  304. };
  305. void disp_func_global_error(void) {
  306. unsigned char i, found_index = 0;
  307. disp_line1(PSTR("*** BLAD ***"));
  308. if (System.global_error == ERROR_NO) {
  309. disp_line2(PSTR("Brak"));
  310. error_browser.count = 0;
  311. error_browser.index = 0;
  312. return;
  313. }
  314. /* Count errors and find current one */
  315. error_browser.count = 0;
  316. for (i = 0; i < sizeof(error_list)/sizeof(error_list[0]); i++) {
  317. if (System.global_error & error_list[i].flag) {
  318. if (error_browser.count == error_browser.index) {
  319. found_index = i;
  320. }
  321. error_browser.count++;
  322. }
  323. }
  324. /* Wrap index if needed */
  325. if (error_browser.index >= error_browser.count) {
  326. error_browser.index = 0;
  327. found_index = 0;
  328. for (i = 0; i < sizeof(error_list)/sizeof(error_list[0]); i++) {
  329. if (System.global_error & error_list[i].flag) {
  330. found_index = i;
  331. break;
  332. }
  333. }
  334. }
  335. /* Display current error */
  336. if (error_browser.count > 1) {
  337. xsprintf(disp.line2, PSTR("<%u/%u> "), error_browser.index + 1, error_browser.count);
  338. } else {
  339. disp.line2[0] = '\0';
  340. }
  341. strcat_P(disp.line2, error_list[found_index].name);
  342. }
  343. unsigned char error_browser_func(unsigned char k) {
  344. if (k == K_LEFT && error_browser.count > 0) {
  345. if (error_browser.index > 0)
  346. error_browser.index--;
  347. else
  348. error_browser.index = error_browser.count - 1;
  349. return 1;
  350. }
  351. if (k == K_RIGHT && error_browser.count > 0) {
  352. error_browser.index++;
  353. if (error_browser.index >= error_browser.count)
  354. error_browser.index = 0;
  355. return 1;
  356. }
  357. /* Long press on UP to reset errors */
  358. if (k == (K_UP | K_DOWN)) { /* both up and down pressed together as "confirm" */
  359. System.global_error = ERROR_NO;
  360. error_browser.index = 0;
  361. error_browser.count = 0;
  362. return 1;
  363. }
  364. return 0;
  365. }
  366. void display_refresh(unsigned char changed) {
  367. if (timer_expired(lcd)) {
  368. changed = 1;
  369. }
  370. /* write to LCD */
  371. if (changed) {
  372. set_timer(lcd, 1000);
  373. battery_state_display();
  374. unsigned char len;
  375. LCD_GoTo(0,0);
  376. len = strlen(disp.line1);
  377. LCD_WriteText(disp.line1);
  378. while (len<15) {
  379. len++;
  380. LCD_WriteData(' ');
  381. }
  382. #ifndef LCD_GRAPHIC
  383. LCD_WriteData(0); /* battery symbol */
  384. #endif
  385. LCD_GoTo(0,1);
  386. len = strlen(disp.line2);
  387. LCD_WriteText(disp.line2);
  388. while (len<16) {
  389. len++;
  390. LCD_WriteData(' ');
  391. }
  392. }
  393. }