display.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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.dgps)
  214. strcat_P(disp.line2, PSTR(", DGPS"));
  215. }
  216. void disp_func_elevation_gain(void) {
  217. xsprintf(disp.line1, PSTR("Wznios: %.1fm"), (float)System.elevation_gain / 10.0);
  218. xsprintf(disp.line2, PSTR("Zjazd: %.1fm"), (float)System.elevation_loss / 10.0);
  219. }
  220. static void format_time(char *buf, unsigned long int seconds) {
  221. unsigned long int hours;
  222. unsigned char mins, secs;
  223. hours = seconds / 3600;
  224. mins = (seconds % 3600) / 60;
  225. secs = seconds % 60;
  226. if (seconds < 60) {
  227. /* Under 1 minute: show seconds only */
  228. xsprintf(buf, PSTR("%us"), secs);
  229. } else if (seconds < 3600) {
  230. /* Under 1 hour: show minutes and seconds */
  231. xsprintf(buf, PSTR("%um%02us"), mins, secs);
  232. } else if (hours < 10) {
  233. /* Under 10 hours: show full format */
  234. xsprintf(buf, PSTR("%uh%02um%02us"), hours, mins, secs);
  235. } else {
  236. /* 10 hours or more: drop seconds to save space */
  237. xsprintf(buf, PSTR("%uh%02um"), hours, mins);
  238. }
  239. }
  240. void disp_distance_and_time(void) {
  241. unsigned int time = get_logging_time();
  242. xsprintf(disp.line1, PSTR("%.2f km"), (float)System.distance / 100000.0);
  243. if (time) {
  244. strcpy(disp.line2, "t=");
  245. format_time(disp.line2 + 2, time);
  246. } else {
  247. disp_line2(PSTR("Czas nieznany"));
  248. }
  249. }
  250. void disp_pause_time(void) {
  251. strcpy_P(disp.line1, PSTR("Pauza: "));
  252. format_time(disp.line1 + 7, get_pause_time());
  253. disp.line2[0] = '\0';
  254. }
  255. void disp_speed(void) {
  256. unsigned int avg = get_avg_speed_x100();
  257. disp_line1(PSTR("Sr. predkosc:"));
  258. if (avg) {
  259. xsprintf(disp.line2, PSTR("%.2f km/h"), (float)avg / 100.0);
  260. } else {
  261. disp_line2(PSTR("nieznana"));
  262. }
  263. }
  264. void disp_time(void) {
  265. if (utc == 0) {
  266. disp_line1(PSTR("?"));
  267. disp_line2(PSTR("?"));
  268. return;
  269. }
  270. time_t time = utc;
  271. time += local_time_diff(time) * (signed int)3600;
  272. struct tm *ct = gmtime(&time);
  273. xsprintf(disp.line1, PSTR("%d.%02d.%4d"), ct->tm_mday, ct->tm_mon+1, ct->tm_year+1900);
  274. xsprintf(disp.line2, PSTR("%d:%02d:%02d"), ct->tm_hour, ct->tm_min, ct->tm_sec);
  275. }
  276. void disp_func_temperature(void) {
  277. disp_line1(PSTR("Temperatura"));
  278. if (System.temperature_ok) {
  279. xsprintf(disp.line2, PSTR("%.1f stC"), System.temperature);
  280. } else {
  281. disp_line2(PSTR("Blad!"));
  282. }
  283. }
  284. static struct {
  285. unsigned char index;
  286. unsigned char count;
  287. } error_browser;
  288. __flash const char _error_temp[] = "Czujnik temp.";
  289. __flash const char _error_i2c[] = "I2C";
  290. __flash const char _error_i2c_timeout[] = "I2C timeout";
  291. __flash const char _error_disk[] = "Blad karty";
  292. __flash const char _error_file_write[] = "Blad zapisu";
  293. __flash const char _error_file_sync[] = "Blad zapisu FAT";
  294. __flash const char _error_file_close[] = "Blad zamk.pliku";
  295. __flash const char _error_file_open[] = "Blad otw. pliku";
  296. static __flash const struct {
  297. unsigned int flag;
  298. __flash const char *name;
  299. } error_list[] = {
  300. {ERROR_TEMPERATURE, _error_temp},
  301. {ERROR_I2C, _error_i2c},
  302. {ERROR_I2C_TIMEOUT, _error_i2c_timeout},
  303. {ERROR_DISK, _error_disk},
  304. {ERROR_FILE_WRITE, _error_file_write},
  305. {ERROR_FILE_SYNC, _error_file_sync},
  306. {ERROR_FILE_CLOSE, _error_file_close},
  307. {ERROR_FILE_OPEN, _error_file_open},
  308. };
  309. void disp_func_global_error(void) {
  310. unsigned char i, found_index = 0;
  311. disp_line1(PSTR("*** BLAD ***"));
  312. if (System.global_error == ERROR_NO) {
  313. disp_line2(PSTR("Brak"));
  314. error_browser.count = 0;
  315. error_browser.index = 0;
  316. return;
  317. }
  318. /* Count errors and find current one */
  319. error_browser.count = 0;
  320. for (i = 0; i < sizeof(error_list)/sizeof(error_list[0]); i++) {
  321. if (System.global_error & error_list[i].flag) {
  322. if (error_browser.count == error_browser.index) {
  323. found_index = i;
  324. }
  325. error_browser.count++;
  326. }
  327. }
  328. /* Wrap index if needed */
  329. if (error_browser.index >= error_browser.count) {
  330. error_browser.index = 0;
  331. found_index = 0;
  332. for (i = 0; i < sizeof(error_list)/sizeof(error_list[0]); i++) {
  333. if (System.global_error & error_list[i].flag) {
  334. found_index = i;
  335. break;
  336. }
  337. }
  338. }
  339. /* Display current error */
  340. if (error_browser.count > 1) {
  341. xsprintf(disp.line2, PSTR("<%u/%u> "), error_browser.index + 1, error_browser.count);
  342. } else {
  343. disp.line2[0] = '\0';
  344. }
  345. strcat_P(disp.line2, error_list[found_index].name);
  346. }
  347. unsigned char error_browser_func(unsigned char k) {
  348. if (k == K_LEFT && error_browser.count > 0) {
  349. if (error_browser.index > 0)
  350. error_browser.index--;
  351. else
  352. error_browser.index = error_browser.count - 1;
  353. return 1;
  354. }
  355. if (k == K_RIGHT && error_browser.count > 0) {
  356. error_browser.index++;
  357. if (error_browser.index >= error_browser.count)
  358. error_browser.index = 0;
  359. return 1;
  360. }
  361. /* Long press on UP to reset errors */
  362. if (k == (K_UP | K_DOWN)) { /* both up and down pressed together as "confirm" */
  363. System.global_error = ERROR_NO;
  364. error_browser.index = 0;
  365. error_browser.count = 0;
  366. return 1;
  367. }
  368. return 0;
  369. }
  370. void display_refresh(unsigned char changed) {
  371. if (timer_expired(lcd)) {
  372. changed = 1;
  373. }
  374. /* write to LCD */
  375. if (changed) {
  376. set_timer(lcd, 1000);
  377. battery_state_display();
  378. unsigned char len;
  379. LCD_GoTo(0,0);
  380. len = strlen(disp.line1);
  381. LCD_WriteText(disp.line1);
  382. while (len<15) {
  383. len++;
  384. LCD_WriteData(' ');
  385. }
  386. #ifndef LCD_GRAPHIC
  387. LCD_WriteData(0); /* battery symbol */
  388. #endif
  389. LCD_GoTo(0,1);
  390. len = strlen(disp.line2);
  391. LCD_WriteText(disp.line2);
  392. while (len<16) {
  393. len++;
  394. LCD_WriteData(' ');
  395. }
  396. }
  397. }