display2.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  1. /*
  2. * display2.cpp
  3. *
  4. * Created on: Sep 26, 2017
  5. * Updated:
  6. * Author: Philipp Hinz/Sebastian Vendt
  7. */
  8. #include <stdlib.h>
  9. #include <pthread.h>
  10. #include <time.h>
  11. #include <unistd.h>
  12. #include <string.h>
  13. #include "display2.h"
  14. #include "global.h"
  15. #include "logger.h"
  16. #include "database.h"
  17. #include "timer.h"
  18. #include "lcd.h"
  19. #include "coffee.h"
  20. #include "hal.h"
  21. #include "events.h"
  22. #include "DS18B20.h"
  23. #define CURRENT 0
  24. #define NEXT 1
  25. //timeouts for the transitions in ms
  26. #define TIMEOUT_PREBREW 1000
  27. #define TIMEOUT_POSTBREW 9000
  28. display_lang_t displayLang;
  29. timer displayTimer(displayTimerHandler);
  30. int lcd = 0;
  31. // currently only the history of states is of interest
  32. coffee_status_t coffeeState[] = {STATE_OFF, STATE_NULL}; // current - next state
  33. coffee_mode_t coffeeMode[] = {MODE_STATE, MODE_NULL};
  34. coffee_menuPage_t coffeePage[] = {PAGE_SOFTOFF, PAGE_NULL};
  35. bool coffeeDescaling = false;
  36. refreshRate_t currentRefreshRate = refresh_std;
  37. uint16_t holdNext[3] = {0, 0, 0}; //holdtime of the new {state, Mode, Page} in ms
  38. uint16_t nextWaitTime[3] = {0, 0, 0}; //actual waiting time of the new {state, Mode, Page}
  39. typedef enum {
  40. state_idx = 0,
  41. mode_idx = 1,
  42. page_idx = 2
  43. } idx_t;
  44. void switchToNextPage(coffee_menuPage_t* history);
  45. void switchToNextMode(coffee_mode_t* history);
  46. void switchToNextState(coffee_status_t* history);
  47. void setRefreshRate(refreshRate_t rate);
  48. void setSwitchToNextTimeout(idx_t idx, uint16_t millis);
  49. void displayPrintTemp(int line);
  50. void displayPrintStats(int line);
  51. void displayPrintStats2(int line);
  52. void displayPrintNextDesc(int line);
  53. void displayPrintPostBrew(int line);
  54. void displayPrintBrewManual(int line);
  55. void displayPrintFlow(int line);
  56. void displayPrintCleanCycle(int line);
  57. void displayStateUpdated(event_t *event);
  58. void displayModeUpdated(event_t *event);
  59. void displayPageUpdated(event_t *event);
  60. void displayDescaling(event_t *event);
  61. void displayPrintLogo(void);
  62. void displayPrintNum(int line, uint16_t num, char* unitstr);
  63. void displayClearLine(int line);
  64. void displayTerminate(event_t *e);
  65. void track(idx_t idx);
  66. /**
  67. * Prints out the current time in a centered position
  68. * @param line Target line in display
  69. */
  70. void displayPrintTime(int line) {
  71. time_t rawtime;
  72. struct tm * timeinfo;
  73. if (line > DISPLAY_ROWS)
  74. line = 0;
  75. time(&rawtime);
  76. timeinfo = localtime(&rawtime);
  77. lcdPosition(lcd, 0, line);
  78. lcdPrintf(lcd, " %.2d:%.2d:%.2d ", timeinfo->tm_hour,
  79. timeinfo->tm_min, timeinfo->tm_sec);
  80. }
  81. /**
  82. * Prints out the current temperature in a centered position
  83. * @param line Target line in display
  84. */
  85. void displayPrintTemp(int line) {
  86. //TODO: the temperature is wrong(old value) the first time the page is opened
  87. //after the first refresh the right temperature is displayed
  88. //no idea where this comes from, datasheet says nothing about dummy readouts.
  89. //no old values are used, conversion is started before every readout...
  90. //Quick fix:
  91. DS18B20_readTemp();
  92. if (line > DISPLAY_ROWS)
  93. line = 0;
  94. lcdPosition(lcd, 0, line);
  95. lcdPrintf(lcd, " %d C ", DS18B20_readTemp());
  96. }
  97. /**
  98. * Prints the total epsressi brewed since reset
  99. */
  100. void displayPrintStats(int line) {
  101. char buffer[17];
  102. if (line > DISPLAY_ROWS)
  103. line = 0;
  104. lcdPosition(lcd, 0, line);
  105. sprintf(buffer, "%7d espressi", getBrewCounter());
  106. lcdPrintf(lcd, buffer);
  107. }
  108. /**
  109. * Prints the total heating time in kWh
  110. */
  111. void displayPrintStats2(int line) {
  112. char buffer[17];
  113. if (line > DISPLAY_ROWS)
  114. line = 0;
  115. uint64_t totalkWh = 2 * halGetTotalHeatingTime()/(60*60);
  116. sprintf(buffer, "%lld kWh", totalkWh);
  117. displayPrintLn(line, buffer, true);
  118. }
  119. /**
  120. * Prints the remaining time or the remaining cups until the next descaling is necessary
  121. */
  122. void displayPrintNextDesc(int line) {
  123. char buffer[17];
  124. if (line > DISPLAY_ROWS) line = 0;
  125. sprintf(buffer, "%d d or %d C", checkDirtyTime(), checkDirtyEspresso());
  126. displayPrintLn(line, buffer, true);
  127. }
  128. /**
  129. *
  130. */
  131. void displayPrintPostBrew(int line) {
  132. char buffer[17];
  133. if (line > DISPLAY_ROWS) line = 0;
  134. float brewTime = (float)halGetLastFlowTime();
  135. sprintf(buffer, "%.1f ml / %.1f s", halGetLastFlow(), brewTime / 1000);
  136. displayPrintLn(line, buffer, true);
  137. }
  138. void displayPrintBrewManual(int line) {
  139. char buffer[17];
  140. if (line > DISPLAY_ROWS) line = 0;
  141. float brewTime = (float)halGetFlowTime();
  142. sprintf(buffer, "%.1f ml / %.1f s", halGetFlow(), brewTime / 1000);
  143. displayPrintLn(line, buffer, true);
  144. }
  145. /**
  146. * Prints out the total volume flow
  147. * @param line Target line in display
  148. */
  149. void displayPrintFlow(int line) {
  150. float flow = halGetFlow();
  151. lcdPosition(lcd, 0, line);
  152. lcdPrintf(lcd, "%s: %.0f ml ", displayGetString(str_flow), flow);
  153. }
  154. /**
  155. * Prints the current cycle of the cleaning process
  156. */
  157. void displayPrintCleanCycle(int line) {
  158. char buffer[17];
  159. if (line > DISPLAY_ROWS) line = 0;
  160. sprintf(buffer, "%2d of %2d", getCurrentCleanCycle(), CLEANING_CYCLES);
  161. displayPrintLn(line, buffer, true);
  162. }
  163. /**
  164. * Prints a string to a specific line, optionally centered.
  165. * This function also fills out the remaining row of the display with spaces,
  166. * to ensure there is no old data left.
  167. * @param line Target line in display
  168. * @param *str String to print
  169. * @param centered Print centered or not
  170. */
  171. void displayPrintLn(int line, const char* str, bool centered) {
  172. char buf[DISPLAY_COLS + 1];
  173. int len = strlen(str);
  174. int i = 0;
  175. int spaces = 0;
  176. if (len > DISPLAY_COLS)
  177. len = DISPLAY_COLS;
  178. if (line > DISPLAY_ROWS)
  179. line = 0;
  180. if (centered) {
  181. spaces = (DISPLAY_COLS - len) / 2;
  182. if (spaces) {
  183. for (i = 0; i < spaces; i++) {
  184. buf[i] = ' ';
  185. }
  186. }
  187. }
  188. for (i = 0; i < len; i++) {
  189. buf[spaces + i] = str[i];
  190. }
  191. if ((len + spaces) < DISPLAY_COLS) { // fill remaining space
  192. for (i = i + spaces; i < DISPLAY_COLS; i++) {
  193. buf[i] = ' ';
  194. }
  195. }
  196. //draw the descaling star
  197. if(coffeeDescaling && line == 0){
  198. buf[15] = '*';
  199. }
  200. lcdPosition(lcd, 0, line);
  201. buf[DISPLAY_COLS] = '\0';
  202. lcdPrintf(lcd, buf);
  203. }
  204. /**
  205. * Updates the display state to the matching coffee state
  206. * @param event Event data
  207. */
  208. void displayStateUpdated(event_t *event) {
  209. if (event->len != sizeof(coffee_status_t)) {
  210. logger_error("display2.cpp: Invalid use of event %s\n", event->event);
  211. return;
  212. }
  213. coffee_status_t state = *(coffee_status_t*) event->data;
  214. coffeeState[NEXT] = state;
  215. displayTimer.call();
  216. }
  217. /**
  218. * Updates the display state to the matching coffee display mode
  219. * @param event Event data
  220. */
  221. void displayModeUpdated(event_t *event) {
  222. if (event->len != sizeof(coffee_mode_t)) {
  223. logger_error("display2.cpp: Invalid use of event %s\n", event->event);
  224. return;
  225. }
  226. coffee_mode_t mode = *(coffee_mode_t*) event->data;
  227. coffeeMode[NEXT] = mode;
  228. displayTimer.call();
  229. }
  230. /**
  231. * Updates the display state to the matching coffee display page
  232. * The new state is put on hold (next) and the display can decided if it immediately makes the
  233. * new state to the current one or if a timeout is specified in which the new state is put on hold and the
  234. * state transition is processed.
  235. * One initial asynchronous call
  236. * @param event Event data
  237. */
  238. void displayPageUpdated(event_t *event) {
  239. if (event->len != sizeof(coffee_menuPage_t)) {
  240. logger_error("display2.cpp: Invalid use of event %s\n", event->event);
  241. return;
  242. }
  243. coffee_menuPage_t page = *(coffee_menuPage_t*) event->data;
  244. coffeePage[NEXT] = page;
  245. displayTimer.call();
  246. }
  247. /**
  248. * Updates the current descaling status of the machine
  249. */
  250. void displayDescaling(event_t *event) {
  251. if (event->len != sizeof(bool)) {
  252. logger_error("display2.cpp: Invalid use of event %s\n", event->event);
  253. return;
  254. }
  255. coffeeDescaling = *(bool*) event->data;
  256. }
  257. /**
  258. * Prints the logo (CoffeePi) and also the temperature with the logo (CoffeePi@72C) if the machine is on
  259. */
  260. void displayPrintLogo(void) {
  261. char buffer[17];
  262. switch (coffeeState[CURRENT]) {
  263. case STATE_HEATING:
  264. case STATE_INITALHEATING:
  265. case STATE_IDLE:
  266. sprintf(buffer, "CoffeePi @ %dC", DS18B20_readTemp());
  267. break;
  268. default:
  269. sprintf(buffer, "CoffeePi");
  270. break;
  271. }
  272. displayPrintLn(0, buffer, true);
  273. }
  274. /**
  275. * Prints a integer number on the display
  276. * @param line: The line number where the number shall be printed
  277. * @param num: The number to be printed
  278. * @param unitstr: The unit string, e.g. ms
  279. */
  280. void displayPrintNum(int line, uint16_t num, const char* unitstr) {
  281. displayClearLine(line);
  282. lcdPosition(lcd, 0, line);
  283. lcdPrintf(lcd, " %d %s", num, unitstr);
  284. }
  285. /**
  286. * Write spaces to the display line to clear previous content
  287. * @param num: The line number
  288. */
  289. void displayClearLine(int line) {
  290. lcdPosition(lcd, 0, line);
  291. lcdPrintf(lcd, " ");
  292. }
  293. /**
  294. * Handles cleanup before program termination
  295. */
  296. void displayTerminate(event_t *e) {
  297. logger(V_BASIC, "display.cpp: Terminating\n");
  298. displayPrintLn(0, "CoffeePi", true);
  299. displayPrintLn(1, displayGetString(str_bye), true);
  300. displayTimer.stop();
  301. }
  302. /**
  303. * Main thread to handle display data
  304. * @param *threadid Thread ID
  305. */
  306. void* displayThread(void* threadid) {
  307. //sleep(1); // Wait for other components to initialize
  308. displayTimer.start();
  309. logger(V_BASIC, "display.cpp: Initialized display Thread. Timer state: %d \n", displayTimer.isActive());
  310. while (1) {
  311. pause();
  312. if (1) {
  313. displayTimer.call();
  314. }
  315. }
  316. pthread_exit(EXIT_SUCCESS);
  317. }
  318. /**
  319. * Timer handler for display update
  320. * @param *threadid Thread ID
  321. */
  322. void* displayTimerHandler(void* threadid) {
  323. //track time of the new state in hold and switch if necessary
  324. track(state_idx);
  325. track(page_idx);
  326. track(mode_idx);
  327. displayRefresh();
  328. pthread_exit(EXIT_SUCCESS);
  329. }
  330. /**
  331. * Tracks the elapsed time in ms of the new state waiting to become the current one if a hold time is specified
  332. */
  333. void track(idx_t idx){
  334. if (holdNext[idx] != 0) {
  335. nextWaitTime[idx] += 1000 / currentRefreshRate;
  336. if (holdNext[idx] <= nextWaitTime[idx]) {
  337. switch(idx){
  338. case state_idx:
  339. switchToNextState(coffeeState);
  340. break;
  341. case page_idx:
  342. switchToNextPage(coffeePage);
  343. break;
  344. case mode_idx:
  345. switchToNextMode(coffeeMode);
  346. break;
  347. }
  348. }
  349. }
  350. }
  351. /**
  352. * Initializes display
  353. */
  354. void displayInit(void) {
  355. lcd = lcdInit();
  356. if (lcd < 0)
  357. logger_error("display2.cpp: Error: unable to init LCD (%d)\n", lcd);
  358. lcdClear(lcd);
  359. lcdHome(lcd);
  360. displayPrintLn(0, (char*) "CoffeePi", true);
  361. displayPrintLn(1, (char*) "booting...", true);
  362. //lcdPrintf(lcd, " CoffeePi booting...");
  363. //setRefreshRate(refresh_std);
  364. currentRefreshRate = refresh_std;
  365. displayTimer.setDivider(20 / refresh_std);
  366. /**The following block comes from void* displayThread(void* threadid)
  367. * The idea is that the initialization functions get the component ready to react on external events
  368. * once the threads start, events might be triggered and every component can process them
  369. * This should fix the TO_DO where a descaling event was triggered during startup of the coffeethread and
  370. * the displaythread did not react to it since it hadn't subscribed to the event yet
  371. */
  372. int tmp = sqlGetConf(CFGdisplaylang);
  373. if (!tmp || tmp >= lang_last)
  374. tmp = DEFAULT_LANG;
  375. displaySetLang((display_lang_t) tmp);
  376. event_subscribe("statechange", &displayStateUpdated, "display.cpp");
  377. event_subscribe("modechange", &displayModeUpdated, "display.cpp");
  378. event_subscribe("pagechange", &displayPageUpdated, "display.cpp");
  379. event_subscribe("terminate", &displayTerminate, "display.cpp");
  380. event_subscribe("descaling", &displayDescaling, "display.cpp");
  381. logger(V_BASIC, "display2.cpp Initialized display with a refresh rate of %d Hz\n",
  382. refresh_std);
  383. }
  384. /**
  385. * Sets the language of the display text
  386. * @param lang New language
  387. */
  388. void displaySetLang(display_lang_t lang) {
  389. displayLang = lang;
  390. }
  391. /*
  392. *
  393. */
  394. void switchToNextPage(coffee_menuPage_t* history){
  395. if(history[NEXT] != PAGE_NULL) {
  396. history[CURRENT] = history[NEXT];
  397. history[NEXT] = PAGE_NULL;
  398. holdNext[page_idx] = 0;
  399. nextWaitTime[page_idx] = 0;
  400. }
  401. }
  402. /*
  403. *
  404. */
  405. void switchToNextMode(coffee_mode_t* history){
  406. if(history[NEXT] != MODE_NULL) {
  407. history[CURRENT] = history[NEXT];
  408. history[NEXT] = MODE_NULL;
  409. holdNext[mode_idx] = 0;
  410. nextWaitTime[mode_idx] = 0;
  411. }
  412. }
  413. /*
  414. *
  415. */
  416. void switchToNextState(coffee_status_t* history){
  417. if(history[NEXT] != STATE_NULL) {
  418. history[CURRENT] = history[NEXT];
  419. history[NEXT] = STATE_NULL;
  420. holdNext[state_idx] = 0;
  421. nextWaitTime[state_idx] = 0;
  422. }
  423. }
  424. /**
  425. * sets the refresh rate of the the display
  426. * to one of the predefined refresh rates.
  427. */
  428. void setRefreshRate(refreshRate_t rate) {
  429. if (currentRefreshRate != rate) {
  430. currentRefreshRate = rate;
  431. displayTimer.setDivider(20 / rate);
  432. }
  433. }
  434. /**
  435. * specifies a timeout at which the new state/mode/page will be made to the current one
  436. * This function is enables for special state/mode/page transitions which hold the new state while
  437. * the current transition is displayed. These cases set a timeout specifying how long the state transition should be paused.
  438. * After the time specified in the timeout the timerhandler of the display will switch the states and makes the new one to the current one.
  439. */
  440. void setSwitchToNextTimeout(idx_t idx, uint16_t millis) {
  441. holdNext[idx] = millis;
  442. }
  443. /**
  444. * The core description of what will be displayed in what displaystate
  445. */
  446. void displayRefresh(void) {
  447. //handle mode trainsitions
  448. switchToNextMode(coffeeMode);
  449. //FSM of the display
  450. if (coffeeMode[CURRENT] == MODE_STATE) {
  451. //handle state transitions
  452. if (coffeeState[NEXT] == STATE_BREW) { //Pre brew
  453. //check how long the new state is already in hold ... and either switch or process transition
  454. setSwitchToNextTimeout(state_idx, TIMEOUT_PREBREW);
  455. setRefreshRate(refresh_fast);
  456. displayPrintLogo();
  457. displayPrintLn(1, displayGetString(str_brewing), true);
  458. return;
  459. } else if ((coffeeState[CURRENT] == STATE_BREW || coffeeState[CURRENT] == STATE_BREWMANUAL) && coffeeState[NEXT] != STATE_NULL) { //Post brew
  460. setSwitchToNextTimeout(state_idx, TIMEOUT_POSTBREW);
  461. setRefreshRate(refresh_std);
  462. displayPrintLn(0, displayGetString(str_postBrew), true);
  463. displayPrintPostBrew(1);
  464. return;
  465. } else { //no special state transition -> make new state to the current one
  466. switchToNextState(coffeeState);
  467. }
  468. switch (coffeeState[CURRENT]) { //coffeeGetState()
  469. case STATE_IDLE:
  470. displayPrintLogo();
  471. displayPrintLn(1, displayGetString(str_ready), true);
  472. break;
  473. case STATE_INITALHEATING:
  474. displayPrintLogo();
  475. displayPrintLn(1, displayGetString(str_heating), true);
  476. break;
  477. case STATE_HEATING:
  478. displayPrintLogo();
  479. displayPrintLn(1, displayGetString(str_heatingready), true);
  480. break;
  481. case STATE_BREW:
  482. displayPrintLn(0, displayGetString(str_brewing), true);
  483. displayPrintFlow(1);
  484. break;
  485. case STATE_BREWMANUAL:
  486. setRefreshRate(refresh_fast);
  487. displayPrintLn(0, displayGetString(str_brewing), true);
  488. //displayPrintFlow(1);
  489. displayPrintBrewManual(1);
  490. break;
  491. case STATE_CLEANING:
  492. displayPrintLn(0, displayGetString(str_cleaning), true);
  493. displayPrintCleanCycle(1);
  494. break;
  495. case STATE_ERROR:
  496. displayPrintLogo();
  497. displayPrintLn(1, displayGetString(str_error), true);
  498. break;
  499. case STATE_WAIT_OFF:
  500. displayPrintLogo();
  501. displayPrintLn(1, displayGetString(str_waitoff), true);
  502. break;
  503. case STATE_OFF:
  504. displayPrintLogo();
  505. displayPrintTime(1);
  506. break;
  507. case STATE_FULLTANK:
  508. displayPrintLn(0, displayGetString(str_fullTank), true);
  509. break;
  510. default:
  511. displayPrintLn(0, displayGetString(str_error), true);
  512. displayPrintLn(0, "???", true);
  513. break;
  514. }
  515. } else if (coffeeMode[CURRENT] == MODE_MENU) {
  516. //handle page transitions
  517. switchToNextPage(coffeePage);
  518. switch (coffeePage[CURRENT]) {
  519. case PAGE_SOFTOFF:
  520. displayPrintLn(0, displayGetString(str_menu), true);
  521. displayPrintLn(1, displayGetString(str_menu_softoff), true);
  522. break;
  523. case PAGE_KILL:
  524. displayPrintLn(0, displayGetString(str_menu), true);
  525. displayPrintLn(1, displayGetString(str_menu_kill), true);
  526. break;
  527. case PAGE_STATS:
  528. displayPrintLn(0, displayGetString(str_menu_stats), true);
  529. displayPrintStats(1);
  530. break;
  531. case PAGE_STATS2:
  532. displayPrintLn(0, displayGetString(str_menu_stats2), true);
  533. displayPrintStats2(1);
  534. break;
  535. case PAGE_DESCALING:
  536. displayPrintLn(0, displayGetString(str_menu_nextdesc), true);
  537. displayPrintNextDesc(1);
  538. break;
  539. case PAGE_TEMP:
  540. displayPrintLn(0, displayGetString(str_menu_temp), true);
  541. displayPrintTemp(1);
  542. break;
  543. case PAGE_CLEAN:
  544. displayPrintLn(0, displayGetString(str_menu), true);
  545. displayPrintLn(1, displayGetString(str_menu_clean), true);
  546. break;
  547. case PAGE_REBOOT:
  548. displayPrintLn(0, displayGetString(str_menu), true);
  549. displayPrintLn(1, displayGetString(str_menu_reboot), true);
  550. break;
  551. case PAGE_EXIT:
  552. displayPrintLn(0, displayGetString(str_menu), true);
  553. displayPrintLn(1, displayGetString(str_menu_exit), true);
  554. break;
  555. case PAGE_SETTINGS:
  556. displayPrintLn(0, displayGetString(str_menu), true);
  557. displayPrintLn(1, displayGetString(str_menu_settings), true);
  558. break;
  559. case PAGE_RESETKWH:
  560. displayPrintLn(0, displayGetString(str_menu_settings), true);
  561. displayPrintLn(1, displayGetString(str_menu_resetkwh), true);
  562. break;
  563. case PAGE_RESETKWH_VAL: //confirmation dialog
  564. displayPrintLn(0, displayGetString(str_menu_resetkwh_val), true);
  565. break;
  566. case PAGE_CHANGEPREINF:
  567. displayPrintLn(0, displayGetString(str_menu_settings), true);
  568. displayPrintLn(1, displayGetString(str_menu_changepreinf), true);
  569. break;
  570. case PAGE_CHANGEPREINF_VAL:
  571. displayPrintLn(0, displayGetString(str_menu_changepreinf), true);
  572. displayPrintNum(1, getCoffeeCfg()->amount_preinfusion, "ml");
  573. break;
  574. case PAGE_CHANGEBREWTIME:
  575. displayPrintLn(0, displayGetString(str_menu_settings), true);
  576. displayPrintLn(1, displayGetString(str_menu_changebrewtime), true);
  577. break;
  578. case PAGE_CHANGEBREWTIME_VAL:
  579. displayPrintLn(0, displayGetString(str_menu_changebrewtime), true);
  580. displayPrintNum(1, getCoffeeCfg()->time_infusion, "ms");
  581. break;
  582. case PAGE_CHANGEBREWML:
  583. displayPrintLn(0, displayGetString(str_menu_settings), true);
  584. displayPrintLn(1, displayGetString(str_menu_changebrewml), true);
  585. break;
  586. case PAGE_CHANGEBREWML_VAL:
  587. displayPrintLn(0, displayGetString(str_menu_changebrewml), true);
  588. displayPrintNum(1, getCoffeeCfg()->amount_espresso, "ml");
  589. break;
  590. case PAGE_CHANGESOAKTIME:
  591. displayPrintLn(0, displayGetString(str_menu_settings), true);
  592. displayPrintLn(1, displayGetString(str_menu_changesoaktime), true);
  593. break;
  594. case PAGE_CHANGESOAKTIME_VAL:
  595. displayPrintLn(0, displayGetString(str_menu_changesoaktime), true);
  596. displayPrintNum(1, getCoffeeCfg()->time_soak, "ms");
  597. break;
  598. case PAGE_CHANGEAUTORESET:
  599. displayPrintLn(0, displayGetString(str_menu_settings), true);
  600. displayPrintLn(1, displayGetString(str_menu_changeAutoReset), true);
  601. break;
  602. case PAGE_CHANGEAUTORESET_VAL:
  603. displayPrintLn(0, displayGetString(str_menu_changeAutoReset), true);
  604. displayPrintNum(1, halGetFlowResetTime(), "ms");
  605. break;
  606. case PAGE_LEAVESETTINGS:
  607. displayPrintLn(0, displayGetString(str_menu_settings), true);
  608. displayPrintLn(1, displayGetString(str_menu_leavesettings), true);
  609. break;
  610. default:
  611. displayPrintLn(0, displayGetString(str_menu), true);
  612. displayPrintLn(1, "???", true);
  613. break;
  614. }
  615. }
  616. }
  617. /**
  618. * Returns the matching translation of a string
  619. * @param string Requested string
  620. * @return Translated string
  621. */
  622. const char* displayGetString(display_strings_t string) {
  623. if (displayLang >= lang_last)
  624. displayLang = DEFAULT_LANG;
  625. return display_strings[string].text[displayLang];
  626. }