Sat, 20 Oct 2018 13:23:15 +0200
Initial checkin brewboard
0 | 1 | /** |
2 | * @file task_tft.c | |
3 | * @brief BrewBoard TFT and Touch screen driver. | |
4 | * But because the application is controlled using the touch screen, | |
5 | * all the processing of menus is also found here. | |
6 | * It's the first started task, but it does nothing until the | |
7 | * Main_Screen variable is set. | |
8 | * | |
9 | */ | |
10 | ||
11 | #include "config.h" | |
12 | ||
13 | spi_lobo_device_handle_t spi; | |
14 | spi_lobo_device_handle_t tsspi = NULL; | |
15 | extern sButton Buttons[MAXBUTTONS]; // 40 buttons on a screen. | |
16 | time_t now; | |
17 | struct tm timeinfo; | |
18 | char s_timer[10]; | |
19 | char s_top_msg[64]; | |
20 | ||
21 | extern float stageTemp; | |
22 | extern uint16_t stageTime; | |
23 | extern uint16_t TimeWhirlPool; | |
24 | extern uint32_t TimeLeft; | |
25 | extern uint32_t TimeSpent; | |
26 | extern uint32_t SecsCount; | |
27 | extern uint32_t pumpTime; | |
28 | extern uint32_t TimeBrewing; | |
29 | extern uint16_t Steady; | |
30 | esp_timer_handle_t timerHandle; | |
31 | extern bool _NewMinute; | |
32 | extern bool _UseHLT; | |
33 | extern bool System_TimeOk; | |
34 | ||
35 | static const char *TAG = "task_tft"; | |
36 | ||
37 | // Define which spi bus to use TFT_VSPI_HOST or TFT_HSPI_HOST | |
38 | #define SPI_BUS TFT_HSPI_HOST | |
39 | ||
40 | extern int Main_Screen; | |
41 | extern int Old_Screen; | |
42 | extern int MLT_pin; | |
43 | extern int HLT_pin; | |
44 | extern int Pump_pin; | |
45 | extern DS18B20_State *ds18b20_state; | |
46 | extern DRIVER_State *driver_state; | |
47 | extern JSON_log *json_log; | |
48 | extern SemaphoreHandle_t xSemaphoreDS18B20; | |
49 | extern SemaphoreHandle_t xSemaphoreDriver; | |
50 | extern SemaphoreHandle_t xSemaphoreWiFi; | |
51 | extern WIFI_State *wifi_state; | |
52 | extern double Output; | |
53 | extern sButton Buttons[MAXBUTTONS]; | |
54 | ||
55 | extern int BoilPower, LastMashStep; | |
56 | extern char temp_buf[], logline[], strftime_buf[64]; | |
57 | extern bool loop, CoolBeep, Resume, pumpRest, updateRuntime; | |
58 | extern bool NewMinute, TempReached; | |
59 | extern uint8_t MashState; | |
60 | extern float temp_MLT, MinMash, MaxMash; | |
61 | extern uint32_t power_MLT, power_HLT, counts; | |
62 | ||
63 | ||
64 | #ifdef CONFIG_TEMP_SENSORS_SIMULATOR | |
65 | extern float Fake_MLT; | |
66 | extern float Fake_HLT; | |
67 | #endif | |
68 | ||
69 | ||
70 | ||
71 | /** | |
72 | * @brief Seconds timer callback. | |
73 | */ | |
74 | void TimerCallback(void *arg); | |
75 | ||
76 | ||
77 | /***************************************************************************/ | |
78 | ||
79 | ||
80 | ||
81 | int init_tft_display(void) | |
82 | { | |
83 | esp_err_t ret; | |
84 | esp_timer_create_args_t timerSecond = { | |
85 | .callback = &TimerCallback, | |
86 | .name = "SecondsTimer" | |
87 | }; | |
88 | ||
89 | ESP_LOGI(TAG, "Initialize TFT"); | |
90 | ||
91 | max_rdclock = 8000000; | |
92 | TFT_PinsInit(); | |
93 | ||
94 | spi_lobo_bus_config_t buscfg = { | |
95 | .miso_io_num=PIN_NUM_MISO, // set SPI MISO pin | |
96 | .mosi_io_num=PIN_NUM_MOSI, // set SPI MOSI pin | |
97 | .sclk_io_num=PIN_NUM_CLK, // set SPI CLK pin | |
98 | .quadwp_io_num=-1, | |
99 | .quadhd_io_num=-1, | |
100 | .max_transfer_sz = 6*1024, | |
101 | }; | |
102 | spi_lobo_device_interface_config_t devcfg={ | |
103 | .clock_speed_hz=8000000, // Initial clock out at 8 MHz | |
104 | .mode=0, // SPI mode 0 | |
105 | .spics_io_num=-1, // we will use external CS pin | |
106 | .spics_ext_io_num=PIN_NUM_CS, // external CS pin | |
107 | .flags=LB_SPI_DEVICE_HALFDUPLEX, // ALWAYS SET to HALF DUPLEX MODE!! for display spi | |
108 | }; | |
109 | spi_lobo_device_interface_config_t tsdevcfg={ | |
110 | .clock_speed_hz=2500000, //Clock out at 2.5 MHz | |
111 | .mode=0, //SPI mode 0 | |
112 | .spics_io_num=PIN_NUM_TCS, //Touch CS pin | |
113 | .spics_ext_io_num=-1, //Not using the external CS | |
114 | }; | |
115 | ||
116 | ESP_LOGI(TAG, "TFT pins: miso=%d, mosi=%d, sck=%d, cs=%d", PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_CS); | |
117 | ||
118 | ret = spi_lobo_bus_add_device(SPI_BUS, &buscfg, &devcfg, &spi); | |
119 | assert(ret == ESP_OK); | |
120 | disp_spi = spi; | |
121 | ||
122 | // ==== Test select/deselect ==== | |
123 | ret = spi_lobo_device_select(spi, 1); | |
124 | assert(ret == ESP_OK); | |
125 | ret = spi_lobo_device_deselect(spi); | |
126 | assert(ret == ESP_OK); | |
127 | ||
128 | ESP_LOGI(TAG, "SPI: attached display, spi bus: %d, speed: %u, bus uses native pins: %s", | |
129 | SPI_BUS, spi_lobo_get_speed(spi), spi_lobo_uses_native_pins(spi) ? "true" : "false"); | |
130 | ||
131 | ESP_LOGI(TAG, "TS pins : miso=%d, mosi=%d, sck=%d, cs=%d", PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_TCS); | |
132 | ||
133 | ret=spi_lobo_bus_add_device(SPI_BUS, &buscfg, &tsdevcfg, &tsspi); | |
134 | assert(ret == ESP_OK); | |
135 | ts_spi = tsspi; | |
136 | ||
137 | // ==== Test select/deselect ==== | |
138 | ret = spi_lobo_device_select(tsspi, 1); | |
139 | assert(ret == ESP_OK); | |
140 | ret = spi_lobo_device_deselect(tsspi); | |
141 | assert(ret == ESP_OK); | |
142 | ||
143 | ESP_LOGI(TAG, "SPI: attached TS device, spi bus: %d, speed: %u", SPI_BUS, spi_lobo_get_speed(tsspi)); | |
144 | ||
145 | // ==== Initialize the Display ==== | |
146 | TFT_display_init(); | |
147 | ||
148 | // ---- Detect maximum read speed ---- | |
149 | max_rdclock = find_rd_speed(); | |
150 | ||
151 | // ==== Set SPI clock used for display operations ==== | |
152 | spi_lobo_set_speed(spi, DEFAULT_SPI_CLOCK); | |
153 | ESP_LOGI(TAG, "SPI: Max rd speed: %u, changed speed to %u", max_rdclock, spi_lobo_get_speed(spi)); | |
154 | ||
155 | font_rotate = 0; | |
156 | text_wrap = 0; | |
157 | font_transparent = 0; | |
158 | font_forceFixed = 0; | |
159 | gray_scale = 0; | |
160 | TFT_setGammaCurve(DEFAULT_GAMMA_CURVE); | |
161 | TFT_setRotation(LANDSCAPE); | |
162 | TFT_setFont(DEFAULT_FONT, NULL); | |
163 | TFT_resetclipwin(); | |
164 | ||
165 | /* | |
166 | * Create a one second periodic timer. | |
167 | */ | |
168 | ret = esp_timer_create(&timerSecond, &timerHandle); | |
169 | assert(ret == ESP_OK); | |
170 | ret = esp_timer_start_periodic(timerHandle, 1000000); | |
171 | assert(ret == ESP_OK); | |
172 | ||
173 | return ret; | |
174 | } | |
175 | ||
176 | ||
177 | ||
178 | void TimerCallback(void *arg) | |
179 | { | |
180 | TimeSpent++; | |
181 | SecsCount++; | |
182 | Steady++; | |
183 | TimeBrewing++; | |
184 | runtime.TimeBrewing++; | |
185 | if ((SecsCount % 60) == 0) | |
186 | _NewMinute = true; | |
187 | ||
188 | if (TimeLeft) { | |
189 | TimeLeft--; | |
190 | if (TimeLeft == 5) { | |
191 | SoundPlay(SOUND_TimeOut); | |
192 | } | |
193 | if ((TimeLeft % 60) == 0) { | |
194 | pumpTime++; | |
195 | } | |
196 | } | |
197 | } | |
198 | ||
199 | ||
200 | ||
201 | void TimerSet(uint32_t seconds) | |
202 | { | |
203 | Steady = TimeSpent = SecsCount = 0; | |
204 | TimeLeft = seconds; | |
205 | } | |
206 | ||
207 | ||
208 | ||
209 | void TimerShow(uint32_t Time, int X, int Y) | |
210 | { | |
211 | uint8_t Hours = (uint8_t)(Time / 3600); | |
212 | uint8_t Minutes = (uint8_t)((Time % 3600) / 60); | |
213 | uint8_t Seconds = (uint8_t)(Time % 60); | |
214 | char msg[32]; | |
215 | static uint32_t _oldTime = 0; | |
216 | ||
217 | if (Time != _oldTime) { | |
218 | _fg = TFT_GREEN; | |
219 | TFT_setFont(FONT_7SEG, NULL); | |
220 | set_7seg_font_atrib(12, 2, 1, TFT_DARKGREY); | |
221 | snprintf(s_timer, 9, "%02d:%02d:%02d", Hours, Minutes, Seconds); | |
222 | TFT_print(s_timer, X, Y); | |
223 | _oldTime = Time; | |
224 | snprintf(msg, 31, "{\"timer\":\"%s\"}", s_timer); | |
225 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
226 | } | |
227 | } | |
228 | ||
229 | ||
230 | ||
231 | void TopMessage(char *text) | |
232 | { | |
233 | char msg[64]; | |
234 | ||
235 | snprintf(s_top_msg, 63, "%s", text); | |
236 | _fg = TFT_YELLOW; | |
237 | font_transparent = 1; | |
238 | TFT_setFont(DEJAVU24_FONT, NULL); | |
239 | TFT_fillRect(0, 0, 319, 25, TFT_NAVY); | |
240 | TFT_print(s_top_msg, CENTER, 2); | |
241 | font_transparent = 0; | |
242 | snprintf(msg, 63, "{\"top_msg\":\"%s\"}", s_top_msg); | |
243 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
244 | } | |
245 | ||
246 | ||
247 | ||
248 | void MLT_info(int x, int y, bool update) | |
249 | { | |
250 | char ctemp[16], csp[16], cpower[16], msg[32]; | |
251 | static char ltemp[16], lsp[16], lpower[16]; | |
252 | bool con, cpwr, cpump = false; | |
253 | static bool lon, lpwr, lpump; | |
254 | ||
255 | _bg = (color_t){ 48, 48, 48 }; | |
256 | _fg = TFT_WHITE; | |
257 | color_t _led = { 31,255, 31}; | |
258 | color_t _pump = {127,175,255}; | |
259 | color_t _pwr = {255, 47, 47}; | |
260 | ||
261 | if (! update) { | |
262 | TFT_fillRect(x, y, 178, 90, _bg); | |
263 | TFT_drawRect(x, y, 178, 90, _fg); | |
264 | TFT_drawFastHLine(x, y + 21, 178, _fg); | |
265 | TFT_setFont(DEJAVU18_FONT, NULL); | |
266 | TFT_print("MLT", x + 67, y + 3); | |
267 | } | |
268 | ||
269 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
270 | sprintf(ctemp, "%7.3f", driver_state->mlt_pv); | |
271 | if (driver_state->mlt_mode) { | |
272 | sprintf(csp, "%6.2f sp", driver_state->mlt_sp); | |
273 | } else { | |
274 | csp[0] = '\0'; | |
275 | } | |
276 | if ((driver_state->mlt_mode == MLT_MODE_BANG) || (driver_state->mlt_mode == MLT_MODE_PID) || (driver_state->mlt_mode == MLT_MODE_EXT)) { | |
277 | sprintf(cpower, "%3d%%", driver_state->mlt_power); | |
278 | } else { | |
279 | cpower[0] = '\0'; | |
280 | } | |
281 | xSemaphoreGive(xSemaphoreDriver); | |
282 | } | |
283 | ||
284 | con = (MLT_pin) ? true : false; | |
285 | if ((con != lon) || (! update)) { | |
286 | if (con) { | |
287 | TFT_fillCircle(x + 166, y + 11, 8, _led); | |
288 | } else { | |
289 | TFT_fillCircle(x + 166, y + 11, 8, _bg); | |
290 | } | |
291 | lon = con; | |
292 | snprintf(msg, 31, "{\"mlt_led\":\"%s\"}", con ? "1":"0"); | |
293 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
294 | } | |
295 | ||
296 | cpump = (Pump_pin) ? true : false; | |
297 | if ((cpump != lpump) || (! update)) { | |
298 | if (cpump) { | |
299 | TFT_fillCircle(x + 146, y + 11, 8, _pump); | |
300 | } else { | |
301 | TFT_fillCircle(x + 146, y + 11, 8, _bg); | |
302 | } | |
303 | lpump = cpump; | |
304 | snprintf(msg, 31, "{\"pump_led\":\"%s\"}", cpump ? "1":"0"); | |
305 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
306 | } | |
307 | ||
308 | if (equipment.SSR2 == SSR2_ON_IDLE) { | |
309 | cpwr = (HLT_pin) ? true : false; | |
310 | if ((cpwr != lpwr) || (! update)) { | |
311 | if (cpwr) { | |
312 | TFT_fillCircle(x + 126, y + 11, 8, _pwr); | |
313 | } else { | |
314 | TFT_fillCircle(x + 126, y + 11, 8, _bg); | |
315 | } | |
316 | lpwr = cpwr; | |
317 | snprintf(msg, 31, "{\"hlt_led\":\"%s\"}", cpwr ? "1":"0"); | |
318 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
319 | } | |
320 | } | |
321 | ||
322 | if (strcmp(ctemp, ltemp) || (! update)) { | |
323 | TFT_setFont(USER_FONT, "/spiffs/fonts/Grotesk24x48.fon"); | |
324 | TFT_print(ctemp, x + 5, y + 23); | |
325 | strncpy(ltemp, ctemp, 16); | |
326 | snprintf(msg, 31, "{\"mlt_pv\":\"%s\"}", ctemp); | |
327 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
328 | } | |
329 | ||
330 | TFT_setFont(DEJAVU18_FONT, NULL); | |
331 | if (strcmp(csp, lsp) || (! update)) { | |
332 | TFT_clearStringRect(x + 5, y + 70, "123.45 sp"); | |
333 | TFT_print(csp, x + 5, y + 70); | |
334 | strncpy(lsp, csp, 16); | |
335 | snprintf(msg, 31, "{\"mlt_sp\":\"%s\"}", csp); | |
336 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
337 | } | |
338 | if (strcmp(cpower, lpower) || (! update)) { | |
339 | TFT_clearStringRect(x + 120, y + 70, "100%"); | |
340 | TFT_print(cpower, x + 120, y + 70); | |
341 | strncpy(lpower, cpower, 16); | |
342 | snprintf(msg, 31, "{\"mlt_power\":\"%s\"}", cpower); | |
343 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
344 | } | |
345 | } | |
346 | ||
347 | ||
348 | ||
349 | void HLT_info(int x, int y, bool update, bool small) | |
350 | { | |
351 | char ctemp[16], csp[16], cpower[16], msg[32]; | |
352 | static char ltemp[16], lsp[16], lpower[16]; | |
353 | bool con = false; | |
354 | static bool lon; | |
355 | uint8_t H; | |
356 | ||
357 | _bg = (color_t){ 63, 63, 64 }; | |
358 | _fg = TFT_YELLOW; | |
359 | color_t _led = {255, 47, 47}; | |
360 | H = (small) ? 70 : 90; | |
361 | ||
362 | if (! update) { | |
363 | TFT_fillRect(x, y, 178, H, _bg); | |
364 | TFT_drawRect(x, y, 178, H, _fg); | |
365 | TFT_drawFastHLine(x, y + 21, 178, _fg); | |
366 | TFT_setFont(DEJAVU18_FONT, NULL); | |
367 | TFT_print("HLT", x + 67, y + 3); | |
368 | } | |
369 | ||
370 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
371 | sprintf(ctemp, "%7.3f", driver_state->hlt_pv); | |
372 | if (driver_state->hlt_mode == HLT_MODE_BANG) { | |
373 | sprintf(cpower, "%3d%%", driver_state->hlt_power); | |
374 | } else { | |
375 | cpower[0] = '\0'; | |
376 | } | |
377 | if (driver_state->hlt_mode == HLT_MODE_BANG || driver_state->hlt_mode == HLT_MODE_OFF) { | |
378 | sprintf(csp, "%6.2f sp", driver_state->hlt_sp); | |
379 | } else { | |
380 | csp[0] = '\0'; | |
381 | } | |
382 | xSemaphoreGive(xSemaphoreDriver); | |
383 | } | |
384 | ||
385 | con = (HLT_pin) ? true : false; | |
386 | if ((con != lon) || (! update)) { | |
387 | if (con) { | |
388 | TFT_fillCircle(x + 166, y + 11, 8, _led); | |
389 | } else { | |
390 | TFT_fillCircle(x + 166, y + 11, 8, _bg); | |
391 | } | |
392 | lon = con; | |
393 | snprintf(msg, 31, "{\"hlt_led\":\"%s\"}", con ? "1":"0"); | |
394 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
395 | } | |
396 | ||
397 | if (strcmp(ltemp, ctemp) || (! update)) { | |
398 | if (small) { | |
399 | TFT_setFont(USER_FONT, "/spiffs/fonts/DejaVuSans24.fon"); | |
400 | TFT_print(ctemp, x + 40, y + 25); | |
401 | } else { | |
402 | TFT_setFont(USER_FONT, "/spiffs/fonts/Grotesk24x48.fon"); | |
403 | TFT_print(ctemp, x + 5, y + 23); | |
404 | } | |
405 | strncpy(ltemp, ctemp, 16); | |
406 | snprintf(msg, 31, "{\"hlt_pv\":\"%s\"}", ctemp); | |
407 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
408 | } | |
409 | ||
410 | H = (small) ? 50 : 70; | |
411 | TFT_setFont(DEJAVU18_FONT, NULL); | |
412 | if (strcmp(csp, lsp) || (! update)) { | |
413 | TFT_clearStringRect(x + 5, y + H, "123.45 sp"); | |
414 | TFT_print(csp, x + 5, y + H); | |
415 | strncpy(lsp, csp, 16); | |
416 | snprintf(msg, 31, "{\"hlt_sp\":\"%s\"}", csp); | |
417 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
418 | } | |
419 | if (strcmp(cpower, lpower) || (! update)) { | |
420 | TFT_clearStringRect(x + 120, y + H, "100%"); | |
421 | TFT_print(cpower, x + 120, y + H); | |
422 | strncpy(lpower, cpower, 16); | |
423 | snprintf(msg, 31, "{\"hlt_power\":\"%s\"}", cpower); | |
424 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
425 | } | |
426 | } | |
427 | ||
428 | ||
429 | ||
430 | void update_json(void) | |
431 | { | |
432 | int Hour = (TimeBrewing / 3600); | |
433 | int Minute = ((TimeBrewing % 3600) / 60); | |
434 | ||
435 | if (counts == 0) | |
436 | counts = 1; // Prevent division by zero. | |
437 | ||
438 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
439 | snprintf(json_log->time, 8, "%02d:%02d", Hour, Minute); | |
440 | json_log->mlt_sp = driver_state->mlt_sp; | |
441 | json_log->mlt_pv = driver_state->mlt_pv; | |
442 | json_log->mlt_power = power_MLT / counts; | |
443 | json_log->mlt_tempreached = TempReached ? 1:0; | |
444 | json_log->pump_run = driver_state->pump_run; | |
445 | json_log->hlt_sp = driver_state->hlt_sp; | |
446 | json_log->hlt_pv = driver_state->hlt_pv; | |
447 | json_log->hlt_power = power_HLT / counts; | |
448 | json_log->event[0] = '\0'; | |
449 | xSemaphoreGive(xSemaphoreDriver); | |
450 | } | |
451 | } | |
452 | ||
453 | ||
454 | ||
455 | void TFTstartWS(int client) | |
456 | { | |
457 | char msg[1024]; | |
458 | char mlt_sp[16], mlt_power[16], hlt_sp[16], hlt_power[16]; | |
459 | ||
460 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
461 | if (driver_state->mlt_sp) { | |
462 | snprintf(mlt_sp, 15, "%6.2f sp", driver_state->mlt_sp); | |
463 | snprintf(mlt_power, 15, "%3d%%", driver_state->mlt_power); | |
464 | } else { | |
465 | mlt_sp[0] = '\0'; | |
466 | mlt_power[0] = '\0'; | |
467 | } | |
468 | if (driver_state->hlt_sp) { | |
469 | snprintf(hlt_sp, 15, "%6.2f sp", driver_state->hlt_sp); | |
470 | snprintf(hlt_power, 15, "%3d%%", driver_state->hlt_power); | |
471 | } else { | |
472 | hlt_sp[0] = '\0'; | |
473 | hlt_power[0] = '\0'; | |
474 | } | |
475 | snprintf(msg, 1023, "{\"main\":\"%d\",\"mlt_led\":\"%d\",\"mlt_pv\":\"%7.3f\",\"mlt_sp\":\"%s\",\"mlt_power\":\"%s\"" \ | |
476 | ",\"pump_led\":\"%d\",\"hlt_led\":\"%d\",\"hlt_pv\":\"%7.3f\",\"hlt_sp\":\"%s\",\"hlt_power\":\"%s\"" \ | |
477 | ",\"timer\":\"%s\",\"top_msg\":\"%s\"}", | |
478 | Main_Screen, (MLT_pin) ? 1:0, driver_state->mlt_pv, mlt_sp, mlt_power, | |
479 | (Pump_pin) ? 1:0, (HLT_pin) ? 1:0, driver_state->hlt_pv, hlt_sp, hlt_power, | |
480 | s_timer, s_top_msg); | |
481 | ||
482 | xSemaphoreGive(xSemaphoreDriver); | |
483 | ws_server_send_text_client(client, msg, strlen(msg)); | |
484 | } | |
485 | ||
486 | } | |
487 | ||
488 | ||
489 | ||
490 | void task_tft(void *pvParameter) | |
491 | { | |
492 | char msg[32]; | |
493 | ||
494 | ESP_LOGI(TAG, "Initialize TFT/Touch task"); | |
495 | ||
496 | /* | |
497 | * Task loop. Read touchscreen events. | |
498 | */ | |
499 | while (1) { | |
500 | /* | |
501 | * Build new screen. | |
502 | */ | |
503 | startover: | |
504 | ||
505 | updateRuntime = false; | |
506 | if (_NewMinute) { | |
507 | _NewMinute = false; | |
508 | NewMinute = true; | |
509 | } | |
510 | ||
511 | /* | |
512 | * Timekeeping. In the WiFi task sntp is started if there | |
513 | * is a valid internet connection. | |
514 | */ | |
515 | time(&now); | |
516 | localtime_r(&now, &timeinfo); | |
517 | // Is time set? If not, tm_year will be (1970 - 1900). | |
518 | if ((timeinfo.tm_year > (2016 - 1900)) && (! System_TimeOk)) { | |
519 | System_TimeOk = true; | |
520 | strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); | |
521 | ESP_LOGI(TAG, "System time is set: %s", strftime_buf); | |
522 | } | |
523 | ||
524 | if (Old_Screen != Main_Screen) { | |
525 | ||
526 | if ((Main_Screen == MAIN_MODE_FREE) && ((config.ts_xleft == 0) || (config.ts_ybottom == 0))) { | |
527 | Main_Screen = MAIN_MODE_CALIBRATION; | |
528 | } | |
529 | ||
530 | /* | |
531 | * With each screenchange, remove the timer too. | |
532 | */ | |
533 | snprintf(msg, 31, "{\"main\":\"%d\",\"timer\":\"\"}", Main_Screen); | |
534 | ws_server_send_text_clients("/ws", msg, strlen(msg)); | |
535 | ||
536 | ESP_LOGI(TAG, "Change screen %d to %d", Old_Screen, Main_Screen); | |
537 | _bg = TFT_BLACK; | |
538 | TFT_fillScreen(_bg); | |
539 | TFT_resetclipwin(); | |
540 | Buttons_Clear(); | |
541 | Old_Screen = Main_Screen; | |
542 | ||
543 | switch (Main_Screen) { | |
544 | case MAIN_MODE_FREE: | |
545 | TopMessage("Hoofdmenu"); | |
546 | MLT_info(71, 26, false); | |
547 | if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_HLT_IND)) { | |
548 | HLT_info(71,150, false, false); | |
549 | } | |
550 | Buttons_Add( 5, 26, 60, 40, "Hand", 0); | |
551 | Buttons_Add(255, 26, 60, 40, "Auto", 1); | |
552 | Buttons_Add( 5, 200, 60, 40, "Info", 2); | |
553 | Buttons_Add(255, 200, 60, 40, "Tools", 3); | |
554 | Buttons_Show(); | |
555 | break; | |
556 | ||
557 | case MAIN_MODE_CALIBRATION: | |
558 | Calibration_Init(); | |
559 | break; | |
560 | ||
561 | case MAIN_INFO: | |
562 | sprintf(temp_buf, "BrewBoard %s", VERSION); | |
563 | TopMessage(temp_buf); | |
564 | _fg = TFT_YELLOW; | |
565 | TFT_setFont(UBUNTU16_FONT, NULL); | |
566 | TFT_print("Written by Michiel Broek (C) 2018\r\n\n", 0, 50); | |
567 | // ------------------------------------- | |
568 | _fg = TFT_ORANGE; | |
569 | TFT_print("Parts are written by Chris Morgan,\r\n", 0, LASTY); | |
570 | TFT_print("Brett Beauregard, Chris Garry, LoBo,\r\n", 0, LASTY); | |
571 | TFT_print("and David Antliff.\r\n", 0, LASTY); | |
572 | ShowInteger(1,140, "Free memory", " bytes", esp_get_free_heap_size()); | |
573 | ShowText(1,158, "IDF version", (char *)esp_get_idf_version()); | |
574 | Buttons_Add(130, 200, 60, 40, "Ok", 0); | |
575 | Buttons[0].dark = true; | |
576 | Buttons_Show(); | |
577 | break; | |
578 | ||
579 | case MAIN_TOOLS: | |
580 | TopMessage("Tools menu"); | |
581 | Buttons_Add( 20, 40,120, 40, "Setup", 0); | |
582 | Buttons_Add( 20,120,120, 40, "Bestanden", 1); | |
583 | Buttons_Add(180, 40,120, 40, "Recepten", 2); | |
584 | Buttons_Add(180,120,120, 40, "Updates", 3); | |
585 | Buttons_Add(130, 200, 60, 40, "Ok", 4); | |
586 | Buttons[4].dark = true; | |
587 | Buttons_Show(); | |
588 | break; | |
589 | ||
590 | case MAIN_TOOLS_SETUP: | |
591 | case MAIN_TOOLS_SETUP_CONFIG: | |
592 | case MAIN_TOOLS_SETUP_CO_EDIT: | |
593 | case MAIN_TOOLS_SETUP_EQUIPMENT: | |
594 | case MAIN_TOOLS_SETUP_EQ_EDIT: | |
595 | case MAIN_TOOLS_SETUP_CALIBRATION: | |
596 | Setup_Init(); | |
597 | break; | |
598 | ||
599 | case MAIN_TOOLS_SETUP_WIFI: | |
600 | case MAIN_TOOLS_SETUP_WIFI_CUR: | |
601 | case MAIN_TOOLS_SETUP_WIFI_CON: | |
602 | case MAIN_TOOLS_SETUP_WIFI_NEW: | |
603 | if (WiFi_Init()) | |
604 | goto startover; | |
605 | break; | |
606 | ||
607 | case MAIN_TOOLS_RECIPE: | |
608 | case MAIN_TOOLS_RECIPE_EDIT: | |
609 | Recipes_Init(); | |
610 | break; | |
611 | ||
612 | case MAIN_TOOLS_FILES: | |
613 | Files_Init(); | |
614 | break; | |
615 | ||
616 | case MAIN_TOOLS_UPDATES: | |
617 | Updates_Init(); | |
618 | break; | |
619 | ||
620 | case MAIN_AUTO_INIT: | |
621 | case MAIN_AUTO_DELAYSTART: | |
622 | case MAIN_AUTO_HEATUP: | |
623 | case MAIN_AUTO_MASH_IN: | |
624 | case MAIN_AUTO_MASH_1: | |
625 | case MAIN_AUTO_MASH_2: | |
626 | case MAIN_AUTO_MASH_3: | |
627 | case MAIN_AUTO_MASH_4: | |
628 | case MAIN_AUTO_MASH_5: | |
629 | case MAIN_AUTO_MASH_6: | |
630 | case MAIN_AUTO_MASH_OUT: | |
631 | case MAIN_AUTO_TOBOIL: | |
632 | case MAIN_AUTO_BOILING: | |
633 | case MAIN_AUTO_COOLING_H: | |
634 | case MAIN_AUTO_COOLING_M: | |
635 | case MAIN_AUTO_COOLING_C: | |
636 | case MAIN_AUTO_WHIRLPOOL9: | |
637 | case MAIN_AUTO_WHIRLPOOL7: | |
638 | case MAIN_AUTO_WHIRLPOOL6: | |
639 | case MAIN_AUTO_WHIRLPOOL2: | |
640 | case MAIN_AUTO_DONE: | |
641 | case MAIN_AUTO_ABORT: | |
642 | if (Automation_Init()) | |
643 | goto startover; | |
644 | break; | |
645 | ||
646 | case MAIN_MANUAL_INIT: | |
647 | case MAIN_MANUAL_MAIN: | |
648 | if (Manual_Init()) | |
649 | goto startover; | |
650 | break; | |
651 | ||
652 | default: | |
653 | break; | |
654 | } | |
655 | } | |
656 | ||
657 | /* | |
658 | * Update screen | |
659 | */ | |
660 | switch (Main_Screen) { | |
661 | case MAIN_MODE_FREE: | |
662 | MLT_info(71, 26, true); | |
663 | if ((equipment.SSR2 == SSR2_HLT_SHARE) || (equipment.SSR2 == SSR2_HLT_IND)) { | |
664 | HLT_info(71, 150, true, false); | |
665 | } | |
666 | switch (Buttons_Scan()) { | |
667 | case 0: Main_Screen = MAIN_MANUAL_INIT; break; | |
668 | case 1: Main_Screen = MAIN_AUTO_INIT; break; | |
669 | case 2: Main_Screen = MAIN_INFO; break; | |
670 | case 3: Main_Screen = MAIN_TOOLS; break; | |
671 | default: break; | |
672 | } | |
673 | break; | |
674 | ||
675 | case MAIN_MODE_CALIBRATION: | |
676 | Calibration_Loop(); | |
677 | Main_Screen = MAIN_MODE_FREE; | |
678 | break; | |
679 | ||
680 | case MAIN_TOOLS: | |
681 | switch (Buttons_Scan()) { | |
682 | case 0: Main_Screen = MAIN_TOOLS_SETUP; break; | |
683 | case 1: Main_Screen = MAIN_TOOLS_FILES; break; | |
684 | case 2: Main_Screen = MAIN_TOOLS_RECIPE; break; | |
685 | case 3: Main_Screen = MAIN_TOOLS_UPDATES; break; | |
686 | case 4: Main_Screen = MAIN_MODE_FREE; break; | |
687 | default: break; | |
688 | } | |
689 | break; | |
690 | ||
691 | case MAIN_TOOLS_SETUP: | |
692 | case MAIN_TOOLS_SETUP_CONFIG: | |
693 | case MAIN_TOOLS_SETUP_CO_EDIT: | |
694 | case MAIN_TOOLS_SETUP_EQUIPMENT: | |
695 | case MAIN_TOOLS_SETUP_EQ_EDIT: | |
696 | case MAIN_TOOLS_SETUP_CALIBRATION: | |
697 | Setup_Loop(); | |
698 | break; | |
699 | ||
700 | case MAIN_TOOLS_SETUP_WIFI: | |
701 | case MAIN_TOOLS_SETUP_WIFI_CUR: | |
702 | case MAIN_TOOLS_SETUP_WIFI_CON: | |
703 | case MAIN_TOOLS_SETUP_WIFI_NEW: | |
704 | if (WiFi_Loop()) | |
705 | goto startover; | |
706 | break; | |
707 | ||
708 | case MAIN_TOOLS_RECIPE: | |
709 | case MAIN_TOOLS_RECIPE_EDIT: | |
710 | Recipes_Loop(); | |
711 | break; | |
712 | ||
713 | case MAIN_TOOLS_FILES: | |
714 | Files_Loop(); | |
715 | break; | |
716 | ||
717 | case MAIN_TOOLS_UPDATES: | |
718 | Updates_Loop(); | |
719 | break; | |
720 | ||
721 | case MAIN_INFO: | |
722 | if (Buttons_Scan() == 0) { | |
723 | Main_Screen = MAIN_MODE_FREE; | |
724 | } | |
725 | break; | |
726 | ||
727 | case MAIN_AUTO_INIT: | |
728 | case MAIN_AUTO_DELAYSTART: | |
729 | case MAIN_AUTO_HEATUP: | |
730 | case MAIN_AUTO_MASH_IN: | |
731 | case MAIN_AUTO_MASH_1: | |
732 | case MAIN_AUTO_MASH_2: | |
733 | case MAIN_AUTO_MASH_3: | |
734 | case MAIN_AUTO_MASH_4: | |
735 | case MAIN_AUTO_MASH_5: | |
736 | case MAIN_AUTO_MASH_6: | |
737 | case MAIN_AUTO_MASH_OUT: | |
738 | case MAIN_AUTO_TOBOIL: | |
739 | case MAIN_AUTO_BOILING: | |
740 | case MAIN_AUTO_COOLING_H: | |
741 | case MAIN_AUTO_COOLING_M: | |
742 | case MAIN_AUTO_COOLING_C: | |
743 | case MAIN_AUTO_WHIRLPOOL9: | |
744 | case MAIN_AUTO_WHIRLPOOL7: | |
745 | case MAIN_AUTO_WHIRLPOOL6: | |
746 | case MAIN_AUTO_WHIRLPOOL2: | |
747 | case MAIN_AUTO_DONE: | |
748 | case MAIN_AUTO_ABORT: | |
749 | if (Automation_Loop()) | |
750 | goto startover; | |
751 | break; | |
752 | ||
753 | case MAIN_MANUAL_INIT: | |
754 | case MAIN_MANUAL_MAIN: | |
755 | if (Manual_Loop()) | |
756 | goto startover; | |
757 | break; | |
758 | ||
759 | default: | |
760 | break; | |
761 | } | |
762 | ||
763 | if (updateRuntime) { | |
764 | write_runtime(); | |
765 | } | |
766 | ||
767 | /* | |
768 | * Count power average during brewing. | |
769 | */ | |
770 | if ((Main_Screen >= MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_DONE)) { | |
771 | if (xSemaphoreTake(xSemaphoreDriver, 10) == pdTRUE) { | |
772 | power_MLT += driver_state->mlt_power; | |
773 | power_HLT += driver_state->hlt_power; | |
774 | counts++; | |
775 | xSemaphoreGive(xSemaphoreDriver); | |
776 | } | |
777 | } | |
778 | ||
779 | if (NewMinute) { | |
780 | /* | |
781 | * Brew logging. | |
782 | */ | |
783 | if ((Main_Screen >= MAIN_AUTO_MASH_IN) && (Main_Screen < MAIN_AUTO_DONE)) { | |
784 | update_json(); | |
785 | log_json(); | |
786 | power_MLT = power_HLT = counts = 0; | |
787 | } | |
788 | } | |
789 | ||
790 | NewMinute = false; | |
791 | vTaskDelay(50 / portTICK_PERIOD_MS); | |
792 | } | |
793 | } | |
794 | ||
795 |