Browse Source

add Bitty HTTP server and some other tweaks

Thomas Buck 1 year ago
parent
commit
8210ddce33
31 changed files with 871 additions and 71 deletions
  1. 3
    0
      .gitmodules
  2. 1
    0
      BittyHTTP
  3. 19
    1
      CMakeLists.txt
  4. 47
    0
      conf/Options.h
  5. 0
    0
      conf/ffconf.h
  6. 0
    0
      conf/lwipopts.h
  7. 0
    0
      conf/memmap_custom.ld
  8. 0
    0
      conf/tusb_config.h
  9. 1
    1
      include/console.h
  10. 26
    0
      include/http.h
  11. 1
    1
      include/log.h
  12. 4
    0
      include/main.h
  13. 10
    8
      include/ring.h
  14. 1
    1
      include/serial.h
  15. 1
    1
      include/usb_cdc.h
  16. 9
    0
      include/venty.h
  17. 1
    0
      pack_data.sh
  18. 1
    1
      src/console.c
  19. 43
    0
      src/http.c
  20. 101
    0
      src/http_files.c
  21. 392
    0
      src/http_socket.c
  22. 5
    5
      src/log.c
  23. 25
    2
      src/main.c
  24. 24
    14
      src/ring.c
  25. 12
    7
      src/serial.c
  26. 3
    2
      src/state_settings.c
  27. 1
    1
      src/state_string.c
  28. 51
    14
      src/state_venty.c
  29. 1
    1
      src/usb_cdc.c
  30. 87
    8
      src/venty.c
  31. 1
    3
      src/wifi.c

+ 3
- 0
.gitmodules View File

13
 [submodule "picowota"]
13
 [submodule "picowota"]
14
 	path = picowota
14
 	path = picowota
15
 	url = https://github.com/usedbytes/picowota
15
 	url = https://github.com/usedbytes/picowota
16
+[submodule "BittyHTTP"]
17
+	path = BittyHTTP
18
+	url = https://github.com/TheBeef/BittyHTTP

+ 1
- 0
BittyHTTP

1
+Subproject commit 0c531a062fe44ce9ee372361e14906924737ced1

+ 19
- 1
CMakeLists.txt View File

24
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mcufont/fonts
24
     WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mcufont/fonts
25
 )
25
 )
26
 
26
 
27
+# remove Options.h from BittyHTTP so we can use our own (TODO ugly)
28
+execute_process(COMMAND rm Options.h
29
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/BittyHTTP/src
30
+)
31
+
27
 # initialize pico-sdk from submodule
32
 # initialize pico-sdk from submodule
28
 include(pico-sdk/pico_sdk_init.cmake)
33
 include(pico-sdk/pico_sdk_init.cmake)
29
 
34
 
101
     src/state_wifi.c
106
     src/state_wifi.c
102
     src/state_wifi_edit.c
107
     src/state_wifi_edit.c
103
     src/state_string.c
108
     src/state_string.c
109
+    src/http.c
110
+    src/http_socket.c
111
+    src/http_files.c
104
 
112
 
105
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
113
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ff.c
106
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c
114
     ${CMAKE_CURRENT_BINARY_DIR}/fatfs/ffunicode.c
115
     mcufont/decoder/mf_bwfont.c
123
     mcufont/decoder/mf_bwfont.c
116
     mcufont/decoder/mf_scaledfont.c
124
     mcufont/decoder/mf_scaledfont.c
117
     mcufont/decoder/mf_wordwrap.c
125
     mcufont/decoder/mf_wordwrap.c
126
+
127
+    BittyHTTP/src/WebServer.c
118
 )
128
 )
119
 
129
 
120
 # external dependency include directories
130
 # external dependency include directories
131
+target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/conf)
121
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
132
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include)
122
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/fatfs)
133
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/fatfs)
123
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/st7789/src)
134
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/st7789/src)
125
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mcufont/decoder)
136
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/mcufont/decoder)
126
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/data)
137
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/data)
127
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/build)
138
 target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/build)
139
+target_include_directories(gadget PUBLIC ${CMAKE_CURRENT_LIST_DIR}/BittyHTTP/src)
128
 
140
 
129
 # compress source code and stuff we want to include
141
 # compress source code and stuff we want to include
130
 add_custom_target(pack bash -c "./pack_data.sh"
142
 add_custom_target(pack bash -c "./pack_data.sh"
148
 set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_client.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
160
 set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_client.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
149
 set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_server.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
161
 set_source_files_properties(pico-sdk/lib/btstack/src/classic/goep_server.c PROPERTIES COMPILE_FLAGS -Wno-unused-parameter)
150
 
162
 
163
+# suppress warnings for BittyHTTP
164
+set_source_files_properties(BittyHTTP/src/WebServer.c PROPERTIES COMPILE_FLAGS "-Wno-sign-compare -Wno-unused-parameter -Wno-maybe-uninitialized")
165
+
151
 # pull in common dependencies
166
 # pull in common dependencies
152
 target_link_libraries(gadget
167
 target_link_libraries(gadget
153
     pico_stdlib
168
     pico_stdlib
166
     picowota_reboot
181
     picowota_reboot
167
 )
182
 )
168
 
183
 
169
-pico_set_linker_script(gadget ${CMAKE_CURRENT_SOURCE_DIR}/src/memmap_custom.ld)
184
+pico_set_linker_script(gadget ${CMAKE_CURRENT_SOURCE_DIR}/conf/memmap_custom.ld)
170
 
185
 
171
 # fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
186
 # fix for Errata RP2040-E5 (the fix requires use of GPIO 15)
172
 target_compile_definitions(gadget PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1)
187
 target_compile_definitions(gadget PUBLIC PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1)
175
 set(PICOWOTA_WIFI_PASS "WIFI_PASS_HERE")
190
 set(PICOWOTA_WIFI_PASS "WIFI_PASS_HERE")
176
 set(PICOWOTA_WIFI_AP 0)
191
 set(PICOWOTA_WIFI_AP 0)
177
 
192
 
193
+# TODO set DOCVER to hash of static http files?
194
+
178
 target_compile_definitions(gadget PUBLIC
195
 target_compile_definitions(gadget PUBLIC
179
     RUNNING_AS_CLIENT=1
196
     RUNNING_AS_CLIENT=1
180
     DEFAULT_WIFI_SSID="${PICOWOTA_WIFI_SSID}"
197
     DEFAULT_WIFI_SSID="${PICOWOTA_WIFI_SSID}"
181
     DEFAULT_WIFI_PASS="${PICOWOTA_WIFI_PASS}"
198
     DEFAULT_WIFI_PASS="${PICOWOTA_WIFI_PASS}"
199
+    DOCVER="1.0.0.0"
182
 )
200
 )
183
 
201
 
184
 add_subdirectory(picowota)
202
 add_subdirectory(picowota)

+ 47
- 0
conf/Options.h View File

1
+/*
2
+ * Options.h
3
+ *
4
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5
+ * Copyright (c) 2019 Paul Hutchinson
6
+ *
7
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ * of this software and associated documentation files (the "Software"), to deal
9
+ * in the Software without restriction, including without limitation the rights
10
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the Software is
12
+ * furnished to do so, subject to the following conditions:
13
+ *
14
+ * The above copyright notice and this permission notice shall be included in all
15
+ * copies or substantial portions of the Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ * SOFTWARE.
24
+ */
25
+
26
+#ifndef __OPTIONS_H_
27
+#define __OPTIONS_H_
28
+
29
+#ifndef DOCVER
30
+#define DOCVER "1.0.0.0"
31
+#endif
32
+
33
+// The max number of connections we can handle at the same time
34
+// (this will include buffers needed for each connection)
35
+#define WS_OPT_MAX_CONNECTIONS              2
36
+
37
+// The memory block to use to store the cookies, get args, and post args
38
+#define WS_OPT_ARG_MEMORY_SIZE              100
39
+
40
+// How many seconds to wait after a connection stops sending to us before we hang up
41
+#define WS_SECONDS_UNTIL_CONNECTION_RELEASE 5
42
+
43
+// The max number of bytes we can handle a single header line can be (including the GET line).
44
+// This is normally in the order of 16K - 128K (we default to a lot less)
45
+#define WS_LINE_BUFFER_SIZE                 256
46
+
47
+#endif // __OPTIONS_H_

include/ffconf.h → conf/ffconf.h View File


include/lwipopts.h → conf/lwipopts.h View File


src/memmap_custom.ld → conf/memmap_custom.ld View File


include/tusb_config.h → conf/tusb_config.h View File


+ 1
- 1
include/console.h View File

21
 
21
 
22
 void cnsl_init(void);
22
 void cnsl_init(void);
23
 void cnsl_run(void);
23
 void cnsl_run(void);
24
-void cnsl_handle_input(const uint8_t *buf, size_t len);
24
+void cnsl_handle_input(const void *buf, size_t len);
25
 
25
 
26
 #endif // __CONSOLE_H__
26
 #endif // __CONSOLE_H__

+ 26
- 0
include/http.h View File

1
+/*
2
+ * http.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 __HTTP_H__
20
+#define __HTTP_H__
21
+
22
+void http_init(void);
23
+void http_deinit(void);
24
+void http_run(void);
25
+
26
+#endif // __HTTP_H__

+ 1
- 1
include/log.h View File

43
 void log_dump_to_uart(void);
43
 void log_dump_to_uart(void);
44
 void log_dump_to_disk(void);
44
 void log_dump_to_disk(void);
45
 
45
 
46
-void debug_handle_input(const uint8_t *buff, size_t len);
46
+void debug_handle_input(const void *buff, size_t len);
47
 
47
 
48
 #endif // __LOG_H__
48
 #endif // __LOG_H__

+ 4
- 0
include/main.h View File

21
 
21
 
22
 void main_loop_hw(void);
22
 void main_loop_hw(void);
23
 
23
 
24
+void networking_init(void);
25
+void networking_deinit(void);
26
+void networking_run(void);
27
+
24
 #endif // __MAIN_H__
28
 #endif // __MAIN_H__

+ 10
- 8
include/ring.h View File

24
 #include <stdbool.h>
24
 #include <stdbool.h>
25
 
25
 
26
 struct ring_buffer {
26
 struct ring_buffer {
27
-    uint8_t *buffer;
27
+    void *buffer;
28
     size_t size;
28
     size_t size;
29
+    size_t el_len;
29
     size_t head, tail;
30
     size_t head, tail;
30
     bool full;
31
     bool full;
31
 };
32
 };
32
-#define RB_INIT(b, s) { .buffer = b, .size = s, .head = 0, .tail = 0, .full = false }
33
+#define RB_INIT(b, s, e) { .buffer = b, .size = s, .el_len = e, .head = 0, .tail = 0, .full = false }
33
 
34
 
34
-void rb_add(struct ring_buffer *rb, const uint8_t *data, size_t length);
35
-#define rb_push(rb, v) rb_add(rb, &v, 1)
35
+void rb_add(struct ring_buffer *rb, const void *data, size_t length);
36
+#define rb_push(rb, v) rb_add(rb, v, 1)
36
 size_t rb_len(struct ring_buffer *rb);
37
 size_t rb_len(struct ring_buffer *rb);
37
 #define rb_space(rb) ((rb)->size - rb_len(rb))
38
 #define rb_space(rb) ((rb)->size - rb_len(rb))
38
-void rb_dump(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t));
39
-void rb_move(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t));
40
-uint8_t rb_peek(struct ring_buffer *rb);
41
-uint8_t rb_pop(struct ring_buffer *rb);
39
+void rb_dump(struct ring_buffer *rb, void (*write)(const void *, size_t));
40
+void rb_move(struct ring_buffer *rb, void (*write)(const void *, size_t));
41
+void rb_peek(struct ring_buffer *rb, void *buf);
42
+void rb_pop(struct ring_buffer *rb, void *buf);
43
+size_t rb_get(struct ring_buffer *rb, void *data, size_t length);
42
 
44
 
43
 #endif // __RING_BUFFER_H__
45
 #endif // __RING_BUFFER_H__

+ 1
- 1
include/serial.h View File

24
 #include <stdbool.h>
24
 #include <stdbool.h>
25
 
25
 
26
 void serial_init(void);
26
 void serial_init(void);
27
-void serial_write(const uint8_t *buf, size_t count);
27
+void serial_write(const void *buf, size_t count);
28
 void serial_set_reroute(bool reroute);
28
 void serial_set_reroute(bool reroute);
29
 void serial_run(void);
29
 void serial_run(void);
30
 
30
 

+ 1
- 1
include/usb_cdc.h View File

23
 #include <stdint.h>
23
 #include <stdint.h>
24
 #include <stdbool.h>
24
 #include <stdbool.h>
25
 
25
 
26
-void usb_cdc_write(const uint8_t *buf, size_t count);
26
+void usb_cdc_write(const void *buf, size_t count);
27
 void usb_cdc_set_reroute(bool reroute);
27
 void usb_cdc_set_reroute(bool reroute);
28
 
28
 
29
 #endif // __USB_CDC_H__
29
 #endif // __USB_CDC_H__

+ 9
- 0
include/venty.h View File

32
 int8_t venty_set_heater_state(bool value);
32
 int8_t venty_set_heater_state(bool value);
33
 int8_t venty_set_eco_current(bool value);
33
 int8_t venty_set_eco_current(bool value);
34
 int8_t venty_set_eco_voltage(bool value);
34
 int8_t venty_set_eco_voltage(bool value);
35
+int8_t venty_set_vibration(bool value);
36
+
37
+// v from 1 to 9, returns < 0 on error
38
+int8_t venty_set_brightness(uint8_t value);
35
 
39
 
36
 // in percent, or < 0 on error
40
 // in percent, or < 0 on error
37
 int8_t venty_get_battery_state(void);
41
 int8_t venty_get_battery_state(void);
38
 
42
 
39
 // bool, or < 0 on error
43
 // bool, or < 0 on error
44
+int8_t venty_get_heater_state(void);
40
 int8_t venty_get_eco_current(void);
45
 int8_t venty_get_eco_current(void);
41
 int8_t venty_get_eco_voltage(void);
46
 int8_t venty_get_eco_voltage(void);
47
+int8_t venty_get_vibration(void);
48
+
49
+// returns 1 to 9, or < 0 on error
50
+int8_t venty_get_brightness(void);
42
 
51
 
43
 #endif // __VENTY_H__
52
 #endif // __VENTY_H__

+ 1
- 0
pack_data.sh View File

28
 cp CMakeLists.txt build/src
28
 cp CMakeLists.txt build/src
29
 cp .gitmodules build/src/gitmodules
29
 cp .gitmodules build/src/gitmodules
30
 cp -r include build/src
30
 cp -r include build/src
31
+cp -r conf build/src
31
 cp -r src build/src
32
 cp -r src build/src
32
 
33
 
33
 cd build
34
 cd build

+ 1
- 1
src/console.c View File

600
     }
600
     }
601
 }
601
 }
602
 
602
 
603
-void cnsl_handle_input(const uint8_t *buf, size_t len) {
603
+void cnsl_handle_input(const void *buf, size_t len) {
604
     if ((cnsl_buff_pos + len) > CNSL_BUFF_SIZE) {
604
     if ((cnsl_buff_pos + len) > CNSL_BUFF_SIZE) {
605
         debug("error: console input buffer overflow! %lu > %u", cnsl_buff_pos + len, CNSL_BUFF_SIZE);
605
         debug("error: console input buffer overflow! %lu > %u", cnsl_buff_pos + len, CNSL_BUFF_SIZE);
606
         cnsl_init();
606
         cnsl_init();

+ 43
- 0
src/http.c View File

1
+/*
2
+ * http.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 "WebServer.h"
20
+
21
+#include "config.h"
22
+#include "log.h"
23
+#include "http.h"
24
+
25
+void http_init(void) {
26
+    SocketsCon_InitSocketConSystem();
27
+    WS_Init();
28
+
29
+    if (!WS_Start(80)) {
30
+        debug("failed to start web server");
31
+    } else {
32
+        debug("listening on :80");
33
+    }
34
+}
35
+
36
+void http_deinit(void) {
37
+    WS_Shutdown();
38
+    SocketsCon_ShutdownSocketConSystem();
39
+}
40
+
41
+void http_run(void) {
42
+    WS_Tick();
43
+}

+ 101
- 0
src/http_files.c View File

1
+/*
2
+ * http_files.c
3
+ *
4
+ * Based on BittyHTTP example.
5
+ *
6
+ * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
7
+ * Copyright (c) 2019 Paul Hutchinson
8
+ *
9
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ * of this software and associated documentation files (the "Software"), to deal
11
+ * in the Software without restriction, including without limitation the rights
12
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ * copies of the Software, and to permit persons to whom the Software is
14
+ * furnished to do so, subject to the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be included in all
17
+ * copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ * SOFTWARE.
26
+ */
27
+
28
+#include <string.h>
29
+
30
+#include "WebServer.h"
31
+
32
+#include "config.h"
33
+#include "log.h"
34
+#include "http.h"
35
+
36
+struct FileInfo {
37
+    const char *Filename; // With Path
38
+    bool Dynamic;
39
+    const char **Cookies;
40
+    const char **Gets;
41
+    const char **Posts;
42
+    void (*WriteFile)(struct WebServer *Web);
43
+};
44
+
45
+void File_Root(struct WebServer *Web);
46
+
47
+static struct FileInfo m_Files[] =  {
48
+    // Filename, Dynamic, Cookies, Gets, Posts, Callback
49
+    {       "/",   false,    NULL, NULL,  NULL, File_Root },
50
+};
51
+
52
+bool FS_GetFileProperties(const char *Filename, struct WSPageProp *PageProp) {
53
+    PageProp->FileID = 0;
54
+
55
+    for (size_t r = 0; r < sizeof(m_Files) / sizeof(struct FileInfo); r++) {
56
+        if (strcmp(Filename, m_Files[r].Filename) != 0) {
57
+            continue;
58
+        }
59
+
60
+        PageProp->FileID = (uintptr_t)&m_Files[r];
61
+        PageProp->DynamicFile = m_Files[r].Dynamic;
62
+        PageProp->Cookies = m_Files[r].Cookies;
63
+        PageProp->Gets = m_Files[r].Gets;
64
+        PageProp->Posts = m_Files[r].Posts;
65
+
66
+        debug("serving '%s'", Filename);
67
+        return true;
68
+    }
69
+
70
+    debug("unknown file '%s'", Filename);
71
+    return false;
72
+}
73
+
74
+void FS_SendFile(struct WebServer *Web, uintptr_t FileID) {
75
+    struct FileInfo *File = (struct FileInfo *)FileID;
76
+    if ((Web == NULL) || (File == NULL)) {
77
+        debug("invalid param");
78
+        return;
79
+    }
80
+
81
+    File->WriteFile(Web);
82
+}
83
+
84
+t_ElapsedTime ReadElapsedClock(void) {
85
+    return to_ms_since_boot(get_absolute_time()) / 1000;
86
+}
87
+
88
+const char RootHTML[]=
89
+"<!DOCTYPE html>"
90
+"<html>"
91
+"<head>"
92
+    "<title>Volcano Remote</title>"
93
+"</head>"
94
+"<body>"
95
+    "<h1>Hello World</h1>"
96
+"</body>"
97
+"</html>";
98
+
99
+void File_Root(struct WebServer *Web) {
100
+    WS_WriteWhole(Web,RootHTML, sizeof(RootHTML) - 1);
101
+}

+ 392
- 0
src/http_socket.c View File

1
+/*
2
+ * http_socket.c
3
+ *
4
+ * Based on BittyHTTP example socket interface.
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 <string.h>
22
+
23
+#include "lwip/tcp.h"
24
+#include "lwip/dns.h"
25
+#include "SocketsCon.h"
26
+
27
+#include "config.h"
28
+#include "log.h"
29
+#include "main.h"
30
+#include "ring.h"
31
+#include "http.h"
32
+
33
+#define MAX_SOCK 4
34
+#define SOCK_RECV_BUFF 512
35
+
36
+#define HTTP_DNS_TIMEOUT_MS 5000
37
+#define HTTP_CONNECT_TIMEOUT_MS 5000
38
+
39
+struct tcp_sock {
40
+    bool set;
41
+    struct tcp_pcb *pcb;
42
+
43
+    // TODO listening server socket has unused buffer
44
+    uint8_t rx_buf[SOCK_RECV_BUFF];
45
+    struct ring_buffer rx_rb;
46
+
47
+    struct tcp_pcb *child_buf[MAX_SOCK];
48
+    struct ring_buffer child_rb;
49
+};
50
+
51
+static struct tcp_sock sock[MAX_SOCK] = {0};
52
+
53
+bool SocketsCon_InitSocketConSystem(void) {
54
+    return true;
55
+}
56
+
57
+void SocketsCon_ShutdownSocketConSystem(void) { }
58
+
59
+static void tcp_server_err(void *arg, err_t err) {
60
+    debug("tcp error %d", err);
61
+
62
+    struct SocketCon *Con = arg;
63
+    Con->ErrorCode = e_ConnectErrorMAX;
64
+    Con->State = e_ConnectState_Error;
65
+}
66
+
67
+static err_t tcp_server_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) {
68
+    (void)tpcb;
69
+    debug("tcp recv %d %d", p->len, err);
70
+
71
+    struct SocketCon *Con = arg;
72
+    size_t idx = Con->SocketFD;
73
+
74
+    if (rb_space(&sock[idx].rx_rb) < p->len) {
75
+        debug("not enough space (%d < %d)", rb_space(&sock[idx].rx_rb), p->len);
76
+        tcp_abort(sock[idx].pcb);
77
+        Con->ErrorCode = e_ConnectErrorMAX;
78
+        Con->State = e_ConnectState_Error;
79
+        return ERR_ABRT;
80
+    }
81
+
82
+    rb_add(&sock[idx].rx_rb, p->payload, p->len);
83
+    return ERR_OK;
84
+}
85
+
86
+bool SocketsCon_InitSockCon(struct SocketCon *Con) {
87
+    if (!Con) {
88
+        debug("invalid param");
89
+        return false;
90
+    }
91
+
92
+    ssize_t next = -1;
93
+    for (size_t i = 0; i < MAX_SOCK; i++) {
94
+        if (!sock[i].set) {
95
+            next = i;
96
+            break;
97
+        }
98
+    }
99
+
100
+    if (next < 0) {
101
+        debug("error: too many sockets");
102
+        return false;
103
+    }
104
+
105
+    debug("new socket at %d", next);
106
+
107
+    sock[next].pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
108
+    if (sock[next].pcb == NULL) {
109
+        debug("error allocating new socket");
110
+        return false;
111
+    }
112
+
113
+    tcp_arg(sock[next].pcb, Con);
114
+    tcp_err(sock[next].pcb, tcp_server_err);
115
+    tcp_recv(sock[next].pcb, tcp_server_recv);
116
+
117
+    Con->SocketFD = next;
118
+    sock[next].set = true;
119
+
120
+    struct ring_buffer tmp = RB_INIT(sock[next].rx_buf, SOCK_RECV_BUFF, sizeof(uint8_t));
121
+    sock[next].rx_rb = tmp;
122
+
123
+    struct ring_buffer tmp2 = RB_INIT(sock[next].child_buf, MAX_SOCK, sizeof(struct tcp_pcb *));
124
+    sock[next].child_rb = tmp2;
125
+
126
+    Con->ErrorCode = e_ConnectError_AllOk;
127
+    Con->State = e_ConnectState_Idle;
128
+    Con->ReadInProgress = false;
129
+
130
+    return true;
131
+}
132
+
133
+static err_t tcp_server_connected(void *arg, struct tcp_pcb *tpcb, err_t err) {
134
+    (void)tpcb;
135
+    debug("tcp connected");
136
+
137
+    struct SocketCon *Con = arg;
138
+    Con->State = (err == ERR_OK) ? e_ConnectState_Connected : e_ConnectState_Idle;
139
+    return ERR_OK;
140
+}
141
+
142
+bool SocketsCon_Connect(struct SocketCon *Con,
143
+                        const char *ServerName, int portNo) {
144
+    if ((!Con) || (!ServerName)) {
145
+        debug("invalid param");
146
+        return false;
147
+    }
148
+
149
+    ip_addr_t ipaddr;
150
+    err_t err;
151
+    uint32_t start_time = to_ms_since_boot(get_absolute_time());
152
+    do {
153
+        err = dns_gethostbyname(ServerName, &ipaddr, NULL, NULL);
154
+        main_loop_hw();
155
+
156
+        uint32_t now = to_ms_since_boot(get_absolute_time());
157
+        if ((now - start_time) >= HTTP_DNS_TIMEOUT_MS) {
158
+            break;
159
+        }
160
+    } while (err == ERR_INPROGRESS);
161
+    if (err != ERR_OK) {
162
+        debug("error getting IP for '%s'", ServerName);
163
+        return false;
164
+    } else {
165
+        debug("IP %s for '%s'", ip4addr_ntoa(&ipaddr), ServerName);
166
+    }
167
+
168
+    Con->State = e_ConnectState_Connecting;
169
+
170
+    size_t idx = Con->SocketFD;
171
+    err = tcp_connect(sock[idx].pcb,
172
+                            &ipaddr, portNo,
173
+                            tcp_server_connected);
174
+    if (err != ERR_OK) {
175
+        debug("error connecting (%d)", err);
176
+        Con->State = e_ConnectState_Idle;
177
+        return false;
178
+    }
179
+
180
+    start_time = to_ms_since_boot(get_absolute_time());
181
+    while (Con->State == e_ConnectState_Connecting) {
182
+        main_loop_hw();
183
+
184
+        uint32_t now = to_ms_since_boot(get_absolute_time());
185
+        if ((now - start_time) >= HTTP_CONNECT_TIMEOUT_MS) {
186
+            break;
187
+        }
188
+    }
189
+
190
+    // TODO ?
191
+    //if (Con->State == e_ConnectState_Error) {
192
+    //    Con->State = e_ConnectState_Idle;
193
+    //}
194
+
195
+    return (Con->State == e_ConnectState_Connected);
196
+}
197
+
198
+bool SocketsCon_EnableAddressReuse(struct SocketCon *Con, bool Enable) {
199
+    (void)Con;
200
+    (void)Enable;
201
+    return true;
202
+}
203
+
204
+void SocketsCon_Tick(struct SocketCon *Con) { (void)Con; }
205
+
206
+bool SocketsCon_Write(struct SocketCon *Con, const void *buf, int num) {
207
+    if ((!Con) || (!buf) || (num <= 0)) {
208
+        debug("invalid param");
209
+        return false;
210
+    }
211
+
212
+    size_t idx = Con->SocketFD;
213
+    err_t err = tcp_write(sock[idx].pcb,
214
+                          buf, num, TCP_WRITE_FLAG_COPY);
215
+    if (err != ERR_OK) {
216
+        debug("error writing to socket");
217
+        return false;
218
+    }
219
+
220
+    return true;
221
+}
222
+
223
+int SocketsCon_Read(struct SocketCon *Con, void *buf, int num) {
224
+    if ((!Con) || (!buf) || (num <= 0)) {
225
+        debug("invalid param");
226
+        return false;
227
+    }
228
+
229
+    // TODO irq disable?
230
+
231
+    size_t idx = Con->SocketFD;
232
+    size_t len = rb_get(&sock[idx].rx_rb, buf, num);
233
+
234
+    // TODO irq enable?
235
+
236
+    return len;
237
+}
238
+
239
+void SocketsCon_Close(struct SocketCon *Con) {
240
+    if (!Con) {
241
+        debug("invalid param");
242
+        return;
243
+    }
244
+
245
+    size_t idx = Con->SocketFD;
246
+    sock[idx].set = false;
247
+
248
+    err_t err = tcp_close(sock[idx].pcb);
249
+    if (err != ERR_OK) {
250
+        debug("error closing socket (%d)", err);
251
+        // TODO retry?
252
+    }
253
+}
254
+
255
+static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
256
+    (void)err; // TODO?
257
+
258
+    struct SocketCon *Con = arg;
259
+    size_t idx = Con->SocketFD;
260
+    if (rb_space(&sock[idx].child_rb) <= 0) {
261
+        debug("no space for new connection");
262
+        tcp_abort(newpcb);
263
+        return ERR_ABRT;
264
+    }
265
+
266
+    debug("new connection");
267
+
268
+    rb_push(&sock[idx].child_rb, &newpcb);
269
+    return ERR_OK;
270
+}
271
+
272
+bool SocketsCon_Listen(struct SocketCon *Con, const char *bindadd, int PortNo) {
273
+    if (!Con) {
274
+        debug("invalid param");
275
+        return false;
276
+    }
277
+
278
+    ip_addr_t ipaddr;
279
+    err_t err;
280
+    if (bindadd) {
281
+        uint32_t start_time = to_ms_since_boot(get_absolute_time());
282
+        do {
283
+            err = dns_gethostbyname(bindadd, &ipaddr, NULL, NULL);
284
+            main_loop_hw();
285
+
286
+            uint32_t now = to_ms_since_boot(get_absolute_time());
287
+            if ((now - start_time) >= HTTP_DNS_TIMEOUT_MS) {
288
+                break;
289
+            }
290
+        } while (err == ERR_INPROGRESS);
291
+        if (err != ERR_OK) {
292
+            debug("error getting IP for '%s'", bindadd);
293
+            return false;
294
+        } else {
295
+            debug("IP %s for '%s'", ip4addr_ntoa(&ipaddr), bindadd);
296
+        }
297
+    }
298
+
299
+    size_t idx = Con->SocketFD;
300
+    err = tcp_bind(sock[idx].pcb,
301
+                   bindadd ? &ipaddr : IP_ANY_TYPE,
302
+                   PortNo);
303
+    if (err != ERR_OK) {
304
+        debug("error binding to '%s'", bindadd);
305
+        return false;
306
+    }
307
+
308
+    struct tcp_pcb *tmp = tcp_listen(sock[idx].pcb);
309
+    if (tmp == NULL) {
310
+        debug("error listening on socket");
311
+        return false;
312
+    }
313
+    sock[idx].pcb = tmp;
314
+
315
+    tcp_accept(sock[idx].pcb, tcp_server_accept);
316
+
317
+    return true;
318
+}
319
+
320
+bool SocketsCon_Accept(struct SocketCon *Con, struct SocketCon *NewCon) {
321
+    if ((!Con) || (!NewCon)) {
322
+        debug("invalid param");
323
+        return false;
324
+    }
325
+
326
+    size_t idx = Con->SocketFD;
327
+    size_t new_idx = NewCon->SocketFD;
328
+
329
+    if (rb_len(&sock[idx].child_rb) <= 0) {
330
+        return false;
331
+    }
332
+
333
+    debug("accepting new connection");
334
+
335
+    struct tcp_pcb *new_pcb;
336
+    rb_pop(&sock[idx].child_rb, &new_pcb);
337
+
338
+    err_t err = tcp_close(sock[new_idx].pcb);
339
+    if (err != ERR_OK) {
340
+        debug("error closing prev new socket");
341
+    }
342
+
343
+    sock[new_idx].pcb = new_pcb;
344
+    return true;
345
+}
346
+
347
+bool SocketsCon_HasError(struct SocketCon *Con) {
348
+    if (!Con) {
349
+        debug("invalid param");
350
+        return true;
351
+    }
352
+    return Con->State == e_ConnectState_Error;
353
+}
354
+
355
+bool SocketsCon_IsConnected(struct SocketCon *Con) {
356
+    if (!Con) {
357
+        debug("invalid param");
358
+        return false;
359
+    }
360
+    return Con->State == e_ConnectState_Connected;
361
+}
362
+
363
+int SocketsCon_GetLastErrNo(struct SocketCon *Con) {
364
+    if (!Con) {
365
+        debug("invalid param");
366
+        return -1;
367
+    }
368
+    return Con->Last_errno;
369
+}
370
+
371
+e_ConnectErrorType SocketsCon_GetErrorCode(struct SocketCon *Con) {
372
+    if (!Con) {
373
+        debug("invalid param");
374
+        return e_ConnectErrorMAX;
375
+    }
376
+    return Con->ErrorCode;
377
+}
378
+
379
+bool SocketsCon_GetSocketHandle(struct SocketCon *Con,
380
+                                t_ConSocketHandle *RetHandle) {
381
+    if (!Con) {
382
+        debug("invalid param");
383
+        return false;
384
+    }
385
+
386
+    if (Con->SocketFD < 0) {
387
+        return false;
388
+    }
389
+
390
+    *RetHandle = Con->SocketFD;
391
+    return true;
392
+}

+ 5
- 5
src/log.c View File

29
 #include "log.h"
29
 #include "log.h"
30
 
30
 
31
 static uint8_t log_buff[4096] = {0};
31
 static uint8_t log_buff[4096] = {0};
32
-static struct ring_buffer log = RB_INIT(log_buff, sizeof(log_buff));
32
+static struct ring_buffer log = RB_INIT(log_buff, sizeof(log_buff), 1);
33
 
33
 
34
 static uint8_t line_buff[256] = {0};
34
 static uint8_t line_buff[256] = {0};
35
 static volatile bool got_input = false;
35
 static volatile bool got_input = false;
36
 static FIL log_file_fat;
36
 static FIL log_file_fat;
37
 
37
 
38
-static void add_to_log(const uint8_t *buff, size_t len) {
38
+static void add_to_log(const void *buff, size_t len) {
39
     rb_add(&log, buff, len);
39
     rb_add(&log, buff, len);
40
 }
40
 }
41
 
41
 
42
-static void log_dump_to_x(void (*write)(const uint8_t *, size_t)) {
42
+static void log_dump_to_x(void (*write)(const void *, size_t)) {
43
     if (rb_len(&log) == 0) {
43
     if (rb_len(&log) == 0) {
44
         return;
44
         return;
45
     }
45
     }
67
 #endif
67
 #endif
68
 }
68
 }
69
 
69
 
70
-static void log_file_write_callback(const uint8_t *data, size_t len) {
70
+static void log_file_write_callback(const void *data, size_t len) {
71
     UINT bw;
71
     UINT bw;
72
     FRESULT res = f_write(&log_file_fat, data, len, &bw);
72
     FRESULT res = f_write(&log_file_fat, data, len, &bw);
73
     if ((res != FR_OK) || (bw != len)) {
73
     if ((res != FR_OK) || (bw != len)) {
120
     va_end(args);
120
     va_end(args);
121
 }
121
 }
122
 
122
 
123
-void debug_handle_input(const uint8_t *buff, size_t len) {
123
+void debug_handle_input(const void *buff, size_t len) {
124
     (void)buff;
124
     (void)buff;
125
 
125
 
126
     if (len > 0) {
126
     if (len > 0) {

+ 25
- 2
src/main.c View File

39
 #include "serial.h"
39
 #include "serial.h"
40
 #include "workflow.h"
40
 #include "workflow.h"
41
 #include "wifi.h"
41
 #include "wifi.h"
42
+#include "http.h"
43
+#include "main.h"
42
 
44
 
43
 void main_loop_hw(void) {
45
 void main_loop_hw(void) {
44
     watchdog_update();
46
     watchdog_update();
50
         lcd_set_backlight(mem_data()->backlight);
52
         lcd_set_backlight(mem_data()->backlight);
51
     }
53
     }
52
 
54
 
55
+    networking_run();
56
+}
57
+
58
+void networking_init(void) {
59
+    debug("wifi_init");
60
+    wifi_init();
61
+
62
+    debug("http_init");
63
+    http_init();
64
+}
65
+
66
+void networking_deinit(void) {
67
+    debug("http_deinit");
68
+    http_deinit();
69
+
70
+    debug("wifi_deinit");
71
+    wifi_deinit();
72
+}
73
+
74
+void networking_run(void) {
75
+    http_run();
53
     wifi_run();
76
     wifi_run();
54
 }
77
 }
55
 
78
 
124
     }
147
     }
125
 
148
 
126
     if (mem_data()->enable_wifi) {
149
     if (mem_data()->enable_wifi) {
127
-        debug("wifi_init");
128
-        wifi_init();
150
+        debug("networking_init");
151
+        networking_init();
129
     } else {
152
     } else {
130
         debug("wifi not enabled");
153
         debug("wifi not enabled");
131
     }
154
     }

+ 24
- 14
src/ring.c View File

16
  * See <http://www.gnu.org/licenses/>.
16
  * See <http://www.gnu.org/licenses/>.
17
  */
17
  */
18
 
18
 
19
+#include <string.h>
20
+
19
 #include "config.h"
21
 #include "config.h"
20
 #include "ring.h"
22
 #include "ring.h"
21
 
23
 
22
-void rb_add(struct ring_buffer *rb, const uint8_t *data, size_t length) {
24
+void rb_add(struct ring_buffer *rb, const void *data, size_t length) {
23
     for (size_t i = 0; i < length; i++) {
25
     for (size_t i = 0; i < length; i++) {
24
-        rb->buffer[rb->head] = data[i];
26
+        memcpy(rb->buffer + rb->head * rb->el_len, data + i * rb->el_len, rb->el_len);
25
 
27
 
26
         if (rb->full && (++(rb->tail) == rb->size)) {
28
         if (rb->full && (++(rb->tail) == rb->size)) {
27
             rb->tail = 0;
29
             rb->tail = 0;
49
     }
51
     }
50
 }
52
 }
51
 
53
 
52
-void rb_dump(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t)) {
54
+void rb_dump(struct ring_buffer *rb, void (*write)(const void *, size_t)) {
53
     if (rb_len(rb) == 0) {
55
     if (rb_len(rb) == 0) {
54
         return;
56
         return;
55
     }
57
     }
56
 
58
 
57
     if (rb->head > rb->tail) {
59
     if (rb->head > rb->tail) {
58
-        write(rb->buffer + rb->tail, rb->head - rb->tail);
60
+        write(rb->buffer + rb->tail * rb->el_len, rb->head - rb->tail);
59
     } else {
61
     } else {
60
-        write(rb->buffer + rb->tail, rb->size - rb->tail);
62
+        write(rb->buffer + rb->tail * rb->el_len, rb->size - rb->tail);
61
         write(rb->buffer, rb->head);
63
         write(rb->buffer, rb->head);
62
     }
64
     }
63
 }
65
 }
64
 
66
 
65
-void rb_move(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t)) {
67
+void rb_move(struct ring_buffer *rb, void (*write)(const void *, size_t)) {
66
     rb_dump(rb, write);
68
     rb_dump(rb, write);
67
     rb->head = 0;
69
     rb->head = 0;
68
     rb->tail = 0;
70
     rb->tail = 0;
69
     rb->full = false;
71
     rb->full = false;
70
 }
72
 }
71
 
73
 
72
-uint8_t rb_peek(struct ring_buffer *rb) {
74
+void rb_peek(struct ring_buffer *rb, void *buf) {
73
     if (rb_len(rb) == 0) {
75
     if (rb_len(rb) == 0) {
74
-        return 0;
76
+        return;
75
     }
77
     }
76
 
78
 
77
-    uint8_t v = rb->buffer[rb->tail];
78
-    return v;
79
+    memcpy(buf, rb->buffer + rb->tail * rb->el_len, rb->el_len);
79
 }
80
 }
80
 
81
 
81
-uint8_t rb_pop(struct ring_buffer *rb) {
82
+void rb_pop(struct ring_buffer *rb, void *buf) {
82
     if (rb_len(rb) == 0) {
83
     if (rb_len(rb) == 0) {
83
-        return 0;
84
+        return;
84
     }
85
     }
85
 
86
 
86
-    uint8_t v = rb->buffer[rb->tail++];
87
+    memcpy(buf, rb->buffer + rb->tail * rb->el_len, rb->el_len);
88
+    rb->tail++;
87
     if (rb->tail >= rb->size) {
89
     if (rb->tail >= rb->size) {
88
         rb->tail = 0;
90
         rb->tail = 0;
89
     }
91
     }
92
+}
90
 
93
 
91
-    return v;
94
+size_t rb_get(struct ring_buffer *rb, void *data, size_t length) {
95
+    size_t count = 0;
96
+    while ((length > 0) && (rb_len(rb) > 0)) {
97
+        rb_pop(rb, data + count * rb->el_len);
98
+        count++;
99
+        length--;
100
+    }
101
+    return count;
92
 }
102
 }

+ 12
- 7
src/serial.c View File

45
 #include "serial.h"
45
 #include "serial.h"
46
 
46
 
47
 static uint8_t rx_buff[UART_RX_BUFF_LEN] = {0};
47
 static uint8_t rx_buff[UART_RX_BUFF_LEN] = {0};
48
-static struct ring_buffer rx = RB_INIT(rx_buff, sizeof(rx_buff));
48
+static struct ring_buffer rx = RB_INIT(rx_buff, sizeof(rx_buff), 1);
49
 
49
 
50
 static uint8_t tx_buff[UART_TX_BUFF_LEN] = {0};
50
 static uint8_t tx_buff[UART_TX_BUFF_LEN] = {0};
51
-static struct ring_buffer tx = RB_INIT(tx_buff, sizeof(tx_buff));
51
+static struct ring_buffer tx = RB_INIT(tx_buff, sizeof(tx_buff), 1);
52
 
52
 
53
 static bool reroute_serial_debug = false;
53
 static bool reroute_serial_debug = false;
54
 static bool tx_irq_state = false;
54
 static bool tx_irq_state = false;
70
     // Rx - read from UART FIFO to local buffer
70
     // Rx - read from UART FIFO to local buffer
71
     while (uart_is_readable(UART_ID) && (rb_space(&rx) > 0)) {
71
     while (uart_is_readable(UART_ID) && (rb_space(&rx) > 0)) {
72
         uint8_t ch = uart_getc(UART_ID);
72
         uint8_t ch = uart_getc(UART_ID);
73
-        rb_push(&rx, ch);
73
+        rb_push(&rx, &ch);
74
     }
74
     }
75
 
75
 
76
     // Tx - write to UART FIFO if needed
76
     // Tx - write to UART FIFO if needed
77
     while (uart_is_writable(UART_ID)) {
77
     while (uart_is_writable(UART_ID)) {
78
         if (rb_len(&tx) > 0) {
78
         if (rb_len(&tx) > 0) {
79
-            uart_putc_raw(UART_ID, rb_pop(&tx));
79
+            uint8_t c;
80
+            rb_pop(&tx, &c);
81
+            uart_putc_raw(UART_ID, c);
80
         } else {
82
         } else {
81
             SET_TX_IRQ(false);
83
             SET_TX_IRQ(false);
82
             break;
84
             break;
102
     SET_TX_IRQ(false);
104
     SET_TX_IRQ(false);
103
 }
105
 }
104
 
106
 
105
-void serial_write(const uint8_t *buf, size_t count) {
107
+void serial_write(const void *buf, size_t count) {
106
     SET_TX_IRQ(false);
108
     SET_TX_IRQ(false);
107
 
109
 
108
     while ((rb_len(&tx) == 0) && uart_is_writable(UART_ID) && (count > 0)) {
110
     while ((rb_len(&tx) == 0) && uart_is_writable(UART_ID) && (count > 0)) {
109
-        uart_putc_raw(UART_ID, *buf++);
111
+        uart_putc_raw(UART_ID, *(uint8_t *)buf);
112
+        buf++;
110
         count--;
113
         count--;
111
     }
114
     }
112
 
115
 
144
     SET_RX_IRQ(false);
147
     SET_RX_IRQ(false);
145
 
148
 
146
     if (rb_len(&rx) >= 1) {
149
     if (rb_len(&rx) >= 1) {
147
-        if (rb_peek(&rx) == ENTER_BOOTLOADER_MAGIC) {
150
+        uint8_t c;
151
+        rb_peek(&rx, &c);
152
+        if (c == ENTER_BOOTLOADER_MAGIC) {
148
             reset_to_bootloader();
153
             reset_to_bootloader();
149
         } else if (reroute_serial_debug) {
154
         } else if (reroute_serial_debug) {
150
             rb_move(&rx, debug_handle_input);
155
             rb_move(&rx, debug_handle_input);

+ 3
- 2
src/state_settings.c View File

23
 
23
 
24
 #include "config.h"
24
 #include "config.h"
25
 #include "log.h"
25
 #include "log.h"
26
+#include "main.h"
26
 #include "menu.h"
27
 #include "menu.h"
27
 #include "mem.h"
28
 #include "mem.h"
28
 #include "state.h"
29
 #include "state.h"
104
     // apply changed wifi state
105
     // apply changed wifi state
105
     if (mem_data()->enable_wifi) {
106
     if (mem_data()->enable_wifi) {
106
         if (!wifi_initialized()) {
107
         if (!wifi_initialized()) {
107
-            wifi_init();
108
+            networking_init();
108
         }
109
         }
109
     } else {
110
     } else {
110
         if (wifi_initialized()) {
111
         if (wifi_initialized()) {
111
-            wifi_deinit();
112
+            networking_deinit();
112
         }
113
         }
113
     }
114
     }
114
 }
115
 }

+ 1
- 1
src/state_string.c View File

102
     while (edit < offset) {
102
     while (edit < offset) {
103
         offset -= 1;
103
         offset -= 1;
104
     }
104
     }
105
-    while (edit >= (offset + (LCD_WIDTH / 10 - 2))) {
105
+    while (edit >= (offset + (LCD_WIDTH / 10 - 3))) {
106
         offset += 1;
106
         offset += 1;
107
     }
107
     }
108
 
108
 

+ 51
- 14
src/state_venty.c View File

38
 static int8_t battery = 0;
38
 static int8_t battery = 0;
39
 static int8_t eco_current = 0;
39
 static int8_t eco_current = 0;
40
 static int8_t eco_voltage = 0;
40
 static int8_t eco_voltage = 0;
41
+static int8_t vibration = 0;
42
+static int8_t brightness = 0;
41
 
43
 
42
 void state_venty_target(bd_addr_t addr, bd_addr_type_t type) {
44
 void state_venty_target(bd_addr_t addr, bd_addr_type_t type) {
43
     memcpy(ble_addr, addr, sizeof(bd_addr_t));
45
     memcpy(ble_addr, addr, sizeof(bd_addr_t));
46
     connected = false;
48
     connected = false;
47
 }
49
 }
48
 
50
 
51
+static void exit_cb(void) {
52
+    debug("venty disconnect");
53
+    ble_disconnect();
54
+    wait_for_disconnect = true;
55
+}
56
+
49
 static void enter_cb(int selection) {
57
 static void enter_cb(int selection) {
50
     switch (selection) {
58
     switch (selection) {
51
     case 0:
59
     case 0:
60
+        // Battery
61
+        break;
62
+
63
+    case 1:
52
         // Target
64
         // Target
53
         state_value_set(&target_temp,
65
         state_value_set(&target_temp,
54
                         sizeof(target_temp),
66
                         sizeof(target_temp),
58
         state_switch(STATE_VALUE);
70
         state_switch(STATE_VALUE);
59
         break;
71
         break;
60
 
72
 
61
-    case 1:
73
+    case 2:
62
         // Heater
74
         // Heater
63
         state_value_set(&heater_state,
75
         state_value_set(&heater_state,
64
                         sizeof(heater_state),
76
                         sizeof(heater_state),
68
         state_switch(STATE_VALUE);
80
         state_switch(STATE_VALUE);
69
         break;
81
         break;
70
 
82
 
71
-    case 2:
83
+    case 3:
72
         // Eco Current
84
         // Eco Current
73
         state_value_set(&eco_current,
85
         state_value_set(&eco_current,
74
                         sizeof(eco_current),
86
                         sizeof(eco_current),
78
         state_switch(STATE_VALUE);
90
         state_switch(STATE_VALUE);
79
         break;
91
         break;
80
 
92
 
81
-    case 3:
93
+    case 4:
82
         // Eco Voltage
94
         // Eco Voltage
83
         state_value_set(&eco_voltage,
95
         state_value_set(&eco_voltage,
84
                         sizeof(eco_voltage),
96
                         sizeof(eco_voltage),
87
         state_value_return(STATE_VENTY);
99
         state_value_return(STATE_VENTY);
88
         state_switch(STATE_VALUE);
100
         state_switch(STATE_VALUE);
89
         break;
101
         break;
102
+
103
+    case 5:
104
+        // Vibration
105
+        state_value_set(&vibration,
106
+                        sizeof(vibration),
107
+                        0, 1, VAL_STEP_INCREMENT, 1,
108
+                        "Vibration");
109
+        state_value_return(STATE_VENTY);
110
+        state_switch(STATE_VALUE);
111
+        break;
112
+
113
+    case 6:
114
+        // Brightness
115
+        state_value_set(&brightness,
116
+                        sizeof(brightness),
117
+                        1, 9, VAL_STEP_INCREMENT, 1,
118
+                        "Brightness");
119
+        state_value_return(STATE_VENTY);
120
+        state_switch(STATE_VALUE);
121
+        break;
122
+
123
+    default:
124
+        exit_cb();
125
+        break;
90
     }
126
     }
91
 }
127
 }
92
 
128
 
98
     venty_set_eco_current(eco_current);
134
     venty_set_eco_current(eco_current);
99
     sleep_ms(250);
135
     sleep_ms(250);
100
     venty_set_eco_voltage(eco_voltage);
136
     venty_set_eco_voltage(eco_voltage);
137
+    sleep_ms(250);
138
+    venty_set_vibration(vibration);
139
+    sleep_ms(250);
140
+    venty_set_brightness(brightness);
101
 }
141
 }
102
 
142
 
103
-
104
 static void fetch_values(void) {
143
 static void fetch_values(void) {
105
-    venty_set_heater_state(false);
106
-    heater_state = false;
107
-
144
+    heater_state = venty_get_heater_state();
108
     target_temp = venty_get_target_temp();
145
     target_temp = venty_get_target_temp();
109
     battery = venty_get_battery_state();
146
     battery = venty_get_battery_state();
110
     eco_current = venty_get_eco_current();
147
     eco_current = venty_get_eco_current();
111
     eco_voltage = venty_get_eco_voltage();
148
     eco_voltage = venty_get_eco_voltage();
112
-}
113
-
114
-static void exit_cb(void) {
115
-    debug("venty disconnect");
116
-    ble_disconnect();
117
-    wait_for_disconnect = true;
149
+    vibration = venty_get_vibration();
150
+    brightness = venty_get_brightness();
118
 }
151
 }
119
 
152
 
120
 void state_venty_enter(void) {
153
 void state_venty_enter(void) {
148
     int pos = 0;
181
     int pos = 0;
149
     menu->length = 0;
182
     menu->length = 0;
150
 
183
 
184
+    ADD_STATIC_ELEMENT("Battery: %d %%", battery);
151
     ADD_STATIC_ELEMENT("Target (%d C)", target_temp / 10);
185
     ADD_STATIC_ELEMENT("Target (%d C)", target_temp / 10);
152
     ADD_STATIC_ELEMENT("Heater (%d)", heater_state);
186
     ADD_STATIC_ELEMENT("Heater (%d)", heater_state);
153
     ADD_STATIC_ELEMENT("Eco Amps (%d)", eco_current);
187
     ADD_STATIC_ELEMENT("Eco Amps (%d)", eco_current);
154
     ADD_STATIC_ELEMENT("Eco Volt (%d)", eco_voltage);
188
     ADD_STATIC_ELEMENT("Eco Volt (%d)", eco_voltage);
155
-    ADD_STATIC_ELEMENT("Battery: %d %%", battery);
189
+    ADD_STATIC_ELEMENT("Vibration (%d)", vibration);
190
+    ADD_STATIC_ELEMENT("Brightness (%d)", brightness);
191
+
192
+    ADD_STATIC_ELEMENT("... go back");
156
 
193
 
157
     if (menu->selection < 0) {
194
     if (menu->selection < 0) {
158
         menu->selection = 0;
195
         menu->selection = 0;

+ 1
- 1
src/usb_cdc.c View File

39
 
39
 
40
 static bool reroute_cdc_debug = false;
40
 static bool reroute_cdc_debug = false;
41
 
41
 
42
-void usb_cdc_write(const uint8_t *buf, size_t count) {
42
+void usb_cdc_write(const void *buf, size_t count) {
43
 #ifndef DISABLE_CDC_DTR_CHECK
43
 #ifndef DISABLE_CDC_DTR_CHECK
44
     if (!tud_cdc_connected()) {
44
     if (!tud_cdc_connected()) {
45
         return;
45
         return;

+ 87
- 8
src/venty.c View File

24
 
24
 
25
 #define VENTY_READ_TIMEOUT_MS 500
25
 #define VENTY_READ_TIMEOUT_MS 500
26
 
26
 
27
+enum venty_commands {
28
+    CMD_SETTINGS  = 1,
29
+    CMD_INTERFACE = 6,
30
+};
31
+
27
 enum venty_values {
32
 enum venty_values {
28
     MASK_SET_TEMPERATURE = 1 << 1,
33
     MASK_SET_TEMPERATURE = 1 << 1,
29
     MASK_SET_BOOST       = 1 << 2,
34
     MASK_SET_BOOST       = 1 << 2,
42
     SETTING_BOOST_VISUALIZATION = 1 << 6,
47
     SETTING_BOOST_VISUALIZATION = 1 << 6,
43
 };
48
 };
44
 
49
 
50
+enum venty_interface {
51
+    UI_BRIGHTNESS = 1 << 0,
52
+    UI_VIBRATION  = 1 << 3,
53
+};
54
+
45
 // "00000000-5354-4f52-5a26-4249434b454c"
55
 // "00000000-5354-4f52-5a26-4249434b454c"
46
 static uint8_t uuid_service[16] = {
56
 static uint8_t uuid_service[16] = {
47
     0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x4f, 0x52,
57
     0x00, 0x00, 0x00, 0x00, 0x53, 0x54, 0x4f, 0x52,
100
     uint8_t cmd[20] = {0};
110
     uint8_t cmd[20] = {0};
101
     uint8_t buff[20] = {0};
111
     uint8_t buff[20] = {0};
102
 
112
 
103
-    cmd[0] = 1;
113
+    cmd[0] = CMD_SETTINGS;
104
 
114
 
105
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
115
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
106
     if (r < 0) {
116
     if (r < 0) {
115
     uint8_t cmd[20] = {0};
125
     uint8_t cmd[20] = {0};
116
     uint8_t buff[20] = {0};
126
     uint8_t buff[20] = {0};
117
 
127
 
118
-    cmd[0] = 1;
128
+    cmd[0] = CMD_SETTINGS;
119
     cmd[1] = MASK_SET_TEMPERATURE;
129
     cmd[1] = MASK_SET_TEMPERATURE;
120
     uint16_t *val = (uint16_t *)(cmd + 4);
130
     uint16_t *val = (uint16_t *)(cmd + 4);
121
     *val = value;
131
     *val = value;
124
     return r;
134
     return r;
125
 }
135
 }
126
 
136
 
137
+int8_t venty_get_heater_state(void) {
138
+    uint8_t cmd[20] = {0};
139
+    uint8_t buff[20] = {0};
140
+
141
+    cmd[0] = CMD_SETTINGS;
142
+
143
+    int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
144
+    if (r < 0) {
145
+        return r;
146
+    }
147
+
148
+    int8_t *val = (int8_t *)(buff + 11);
149
+    return *val;
150
+}
151
+
127
 int8_t venty_set_heater_state(bool value) {
152
 int8_t venty_set_heater_state(bool value) {
128
     uint8_t cmd[20] = {0};
153
     uint8_t cmd[20] = {0};
129
     uint8_t buff[20] = {0};
154
     uint8_t buff[20] = {0};
130
 
155
 
131
-    cmd[0] = 1;
156
+    cmd[0] = CMD_SETTINGS;
132
     cmd[1] = MASK_HEATER;
157
     cmd[1] = MASK_HEATER;
133
     cmd[11] = value ? 1 : 0;
158
     cmd[11] = value ? 1 : 0;
134
 
159
 
140
     uint8_t cmd[20] = {0};
165
     uint8_t cmd[20] = {0};
141
     uint8_t buff[20] = {0};
166
     uint8_t buff[20] = {0};
142
 
167
 
143
-    cmd[0] = 1;
168
+    cmd[0] = CMD_SETTINGS;
144
 
169
 
145
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
170
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
146
     if (r < 0) {
171
     if (r < 0) {
155
     uint8_t cmd[20] = {0};
180
     uint8_t cmd[20] = {0};
156
     uint8_t buff[20] = {0};
181
     uint8_t buff[20] = {0};
157
 
182
 
158
-    cmd[0] = 1;
183
+    cmd[0] = CMD_SETTINGS;
159
 
184
 
160
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
185
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
161
     if (r < 0) {
186
     if (r < 0) {
171
     uint8_t cmd[20] = {0};
196
     uint8_t cmd[20] = {0};
172
     uint8_t buff[20] = {0};
197
     uint8_t buff[20] = {0};
173
 
198
 
174
-    cmd[0] = 1;
199
+    cmd[0] = CMD_SETTINGS;
175
 
200
 
176
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
201
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
177
     if (r < 0) {
202
     if (r < 0) {
186
     uint8_t cmd[20] = {0};
211
     uint8_t cmd[20] = {0};
187
     uint8_t buff[20] = {0};
212
     uint8_t buff[20] = {0};
188
 
213
 
189
-    cmd[0] = 1;
214
+    cmd[0] = CMD_SETTINGS;
190
     cmd[1] = MASK_SETTINGS;
215
     cmd[1] = MASK_SETTINGS;
191
     cmd[14] = value ? SETTING_ECOMODE_CHARGE : 0;
216
     cmd[14] = value ? SETTING_ECOMODE_CHARGE : 0;
192
     cmd[15] = SETTING_ECOMODE_CHARGE;
217
     cmd[15] = SETTING_ECOMODE_CHARGE;
199
     uint8_t cmd[20] = {0};
224
     uint8_t cmd[20] = {0};
200
     uint8_t buff[20] = {0};
225
     uint8_t buff[20] = {0};
201
 
226
 
202
-    cmd[0] = 1;
227
+    cmd[0] = CMD_SETTINGS;
203
     cmd[1] = MASK_SETTINGS;
228
     cmd[1] = MASK_SETTINGS;
204
     cmd[14] = value ? SETTING_ECOMODE_VOLTAGE : 0;
229
     cmd[14] = value ? SETTING_ECOMODE_VOLTAGE : 0;
205
     cmd[15] = SETTING_ECOMODE_VOLTAGE;
230
     cmd[15] = SETTING_ECOMODE_VOLTAGE;
207
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
232
     int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
208
     return r;
233
     return r;
209
 }
234
 }
235
+
236
+int8_t venty_get_vibration(void) {
237
+    uint8_t cmd[6] = {0};
238
+    uint8_t buff[6] = {0};
239
+
240
+    cmd[0] = CMD_INTERFACE;
241
+
242
+    int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
243
+    if (r < 0) {
244
+        return r;
245
+    }
246
+
247
+    int8_t *val = (int8_t *)(buff + 5);
248
+    return *val;
249
+}
250
+
251
+int8_t venty_get_brightness(void) {
252
+    uint8_t cmd[6] = {0};
253
+    uint8_t buff[6] = {0};
254
+
255
+    cmd[0] = CMD_INTERFACE;
256
+
257
+    int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
258
+    if (r < 0) {
259
+        return r;
260
+    }
261
+
262
+    int8_t *val = (int8_t *)(buff + 2);
263
+    return *val;
264
+}
265
+
266
+int8_t venty_set_vibration(bool value) {
267
+    uint8_t cmd[6] = {0};
268
+    uint8_t buff[6] = {0};
269
+
270
+    cmd[0] = CMD_INTERFACE;
271
+    cmd[1] = UI_VIBRATION;
272
+    cmd[5] = value ? 1 : 0;
273
+
274
+    int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
275
+    return r;
276
+}
277
+
278
+int8_t venty_set_brightness(uint8_t value) {
279
+    uint8_t cmd[6] = {0};
280
+    uint8_t buff[6] = {0};
281
+
282
+    cmd[0] = CMD_INTERFACE;
283
+    cmd[1] = UI_BRIGHTNESS;
284
+    cmd[2] = MIN(MAX(value, 1), 9);
285
+
286
+    int8_t r = venty_cmd(buff, sizeof(buff), cmd, sizeof(cmd));
287
+    return r;
288
+}

+ 1
- 3
src/wifi.c View File

1
 /*
1
 /*
2
  * wifi.c
2
  * wifi.c
3
  *
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)
4
  * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
7
  *
5
  *
8
  * This program is free software: you can redistribute it and/or modify
6
  * This program is free software: you can redistribute it and/or modify
120
         return "Connecting";
118
         return "Connecting";
121
 
119
 
122
     case WS_READY:
120
     case WS_READY:
123
-        return "Connected";
121
+        return ip4addr_ntoa(netif_ip4_addr(netif_default));
124
     }
122
     }
125
 
123
 
126
     return NULL;
124
     return NULL;

Loading…
Cancel
Save