Просмотр исходного кода

generalize menu infrastructure to also use it for workflow selection

Thomas Buck 6 месяцев назад
Родитель
Сommit
f064eb3a5a
14 измененных файлов: 384 добавлений и 144 удалений
  1. 2
    0
      CMakeLists.txt
  2. 2
    0
      include/buttons.h
  3. 35
    0
      include/menu.h
  4. 1
    0
      include/state.h
  5. 26
    0
      include/state_volcano_workflow.h
  6. 2
    0
      include/text.h
  7. 11
    1
      include/workflow.h
  8. 6
    3
      src/console.c
  9. 95
    0
      src/menu.c
  10. 16
    2
      src/state.c
  11. 39
    105
      src/state_scan.c
  12. 69
    0
      src/state_volcano_workflow.c
  13. 29
    0
      src/text.c
  14. 51
    33
      src/workflow.c

+ 2
- 0
CMakeLists.txt Просмотреть файл

66
     src/models.c
66
     src/models.c
67
     src/state_scan.c
67
     src/state_scan.c
68
     src/workflow.c
68
     src/workflow.c
69
+    src/menu.c
70
+    src/state_volcano_workflow.c
69
 
71
 
70
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
72
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
71
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c
73
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c

+ 2
- 0
include/buttons.h Просмотреть файл

19
 #ifndef __BUTTONS_H__
19
 #ifndef __BUTTONS_H__
20
 #define __BUTTONS_H__
20
 #define __BUTTONS_H__
21
 
21
 
22
+#include <stdbool.h>
23
+
22
 enum buttons {
24
 enum buttons {
23
     BTN_A = 0,
25
     BTN_A = 0,
24
     BTN_B,
26
     BTN_B,

+ 35
- 0
include/menu.h Просмотреть файл

1
+/*
2
+ * menu.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __MENU_H__
20
+#define __MENU_H__
21
+
22
+#define MENU_MAX_LINES 5
23
+#define MENU_MAX_LEN (MENU_MAX_LINES * 32)
24
+
25
+struct menu_state {
26
+    int off;
27
+    int selection;
28
+    int length;
29
+    char *buff;
30
+};
31
+
32
+void menu_init(void (*cb)(int));
33
+void menu_run(void (*cb)(struct menu_state *));
34
+
35
+#endif // __MENU_H__

+ 1
- 0
include/state.h Просмотреть файл

22
 enum system_state {
22
 enum system_state {
23
     STATE_INIT = 0,
23
     STATE_INIT = 0,
24
     STATE_SCAN,
24
     STATE_SCAN,
25
+    STATE_VOLCANO_WORKFLOW,
25
 };
26
 };
26
 
27
 
27
 void state_switch(enum system_state next);
28
 void state_switch(enum system_state next);

+ 26
- 0
include/state_volcano_workflow.h Просмотреть файл

1
+/*
2
+ * state_volcano_workflow.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef __STATE_VOLCANO_WORKFLOW_H__
20
+#define __STATE_VOLCANO_WORKFLOW_H__
21
+
22
+void state_volcano_wf_enter(void);
23
+void state_volcano_wf_exit(void);
24
+void state_volcano_wf_run(void);
25
+
26
+#endif // __STATE_VOLCANO_WORKFLOW_H__

+ 2
- 0
include/text.h Просмотреть файл

48
 void text_prepare_font(struct text_font *tf);
48
 void text_prepare_font(struct text_font *tf);
49
 void text_draw(struct text_conf *tc);
49
 void text_draw(struct text_conf *tc);
50
 
50
 
51
+void text_box(const char *s);
52
+
51
 #endif // __TEXT_H__
53
 #endif // __TEXT_H__

+ 11
- 1
include/workflow.h Просмотреть файл

19
 #ifndef __WORKFLOW_H__
19
 #ifndef __WORKFLOW_H__
20
 #define __WORKFLOW_H__
20
 #define __WORKFLOW_H__
21
 
21
 
22
+#include <stdint.h>
23
+
22
 enum wf_status {
24
 enum wf_status {
23
     WF_IDLE = 0,
25
     WF_IDLE = 0,
24
     WF_RUNNING,
26
     WF_RUNNING,
25
 };
27
 };
26
 
28
 
29
+struct wf_state {
30
+    enum wf_status status;
31
+
32
+    uint16_t step;
33
+    uint16_t count;
34
+};
35
+
27
 uint16_t wf_count(void);
36
 uint16_t wf_count(void);
28
 const char *wf_name(uint16_t index);
37
 const char *wf_name(uint16_t index);
38
+const char *wf_author(uint16_t index);
29
 
39
 
30
-enum wf_status wf_status(void);
40
+struct wf_state wf_status(void);
31
 void wf_start(uint16_t index);
41
 void wf_start(uint16_t index);
32
 
42
 
33
 void wf_run(void);
43
 void wf_run(void);

+ 6
- 3
src/console.c Просмотреть файл

321
     } else if (strcmp(line, "wfl") == 0) {
321
     } else if (strcmp(line, "wfl") == 0) {
322
         println("%d workflows", wf_count());
322
         println("%d workflows", wf_count());
323
         for (int i = 0; i < wf_count(); i++) {
323
         for (int i = 0; i < wf_count(); i++) {
324
-            println("  %s", wf_name(i));
324
+            println("  '%s' by %s", wf_name(i), wf_author(i));
325
         }
325
         }
326
     } else if (str_startswith(line, "wf ")) {
326
     } else if (str_startswith(line, "wf ")) {
327
         int wf = -1;
327
         int wf = -1;
335
         if (wf < 0) {
335
         if (wf < 0) {
336
             println("unknown workflow");
336
             println("unknown workflow");
337
         } else {
337
         } else {
338
-            if (wf_status() != WF_IDLE) {
338
+            struct wf_state s = wf_status();
339
+            if (s.status != WF_IDLE) {
339
                 println("workflow in progress");
340
                 println("workflow in progress");
340
             } else {
341
             } else {
341
 #ifdef TEST_VOLCANO_AUTO_CONNECT
342
 #ifdef TEST_VOLCANO_AUTO_CONNECT
345
                 println("starting workflow");
346
                 println("starting workflow");
346
                 wf_start(wf);
347
                 wf_start(wf);
347
 
348
 
348
-                while (wf_status() != WF_IDLE) {
349
+                s = wf_status();
350
+                while (s.status != WF_IDLE) {
349
                     main_loop_hw();
351
                     main_loop_hw();
350
                     wf_run();
352
                     wf_run();
353
+                    s = wf_status();
351
                 }
354
                 }
352
 
355
 
353
                 println("done");
356
                 println("done");

+ 95
- 0
src/menu.c Просмотреть файл

1
+/*
2
+ * menu.c
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <string.h>
20
+
21
+#include "config.h"
22
+#include "buttons.h"
23
+#include "text.h"
24
+#include "menu.h"
25
+
26
+static char prev_buff[MENU_MAX_LEN] = {0};
27
+static char buff[MENU_MAX_LEN] = {0};
28
+static struct menu_state menu = { .off = 0, .selection = -1, .length = 0, .buff = buff };
29
+static void (*enter_callback)(int) = NULL;
30
+
31
+static void menu_buttons(enum buttons btn, bool state) {
32
+    if (state && (btn == BTN_LEFT)) {
33
+        // TODO brightness down
34
+        return;
35
+    } else if (state && (btn == BTN_RIGHT)) {
36
+        // TODO brightness up
37
+        return;
38
+    } else if (state && ((btn == BTN_ENTER) || (btn == BTN_A))) {
39
+        if (enter_callback) {
40
+            enter_callback(menu.selection);
41
+        }
42
+        return;
43
+    } else if ((!state) || ((btn != BTN_UP) && (btn != BTN_DOWN))) {
44
+        return;
45
+    }
46
+
47
+    if (state && (btn == BTN_UP)) {
48
+        if (menu.selection < 0) {
49
+            menu.selection = menu.length - 1;
50
+        } else {
51
+            menu.selection -= 1;
52
+        }
53
+    } else if (state && (btn == BTN_DOWN)) {
54
+        if (menu.selection < 0) {
55
+            menu.selection = 0;
56
+        } else {
57
+            menu.selection += 1;
58
+        }
59
+    }
60
+
61
+    if (menu.selection < 0) {
62
+        menu.selection += menu.length;
63
+    }
64
+    if (menu.selection >= menu.length) {
65
+        menu.selection -= menu.length;
66
+    }
67
+    if (menu.selection >= 0) {
68
+        while (menu.selection < menu.off) {
69
+            menu.off -= 1;
70
+        }
71
+        while (menu.selection >= (menu.off + MENU_MAX_LINES)) {
72
+            menu.off += 1;
73
+        }
74
+    }
75
+}
76
+
77
+void menu_init(void (*cb)(int)) {
78
+    menu.off = 0;
79
+    menu.selection = -1;
80
+    menu.length = 0;
81
+
82
+    enter_callback = cb;
83
+    buttons_callback(menu_buttons);
84
+}
85
+
86
+void menu_run(void (*draw)(struct menu_state *)) {
87
+    if (draw) {
88
+        draw(&menu);
89
+    }
90
+
91
+    if (strncmp(buff, prev_buff, MENU_MAX_LEN) != 0) {
92
+        strncpy(prev_buff, buff, MENU_MAX_LEN);
93
+        text_box(buff);
94
+    }
95
+}

+ 16
- 2
src/state.c Просмотреть файл

19
 #include "config.h"
19
 #include "config.h"
20
 #include "log.h"
20
 #include "log.h"
21
 #include "state_scan.h"
21
 #include "state_scan.h"
22
+#include "state_volcano_workflow.h"
22
 #include "state.h"
23
 #include "state.h"
23
 
24
 
24
 static enum system_state state = STATE_INIT;
25
 static enum system_state state = STATE_INIT;
35
         state_scan_exit();
36
         state_scan_exit();
36
         break;
37
         break;
37
 
38
 
39
+    case STATE_VOLCANO_WORKFLOW:
40
+        debug("leaving STATE_VOLCANO_WORKFLOW");
41
+        state_volcano_wf_exit();
42
+        break;
43
+
38
     default:
44
     default:
39
         break;
45
         break;
40
     }
46
     }
46
         state_scan_enter();
52
         state_scan_enter();
47
         break;
53
         break;
48
 
54
 
55
+    case STATE_VOLCANO_WORKFLOW:
56
+        debug("entering STATE_VOLCANO_WORKFLOW");
57
+        state_volcano_wf_enter();
58
+        break;
59
+
49
     default:
60
     default:
50
         break;
61
         break;
51
     }
62
     }
58
     case STATE_INIT:
69
     case STATE_INIT:
59
         break;
70
         break;
60
 
71
 
61
-    case STATE_SCAN: {
72
+    case STATE_SCAN:
62
         state_scan_run();
73
         state_scan_run();
63
         break;
74
         break;
64
-    }
75
+
76
+    case STATE_VOLCANO_WORKFLOW:
77
+        state_volcano_wf_run();
78
+        break;
65
 
79
 
66
     default:
80
     default:
67
         debug("invalid main state %d", state);
81
         debug("invalid main state %d", state);

+ 39
- 105
src/state_scan.c Просмотреть файл

17
  */
17
  */
18
 
18
 
19
 #include <stdio.h>
19
 #include <stdio.h>
20
+#include <string.h>
20
 
21
 
21
 #include "config.h"
22
 #include "config.h"
22
-#include "log.h"
23
-#include "buttons.h"
24
 #include "ble.h"
23
 #include "ble.h"
25
-#include "lcd.h"
26
-#include "text.h"
27
 #include "models.h"
24
 #include "models.h"
25
+#include "menu.h"
28
 #include "state.h"
26
 #include "state.h"
27
+#include "state_scan.h"
29
 
28
 
30
-static const int max_lines = 5;
29
+static struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
30
+static int result_count = 0;
31
 
31
 
32
-static int menu_off = 0;
33
-static int menu_selection = -1;
34
-static int menu_length = 0;
35
-
36
-static void text_box(const char *s) {
37
-    static struct text_font font = {
38
-        .fontname = "fixed_10x20",
39
-        .font = NULL,
40
-    };
41
-    if (font.font == NULL) {
42
-        text_prepare_font(&font);
43
-    }
44
-
45
-    struct text_conf text = {
46
-        .text = "",
47
-        .x = 0,
48
-        .y = 50,
49
-        .justify = false,
50
-        .alignment = MF_ALIGN_CENTER,
51
-        .width = 240,
52
-        .height = 240 - 80,
53
-        .margin = 2,
54
-        .fg = RGB_565(0xFF, 0xFF, 0xFF),
55
-        .bg = RGB_565(0x00, 0x00, 0x00),
56
-        .font = &font,
57
-    };
58
-
59
-    // TODO clear background?!
60
-
61
-    text.text = s;
62
-    text_draw(&text);
63
-}
64
-
65
-static void state_scan_buttons(enum buttons btn, bool state) {
66
-    if (state && (btn == BTN_LEFT)) {
67
-        // TODO brightness down
68
-        return;
69
-    } else if (state && (btn == BTN_RIGHT)) {
70
-        // TODO brightness up
71
-        return;
72
-    } else if (state && ((btn == BTN_ENTER) || (btn == BTN_A))) {
73
-        // TODO menu_selection
74
-        return;
75
-    } else if ((!state) || ((btn != BTN_UP) && (btn != BTN_DOWN))) {
76
-        return;
77
-    }
78
-
79
-    if (state && (btn == BTN_UP)) {
80
-        if (menu_selection < 0) {
81
-            menu_selection = menu_length - 1;
82
-        } else {
83
-            menu_selection -= 1;
84
-        }
85
-    } else if (state && (btn == BTN_DOWN)) {
86
-        if (menu_selection < 0) {
87
-            menu_selection = 0;
88
-        } else {
89
-            menu_selection += 1;
32
+static void enter_cb(int selection) {
33
+    int devs = 0;
34
+    for (int i = 0; i < result_count; i++) {
35
+        enum known_devices dev = models_filter_name(results[i].name);
36
+        if (dev == DEV_UNKNOWN) {
37
+            continue;
90
         }
38
         }
91
-    }
92
 
39
 
93
-    if (menu_selection < 0) {
94
-        menu_selection += menu_length;
95
-    }
96
-    if (menu_selection >= menu_length) {
97
-        menu_selection -= menu_length;
98
-    }
99
-    if (menu_selection >= 0) {
100
-        while (menu_selection < menu_off) {
101
-            menu_off -= 1;
102
-        }
103
-        while (menu_selection >= (menu_off + max_lines)) {
104
-            menu_off += 1;
40
+        if (devs++ == selection) {
41
+            if (dev == DEV_VOLCANO) {
42
+                state_switch(STATE_VOLCANO_WORKFLOW);
43
+            }
44
+            return;
105
         }
45
         }
106
     }
46
     }
107
 }
47
 }
108
 
48
 
109
 void state_scan_enter(void) {
49
 void state_scan_enter(void) {
110
-    buttons_callback(state_scan_buttons);
50
+    menu_init(enter_cb);
111
     ble_scan(BLE_SCAN_ON);
51
     ble_scan(BLE_SCAN_ON);
112
 }
52
 }
113
 
53
 
114
 void state_scan_exit(void) {
54
 void state_scan_exit(void) {
115
-    buttons_callback(NULL);
116
     ble_scan(BLE_SCAN_OFF);
55
     ble_scan(BLE_SCAN_OFF);
117
 }
56
 }
118
 
57
 
119
-void state_scan_run(void) {
120
-    static char prev_buff[512] = {0};
121
-    char buff[512] = {0};
122
-
123
-    struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
124
-    int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);
58
+static void draw(struct menu_state *menu) {
59
+    result_count = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);
125
 
60
 
126
     int pos = 0, devs = 0;
61
     int pos = 0, devs = 0;
127
-    for (int i = 0; i < n; i++) {
62
+    for (int i = 0; i < result_count; i++) {
128
         enum known_devices dev = models_filter_name(results[i].name);
63
         enum known_devices dev = models_filter_name(results[i].name);
129
         if (dev == DEV_UNKNOWN) {
64
         if (dev == DEV_UNKNOWN) {
130
             continue;
65
             continue;
132
 
67
 
133
         devs++;
68
         devs++;
134
 
69
 
135
-        if (((devs - 1) < menu_off)
136
-            || ((devs - 1 - menu_off) >= max_lines)) {
70
+        if (((devs - 1) < menu->off)
71
+            || ((devs - 1 - menu->off) >= MENU_MAX_LINES)) {
137
             continue;
72
             continue;
138
         }
73
         }
139
 
74
 
140
 #if defined(MENU_PREFER_VOLCANO) || defined(MENU_PREFER_CRAFTY)
75
 #if defined(MENU_PREFER_VOLCANO) || defined(MENU_PREFER_CRAFTY)
141
-        if (menu_selection < 0) {
76
+        if (menu->selection < 0) {
142
 #ifdef MENU_PREFER_VOLCANO
77
 #ifdef MENU_PREFER_VOLCANO
143
             if (dev == DEV_VOLCANO) {
78
             if (dev == DEV_VOLCANO) {
144
-                menu_selection = devs - 1;
79
+                menu->selection = devs - 1;
145
             }
80
             }
146
 #endif // MENU_PREFER_VOLCANO
81
 #endif // MENU_PREFER_VOLCANO
147
 #ifdef MENU_PREFER_CRAFTY
82
 #ifdef MENU_PREFER_CRAFTY
148
             if (dev == DEV_CRAFTY) {
83
             if (dev == DEV_CRAFTY) {
149
-                menu_selection = devs - 1;
84
+                menu->selection = devs - 1;
150
             }
85
             }
151
 #endif // MENU_PREFER_CRAFTY
86
 #endif // MENU_PREFER_CRAFTY
152
         }
87
         }
153
 #endif // defined(MENU_PREFER_VOLCANO) || defined(MENU_PREFER_CRAFTY)
88
 #endif // defined(MENU_PREFER_VOLCANO) || defined(MENU_PREFER_CRAFTY)
154
 
89
 
155
-        if ((devs - 1) == menu_selection) {
156
-            pos += snprintf(buff + pos, sizeof(buff) - pos, "> ");
90
+        if ((devs - 1) == menu->selection) {
91
+            pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "> ");
157
         } else {
92
         } else {
158
-            pos += snprintf(buff + pos, sizeof(buff) - pos, "  ");
93
+            pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "  ");
159
         }
94
         }
160
 
95
 
161
         if (dev == DEV_VOLCANO) {
96
         if (dev == DEV_VOLCANO) {
162
-            pos += snprintf(buff + pos, sizeof(buff) - pos, "Volcano ");
97
+            pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "Volcano ");
163
         } else if (dev == DEV_CRAFTY) {
98
         } else if (dev == DEV_CRAFTY) {
164
-            pos += snprintf(buff + pos, sizeof(buff) - pos, "Crafty+ ");
99
+            pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "Crafty+ ");
165
         }
100
         }
166
 
101
 
167
         char info[32] = "";
102
         char info[32] = "";
169
                               info, sizeof(info)) < 0) {
104
                               info, sizeof(info)) < 0) {
170
             strcpy(info, "-error-");
105
             strcpy(info, "-error-");
171
         }
106
         }
172
-        pos += snprintf(buff + pos, sizeof(buff) - pos, "%s\n", info);
107
+        pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "%s\n", info);
173
     }
108
     }
174
 
109
 
175
-    menu_length = devs;
110
+    menu->length = devs;
176
 
111
 
177
 #if !defined(MENU_PREFER_VOLCANO) && !defined(MENU_PREFER_CRAFTY)
112
 #if !defined(MENU_PREFER_VOLCANO) && !defined(MENU_PREFER_CRAFTY)
178
-    if ((menu_selection < 0) && (menu_length > 0)) {
179
-        menu_selection = 0;
113
+    if ((menu->selection < 0) && (menu->length > 0)) {
114
+        menu->selection = 0;
180
     }
115
     }
181
 #endif // !defined(MENU_PREFER_VOLCANO) && !defined(MENU_PREFER_CRAFTY)
116
 #endif // !defined(MENU_PREFER_VOLCANO) && !defined(MENU_PREFER_CRAFTY)
182
 
117
 
183
-    if (menu_length == 0) {
184
-        strncpy(buff, "NONE", sizeof(buff));
118
+    if (menu->length == 0) {
119
+        strncpy(menu->buff, "NONE", MENU_MAX_LEN);
185
     }
120
     }
121
+}
186
 
122
 
187
-    if (strncmp(buff, prev_buff, sizeof(buff)) != 0) {
188
-        strncpy(prev_buff, buff, sizeof(prev_buff));
189
-        text_box(buff);
190
-    }
123
+void state_scan_run(void) {
124
+    menu_run(draw);
191
 }
125
 }

+ 69
- 0
src/state_volcano_workflow.c Просмотреть файл

1
+/*
2
+ * state_volcano_workflow.c
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ *
6
+ * This program is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * (at your option) any later version.
10
+ *
11
+ * This program is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU General Public License for more details.
15
+ *
16
+ * See <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include <stdio.h>
20
+#include <string.h>
21
+
22
+#include "config.h"
23
+#include "menu.h"
24
+#include "workflow.h"
25
+#include "state_volcano_workflow.h"
26
+
27
+static void enter_cb(int selection) {
28
+    (void)(selection); // TODO
29
+}
30
+
31
+void state_volcano_wf_enter(void) {
32
+    menu_init(enter_cb);
33
+}
34
+
35
+void state_volcano_wf_exit(void) {
36
+    // nothing to do
37
+}
38
+
39
+static void draw(struct menu_state *menu) {
40
+    menu->length = wf_count();
41
+
42
+    int pos = 0;
43
+    for (uint16_t i = 0; i < menu->length; i++) {
44
+        if ((i < menu->off)
45
+            || ((i - menu->off) >= MENU_MAX_LINES)) {
46
+            continue;
47
+        }
48
+
49
+        if (i == menu->selection) {
50
+            pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "> ");
51
+        } else {
52
+            pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "  ");
53
+        }
54
+
55
+        pos += snprintf(menu->buff + pos, MENU_MAX_LEN - pos, "'%s' by %s\n", wf_name(i), wf_author(i));
56
+    }
57
+
58
+    if ((menu->selection < 0) && (menu->length > 0)) {
59
+        menu->selection = 0;
60
+    }
61
+
62
+    if (menu->length == 0) {
63
+        strncpy(menu->buff, "NONE", MENU_MAX_LEN);
64
+    }
65
+}
66
+
67
+void state_volcano_wf_run(void) {
68
+    menu_run(draw);
69
+}

+ 29
- 0
src/text.c Просмотреть файл

151
     mf_wordwrap(tc->font->font, tc->width - 2 * tc->margin,
151
     mf_wordwrap(tc->font->font, tc->width - 2 * tc->margin,
152
                 tc->text, line_callback, &state);
152
                 tc->text, line_callback, &state);
153
 }
153
 }
154
+
155
+void text_box(const char *s) {
156
+    static struct text_font font = {
157
+        .fontname = "fixed_10x20",
158
+        .font = NULL,
159
+    };
160
+    if (font.font == NULL) {
161
+        text_prepare_font(&font);
162
+    }
163
+
164
+    struct text_conf text = {
165
+        .text = "",
166
+        .x = 0,
167
+        .y = 50,
168
+        .justify = false,
169
+        .alignment = MF_ALIGN_CENTER,
170
+        .width = 240,
171
+        .height = 240 - 80,
172
+        .margin = 2,
173
+        .fg = RGB_565(0xFF, 0xFF, 0xFF),
174
+        .bg = RGB_565(0x00, 0x00, 0x00),
175
+        .font = &font,
176
+    };
177
+
178
+    // TODO clear background?!
179
+
180
+    text.text = s;
181
+    text_draw(&text);
182
+}

+ 51
- 33
src/workflow.c Просмотреть файл

21
 #include "volcano.h"
21
 #include "volcano.h"
22
 #include "workflow.h"
22
 #include "workflow.h"
23
 
23
 
24
-#define WF_MAX_STEPS 32
25
-#define WF_MAX_FLOWS 5
24
+#define WF_MAX_STEPS 42
25
+#define WF_MAX_FLOWS 6
26
 
26
 
27
 enum wf_op {
27
 enum wf_op {
28
     OP_SET_TEMPERATURE = 0,
28
     OP_SET_TEMPERATURE = 0,
38
 
38
 
39
 struct workflow {
39
 struct workflow {
40
     const char *name;
40
     const char *name;
41
+    const char *author;
41
     struct wf_step steps[WF_MAX_STEPS];
42
     struct wf_step steps[WF_MAX_STEPS];
42
     uint16_t count;
43
     uint16_t count;
43
 };
44
 };
45
 static const struct workflow wf[WF_MAX_FLOWS] = {
46
 static const struct workflow wf[WF_MAX_FLOWS] = {
46
     {
47
     {
47
         .name = "Default",
48
         .name = "Default",
49
+        .author = "xythobuz",
48
         .steps = {
50
         .steps = {
49
             { .op = OP_WAIT_TEMPERATURE, .val = 1850 },
51
             { .op = OP_WAIT_TEMPERATURE, .val = 1850 },
50
-            { .op = OP_WAIT_TIME, .val = 15000 },
52
+            { .op = OP_WAIT_TIME, .val = 10000 },
51
             { .op = OP_PUMP_TIME, .val = 5000 },
53
             { .op = OP_PUMP_TIME, .val = 5000 },
52
 
54
 
53
             { .op = OP_WAIT_TEMPERATURE, .val = 1950 },
55
             { .op = OP_WAIT_TEMPERATURE, .val = 1950 },
54
-            { .op = OP_WAIT_TIME, .val = 10000 },
56
+            { .op = OP_WAIT_TIME, .val = 5000 },
55
             { .op = OP_PUMP_TIME, .val = 20000 },
57
             { .op = OP_PUMP_TIME, .val = 20000 },
56
 
58
 
57
             { .op = OP_WAIT_TEMPERATURE, .val = 2050 },
59
             { .op = OP_WAIT_TEMPERATURE, .val = 2050 },
58
-            { .op = OP_WAIT_TIME, .val = 10000 },
60
+            { .op = OP_WAIT_TIME, .val = 5000 },
59
             { .op = OP_PUMP_TIME, .val = 20000 },
61
             { .op = OP_PUMP_TIME, .val = 20000 },
60
 
62
 
61
             { .op = OP_PUMP_TIME, .val = 1000 },
63
             { .op = OP_PUMP_TIME, .val = 1000 },
74
         },
76
         },
75
         .count = 18,
77
         .count = 18,
76
     }, {
78
     }, {
79
+        .name = "Vorbi",
80
+        .author = "Rinor",
81
+        .steps = {
82
+            { .op = OP_WAIT_TEMPERATURE, .val = 1760 },
83
+            { .op = OP_WAIT_TIME, .val = 10000 },
84
+            { .op = OP_PUMP_TIME, .val = 6000 },
85
+
86
+            { .op = OP_WAIT_TEMPERATURE, .val = 1870 },
87
+            { .op = OP_WAIT_TIME, .val = 5000 },
88
+            { .op = OP_PUMP_TIME, .val = 10000 },
89
+
90
+            { .op = OP_WAIT_TEMPERATURE, .val = 2040 },
91
+            { .op = OP_WAIT_TIME, .val = 3000 },
92
+            { .op = OP_PUMP_TIME, .val = 10000 },
93
+
94
+            { .op = OP_WAIT_TEMPERATURE, .val = 2170 },
95
+            { .op = OP_WAIT_TIME, .val = 5000 },
96
+            { .op = OP_PUMP_TIME, .val = 10000 },
97
+        },
98
+        .count = 12,
99
+    }, {
77
         .name = "Relaxo",
100
         .name = "Relaxo",
101
+        .author = "xythobuz",
78
         .steps = {
102
         .steps = {
79
             { .op = OP_WAIT_TEMPERATURE, .val = 1750 },
103
             { .op = OP_WAIT_TEMPERATURE, .val = 1750 },
80
-            { .op = OP_WAIT_TIME, .val = 15000 },
104
+            { .op = OP_WAIT_TIME, .val = 10000 },
81
             { .op = OP_PUMP_TIME, .val = 5000 },
105
             { .op = OP_PUMP_TIME, .val = 5000 },
82
 
106
 
83
             { .op = OP_WAIT_TEMPERATURE, .val = 1850 },
107
             { .op = OP_WAIT_TEMPERATURE, .val = 1850 },
84
-            { .op = OP_WAIT_TIME, .val = 10000 },
108
+            { .op = OP_WAIT_TIME, .val = 5000 },
85
             { .op = OP_PUMP_TIME, .val = 20000 },
109
             { .op = OP_PUMP_TIME, .val = 20000 },
86
 
110
 
87
             { .op = OP_WAIT_TEMPERATURE, .val = 1950 },
111
             { .op = OP_WAIT_TEMPERATURE, .val = 1950 },
88
-            { .op = OP_WAIT_TIME, .val = 10000 },
112
+            { .op = OP_WAIT_TIME, .val = 5000 },
89
             { .op = OP_PUMP_TIME, .val = 20000 },
113
             { .op = OP_PUMP_TIME, .val = 20000 },
90
 
114
 
91
             { .op = OP_PUMP_TIME, .val = 1000 },
115
             { .op = OP_PUMP_TIME, .val = 1000 },
105
         .count = 18,
129
         .count = 18,
106
     }, {
130
     }, {
107
         .name = "Hardcore",
131
         .name = "Hardcore",
132
+        .author = "xythobuz",
108
         .steps = {
133
         .steps = {
109
             { .op = OP_WAIT_TEMPERATURE, .val = 1900 },
134
             { .op = OP_WAIT_TEMPERATURE, .val = 1900 },
110
-            { .op = OP_WAIT_TIME, .val = 15000 },
135
+            { .op = OP_WAIT_TIME, .val = 10000 },
111
             { .op = OP_PUMP_TIME, .val = 5000 },
136
             { .op = OP_PUMP_TIME, .val = 5000 },
112
 
137
 
113
             { .op = OP_WAIT_TEMPERATURE, .val = 2050 },
138
             { .op = OP_WAIT_TEMPERATURE, .val = 2050 },
114
-            { .op = OP_WAIT_TIME, .val = 10000 },
139
+            { .op = OP_WAIT_TIME, .val = 5000 },
115
             { .op = OP_PUMP_TIME, .val = 20000 },
140
             { .op = OP_PUMP_TIME, .val = 20000 },
116
 
141
 
117
             { .op = OP_WAIT_TEMPERATURE, .val = 2200 },
142
             { .op = OP_WAIT_TEMPERATURE, .val = 2200 },
118
-            { .op = OP_WAIT_TIME, .val = 10000 },
143
+            { .op = OP_WAIT_TIME, .val = 5000 },
119
             { .op = OP_PUMP_TIME, .val = 20000 },
144
             { .op = OP_PUMP_TIME, .val = 20000 },
120
 
145
 
121
             { .op = OP_PUMP_TIME, .val = 1000 },
146
             { .op = OP_PUMP_TIME, .val = 1000 },
133
             { .op = OP_SET_TEMPERATURE, .val = 1900 },
158
             { .op = OP_SET_TEMPERATURE, .val = 1900 },
134
         },
159
         },
135
         .count = 18,
160
         .count = 18,
136
-    }, {
137
-        .name = "Vorbi",
138
-        .steps = {
139
-            { .op = OP_WAIT_TEMPERATURE, .val = 1760 },
140
-            { .op = OP_WAIT_TIME, .val = 10000 },
141
-            { .op = OP_PUMP_TIME, .val = 6000 },
142
-
143
-            { .op = OP_WAIT_TEMPERATURE, .val = 1870 },
144
-            { .op = OP_WAIT_TIME, .val = 5000 },
145
-            { .op = OP_PUMP_TIME, .val = 10000 },
146
-
147
-            { .op = OP_WAIT_TEMPERATURE, .val = 2040 },
148
-            { .op = OP_WAIT_TIME, .val = 3000 },
149
-            { .op = OP_PUMP_TIME, .val = 10000 },
150
-
151
-            { .op = OP_WAIT_TEMPERATURE, .val = 2170 },
152
-            { .op = OP_WAIT_TIME, .val = 5000 },
153
-            { .op = OP_PUMP_TIME, .val = 10000 },
154
-        },
155
-        .count = 12,
156
     },
161
     },
157
 };
162
 };
158
 
163
 
194
     return wf[index].name;
199
     return wf[index].name;
195
 }
200
 }
196
 
201
 
197
-enum wf_status wf_status(void) {
198
-    return status;
202
+const char *wf_author(uint16_t index) {
203
+    if (index >= count) {
204
+        debug("invalid index %d", index);
205
+        return NULL;
206
+    }
207
+    return wf[index].author;
208
+}
209
+
210
+struct wf_state wf_status(void) {
211
+    struct wf_state s = {
212
+        .status = status,
213
+        .step = step,
214
+        .count = wf[wf_i].count,
215
+    };
216
+    return s;
199
 }
217
 }
200
 
218
 
201
 void wf_start(uint16_t index) {
219
 void wf_start(uint16_t index) {

Загрузка…
Отмена
Сохранить