|
@@ -10,8 +10,9 @@
|
|
|
#include <unistd.h>
|
|
|
#include <string.h>
|
|
|
|
|
|
+#include "display2.h"
|
|
|
+
|
|
|
#include "global.h"
|
|
|
-#include "display.h"
|
|
|
#include "logger.h"
|
|
|
#include "database.h"
|
|
|
#include "timer.h"
|
|
@@ -21,15 +22,39 @@
|
|
|
#include "events.h"
|
|
|
#include "DS18B20.h"
|
|
|
|
|
|
+#define CURRENT 0
|
|
|
+#define NEXT 1
|
|
|
+
|
|
|
+//timeouts for the transitions in ms
|
|
|
+#define TIMEOUT_PREBREW 1000
|
|
|
+#define TIMEOUT_POSTBREW 4000
|
|
|
+
|
|
|
display_lang_t displayLang;
|
|
|
timer displayTimer(displayTimerHandler);
|
|
|
int lcd = 0;
|
|
|
-volatile int timerScaler = 0;
|
|
|
-volatile int elapsedCnt = 0;
|
|
|
-coffee_status_t coffeeState = STATE_OFF;
|
|
|
-coffee_mode_t coffeeMode = MODE_STATE;
|
|
|
-coffee_menuPage_t coffeePage = PAGE_SOFTOFF;
|
|
|
+// currently only the history of states is of interest
|
|
|
+coffee_status_t coffeeState[] = {STATE_OFF, STATE_NULL}; // current - next state
|
|
|
+coffee_mode_t coffeeMode[] = {MODE_STATE, MODE_NULL};
|
|
|
+coffee_menuPage_t coffeePage[] = {PAGE_SOFTOFF, PAGE_NULL};
|
|
|
bool coffeeDescaling = false;
|
|
|
+refreshRate_t currentRefreshRate = refresh_std;
|
|
|
+uint16_t holdNext[3] = {0, 0, 0}; //holdtime of the new {state, Mode, Page} in ms
|
|
|
+uint16_t nextWaitTime[3] = {0, 0, 0}; //actual waiting time of the new {state, Mode, Page}
|
|
|
+
|
|
|
+
|
|
|
+typedef enum {
|
|
|
+ state_idx = 0,
|
|
|
+ mode_idx = 1,
|
|
|
+ page_idx = 2
|
|
|
+} idx_t;
|
|
|
+
|
|
|
+void track(idx_t idx);
|
|
|
+void switchToNextPage(coffee_menuPage_t* history);
|
|
|
+void switchToNextMode(coffee_mode_t* history);
|
|
|
+void switchToNextState(coffee_status_t* history);
|
|
|
+void setRefreshRate(refreshRate_t rate);
|
|
|
+void setSwitchToNextTimeout(idx_t idx, uint16_t millis);
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* Prints out the current time in a centered position
|
|
@@ -57,6 +82,8 @@ void displayPrintTemp(int line) {
|
|
|
//after the first refresh the right temperature is displayed
|
|
|
//no idea where this comes from, datasheet says nothing about dummy readouts.
|
|
|
//no old values are used, conversion is started before every readout...
|
|
|
+ //Quick fix:
|
|
|
+ DS18B20_readTemp();
|
|
|
if (line > DISPLAY_ROWS)
|
|
|
line = 0;
|
|
|
|
|
@@ -93,13 +120,25 @@ void displayPrintStats2(int line) {
|
|
|
*/
|
|
|
void displayPrintNextDesc(int line) {
|
|
|
char buffer[17];
|
|
|
- if (line > DISPLAY_ROWS)
|
|
|
- line = 0;
|
|
|
+ if (line > DISPLAY_ROWS) line = 0;
|
|
|
|
|
|
sprintf(buffer, "%d d or %d C", checkDirtyTime(), checkDirtyEspresso());
|
|
|
displayPrintLn(line, buffer, true);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ *
|
|
|
+ */
|
|
|
+void displayPrintPostBrew(int line){
|
|
|
+ char buffer[17];
|
|
|
+ if (line > DISPLAY_ROWS) line = 0;
|
|
|
+
|
|
|
+ float brewTime = (float)getLastBrewTime();
|
|
|
+
|
|
|
+ sprintf(buffer, "%.1f ml / %.1f s", halGetLastFlow(), brewTime / 1000);
|
|
|
+ displayPrintLn(line, buffer, true);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Prints out the total volume flow
|
|
|
* @param line Target line in display
|
|
@@ -165,13 +204,8 @@ void displayStateUpdated(event_t *event) {
|
|
|
return;
|
|
|
}
|
|
|
coffee_status_t state = *(coffee_status_t*) event->data;
|
|
|
- if (state != coffeeState) {
|
|
|
- coffeeState = state;
|
|
|
- if (timerScaler)
|
|
|
- timerScaler--;
|
|
|
- elapsedCnt = 0;
|
|
|
- displayTimer.call();
|
|
|
- }
|
|
|
+ coffeeState[NEXT] = state;
|
|
|
+ displayTimer.call();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -185,17 +219,16 @@ void displayModeUpdated(event_t *event) {
|
|
|
return;
|
|
|
}
|
|
|
coffee_mode_t mode = *(coffee_mode_t*) event->data;
|
|
|
- if (mode != coffeeMode) {
|
|
|
- coffeeMode = mode;
|
|
|
- if (timerScaler)
|
|
|
- timerScaler--;
|
|
|
- elapsedCnt = 0;
|
|
|
- displayTimer.call();
|
|
|
- }
|
|
|
+ coffeeMode[NEXT] = mode;
|
|
|
+ displayTimer.call();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Updates the display state to the matching coffee display page
|
|
|
+ * The new state is put on hold (next) and the display can decided if it immediately makes the
|
|
|
+ * new state to the current one or if a timeout is specified in which the new state is put on hold and the
|
|
|
+ * state transition is processed.
|
|
|
+ * One initial asynchronous call
|
|
|
* @param event Event data
|
|
|
*/
|
|
|
|
|
@@ -205,12 +238,8 @@ void displayPageUpdated(event_t *event) {
|
|
|
return;
|
|
|
}
|
|
|
coffee_menuPage_t page = *(coffee_menuPage_t*) event->data;
|
|
|
- if (page != coffeePage) {
|
|
|
- coffeePage = page;
|
|
|
- timerScaler = REFRESH_RATE;
|
|
|
- elapsedCnt = 0;
|
|
|
- displayTimer.call();
|
|
|
- }
|
|
|
+ coffeePage[NEXT] = page;
|
|
|
+ displayTimer.call();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -229,7 +258,7 @@ void displayDescaling(event_t *event) {
|
|
|
*/
|
|
|
void displayPrintLogo(void) {
|
|
|
char buffer[17];
|
|
|
- switch (coffeeState) {
|
|
|
+ switch (coffeeState[CURRENT]) {
|
|
|
case STATE_HEATING:
|
|
|
case STATE_INITALHEATING:
|
|
|
case STATE_IDLE:
|
|
@@ -245,7 +274,6 @@ void displayPrintLogo(void) {
|
|
|
/**
|
|
|
* Handles cleanup before program termination
|
|
|
*/
|
|
|
-
|
|
|
void displayTerminate(event_t *e) {
|
|
|
logger(V_BASIC, "display.cpp: Terminating\n");
|
|
|
displayPrintLn(0, "CoffeePi", true);
|
|
@@ -256,14 +284,12 @@ void displayTerminate(event_t *e) {
|
|
|
* Main thread to handle display data
|
|
|
* @param *threadid Thread ID
|
|
|
*/
|
|
|
-
|
|
|
void* displayThread(void* threadid) {
|
|
|
//sleep(1); // Wait for other components to initialize
|
|
|
displayTimer.start();
|
|
|
while (1) {
|
|
|
pause();
|
|
|
if (1) {
|
|
|
- timerScaler = REFRESH_RATE;
|
|
|
displayTimer.call();
|
|
|
}
|
|
|
}
|
|
@@ -274,52 +300,42 @@ void* displayThread(void* threadid) {
|
|
|
* Timer handler for display update
|
|
|
* @param *threadid Thread ID
|
|
|
*/
|
|
|
-
|
|
|
void* displayTimerHandler(void* threadid) {
|
|
|
- int scale1Hz = 0;
|
|
|
- if (timerScaler++ >= REFRESH_RATE) { // 1s elapsed, reset
|
|
|
- timerScaler = 0;
|
|
|
- scale1Hz = 1;
|
|
|
- }
|
|
|
+ //track time of the new state in hold and switch if necessary
|
|
|
+ track(state_idx);
|
|
|
+ track(page_idx);
|
|
|
+ track(mode_idx);
|
|
|
|
|
|
- if (scale1Hz) {
|
|
|
- if (coffeeMode == MODE_STATE) {
|
|
|
- switch (coffeeState) {
|
|
|
- case STATE_OFF:
|
|
|
- case STATE_HEATING:
|
|
|
- case STATE_INITALHEATING:
|
|
|
- case STATE_IDLE:
|
|
|
- case STATE_CLEANING:
|
|
|
- case STATE_ERROR:
|
|
|
- case STATE_WAIT_OFF:
|
|
|
- displayRefresh();
|
|
|
+ displayRefresh();
|
|
|
+ pthread_exit(EXIT_SUCCESS);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Tracks the elapsed time in ms of the new state waiting to become the current one if a hold time is specified
|
|
|
+ */
|
|
|
+
|
|
|
+void track(idx_t idx){
|
|
|
+ if (holdNext[idx] != 0) {
|
|
|
+ nextWaitTime[idx] += 1000 / currentRefreshRate;
|
|
|
+ if (holdNext[idx] <= nextWaitTime[idx]) {
|
|
|
+ switch(idx){
|
|
|
+ case state_idx:
|
|
|
+ switchToNextState(coffeeState);
|
|
|
+ break;
|
|
|
+ case page_idx:
|
|
|
+ switchToNextPage(coffeePage);
|
|
|
break;
|
|
|
- default:
|
|
|
+ case mode_idx:
|
|
|
+ switchToNextMode(coffeeMode);
|
|
|
break;
|
|
|
}
|
|
|
- } else if (coffeeMode == MODE_MENU) {
|
|
|
- displayRefresh();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- switch (coffeeState) {
|
|
|
- case STATE_BREW:
|
|
|
- case STATE_BREWMANUAL:
|
|
|
- displayRefresh();
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- if (elapsedCnt < (5 * REFRESH_RATE)) // Don't let it grow too large
|
|
|
- elapsedCnt++;
|
|
|
- pthread_exit(EXIT_SUCCESS);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Initializes display
|
|
|
*/
|
|
|
-
|
|
|
void displayInit(void) {
|
|
|
lcd = lcdInit();
|
|
|
if (lcd < 0)
|
|
@@ -330,11 +346,11 @@ void displayInit(void) {
|
|
|
displayPrintLn(1, (char*) "booting...", true);
|
|
|
//lcdPrintf(lcd, " CoffeePi booting...");
|
|
|
|
|
|
- timerScaler = 0;
|
|
|
- displayTimer.setDivider((1000000 / TIMER_DELAY_US) / REFRESH_RATE);
|
|
|
|
|
|
- logger(V_BASIC, "Initialized display with a refresh rate of %d Hz\n",
|
|
|
- REFRESH_RATE);
|
|
|
+ setRefreshRate(refresh_std);
|
|
|
+
|
|
|
+ logger(V_BASIC, "display2.cpp Initialized display with a refresh rate of %d Hz\n",
|
|
|
+ refresh_std);
|
|
|
/**The following block comes from void* displayThread(void* threadid)
|
|
|
* The idea is that the initialization functions get the component ready to react on external events
|
|
|
* once the threads start, events might be triggered and every component can process them
|
|
@@ -361,13 +377,92 @@ void displaySetLang(display_lang_t lang) {
|
|
|
displayLang = lang;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ *
|
|
|
+ */
|
|
|
+void switchToNextPage(coffee_menuPage_t* history){
|
|
|
+ if(history[NEXT] != PAGE_NULL) {
|
|
|
+ history[CURRENT] = history[NEXT];
|
|
|
+ history[NEXT] = PAGE_NULL;
|
|
|
+
|
|
|
+ holdNext[page_idx] = 0;
|
|
|
+ nextWaitTime[page_idx] = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ *
|
|
|
+ */
|
|
|
+void switchToNextMode(coffee_mode_t* history){
|
|
|
+ if(history[NEXT] != MODE_NULL) {
|
|
|
+ history[CURRENT] = history[NEXT];
|
|
|
+ history[NEXT] = MODE_NULL;
|
|
|
+
|
|
|
+ holdNext[mode_idx] = 0;
|
|
|
+ nextWaitTime[mode_idx] = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ *
|
|
|
+ */
|
|
|
+void switchToNextState(coffee_status_t* history){
|
|
|
+ if(history[NEXT] != STATE_NULL) {
|
|
|
+ history[CURRENT] = history[NEXT];
|
|
|
+ history[NEXT] = STATE_NULL;
|
|
|
+
|
|
|
+ holdNext[state_idx] = 0;
|
|
|
+ nextWaitTime[state_idx] = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * sets the refresh rate of the the display
|
|
|
+ * to one of the predefined refresh rates.
|
|
|
+ */
|
|
|
+void setRefreshRate(refreshRate_t rate) {
|
|
|
+ currentRefreshRate = rate;
|
|
|
+ displayTimer.setDivider(20 / rate);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * specifies a timeout at which the new state will be made to the current one
|
|
|
+ * This function is necessary for the special state transitions which hold the new state while they
|
|
|
+ * process the current transition. These cases set a timeout specifying how long the state transition should be paused.
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+void setSwitchToNextTimeout(idx_t idx, uint16_t millis) {
|
|
|
+ holdNext[idx] = millis;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
- * Refreshed the display content and outputs it
|
|
|
+ * The core description of what will be displayed in what displaystate
|
|
|
*/
|
|
|
|
|
|
void displayRefresh(void) {
|
|
|
- if (coffeeMode == MODE_STATE) {
|
|
|
- switch (coffeeState) { //coffeeGetState()
|
|
|
+ //handle mode trainsitions
|
|
|
+ switchToNextMode(coffeeMode);
|
|
|
+
|
|
|
+ //FSM of the display
|
|
|
+ if (coffeeMode[CURRENT] == MODE_STATE) {
|
|
|
+ //handle state transitions
|
|
|
+ if (coffeeState[NEXT] == STATE_BREW) { //Pre brew
|
|
|
+ //check how long the new state is already in hold ... and either switch or process transition
|
|
|
+ setSwitchToNextTimeout(state_idx, TIMEOUT_PREBREW);
|
|
|
+ setRefreshRate(refresh_fast);
|
|
|
+ displayPrintLogo();
|
|
|
+ displayPrintLn(1, displayGetString(str_brewing), true);
|
|
|
+ return;
|
|
|
+ } else if (coffeeState[CURRENT] == STATE_BREW && coffeeState[NEXT] != STATE_NULL) { //Post brew
|
|
|
+ setSwitchToNextTimeout(state_idx, TIMEOUT_POSTBREW);
|
|
|
+ setRefreshRate(refresh_std);
|
|
|
+ displayPrintPostBrew(1);
|
|
|
+ return;
|
|
|
+ } else { //no special state transition -> make new state to the current one
|
|
|
+ switchToNextState(coffeeState);
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (coffeeState[CURRENT]) { //coffeeGetState()
|
|
|
case STATE_IDLE:
|
|
|
displayPrintLogo();
|
|
|
displayPrintLn(1, displayGetString(str_ready), true);
|
|
@@ -384,13 +479,8 @@ void displayRefresh(void) {
|
|
|
break;
|
|
|
|
|
|
case STATE_BREW:
|
|
|
- if (elapsedCnt <= 2 * REFRESH_RATE) {
|
|
|
- displayPrintLogo();
|
|
|
- displayPrintLn(1, displayGetString(str_brewing), true);
|
|
|
- } else {
|
|
|
- displayPrintLn(0, displayGetString(str_brewing), true);
|
|
|
- displayPrintFlow(1);
|
|
|
- }
|
|
|
+ displayPrintLn(0, displayGetString(str_brewing), true);
|
|
|
+ displayPrintFlow(1);
|
|
|
break;
|
|
|
|
|
|
case STATE_BREWMANUAL:
|
|
@@ -419,8 +509,18 @@ void displayRefresh(void) {
|
|
|
displayPrintTime(1);
|
|
|
break;
|
|
|
}
|
|
|
- } else if (coffeeMode == MODE_MENU) {
|
|
|
- switch (coffeePage) {
|
|
|
+ } else if (coffeeMode[CURRENT] == MODE_MENU) {
|
|
|
+ //handle page transitions
|
|
|
+ if(coffeePage[NEXT] == PAGE_EXIT) {
|
|
|
+ setSwitchToNextTimeout(page_idx, 2000);
|
|
|
+ displayPrintLn(0, "test vor exit", true);
|
|
|
+ displayPrintLn(1, "Test", true);
|
|
|
+ return;
|
|
|
+ } else {
|
|
|
+ switchToNextPage(coffeePage);
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (coffeePage[CURRENT]) {
|
|
|
case PAGE_SOFTOFF:
|
|
|
displayPrintLn(0, displayGetString(str_menu), true);
|
|
|
displayPrintLn(1, displayGetString(str_menu_softoff), true);
|