Browse Source

device selection menu

Thomas Buck 1 year ago
parent
commit
00498af11e
9 changed files with 148 additions and 48 deletions
  1. 2
    1
      include/buttons.h
  2. 3
    0
      include/config.h
  3. 1
    1
      include/image.h
  4. 3
    3
      include/logo.h
  5. 8
    0
      src/buttons.c
  6. 2
    2
      src/image.c
  7. 4
    2
      src/main.c
  8. 0
    8
      src/state.c
  9. 125
    31
      src/state_scan.c

+ 2
- 1
include/buttons.h View File

20
 #define __BUTTONS_H__
20
 #define __BUTTONS_H__
21
 
21
 
22
 enum buttons {
22
 enum buttons {
23
-    BTN_A,
23
+    BTN_A = 0,
24
     BTN_B,
24
     BTN_B,
25
     BTN_X,
25
     BTN_X,
26
     BTN_Y,
26
     BTN_Y,
33
 };
33
 };
34
 
34
 
35
 void buttons_init(void);
35
 void buttons_init(void);
36
+void buttons_callback(void (*fp)(enum buttons, bool));
36
 void buttons_run(void);
37
 void buttons_run(void);
37
 
38
 
38
 #endif // __BUTTONS_H__
39
 #endif // __BUTTONS_H__

+ 3
- 0
include/config.h View File

19
 #ifndef __CONFIG_H__
19
 #ifndef __CONFIG_H__
20
 #define __CONFIG_H__
20
 #define __CONFIG_H__
21
 
21
 
22
+#define MENU_PREFER_VOLCANO
23
+//#define MENU_PREFER_CRAFTY
24
+
22
 #define WATCHDOG_PERIOD_MS 1000
25
 #define WATCHDOG_PERIOD_MS 1000
23
 
26
 
24
 // ASCII 0x18 = CAN (cancel)
27
 // ASCII 0x18 = CAN (cancel)

+ 1
- 1
include/image.h View File

21
 
21
 
22
 #include "pico/stdlib.h"
22
 #include "pico/stdlib.h"
23
 
23
 
24
-void image_draw(char *data, uint width, uint height);
24
+void image_draw(const char *data, uint width, uint height);
25
 
25
 
26
 void draw_splash(void);
26
 void draw_splash(void);
27
 void draw_battery_indicator(void);
27
 void draw_battery_indicator(void);

+ 3
- 3
include/logo.h View File

1
 /*  GIMP header image file format (RGB)  */
1
 /*  GIMP header image file format (RGB)  */
2
 
2
 
3
-static unsigned int logo_width = 240;
4
-static unsigned int logo_height = 240;
3
+static const unsigned int logo_width = 240;
4
+static const unsigned int logo_height = 240;
5
 
5
 
6
 /*  Call this macro repeatedly.  After each use, the pixel data can be extracted  */
6
 /*  Call this macro repeatedly.  After each use, the pixel data can be extracted  */
7
 
7
 
11
 pixel[2] = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33))); \
11
 pixel[2] = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33))); \
12
 data += 4; \
12
 data += 4; \
13
 }
13
 }
14
-static char *logo_rgb_data =
14
+static const char *logo_rgb_data =
15
 	"````````````````````````````````````````````````````````````````"
15
 	"````````````````````````````````````````````````````````````````"
16
 	"````````````````````````````````````````````````````````````````"
16
 	"````````````````````````````````````````````````````````````````"
17
 	"````````````````````````````````````````````````````````````````"
17
 	"````````````````````````````````````````````````````````````````"

+ 8
- 0
src/buttons.c View File

39
 };
39
 };
40
 
40
 
41
 static struct button_state buttons[NUM_BTNS];
41
 static struct button_state buttons[NUM_BTNS];
42
+static void (*callback)(enum buttons, bool) = NULL;
42
 
43
 
43
 void buttons_init(void) {
44
 void buttons_init(void) {
44
     for (uint i = 0; i < NUM_BTNS; i++) {
45
     for (uint i = 0; i < NUM_BTNS; i++) {
52
     }
53
     }
53
 }
54
 }
54
 
55
 
56
+void buttons_callback(void (*fp)(enum buttons, bool)) {
57
+    callback = fp;
58
+}
59
+
55
 void buttons_run(void) {
60
 void buttons_run(void) {
56
     for (uint i = 0; i < NUM_BTNS; i++) {
61
     for (uint i = 0; i < NUM_BTNS; i++) {
57
         bool state = !gpio_get(gpio_num[i]);
62
         bool state = !gpio_get(gpio_num[i]);
64
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
69
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
65
             if (state != buttons[i].current_state) {
70
             if (state != buttons[i].current_state) {
66
                 buttons[i].current_state = state;
71
                 buttons[i].current_state = state;
72
+                if (callback) {
73
+                    callback(i, state);
74
+                }
67
             }
75
             }
68
         }
76
         }
69
 
77
 

+ 2
- 2
src/image.c View File

33
 
33
 
34
 #define BATT_INTERVAL_MS 777
34
 #define BATT_INTERVAL_MS 777
35
 
35
 
36
-void image_draw(char *data, uint width, uint height) {
36
+void image_draw(const char *data, uint width, uint height) {
37
     for (uint x = 0; x < width; x++) {
37
     for (uint x = 0; x < width; x++) {
38
         for (uint y = 0; y < height; y++) {
38
         for (uint y = 0; y < height; y++) {
39
             uint32_t pixel[3];
39
             uint32_t pixel[3];
145
 void battery_run(void) {
145
 void battery_run(void) {
146
     static uint32_t last_run = 0;
146
     static uint32_t last_run = 0;
147
     uint32_t now = to_ms_since_boot(get_absolute_time());
147
     uint32_t now = to_ms_since_boot(get_absolute_time());
148
-    if (now >= (last_run + BATT_INTERVAL_MS)) {
148
+    if ((now >= (last_run + BATT_INTERVAL_MS)) || (last_run == 0)) {
149
         last_run = now;
149
         last_run = now;
150
         draw_battery_indicator();
150
         draw_battery_indicator();
151
     }
151
     }

+ 4
- 2
src/main.c View File

52
     debug("lcd_init");
52
     debug("lcd_init");
53
     lcd_init();
53
     lcd_init();
54
     draw_splash();
54
     draw_splash();
55
-    lcd_set_backlight(0x1000);
55
+    lcd_set_backlight(0x8000);
56
 
56
 
57
     if (watchdog_caused_reboot()) {
57
     if (watchdog_caused_reboot()) {
58
         debug("reset by watchdog");
58
         debug("reset by watchdog");
86
     watchdog_enable(WATCHDOG_PERIOD_MS, 1);
86
     watchdog_enable(WATCHDOG_PERIOD_MS, 1);
87
 
87
 
88
     debug("init done");
88
     debug("init done");
89
-    lcd_set_backlight(0x8000);
89
+    battery_run();
90
+    lcd_set_backlight(0x8000); // TODO dynamic
90
 
91
 
91
     // wait for BLE stack to be ready before using it
92
     // wait for BLE stack to be ready before using it
93
+    debug("wait for bt stack");
92
     while (!ble_is_ready()) {
94
     while (!ble_is_ready()) {
93
         sleep_ms(1);
95
         sleep_ms(1);
94
     }
96
     }

+ 0
- 8
src/state.c View File

54
 }
54
 }
55
 
55
 
56
 void state_run(void) {
56
 void state_run(void) {
57
-    // TODO only for testing
58
-    static uint32_t last_heartbeat = 0;
59
-    uint32_t now = to_ms_since_boot(get_absolute_time());
60
-    if (now < (last_heartbeat + 1000)) {
61
-        return;
62
-    }
63
-    last_heartbeat = now;
64
-
65
     switch (state) {
57
     switch (state) {
66
     case STATE_INIT:
58
     case STATE_INIT:
67
         break;
59
         break;

+ 125
- 31
src/state_scan.c View File

27
 #include "models.h"
27
 #include "models.h"
28
 #include "state.h"
28
 #include "state.h"
29
 
29
 
30
+static const int max_lines = 5;
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;
90
+        }
91
+    }
92
+
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;
105
+        }
106
+    }
107
+}
108
+
30
 void state_scan_enter(void) {
109
 void state_scan_enter(void) {
110
+    buttons_callback(state_scan_buttons);
31
     ble_scan(BLE_SCAN_ON);
111
     ble_scan(BLE_SCAN_ON);
32
 }
112
 }
33
 
113
 
34
 void state_scan_exit(void) {
114
 void state_scan_exit(void) {
115
+    buttons_callback(NULL);
35
     ble_scan(BLE_SCAN_OFF);
116
     ble_scan(BLE_SCAN_OFF);
36
 }
117
 }
37
 
118
 
42
     struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
123
     struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
43
     int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);
124
     int n = ble_get_scan_results(results, BLE_MAX_SCAN_RESULTS);
44
 
125
 
45
-    uint pos = 0;
126
+    int pos = 0, devs = 0;
46
     for (int i = 0; i < n; i++) {
127
     for (int i = 0; i < n; i++) {
47
         enum known_devices dev = models_filter_name(results[i].name);
128
         enum known_devices dev = models_filter_name(results[i].name);
48
         if (dev == DEV_UNKNOWN) {
129
         if (dev == DEV_UNKNOWN) {
49
             continue;
130
             continue;
50
         }
131
         }
51
 
132
 
133
+        devs++;
134
+
135
+        if (((devs - 1) < menu_off)
136
+            || ((devs - 1 - menu_off) >= max_lines)) {
137
+            continue;
138
+        }
139
+
140
+#if defined(MENU_PREFER_VOLCANO) || defined(MENU_PREFER_CRAFTY)
141
+        if (menu_selection < 0) {
142
+#ifdef MENU_PREFER_VOLCANO
143
+            if (dev == DEV_VOLCANO) {
144
+                menu_selection = devs - 1;
145
+            }
146
+#endif // MENU_PREFER_VOLCANO
147
+#ifdef MENU_PREFER_CRAFTY
148
+            if (dev == DEV_CRAFTY) {
149
+                menu_selection = devs - 1;
150
+            }
151
+#endif // MENU_PREFER_CRAFTY
152
+        }
153
+#endif // defined(MENU_PREFER_VOLCANO) || defined(MENU_PREFER_CRAFTY)
154
+
155
+        if ((devs - 1) == menu_selection) {
156
+            pos += snprintf(buff + pos, sizeof(buff) - pos, "> ");
157
+        } else {
158
+            pos += snprintf(buff + pos, sizeof(buff) - pos, "  ");
159
+        }
160
+
52
         if (dev == DEV_VOLCANO) {
161
         if (dev == DEV_VOLCANO) {
53
             pos += snprintf(buff + pos, sizeof(buff) - pos, "Volcano ");
162
             pos += snprintf(buff + pos, sizeof(buff) - pos, "Volcano ");
54
         } else if (dev == DEV_CRAFTY) {
163
         } else if (dev == DEV_CRAFTY) {
56
         }
165
         }
57
 
166
 
58
         char info[32] = "";
167
         char info[32] = "";
59
-        models_get_serial(results[i].data, results[i].data_len,
60
-                          info, sizeof(info));
168
+        if (models_get_serial(results[i].data, results[i].data_len,
169
+                              info, sizeof(info)) < 0) {
170
+            strcpy(info, "-error-");
171
+        }
61
         pos += snprintf(buff + pos, sizeof(buff) - pos, "%s\n", info);
172
         pos += snprintf(buff + pos, sizeof(buff) - pos, "%s\n", info);
62
     }
173
     }
63
 
174
 
64
-    if (pos == 0) {
65
-        strncpy(buff, "NONE", sizeof(buff));
66
-    }
175
+    menu_length = devs;
67
 
176
 
68
-    if (strncmp(buff, prev_buff, sizeof(buff)) == 0) {
69
-        return;
177
+#if !defined(MENU_PREFER_VOLCANO) && !defined(MENU_PREFER_CRAFTY)
178
+    if ((menu_selection < 0) && (menu_length > 0)) {
179
+        menu_selection = 0;
70
     }
180
     }
71
-    strncpy(prev_buff, buff, sizeof(prev_buff));
181
+#endif // !defined(MENU_PREFER_VOLCANO) && !defined(MENU_PREFER_CRAFTY)
72
 
182
 
73
-    static struct text_font font = {
74
-        .fontname = "fixed_10x20",
75
-        .font = NULL,
76
-    };
77
-    if (font.font == NULL) {
78
-        text_prepare_font(&font);
183
+    if (menu_length == 0) {
184
+        strncpy(buff, "NONE", sizeof(buff));
79
     }
185
     }
80
 
186
 
81
-    struct text_conf text = {
82
-        .text = "",
83
-        .x = 0,
84
-        .y = 50,
85
-        .justify = false,
86
-        .alignment = MF_ALIGN_CENTER,
87
-        .width = 240,
88
-        .height = 240 - 80,
89
-        .margin = 2,
90
-        .fg = RGB_565(0xFF, 0xFF, 0xFF),
91
-        .bg = RGB_565(0x00, 0x00, 0x00),
92
-        .font = &font,
93
-    };
94
-
95
-    text.text = buff;
96
-    text_draw(&text);
187
+    if (strncmp(buff, prev_buff, sizeof(buff)) != 0) {
188
+        strncpy(prev_buff, buff, sizeof(prev_buff));
189
+        text_box(buff);
190
+    }
97
 }
191
 }

Loading…
Cancel
Save