Browse Source

add basic wifi to app

Thomas Buck 5 months ago
parent
commit
8037e328a0
11 changed files with 371 additions and 16 deletions
  1. 8
    6
      CMakeLists.txt
  2. 6
    1
      flash_ota.sh
  3. 4
    2
      include/config.h
  4. 76
    0
      include/lwipopts.h
  5. 14
    2
      include/mem.h
  6. 39
    0
      include/wifi.h
  7. 38
    1
      src/image.c
  8. 12
    2
      src/main.c
  9. 6
    1
      src/mem.c
  10. 23
    1
      src/state_settings.c
  11. 145
    0
      src/wifi.c

+ 8
- 6
CMakeLists.txt View File

@@ -95,6 +95,7 @@ target_sources(gadget PUBLIC
95 95
     src/state_value.c
96 96
     src/textbox.c
97 97
     src/state_volcano_conf.c
98
+    src/wifi.c
98 99
     src/venty.c
99 100
     src/state_venty.c
100 101
 
@@ -156,17 +157,12 @@ target_link_libraries(gadget
156 157
     hardware_pwm
157 158
     pico_btstack_ble
158 159
     pico_btstack_cyw43
159
-    pico_cyw43_arch_threadsafe_background
160
+    pico_cyw43_arch_lwip_threadsafe_background
160 161
     hardware_flash
161 162
     pico_flash
162 163
     picowota_reboot
163 164
 )
164 165
 
165
-target_compile_definitions(gadget PUBLIC
166
-    RUNNING_AS_CLIENT=1
167
-    CYW43_LWIP=0
168
-)
169
-
170 166
 pico_set_linker_script(gadget ${CMAKE_CURRENT_SOURCE_DIR}/src/memmap_custom.ld)
171 167
 
172 168
 # fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
@@ -176,5 +172,11 @@ set(PICOWOTA_WIFI_SSID "WIFI_SSID_HERE")
176 172
 set(PICOWOTA_WIFI_PASS "WIFI_PASS_HERE")
177 173
 set(PICOWOTA_WIFI_AP 0)
178 174
 
175
+target_compile_definitions(gadget PUBLIC
176
+    RUNNING_AS_CLIENT=1
177
+    DEFAULT_WIFI_SSID="${PICOWOTA_WIFI_SSID}"
178
+    DEFAULT_WIFI_PASS="${PICOWOTA_WIFI_PASS}"
179
+)
180
+
179 181
 add_subdirectory(picowota)
180 182
 picowota_build_combined(gadget)

+ 6
- 1
flash_ota.sh View File

@@ -18,7 +18,12 @@
18 18
 
19 19
 set -euo pipefail
20 20
 
21
-# TODO wait for device to be ready
21
+#echo -n Waiting for target to appear
22
+#while ! nc -z $1 4242; do
23
+#    echo -n .
24
+#    sleep 1
25
+#done
26
+#echo
22 27
 
23 28
 echo Copying binary
24 29
 ~/go/bin/serial-flash tcp:$1:4242 $2

+ 4
- 2
include/config.h View File

@@ -48,11 +48,13 @@
48 48
 #define DISK_BLOCK_SIZE 512
49 49
 
50 50
 #ifdef DEBUG_DISK_WRITE_SOURCES
51
-#define DISK_BLOCK_COUNT (256 + 128)
51
+#define DISK_ADD_BLOCKS_SOURCES 90 //128
52 52
 #else // DEBUG_DISK_WRITE_SOURCES
53
-#define DISK_BLOCK_COUNT 256
53
+#define DISK_ADD_BLOCKS_SOURCES 0
54 54
 #endif // DEBUG_DISK_WRITE_SOURCES
55 55
 
56
+#define DISK_BLOCK_COUNT (256 + DISK_ADD_BLOCKS_SOURCES)
57
+
56 58
 //#define TEST_VOLCANO_AUTO_CONNECT "xx:xx:xx:xx:xx:xx 1"
57 59
 //#define TEST_CRAFTY_AUTO_CONNECT "xx:xx:xx:xx:xx:xx 0"
58 60
 

+ 76
- 0
include/lwipopts.h View File

@@ -0,0 +1,76 @@
1
+#ifndef _LWIPOPTS_H
2
+#define _LWIPOPTS_H
3
+
4
+// see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details
5
+
6
+#define NO_SYS                      1
7
+#define LWIP_SOCKET                 0
8
+#define MEM_LIBC_MALLOC             0
9
+#define MEM_ALIGNMENT               4
10
+#define MEM_SIZE                    4000
11
+#define MEMP_NUM_TCP_SEG            32
12
+#define MEMP_NUM_ARP_QUEUE          10
13
+#define PBUF_POOL_SIZE              24
14
+#define LWIP_ARP                    1
15
+#define LWIP_ETHERNET               1
16
+#define LWIP_ICMP                   1
17
+#define LWIP_RAW                    1
18
+#define TCP_WND                     (8 * TCP_MSS)
19
+#define TCP_MSS                     1460
20
+#define TCP_SND_BUF                 (8 * TCP_MSS)
21
+#define TCP_SND_QUEUELEN            ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
22
+#define LWIP_NETIF_STATUS_CALLBACK  1
23
+#define LWIP_NETIF_LINK_CALLBACK    1
24
+#define LWIP_NETIF_HOSTNAME         1
25
+#define LWIP_NETCONN                0
26
+#define MEM_STATS                   0
27
+#define SYS_STATS                   0
28
+#define MEMP_STATS                  0
29
+#define LINK_STATS                  0
30
+#define LWIP_CHKSUM_ALGORITHM       3
31
+#define LWIP_DHCP                   1
32
+#define LWIP_IPV4                   1
33
+#define LWIP_TCP                    1
34
+#define LWIP_UDP                    1
35
+#define LWIP_DNS                    1
36
+#define LWIP_TCP_KEEPALIVE          1
37
+#define LWIP_NETIF_TX_SINGLE_PBUF   1
38
+#define DHCP_DOES_ARP_CHECK         0
39
+#define LWIP_DHCP_DOES_ACD_CHECK    0
40
+
41
+#ifndef NDEBUG
42
+#define LWIP_DEBUG                  1
43
+#define LWIP_STATS                  1
44
+#define LWIP_STATS_DISPLAY          1
45
+#endif
46
+
47
+#define ETHARP_DEBUG                LWIP_DBG_OFF
48
+#define NETIF_DEBUG                 LWIP_DBG_OFF
49
+#define PBUF_DEBUG                  LWIP_DBG_OFF
50
+#define API_LIB_DEBUG               LWIP_DBG_OFF
51
+#define API_MSG_DEBUG               LWIP_DBG_OFF
52
+#define SOCKETS_DEBUG               LWIP_DBG_OFF
53
+#define ICMP_DEBUG                  LWIP_DBG_OFF
54
+#define INET_DEBUG                  LWIP_DBG_OFF
55
+#define IP_DEBUG                    LWIP_DBG_OFF
56
+#define IP_REASS_DEBUG              LWIP_DBG_OFF
57
+#define RAW_DEBUG                   LWIP_DBG_OFF
58
+#define MEM_DEBUG                   LWIP_DBG_OFF
59
+#define MEMP_DEBUG                  LWIP_DBG_OFF
60
+#define SYS_DEBUG                   LWIP_DBG_OFF
61
+#define TCP_DEBUG                   LWIP_DBG_OFF
62
+#define TCP_INPUT_DEBUG             LWIP_DBG_OFF
63
+#define TCP_OUTPUT_DEBUG            LWIP_DBG_OFF
64
+#define TCP_RTO_DEBUG               LWIP_DBG_OFF
65
+#define TCP_CWND_DEBUG              LWIP_DBG_OFF
66
+#define TCP_WND_DEBUG               LWIP_DBG_OFF
67
+#define TCP_FR_DEBUG                LWIP_DBG_OFF
68
+#define TCP_QLEN_DEBUG              LWIP_DBG_OFF
69
+#define TCP_RST_DEBUG               LWIP_DBG_OFF
70
+#define UDP_DEBUG                   LWIP_DBG_OFF
71
+#define TCPIP_DEBUG                 LWIP_DBG_OFF
72
+#define PPP_DEBUG                   LWIP_DBG_OFF
73
+#define SLIP_DEBUG                  LWIP_DBG_OFF
74
+#define DHCP_DEBUG                  LWIP_DBG_OFF
75
+
76
+#endif /* __LWIPOPTS_H__ */

+ 14
- 2
include/mem.h View File

@@ -23,25 +23,37 @@
23 23
 #include <stdbool.h>
24 24
 
25 25
 #include "workflow.h"
26
+#include "wifi.h"
26 27
 
27 28
 // to migrate settings when struct changes between releases
28 29
 #define MEM_VERSION 0
29 30
 
30 31
 struct mem_data {
32
+    // wifi networks
33
+    // should stay at beginning, for bootloader
34
+    uint16_t net_count;
35
+    struct net_credentials net[WIFI_MAX_NET_COUNT];
36
+
37
+    // settings
31 38
     uint16_t backlight;
32 39
     bool wf_auto_connect;
40
+    bool enable_wifi;
33 41
 
42
+    // workflows
34 43
     uint16_t wf_count;
35 44
     struct workflow wf[WF_MAX_FLOWS];
36 45
 };
37 46
 
38
-// wf and wf_count are assigned in mem_init()
47
+// workflows are assigned in mem_init()
39 48
 #define MEM_DATA_INIT {           \
40 49
     .backlight = (0xFF00 >> 1),   \
41 50
     .wf_auto_connect = false,     \
51
+    .enable_wifi = false,         \
52
+    .wf_count = 0,                \
53
+    .net_count = 0,               \
42 54
 }
43 55
 
44
-void mem_init(void);
56
+void mem_load(void);
45 57
 void mem_write(void);
46 58
 struct mem_data *mem_data(void);
47 59
 void mem_load_defaults(void);

+ 39
- 0
include/wifi.h View File

@@ -0,0 +1,39 @@
1
+/*
2
+ * wifi.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 __WIFI_H__
20
+#define __WIFI_H__
21
+
22
+#define WIFI_MAX_NET_COUNT 5
23
+#define WIFI_MAX_NAME_LEN 32
24
+#define WIFI_MAX_PASS_LEN 32
25
+
26
+struct net_credentials {
27
+    char name[WIFI_MAX_NAME_LEN];
28
+    char pass[WIFI_MAX_PASS_LEN];
29
+};
30
+
31
+void wifi_init(void);
32
+void wifi_deinit(void);
33
+
34
+bool wifi_initialized(void);
35
+const char *wifi_state(void);
36
+
37
+void wifi_run(void);
38
+
39
+#endif // __WIFI_H__

+ 38
- 1
src/image.c View File

@@ -24,6 +24,7 @@
24 24
 #include "text.h"
25 25
 #include "lipo.h"
26 26
 #include "util.h"
27
+#include "wifi.h"
27 28
 #include "image.h"
28 29
 
29 30
 #pragma GCC diagnostic push
@@ -136,7 +137,42 @@ void draw_battery_indicator(void) {
136 137
         .height = 240,
137 138
         .margin = 2,
138 139
         .fg = c,
139
-        .bg = RGB_565(0x00, 0x00, 0x00),
140
+        .bg = LCD_BLACK,
141
+        .font = &font,
142
+    };
143
+    text_draw(&text);
144
+}
145
+
146
+void draw_wifi_indicator(void) {
147
+    static char prev_s[30] = {0};
148
+    char s[30] = {0};
149
+
150
+    snprintf(s, sizeof(s), "WiFi: %17s", wifi_state());
151
+
152
+    if (strcmp(s, prev_s) == 0) {
153
+        return;
154
+    }
155
+    strcpy(prev_s, s);
156
+
157
+    static struct text_font font = {
158
+        .fontname = "fixed_10x20",
159
+        .font = NULL,
160
+    };
161
+    if (font.font == NULL) {
162
+        text_prepare_font(&font);
163
+    }
164
+
165
+    struct text_conf text = {
166
+        .text = s,
167
+        .x = 0,
168
+        .y = 219 - 50,
169
+        .justify = false,
170
+        .alignment = MF_ALIGN_CENTER,
171
+        .width = 240,
172
+        .height = 240,
173
+        .margin = 2,
174
+        .fg = LCD_WHITE,
175
+        .bg = LCD_BLACK,
140 176
         .font = &font,
141 177
     };
142 178
     text_draw(&text);
@@ -148,5 +184,6 @@ void battery_run(void) {
148 184
     if ((now >= (last_run + BATT_INTERVAL_MS)) || (last_run == 0)) {
149 185
         last_run = now;
150 186
         draw_battery_indicator();
187
+        draw_wifi_indicator();
151 188
     }
152 189
 }

+ 12
- 2
src/main.c View File

@@ -38,6 +38,7 @@
38 38
 #include "state.h"
39 39
 #include "serial.h"
40 40
 #include "workflow.h"
41
+#include "wifi.h"
41 42
 
42 43
 void main_loop_hw(void) {
43 44
     watchdog_update();
@@ -48,6 +49,8 @@ void main_loop_hw(void) {
48 49
     if (lcd_get_backlight() != mem_data()->backlight) {
49 50
         lcd_set_backlight(mem_data()->backlight);
50 51
     }
52
+
53
+    wifi_run();
51 54
 }
52 55
 
53 56
 int main(void) {
@@ -60,8 +63,8 @@ int main(void) {
60 63
 #endif
61 64
     usb_init();
62 65
 
63
-    debug("mem_init");
64
-    mem_init();
66
+    debug("mem_load");
67
+    mem_load();
65 68
 
66 69
     debug("lcd_init");
67 70
     lcd_init();
@@ -120,6 +123,13 @@ int main(void) {
120 123
         sleep_ms(1);
121 124
     }
122 125
 
126
+    if (mem_data()->enable_wifi) {
127
+        debug("wifi_init");
128
+        wifi_init();
129
+    } else {
130
+        debug("wifi not enabled");
131
+    }
132
+
123 133
     debug("starting app");
124 134
     state_switch(STATE_SCAN);
125 135
 

+ 6
- 1
src/mem.c View File

@@ -82,9 +82,14 @@ void mem_load_defaults(void) {
82 82
     for (uint16_t i = 0; i < wf_default_count; i++) {
83 83
         data_ram.data.wf[i] = wf_default_data[i];
84 84
     }
85
+
86
+    // TODO
87
+    data_ram.data.net_count = 1;
88
+    strcpy(data_ram.data.net[0].name, DEFAULT_WIFI_SSID);
89
+    strcpy(data_ram.data.net[0].pass, DEFAULT_WIFI_PASS);
85 90
 }
86 91
 
87
-void mem_init(void) {
92
+void mem_load(void) {
88 93
     mem_load_defaults();
89 94
 
90 95
     if (!flash_safe_execute_core_init()) {

+ 23
- 1
src/state_settings.c View File

@@ -59,11 +59,21 @@ static void enter_cb(int selection) {
59 59
         break;
60 60
 
61 61
     case 3:
62
+        // Enable WiFi
63
+        state_value_set(&mem_data()->enable_wifi,
64
+                        sizeof(mem_data()->enable_wifi),
65
+                        0, 1, VAL_STEP_INCREMENT, 1,
66
+                        "Enable WiFi");
67
+        state_value_return(STATE_SETTINGS);
68
+        state_switch(STATE_VALUE);
69
+        break;
70
+
71
+    case 4:
62 72
         // Factory Reset
63 73
         mem_load_defaults();
64 74
         break;
65 75
 
66
-    case 4:
76
+    case 5:
67 77
         // OTA Update
68 78
         picowota_reboot(true);
69 79
         break;
@@ -81,6 +91,17 @@ void state_settings_enter(void) {
81 91
 void state_settings_exit(void) {
82 92
     menu_deinit();
83 93
     mem_write();
94
+
95
+    // apply changed wifi state
96
+    if (mem_data()->enable_wifi) {
97
+        if (!wifi_initialized()) {
98
+            wifi_init();
99
+        }
100
+    } else {
101
+        if (wifi_initialized()) {
102
+            wifi_deinit();
103
+        }
104
+    }
84 105
 }
85 106
 
86 107
 static void draw(struct menu_state *menu) {
@@ -90,6 +111,7 @@ static void draw(struct menu_state *menu) {
90 111
     ADD_STATIC_ELEMENT("Auto Connect (%d)", mem_data()->wf_auto_connect);
91 112
     ADD_STATIC_ELEMENT("Brightness (%d)", __builtin_ffs(mem_data()->backlight));
92 113
     ADD_STATIC_ELEMENT("Edit Workflows");
114
+    ADD_STATIC_ELEMENT("Enable WiFi (%d)", mem_data()->enable_wifi);
93 115
     ADD_STATIC_ELEMENT("Factory Reset");
94 116
     ADD_STATIC_ELEMENT("OTA Update");
95 117
 

+ 145
- 0
src/wifi.c View File

@@ -0,0 +1,145 @@
1
+/*
2
+ * wifi.c
3
+ *
4
+ * https://github.com/raspberrypi/pico-examples/blob/master/adc/read_vsys/power_status.c
5
+ *
6
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * See <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+#include "pico/cyw43_arch.h"
22
+#include "lwip/netif.h"
23
+#include "lwip/ip4_addr.h"
24
+
25
+#include "config.h"
26
+#include "log.h"
27
+#include "mem.h"
28
+#include "wifi.h"
29
+
30
+enum wifi_state {
31
+    WS_IDLE = 0,
32
+    WS_SCAN,
33
+    WS_CONNECT,
34
+    WS_READY,
35
+};
36
+
37
+static enum wifi_state state = WS_IDLE;
38
+
39
+static void wifi_connect(const char *ssid, const char *pw, uint32_t auth) {
40
+    debug("connecting to '%s'", ssid);
41
+
42
+    // https://github.com/raspberrypi/pico-sdk/issues/1413
43
+    uint32_t a = 0;
44
+    if (auth & 4) {
45
+        a = CYW43_AUTH_WPA2_AES_PSK;
46
+    } else if (auth & 2) {
47
+        a = CYW43_AUTH_WPA_TKIP_PSK;
48
+    }
49
+
50
+    int r = cyw43_arch_wifi_connect_async(ssid, pw, a);
51
+    if (r != 0) {
52
+        debug("failed to connect %d", r);
53
+    } else {
54
+        state = WS_CONNECT;
55
+    }
56
+}
57
+
58
+static int scan_result(void *env, const cyw43_ev_scan_result_t *result) {
59
+    (void)env;
60
+    cyw43_thread_enter();
61
+
62
+    if (result && (state == WS_SCAN)) {
63
+        for (int i = 0; i < mem_data()->net_count; i++) {
64
+            if ((strlen(mem_data()->net[i].name) == result->ssid_len)
65
+                 && (memcmp(mem_data()->net[i].name, result->ssid, result->ssid_len) == 0)) {
66
+                wifi_connect(mem_data()->net[i].name,
67
+                             mem_data()->net[i].pass,
68
+                             result->auth_mode);
69
+                break;
70
+            }
71
+        }
72
+    }
73
+
74
+    cyw43_thread_exit();
75
+    return 0;
76
+}
77
+
78
+static void wifi_scan(void) {
79
+    debug("starting scan");
80
+    cyw43_wifi_scan_options_t scan_options = {0};
81
+    int err = cyw43_wifi_scan(&cyw43_state, &scan_options, NULL, scan_result);
82
+    if (err != 0) {
83
+        debug("error %d", err);
84
+    }
85
+    state = WS_SCAN;
86
+}
87
+
88
+void wifi_init(void) {
89
+    if (state != WS_IDLE) {
90
+        debug("invalid state %d", state);
91
+        return;
92
+    }
93
+
94
+    cyw43_thread_enter();
95
+    cyw43_arch_enable_sta_mode();
96
+    wifi_scan();
97
+    cyw43_thread_exit();
98
+}
99
+
100
+void wifi_deinit(void) {
101
+    cyw43_thread_enter();
102
+    cyw43_arch_disable_sta_mode();
103
+    state = WS_IDLE;
104
+    cyw43_thread_exit();
105
+}
106
+
107
+bool wifi_initialized(void) {
108
+    return (state != WS_IDLE);
109
+}
110
+
111
+const char *wifi_state(void) {
112
+    switch (state) {
113
+    case WS_IDLE:
114
+        return "Disabled";
115
+
116
+    case WS_SCAN:
117
+        return "Scanning";
118
+
119
+    case WS_CONNECT:
120
+        return "Connecting";
121
+
122
+    case WS_READY:
123
+        return "Connected";
124
+    }
125
+
126
+    return NULL;
127
+}
128
+
129
+void wifi_run(void) {
130
+    cyw43_thread_enter();
131
+
132
+    if (state == WS_SCAN) {
133
+        if (!cyw43_wifi_scan_active(&cyw43_state)) {
134
+            debug("restarting scan");
135
+            wifi_scan();
136
+        }
137
+    } else if (state == WS_CONNECT) {
138
+        if (cyw43_wifi_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_JOIN) {
139
+            debug("joined network");
140
+            state = WS_READY;
141
+        }
142
+    }
143
+
144
+    cyw43_thread_exit();
145
+}

Loading…
Cancel
Save