ソースを参照

device selection menu

Thomas Buck 1年前
コミット
00498af11e
9個のファイルの変更148行の追加48行の削除
  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 ファイルの表示

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

+ 3
- 0
include/config.h ファイルの表示

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

+ 1
- 1
include/image.h ファイルの表示

@@ -21,7 +21,7 @@
21 21
 
22 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 26
 void draw_splash(void);
27 27
 void draw_battery_indicator(void);

+ 3
- 3
include/logo.h ファイルの表示

@@ -1,7 +1,7 @@
1 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 6
 /*  Call this macro repeatedly.  After each use, the pixel data can be extracted  */
7 7
 
@@ -11,7 +11,7 @@ pixel[1] = ((((data[1] - 33) & 0xF) << 4) | ((data[2] - 33) >> 2)); \
11 11
 pixel[2] = ((((data[2] - 33) & 0x3) << 6) | ((data[3] - 33))); \
12 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 ファイルの表示

@@ -39,6 +39,7 @@ struct button_state {
39 39
 };
40 40
 
41 41
 static struct button_state buttons[NUM_BTNS];
42
+static void (*callback)(enum buttons, bool) = NULL;
42 43
 
43 44
 void buttons_init(void) {
44 45
     for (uint i = 0; i < NUM_BTNS; i++) {
@@ -52,6 +53,10 @@ void buttons_init(void) {
52 53
     }
53 54
 }
54 55
 
56
+void buttons_callback(void (*fp)(enum buttons, bool)) {
57
+    callback = fp;
58
+}
59
+
55 60
 void buttons_run(void) {
56 61
     for (uint i = 0; i < NUM_BTNS; i++) {
57 62
         bool state = !gpio_get(gpio_num[i]);
@@ -64,6 +69,9 @@ void buttons_run(void) {
64 69
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
65 70
             if (state != buttons[i].current_state) {
66 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 ファイルの表示

@@ -33,7 +33,7 @@
33 33
 
34 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 37
     for (uint x = 0; x < width; x++) {
38 38
         for (uint y = 0; y < height; y++) {
39 39
             uint32_t pixel[3];
@@ -145,7 +145,7 @@ void draw_battery_indicator(void) {
145 145
 void battery_run(void) {
146 146
     static uint32_t last_run = 0;
147 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 149
         last_run = now;
150 150
         draw_battery_indicator();
151 151
     }

+ 4
- 2
src/main.c ファイルの表示

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

+ 0
- 8
src/state.c ファイルの表示

@@ -54,14 +54,6 @@ void state_switch(enum system_state next) {
54 54
 }
55 55
 
56 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 57
     switch (state) {
66 58
     case STATE_INIT:
67 59
         break;

+ 125
- 31
src/state_scan.c ファイルの表示

@@ -27,11 +27,92 @@
27 27
 #include "models.h"
28 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 109
 void state_scan_enter(void) {
110
+    buttons_callback(state_scan_buttons);
31 111
     ble_scan(BLE_SCAN_ON);
32 112
 }
33 113
 
34 114
 void state_scan_exit(void) {
115
+    buttons_callback(NULL);
35 116
     ble_scan(BLE_SCAN_OFF);
36 117
 }
37 118
 
@@ -42,13 +123,41 @@ void state_scan_run(void) {
42 123
     struct ble_scan_result results[BLE_MAX_SCAN_RESULTS] = {0};
43 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 127
     for (int i = 0; i < n; i++) {
47 128
         enum known_devices dev = models_filter_name(results[i].name);
48 129
         if (dev == DEV_UNKNOWN) {
49 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 161
         if (dev == DEV_VOLCANO) {
53 162
             pos += snprintf(buff + pos, sizeof(buff) - pos, "Volcano ");
54 163
         } else if (dev == DEV_CRAFTY) {
@@ -56,42 +165,27 @@ void state_scan_run(void) {
56 165
         }
57 166
 
58 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 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
 }

読み込み中…
キャンセル
保存