-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinterface.c
598 lines (571 loc) · 32.6 KB
/
interface.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
/*
OpenDistiller Project
Author: Sergey Avdeev ([email protected])
URL: https://github.com/kasitoru/OpenDistiller
*/
#include "libraries/translate/translate.h" // Перевод
#define GUI_NONE_FORM 0 // Зарезервировано
#define GUI_SETTING_FORM 1 // Параметры ректификации
#define GUI_CUBETEMP_FORM 2 // Температура в кубе
#define GUI_WORKING_FORM 3 // Работа на себя
#define GUI_GETALCOHOL_FORM 4 // Отбор спирта
#define GUI_SAFETY_FORM 5 // Безопасность
#define GUI_BLUETOOTH_FORM 6 // Bluetooth модуль
#define GUI_RESET_FORM 7 // Сброс настроек
#define GUI_ABOUT_FORM 8 // О проекте
#define GUI_RECTIFICATE_FORM 100 // Процесс ректификации
#define GUI_CIRCULATE_FORM 150 // Отбор оборотного спирта
#define GUI_FINISH_FORM 200 // Ректификация завершена
#define GUI_ENWATER_BUTTON 101 // Кнопка "ВКЛ ВОДУ"
#define GUI_SKIP_BUTTON 102 // Кнопка "ПРОПУСТИТЬ"
#define GUI_GETBODY_BUTTON 103 // Кнопка "ОТБОР ТЕЛА"
#define GUI_WORKING_BUTTON 104 // Кнопка "НА СЕБЯ"
#define GUI_FINISH_BUTTON 105 // Кнопка "ЗАВЕРШИТЬ"
// https://github.com/olikraus/u8g2/issues/1988
#define _MUI_FORM(n) MUI_FORM(n)
#define _MUI_GOTO(x, y, n, text) MUI_GOTO(x, y, n, text)
#define _MUI_XYA(id, x, y, a) MUI_XYA(id, x, y, a)
#define _MUI_XYT(id, x, y, text) MUI_XYT(id, x, y, text)
#define _MUI_XYAT(id, x, y, a, text) MUI_XYAT(id, x, y, a, text)
void set_working_mode(uint8_t mode, uint8_t form); // Изменить текущий режим
// Обычный шрифт
const uint8_t mui_style_font_normal(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
u8g2_SetFont(mui_get_U8g2(ui), I18N_NORMAL_FONT);
break;
}
return 0;
}
// Жирный шрифт
const uint8_t mui_style_font_bold(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
u8g2_SetFont(mui_get_U8g2(ui), I18N_BOLD_FONT);
break;
}
return 0;
}
// Текстовая надпись
#define TEXTLABEL_ALIGN_NONE 0 // Без выравнивания
#define TEXTLABEL_ALIGN_LEFT 1 // По левому краю
#define TEXTLABEL_ALIGN_CENTER 2 // По центру
#define TEXTLABEL_ALIGN_RIGHT 3 // По правому краю
uint8_t mui_text_label(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
u8g2_t *u8g2 = mui_get_U8g2(ui);
u8g2_uint_t x = mui_get_x(ui);
switch(ui->arg) { // Выравнивание
case TEXTLABEL_ALIGN_LEFT: x = 0 + mui_get_x(ui); break;
case TEXTLABEL_ALIGN_CENTER: x = (u8g2_GetDisplayWidth(u8g2) - (u8g2_GetUTF8Width(u8g2, ui->text))) / 2; break;
case TEXTLABEL_ALIGN_RIGHT: x = u8g2_GetDisplayWidth(u8g2) - u8g2_GetUTF8Width(u8g2, ui->text) - mui_get_x(ui); break;
}
u8g2_DrawUTF8(u8g2, x, mui_get_y(ui), ui->text); // Отображаем текст
break;
}
return 0;
}
// Заголовок экрана
uint8_t mui_header_label(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
// Выбираем нужный текст, в зависимости от текущей формы
switch(mui_GetCurrentFormId(ui)) {
case GUI_SETTING_FORM: strcpy(ui->text, I18N_SETTING_MENU); break;
case GUI_CUBETEMP_FORM: strcpy(ui->text, I18N_CUBETEMP_MENU); break;
case GUI_WORKING_FORM: strcpy(ui->text, I18N_WORKING_MENU); break;
case GUI_GETALCOHOL_FORM: strcpy(ui->text, I18N_GETALCOHOL_MENU); break;
case GUI_SAFETY_FORM: strcpy(ui->text, I18N_SAFETY_MENU); break;
case GUI_BLUETOOTH_FORM: strcpy(ui->text, I18N_BLUETOOTH_MENU); break;
case GUI_RESET_FORM: strcpy(ui->text, I18N_RESET_MENU); break;
case GUI_ABOUT_FORM: strcpy(ui->text, I18N_ABOUT_MENU); break;
default:
// Текст в зависимости от режима работы
switch(WORKING_MODE) {
case WM_HEATING:
case WM_WATERING: strcpy(ui->text, I18N_HEATING_TITLE); break;
case WM_WORKING: strcpy(ui->text, I18N_WORKING_TITLE); break;
case WM_GETHEAD: strcpy(ui->text, I18N_GETHEAD_TITLE); break;
case WM_GETBODY: strcpy(ui->text, I18N_GETBODY_TITLE); break;
case WM_CIRCULATE: strcpy(ui->text, I18N_CIRCULATE_TITLE); break;
case WM_ERROR: strcpy(ui->text, I18N_ERROR_TITLE); break;
case WM_DONE: strcpy(ui->text, I18N_DONE_TITLE); break;
case WM_FINISH: strcpy(ui->text, I18N_FINISH_TITLE); break;
}
}
// Рендеринг заголовка
u8g2_t *u8g2 = mui_get_U8g2(ui);
const uint8_t *font = u8g2->font; // Запоминаем текущий шрифт
mui_style_font_bold(ui, msg); // Устанавливаем жирный шрифт
ui->x = 0; // Отступ слева
ui->y = 9; // Положение по вертикали
ui->arg = TEXTLABEL_ALIGN_LEFT; // Выравнивание по левому краю
mui_text_label(ui, msg); // Отображаем заголовок
u8g2_DrawHLine(u8g2, 0, 12, u8g2_GetDisplayWidth(u8g2)); // Рисуем горизонтальную линию
u8g2_SetFont(u8g2, font); // Восстанавливаем предыдущий шрифт
break;
}
return 0;
}
// Значение температуры
#define TEMP_VALUE_WATER 1 // Температура на выходе водяного охлаждения
#define TEMP_VALUE_TSA 2 // Температура трубки связи с атмосферой
#define TEMP_VALUE_TSARGA 3 // Температура в царге
#define TEMP_VALUE_CUBE 4 // Температура в кубе
#define TEMP_VALUE_TARGET 5 // Целевая температура царги
uint8_t mui_temp_value(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
int16_t temperature = 0;
// Определяем, значение с какого именно датчика необходимо отобразить
switch(ui->arg) {
case TEMP_VALUE_WATER: temperature = water_temperature; break;
case TEMP_VALUE_TSA: temperature = tsa_temperature; break;
case TEMP_VALUE_TSARGA: temperature = tsarga_temperature; break;
case TEMP_VALUE_CUBE: temperature = cube_temperature; break;
case TEMP_VALUE_TARGET: temperature = target_temperature; break;
}
// Выравнивание
if(strcmp(ui->text, "C") == 0) { ui->arg = TEXTLABEL_ALIGN_CENTER; } // По центру
else if(strcmp(ui->text, "R") == 0) { ui->arg = TEXTLABEL_ALIGN_RIGHT; } // По правому краю
else { ui->arg = TEXTLABEL_ALIGN_LEFT; } // По левому краю
// Формируем текстовую надпись во временный буффер
char buffer[MUI_MAX_TEXT_LEN + 1];
if(snprintf(buffer, (sizeof(buffer)/sizeof(*buffer)), FPN_FORMAT, FPN_FRMT_BD(temperature), FPN_FRMT_AD(temperature)) != -1) {
// Передаем этот буффер в функцию отрисовки
strcpy(ui->text, buffer);
return mui_text_label(ui, msg);
}
break;
}
return 0;
}
// Итоги ректификации (средняя надпись)
uint8_t mui_result_label_1(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
switch(WORKING_MODE) { // Определяем текущий процесс
case WM_ERROR: // Ошибка
strcpy(ui->text, I18N_FINISH_TEXT_3);
break;
case WM_DONE: // Готово
strcpy(ui->text, I18N_FINISH_TEXT_4);
break;
case WM_FINISH: // Завершено
char buffer[MUI_MAX_TEXT_LEN + 1];
uint8_t hours = (last_event_time - rect_start_time) / 1000 / 3600; // Часы
uint8_t minutes = ((last_event_time - rect_start_time) / 1000 - hours * 3600) / 60; // Минуты
uint8_t seconds = (last_event_time - rect_start_time) / 1000 - hours * 3600 - minutes * 60; // Секунды
if(snprintf(buffer, (sizeof(buffer) / sizeof(*buffer)), I18N_FINISH_TIME, hours, minutes, seconds) != -1) {
strcpy(ui->text, buffer);
}
break;
}
return mui_text_label(ui, msg); // Отображаем надпись
}
return 0;
}
// Итоги ректификации (нижняя надпись)
uint8_t mui_result_label_2(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW:
switch(WORKING_MODE) { // Определяем текущий процесс
case WM_ERROR: // Ошибка
case WM_DONE: // Готово
strcpy(ui->text, I18N_FINISH_TEXT_5);
break;
case WM_FINISH: // Завершено
strcpy(ui->text, I18N_FINISH_TEXT_6);
break;
}
return mui_text_label(ui, msg); // Отображаем надпись
}
return 0;
}
// Пункты главного меню
uint8_t mui_u8g2_goto_menu(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_CURSOR_SELECT: // Выбор пункта меню
if(mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, ui->arg + ui->form_scroll_top)) {
if((uint8_t) ui->text[0] == GUI_RECTIFICATE_FORM) { // Если нажали "СТАРТ"
// Переходим к началу ректификации
set_working_mode(WM_HEATING, GUI_RECTIFICATE_FORM);
// Запоминаем время старта
rect_start_time = now_millis;
// И больше ничего не делаем
return 0;
}
}
break;
}
return mui_u8g2_goto_form_w1_pi(ui, msg); // Вызываем нативный callback
}
// Кнопка навигации
uint8_t mui_goto_button(mui_t *ui, uint8_t msg) {
switch(msg) {
case MUIF_MSG_DRAW: // Отрисовка кнопок навигации
case MUIF_MSG_CURSOR_ENTER: // Навели фокус на кнопку
switch(WORKING_MODE) { // Для режимов
case WM_HEATING: // Нагрев куба
switch(ui->arg) {
case GUI_ENWATER_BUTTON: // Кнопка "ВКЛ ВОДУ"
case GUI_FINISH_BUTTON: // Кнопка "ЗАВЕРШИТЬ"
break; // Отображаем
default: // Все остальные кнопки
return 255; // Игнорируем
}
break;
case WM_WATERING: // Включение воды
case WM_GETBODY: // Отбор тела
switch(ui->arg) {
case GUI_WORKING_BUTTON: // Кнопка "НА СЕБЯ"
case GUI_FINISH_BUTTON: // Кнопка "ЗАВЕРШИТЬ"
break; // Отображаем
default: // Все остальные кнопки
return 255; // Игнорируем
}
break;
case WM_WORKING: // Работа на себя
switch(ui->arg) {
case GUI_SKIP_BUTTON: // Кнопка "ПРОПУСТИТЬ"
case GUI_FINISH_BUTTON: // Кнопка "ЗАВЕРШИТЬ"
break; // Отображаем
default: // Все остальные кнопки
return 255; // Игнорируем
}
break;
case WM_GETHEAD: // Отбор голов
switch(ui->arg) {
case GUI_GETBODY_BUTTON: // Кнопка "ОТБОР ТЕЛА"
case GUI_FINISH_BUTTON: // Кнопка "ЗАВЕРШИТЬ"
break; // Отображаем
default: // Все остальные кнопки
return 255; // Игнорируем
}
break;
case WM_ERROR: // Ошибка
case WM_DONE: // Готово
// Только для отрисовки
if(msg == MUIF_MSG_DRAW) {
u8g2_t *u8g2 = mui_get_U8g2(ui);
const uint8_t *font = u8g2->font; // Запоминаем текущий шрифт
mui_style_font_normal(ui, msg); // Устанавливаем обычный шрифт
strcpy(ui->text, I18N_FINISH_TEXT_2); // Текст надписи
ui->arg = TEXTLABEL_ALIGN_CENTER; // Выравнивание по центру
mui_text_label(ui, msg); // Отображаем надпись
u8g2_SetFont(u8g2, font); // Восстанавливаем предыдущий шрифт
return 0; // Кнопки не отображаем
}
break;
}
break;
case MUIF_MSG_CURSOR_SELECT: // Нажатие на одну из кнопок
// Выбираем нужное действие, в зависимости от текущей формы
switch(mui_GetCurrentFormId(ui)) {
case GUI_SETTING_FORM: // Параметры ректификации
case GUI_CUBETEMP_FORM: // Температура в кубе
case GUI_WORKING_FORM: // Работа на себя
case GUI_GETALCOHOL_FORM: // Отбор спирта
case GUI_SAFETY_FORM: // Безопасность
case GUI_BLUETOOTH_FORM: // Bluetooth модуль
case GUI_RESET_FORM: // Сброс настроек
// Рассчитываем контрольную сумму
if(ui->arg == GUI_RESET_FORM) { // Если нужно сбросить настройки
CONFIG.crc = 0x00; // Устанавливаем заведомо неправильную контрольную сумму
} else { // Если же нужно сохранить настройки
CONFIG.crc = crc8((uint8_t *) &CONFIG, sizeof(CONFIG) - 1); // Получаем CRC8
}
// Сохраняем настройки в памяти
eeprom_busy_wait(); // Ждем доступности EEPROM
eeprom_write_block(&CONFIG, 0, sizeof(CONFIG)); // Записываем данные
// После сброса настроек устройство нужно перезагрузить
if(CONFIG.crc == 0x00) {
// При старте, настройки из памяти не пройдут проверку
// по CRC и будут восстановлены до значений по-умолчанию
restart_atmega();
}
break;
case GUI_RECTIFICATE_FORM: // Процесс ректификации
switch(ui->arg) { // Нажатая кнопка
case GUI_FINISH_BUTTON: // Кнопка "ЗАВЕРШИТЬ" (автоматический режим)
set_working_mode(WM_DONE, GUI_FINISH_FORM); // Завершаем отбор
break;
case GUI_ENWATER_BUTTON: // Кнопка "ВКЛ ВОДУ" (нагрев куба)
set_working_mode(WM_WATERING, GUI_RECTIFICATE_FORM); // Включаем воду
break;
case GUI_SKIP_BUTTON: // Кнопка "ПРОПУСТИТЬ" (работа на себя)
target_temperature = tsarga_temperature; // Запоминаем целевую температуру царги
// В зависимости от текущего статуса ректификации
switch(REFLUX_STATUS) {
case RS_NOTHEAD: // Отбора голов еще не было
REFLUX_STATUS = RS_YESHEAD; // Отбор голов в процессе
case RS_YESHEAD: // Отбор голов в процессе
set_working_mode(WM_GETHEAD, GUI_RECTIFICATE_FORM); // Переходим к отбору голов
break;
default: // Отбор тела
if(REFLUX_STATUS == RS_NOTBODY) { // Если отбора тела еще не было
REFLUX_STATUS = RS_YESBODY; // Отбор тела в процессе
}
set_working_mode(WM_GETBODY, GUI_RECTIFICATE_FORM); // Переходим к отбору тела
}
break;
case GUI_GETBODY_BUTTON: // Кнопка "ОТБОР ТЕЛА" (отбор голов)
target_temperature = tsarga_temperature; // Запоминаем целевую температуру царги
REFLUX_STATUS = RS_NOTBODY; // Отбор голов закончили, но к отбору тела еще не приступили
case GUI_WORKING_BUTTON: // Кнопка "НА СЕБЯ" (отбор тела)
set_working_mode(WM_WORKING, GUI_RECTIFICATE_FORM); // Начинаем "работать на себя"
}
return 0;
case GUI_CIRCULATE_FORM: // Подтверждение начала отбора оборотного спирта
switch(ui->arg) { // Нажатая кнопка
case GUI_RECTIFICATE_FORM: // Кнопка "ПРОДОЛЖИТЬ"
REFLUX_STATUS = RS_YESCIRC; // Начинаем отбор оборотки
set_working_mode(WM_GETBODY, GUI_RECTIFICATE_FORM); // Переходим к отбору
break;
case GUI_FINISH_FORM: // Кнопка "ЗАВЕРШИТЬ"
set_working_mode(WM_DONE, GUI_FINISH_FORM); // Завершаем отбор
break;
}
return 0;
case GUI_FINISH_FORM: // Ректификация завершена
switch(WORKING_MODE) { // Определяем текущий процесс
case WM_FINISH: // Завершено
restart_atmega(); // Перезагружаем микроконтроллер
}
return 0;
}
break;
case MUIF_MSG_VALUE_DECREMENT: // Кнопка "-"
// Выбираем нужное действие, в зависимости от текущей формы
switch(mui_GetCurrentFormId(ui)) {
case GUI_RECTIFICATE_FORM: // Процесс ректификации
target_temperature = ((target_temperature > 0) ? target_temperature - 1 : 0); // Уменьшаем целевую температуру
break;
}
return 0;
case MUIF_MSG_VALUE_INCREMENT: // Кнопка "+"
// Выбираем нужное действие, в зависимости от текущей формы
switch(mui_GetCurrentFormId(ui)) {
case GUI_RECTIFICATE_FORM: // Процесс ректификации
target_temperature = ((target_temperature < 2000) ? target_temperature + 1 : 2000); // Увеличиваем целевую температуру
break;
}
return 0;
}
return mui_u8g2_btn_goto_w2_fi(ui, msg); // Вызываем нативный callback
}
// Поле ввода числового значения температуры (int16_t)
struct mui_u8g2_i16_min_max_struct { int16_t *value; int16_t min; int16_t max; } MUI_PROGMEM;
typedef const struct mui_u8g2_i16_min_max_struct mui_u8g2_i16_min_max_t;
#define MUIF_U8G2_I16_MIN_MAX(id, valptr, min, max, muif) MUIF(id, MUIF_CFLAG_IS_CURSOR_SELECTABLE, (void *)((mui_u8g2_i16_min_max_t []) {{ (valptr) MUI_U8G2_COMMA (min) MUI_U8G2_COMMA (max)}}), (muif))
uint8_t mui_u8g2_i16_min_max_wm_mse_pi(mui_t *ui, uint8_t msg) {
mui_u8g2_i16_min_max_t *vmm = (mui_u8g2_i16_min_max_t *) muif_get_data(ui->uif);
int16_t *value = ((int16_t *) mui_pgm_wread(&((vmm)->value)));
int16_t min = mui_pgm_read(&((vmm)->min));
int16_t max = mui_pgm_read(&((vmm)->max));
switch(msg) {
case MUIF_MSG_DRAW:
if(*value > max) { *value = max; }
if(*value <= min) { *value = min; }
char buffer[MUI_MAX_TEXT_LEN + 1];
uint8_t length = snprintf(buffer, (sizeof(buffer) / sizeof(*buffer)), FPN_FORMAT, FPN_FRMT_BD(*value), FPN_FRMT_AD(*value));
mui_u8g2_draw_button_pi(ui, length, 1, buffer);
break;
case MUIF_MSG_VALUE_INCREMENT:
(*value)++;
if(*value > max) { *value = min; }
break;
case MUIF_MSG_VALUE_DECREMENT:
if(*value > min) { (*value)--; }
else { *value = max; }
break;
}
return 0;
}
// Устанавливаем callback`и элементов интерфейса
static const muif_t muif_list[] MUI_PROGMEM = {
MUIF_STYLE(0, mui_style_font_normal), // Обычный шрифт
MUIF_STYLE(1, mui_style_font_bold), // Жирный шрифт
MUIF_RO("HL", mui_header_label), // Заголовок экрана
MUIF_RO("TL", mui_text_label), // Текстовая надпись
MUIF_RO("TV", mui_temp_value), // Значение температуры
MUIF_GOTO(mui_goto_button), // Кнопка навигации
// Параметры ректификации
MUIF_RO("ML", mui_u8g2_goto_data), // Список элементов меню параметров
MUIF_BUTTON("MI", mui_u8g2_goto_menu), // Выбор текущего элемента меню
// Температура в кубе
MUIF_U8G2_U8_MIN_MAX("IC", &CONFIG.water_cube_temperature, 60, 80, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: температура старта подачи воды
MUIF_U8G2_U8_MIN_MAX("EC", &CONFIG.ethanol_cube_temperature, 85, 110, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: макс. температура для товарного спирта
MUIF_U8G2_U8_MIN_MAX("FC", &CONFIG.final_cube_temperature, 85, 110, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: температура окончания работы
// Работа на себя
MUIF_U8G2_U8_MIN_MAX("WT", &CONFIG.itself_working_temperature, 60, 80, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: температура начала "работы на себя"
MUIF_U8G2_U8_MIN_MAX("IW", &CONFIG.itself_working_initial_time, 10, 60, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: длительность "работы на себя" (мин)
// Отбор спирта
MUIF_U8G2_I16_MIN_MAX("TD", &CONFIG.target_temperature_delta, 1 /* 0.0625 */, 159 /* 9.9375 */, mui_u8g2_i16_min_max_wm_mse_pi), // Ввод числа: дельта датчика царги
MUIF_U8G2_U8_MIN_MAX("RT", &CONFIG.target_recovery_time, 1, 30, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: время восстановления (мин)
// Безопасность
MUIF_VARIABLE("SP", &CONFIG.sensors_protection, mui_u8g2_u8_chkbox_wm_pi), // Чекбокс: включить контроль работоспособности датчиков
MUIF_VARIABLE("TP", &CONFIG.tsa_protection, mui_u8g2_u8_chkbox_wm_pi), // Чекбокс: включить защиту по температуре ТСА
MUIF_U8G2_U8_MIN_MAX("TM", &CONFIG.tsa_max_temperature, 40, 60, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: максимальная температура воды
MUIF_VARIABLE("WP", &CONFIG.water_protection, mui_u8g2_u8_chkbox_wm_pi), // Чекбокс: включить защиту по температуре воды
MUIF_U8G2_U8_MIN_MAX("WM", &CONFIG.water_max_temperature, 40, 60, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: максимальная температура воды
MUIF_U8G2_U8_MIN_MAX("FT", &CONFIG.phlegm_wait_time, 1, 10, mui_u8g2_u8_min_max_wm_mse_pi), // Ввод числа: время сброса флегмы (мин)
// Bluetooth модуль
MUIF_VARIABLE("BT", &CONFIG.use_bluetooth, mui_u8g2_u8_radio_wm_pi), // Переключатель: использовать Bluetooth модуль
// Ректификация завершена
MUIF_RO("RU", mui_result_label_1), // Итоги ректификации (средняя надпись)
MUIF_RO("RD", mui_result_label_2), // Итоги ректификации (нижняя надпись)
};
// Описание форм интерфейса
static const fds_t fds_data[] MUI_PROGMEM =
// Параметры ректификации
_MUI_FORM(GUI_SETTING_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
MUI_DATA("ML",
MUI_100 I18N_START_MENU "|" /* GUI_RECTIFICATE_FORM */
MUI_2 I18N_CUBETEMP_MENU "|" /* GUI_CUBETEMP_FORM */
MUI_3 I18N_WORKING_MENU "|" /* GUI_WORKING_FORM */
MUI_4 I18N_GETALCOHOL_MENU "|" /* GUI_GETALCOHOL_FORM */
MUI_5 I18N_SAFETY_MENU "|" /* GUI_SAFETY_FORM */
MUI_6 I18N_BLUETOOTH_MENU "|" /* GUI_BLUETOOTH_FORM */
MUI_7 I18N_RESET_MENU "|" /* GUI_RESET_FORM */
MUI_8 I18N_ABOUT_MENU "|" /* GUI_ABOUT_FORM */
)
_MUI_XYA("MI", 5, 22, 0)
_MUI_XYA("MI", 5, 31, 1)
_MUI_XYA("MI", 5, 40, 2)
_MUI_XYA("MI", 5, 49, 3)
_MUI_XYA("MI", 5, 58, 4)
// Температура в кубе
_MUI_FORM(GUI_CUBETEMP_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYAT("TL", 5, 22, TEXTLABEL_ALIGN_LEFT, I18N_WATER_CUBE_TEMPERATURE)
MUI_XY("IC", 115, 22)
_MUI_XYAT("TL", 5, 31, TEXTLABEL_ALIGN_LEFT, I18N_ETHANOL_CUBE_TEMPERATURE)
MUI_XY("EC", 110, 31)
_MUI_XYAT("TL", 5, 40, TEXTLABEL_ALIGN_LEFT, I18N_FINAL_CUBE_TEMPERATURE)
MUI_XY("FC", 110, 40)
_MUI_GOTO(64, 60, GUI_SETTING_FORM, I18N_OK_BUTTON)
// Работа на себя
_MUI_FORM(GUI_WORKING_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYAT("TL", 5, 22, TEXTLABEL_ALIGN_LEFT, I18N_WORKING_TEMPERATURE)
MUI_XY("WT", 115, 22)
_MUI_XYAT("TL", 5, 31, TEXTLABEL_ALIGN_LEFT, I18N_WORKING_INITIAL_TIME)
MUI_XY("IW", 115, 31)
_MUI_GOTO(64, 60, GUI_SETTING_FORM, I18N_OK_BUTTON)
// Отбор спирта
_MUI_FORM(GUI_GETALCOHOL_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYAT("TL", 5, 22, TEXTLABEL_ALIGN_LEFT, I18N_SELECTION_DELTA)
MUI_XY("TD", 105, 22)
_MUI_XYAT("TL", 5, 31, TEXTLABEL_ALIGN_LEFT, I18N_WORKING_INTERIM_TIME)
MUI_XY("RT", 115, 31)
_MUI_GOTO(64, 60, GUI_SETTING_FORM, I18N_OK_BUTTON)
// Безопасность
_MUI_FORM(GUI_SAFETY_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYT("SP", 5, 22, I18N_SENSORS_PROTECTION)
_MUI_XYT("TP", 5, 31, I18N_TSA_PROTECTION)
MUI_XY("TM", 115, 31)
_MUI_XYT("WP", 5, 40, I18N_WATER_PROTECTION)
MUI_XY("WM", 115, 40)
_MUI_XYAT("TL", 5, 49, TEXTLABEL_ALIGN_LEFT, I18N_PHLEGM_WAIT_TIME)
MUI_XY("FT", 115, 49)
_MUI_GOTO(64, 60, GUI_SETTING_FORM, I18N_OK_BUTTON)
// Bluetooth модуль
_MUI_FORM(GUI_BLUETOOTH_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYAT("BT", 5, 22, 0, I18N_ENABLE_LABEL)
_MUI_XYAT("BT", 5, 31, 1, I18N_DISABLE_LABEL)
_MUI_GOTO(64, 60, GUI_SETTING_FORM, I18N_OK_BUTTON)
// Сброс настроек
_MUI_FORM(GUI_RESET_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
#ifdef I18N_RESET_TEXT_1
_MUI_XYAT("TL", 5, 22, TEXTLABEL_ALIGN_CENTER, I18N_RESET_TEXT_1)
#endif
#ifdef I18N_RESET_TEXT_2
_MUI_XYAT("TL", 5, 31, TEXTLABEL_ALIGN_CENTER, I18N_RESET_TEXT_2)
#endif
#ifdef I18N_RESET_TEXT_3
_MUI_XYAT("TL", 5, 40, TEXTLABEL_ALIGN_CENTER, I18N_RESET_TEXT_3)
#endif
#ifdef I18N_RESET_TEXT_4
_MUI_XYAT("TL", 5, 49, TEXTLABEL_ALIGN_CENTER, I18N_RESET_TEXT_4)
#endif
_MUI_GOTO(33, 60, GUI_SETTING_FORM, I18N_NO_BUTTON)
_MUI_GOTO(95, 60, GUI_RESET_FORM, I18N_YES_BUTTON)
// О проекте
_MUI_FORM(GUI_ABOUT_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
#ifdef I18N_ABOUT_TEXT_1
_MUI_XYAT("TL", 5, 22, TEXTLABEL_ALIGN_CENTER, I18N_ABOUT_TEXT_1)
#endif
#ifdef I18N_ABOUT_TEXT_2
_MUI_XYAT("TL", 5, 31, TEXTLABEL_ALIGN_CENTER, I18N_ABOUT_TEXT_2)
#endif
#ifdef I18N_ABOUT_TEXT_3
_MUI_XYAT("TL", 5, 40, TEXTLABEL_ALIGN_CENTER, I18N_ABOUT_TEXT_3)
#endif
#ifdef I18N_ABOUT_TEXT_4
_MUI_XYAT("TL", 5, 49, TEXTLABEL_ALIGN_CENTER, I18N_ABOUT_TEXT_4)
#endif
_MUI_GOTO(64, 60, GUI_SETTING_FORM, I18N_OK_BUTTON)
// Процесс ректификации
_MUI_FORM(GUI_RECTIFICATE_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYAT("TL", 0, 22, TEXTLABEL_ALIGN_LEFT, I18N_WATER_LABEL)
_MUI_XYAT("TL", 30, 22, TEXTLABEL_ALIGN_RIGHT, I18N_TSA_LABEL)
_MUI_XYAT("TV", 30, 22, TEMP_VALUE_WATER, "L")
_MUI_XYAT("TV", 0, 22, TEMP_VALUE_TSA, "R")
_MUI_XYAT("TL", 0, 35, TEXTLABEL_ALIGN_LEFT, I18N_CUBE_LABEL)
_MUI_XYAT("TL", 0, 35, TEXTLABEL_ALIGN_CENTER, I18N_TARGET_LABEL)
_MUI_XYAT("TL", 0, 35, TEXTLABEL_ALIGN_RIGHT, I18N_TSARGA_LABEL)
MUI_STYLE(1)
_MUI_XYAT("TV", 0, 48, TEMP_VALUE_CUBE, "L")
_MUI_XYAT("TV", 0, 48, TEMP_VALUE_TARGET, "C")
_MUI_XYAT("TV", 0, 48, TEMP_VALUE_TSARGA, "R")
MUI_STYLE(0)
_MUI_GOTO(33, 60, GUI_ENWATER_BUTTON, I18N_ENWATER_BUTTON)
_MUI_GOTO(33, 60, GUI_SKIP_BUTTON, I18N_SKIP_BUTTON)
_MUI_GOTO(33, 60, GUI_GETBODY_BUTTON, I18N_GETBODY_BUTTON)
_MUI_GOTO(33, 60, GUI_WORKING_BUTTON, I18N_WORKING_BUTTON)
_MUI_GOTO(95, 60, GUI_FINISH_BUTTON, I18N_FINISH_BUTTON)
// Отбор оборотного спирта
_MUI_FORM(GUI_CIRCULATE_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
#ifdef I18N_CIRCULATE_TEXT_1
_MUI_XYAT("TL", 5, 22, TEXTLABEL_ALIGN_CENTER, I18N_CIRCULATE_TEXT_1)
#endif
#ifdef I18N_CIRCULATE_TEXT_2
_MUI_XYAT("TL", 5, 31, TEXTLABEL_ALIGN_CENTER, I18N_CIRCULATE_TEXT_2)
#endif
#ifdef I18N_CIRCULATE_TEXT_3
_MUI_XYAT("TL", 5, 40, TEXTLABEL_ALIGN_CENTER, I18N_CIRCULATE_TEXT_3)
#endif
#ifdef I18N_CIRCULATE_TEXT_4
_MUI_XYAT("TL", 5, 49, TEXTLABEL_ALIGN_CENTER, I18N_CIRCULATE_TEXT_4)
#endif
_MUI_GOTO(33, 60, GUI_RECTIFICATE_FORM, I18N_CONTINUE_BUTTON)
_MUI_GOTO(95, 60, GUI_FINISH_FORM, I18N_FINISH_BUTTON)
// Ректификация завершена
_MUI_FORM(GUI_FINISH_FORM)
MUI_AUX("HL")
MUI_STYLE(0)
_MUI_XYAT("TL", 0, 23, TEXTLABEL_ALIGN_CENTER, I18N_FINISH_TEXT_1)
_MUI_XYA("RU", 0, 33, TEXTLABEL_ALIGN_CENTER)
_MUI_XYA("RD", 0, 43, TEXTLABEL_ALIGN_CENTER)
_MUI_GOTO(64, 60, GUI_NONE_FORM, I18N_DONE_BUTTON)
;