3 Commits

Author SHA1 Message Date
  Thomas Buck 944f87e56b basic ble notification support 9 months ago
  Thomas Buck 7680476df9 prefetch volcano ble characteristics 9 months ago
  Thomas Buck 11483f370b only auto connect when device is visible within 10s of boot 9 months ago
15 changed files with 320 additions and 45 deletions
  1. 9
    0
      README.md
  2. 8
    1
      include/ble.h
  3. 1
    0
      include/config.h
  4. 3
    0
      include/lcd.h
  5. 3
    0
      include/volcano.h
  6. 221
    15
      src/ble.c
  7. 2
    1
      src/buttons.c
  8. 8
    0
      src/console.c
  9. 2
    2
      src/lcd.c
  10. 0
    7
      src/mem.c
  11. 2
    2
      src/state_crafty.c
  12. 9
    2
      src/state_scan.c
  13. 9
    10
      src/text.c
  14. 37
    0
      src/volcano.c
  15. 6
    5
      src/workflow.c

+ 9
- 0
README.md View File

1
 # Pi Pico Volcano Remote Control Gadget
1
 # Pi Pico Volcano Remote Control Gadget
2
 
2
 
3
+Supports:
4
+
5
+ * workflows for the Volcano Hybrid
6
+ * basic status and settings for Crafty+
7
+
3
 For use with Raspberry Pi Pico W boards with the [Waveshare Pico LCD 1.3](https://www.waveshare.com/wiki/Pico-LCD-1.3) and the [Pimoroni Pico Lipo Shim](https://shop.pimoroni.com/products/pico-lipo-shim).
8
 For use with Raspberry Pi Pico W boards with the [Waveshare Pico LCD 1.3](https://www.waveshare.com/wiki/Pico-LCD-1.3) and the [Pimoroni Pico Lipo Shim](https://shop.pimoroni.com/products/pico-lipo-shim).
4
 
9
 
5
 Adapted from the [tinyusb-cdc-example](https://github.com/hathach/tinyusb/blob/master/examples/device/cdc_msc/src/main.c), [adc example](https://github.com/raspberrypi/pico-examples/tree/master/adc/read_vsys), [standalone client example](https://github.com/raspberrypi/pico-examples/blob/master/pico_w/bt/standalone/client.c) and my [Trackball firmware](https://git.xythobuz.de/thomas/Trackball).
10
 Adapted from the [tinyusb-cdc-example](https://github.com/hathach/tinyusb/blob/master/examples/device/cdc_msc/src/main.c), [adc example](https://github.com/raspberrypi/pico-examples/tree/master/adc/read_vsys), [standalone client example](https://github.com/raspberrypi/pico-examples/blob/master/pico_w/bt/standalone/client.c) and my [Trackball firmware](https://git.xythobuz.de/thomas/Trackball).
6
 
11
 
12
+`python-test` contains a similar app to the C version in the top level of the repo, but instead written for MicroPython on the Pico W.
13
+Unfortunately I had many performance and space problems with this, so I decided to rewrite it.
14
+`web-app` contains a script to conveniently fetch the original web app JS sources, for "reverse engineering".
15
+
7
 ## Quick Start
16
 ## Quick Start
8
 
17
 
9
 When compiling for the first time, check out the required git submodules.
18
 When compiling for the first time, check out the required git submodules.

+ 8
- 1
include/ble.h View File

54
 bool ble_is_connected(void);
54
 bool ble_is_connected(void);
55
 void ble_disconnect(void);
55
 void ble_disconnect(void);
56
 
56
 
57
+int8_t ble_discover(const uint8_t *service, const uint8_t *characteristic);
58
+
57
 int32_t ble_read(const uint8_t *characteristic, uint8_t *buff, uint16_t buff_len);
59
 int32_t ble_read(const uint8_t *characteristic, uint8_t *buff, uint16_t buff_len);
58
 int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
60
 int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
59
-                 uint8_t *buff, uint16_t buff_len);
61
+                 const uint8_t *buff, uint16_t buff_len);
62
+
63
+int8_t ble_notification_disable(const uint8_t *service, const uint8_t *characteristic);
64
+int8_t ble_notification_enable(const uint8_t *service, const uint8_t *characteristic);
65
+bool ble_notification_ready(void);
66
+uint16_t ble_notification_get(uint8_t *buff, uint16_t buff_len);
60
 
67
 
61
 #endif // __BLE_H__
68
 #endif // __BLE_H__

+ 1
- 0
include/config.h View File

31
 
31
 
32
 #ifdef MENU_PREFER_VOLCANO
32
 #ifdef MENU_PREFER_VOLCANO
33
 #define VOLCANO_AUTO_CONNECT_TIMEOUT_MS 2000
33
 #define VOLCANO_AUTO_CONNECT_TIMEOUT_MS 2000
34
+#define VOLCANO_AUTO_CONNECT_WITHIN_MS 10000
34
 #endif // MENU_PREFER_VOLCANO
35
 #endif // MENU_PREFER_VOLCANO
35
 
36
 
36
 #endif // NDEBUG
37
 #endif // NDEBUG

+ 3
- 0
include/lcd.h View File

21
 
21
 
22
 #include <stdint.h>
22
 #include <stdint.h>
23
 
23
 
24
+#define LCD_WIDTH 240
25
+#define LCD_HEIGHT 240
26
+
24
 #define RGB_565(r, g, b) ( \
27
 #define RGB_565(r, g, b) ( \
25
       (((r) >> 3) << 11)   \
28
       (((r) >> 3) << 11)   \
26
     | (((g) >> 2) << 5)    \
29
     | (((g) >> 2) << 5)    \

+ 3
- 0
include/volcano.h View File

22
 #include <stdint.h>
22
 #include <stdint.h>
23
 #include <stdbool.h>
23
 #include <stdbool.h>
24
 
24
 
25
+// returns < 0 on error
26
+int8_t volcano_discover_characteristics(void);
27
+
25
 // in 1/10th degrees C, or < 0 on error
28
 // in 1/10th degrees C, or < 0 on error
26
 int16_t volcano_get_current_temp(void);
29
 int16_t volcano_get_current_temp(void);
27
 int16_t volcano_get_target_temp(void);
30
 int16_t volcano_get_target_temp(void);

+ 221
- 15
src/ble.c View File

28
 #include "util.h"
28
 #include "util.h"
29
 #include "ble.h"
29
 #include "ble.h"
30
 
30
 
31
-#define BLE_READ_TIMEOUT_MS (2 * 500)
32
-#define BLE_SRVC_TIMEOUT_MS (2 * 500)
33
-#define BLE_CHAR_TIMEOUT_MS (2 * 2000)
34
-#define BLE_WRTE_TIMEOUT_MS (2 * 500)
31
+#define BLE_READ_TIMEOUT_MS (3 * 500)
32
+#define BLE_SRVC_TIMEOUT_MS (3 * 500)
33
+#define BLE_CHAR_TIMEOUT_MS (3 * 2000)
34
+#define BLE_WRTE_TIMEOUT_MS (3 * 500)
35
+#define BLE_NOTY_TIMEOUT_MS (3 * 500)
35
 #define BLE_MAX_SCAN_AGE_MS (10 * 1000)
36
 #define BLE_MAX_SCAN_AGE_MS (10 * 1000)
36
 #define BLE_MAX_SERVICES 8
37
 #define BLE_MAX_SERVICES 8
37
 #define BLE_MAX_CHARACTERISTICS 8
38
 #define BLE_MAX_CHARACTERISTICS 8
48
     TC_W4_CHARACTERISTIC,
49
     TC_W4_CHARACTERISTIC,
49
     TC_W4_WRITE,
50
     TC_W4_WRITE,
50
     TC_WRITE_COMPLETE,
51
     TC_WRITE_COMPLETE,
52
+    TC_W4_NOTIFY_ENABLE,
53
+    TC_NOTIFY_ENABLED,
51
 };
54
 };
52
 
55
 
53
 struct ble_characteristic {
56
 struct ble_characteristic {
54
     bool set;
57
     bool set;
55
     gatt_client_characteristic_t c;
58
     gatt_client_characteristic_t c;
59
+    gatt_client_notification_t n;
56
 };
60
 };
57
 
61
 
58
 struct ble_service {
62
 struct ble_service {
319
             state = TC_WRITE_COMPLETE;
323
             state = TC_WRITE_COMPLETE;
320
             break;
324
             break;
321
 
325
 
326
+        case TC_W4_NOTIFY_ENABLE:
327
+            //debug("notify enable complete");
328
+            state = TC_NOTIFY_ENABLED;
329
+            break;
330
+
322
         default:
331
         default:
323
             debug("gatt query complete in invalid state %d", state);
332
             debug("gatt query complete in invalid state %d", state);
324
             break;
333
             break;
326
         break;
335
         break;
327
     }
336
     }
328
 
337
 
338
+    case GATT_EVENT_NOTIFICATION: {
339
+        if ((state != TC_READY) && (state != TC_WRITE_COMPLETE)) {
340
+            debug("gatt notification in invalid state %d", state);
341
+            return;
342
+        }
343
+
344
+        uint16_t value_length = gatt_event_notification_get_value_length(packet);
345
+        const uint8_t *value = gatt_event_notification_get_value(packet);
346
+        if ((read_len + value_length) <= BLE_MAX_VALUE_LEN) {
347
+            memcpy(data_buff + read_len, value, value_length);
348
+            read_len += value_length;
349
+        }
350
+
351
+        break;
352
+    }
353
+
329
     default:
354
     default:
330
         //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
355
         //debug("unexpected event 0x%02X", hci_event_packet_get_type(packet));
331
         break;
356
         break;
572
 
597
 
573
     memcpy(buff, data_buff, read_len);
598
     memcpy(buff, data_buff, read_len);
574
 
599
 
600
+    uint16_t tmp = read_len;
601
+    read_len = 0;
602
+
575
     cyw43_thread_exit();
603
     cyw43_thread_exit();
576
-    return read_len;
604
+    return tmp;
577
 }
605
 }
578
 
606
 
579
-int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
580
-                  uint8_t *buff, uint16_t buff_len) {
581
-    cyw43_thread_enter();
582
-
583
-    if (state != TC_READY) {
584
-        cyw43_thread_exit();
585
-        debug("invalid state for write (%d)", state);
586
-        return -1;
587
-    }
588
-
607
+static int discover_service(const uint8_t *service) {
589
     // check if service has already been discovered
608
     // check if service has already been discovered
590
     int srvc = -1, free_srvc = -1;
609
     int srvc = -1, free_srvc = -1;
591
     for (int i = 0; i < BLE_MAX_SERVICES; i++) {
610
     for (int i = 0; i < BLE_MAX_SERVICES; i++) {
652
         cyw43_thread_enter();
671
         cyw43_thread_enter();
653
     }
672
     }
654
 
673
 
674
+    return srvc;
675
+}
676
+
677
+static int discover_characteristic(int srvc, const uint8_t *characteristic) {
655
     // check if characteristic has already been discovered
678
     // check if characteristic has already been discovered
656
     int ch = -1, free_ch = -1;
679
     int ch = -1, free_ch = -1;
657
     for (int i = 0; i < BLE_MAX_CHARACTERISTICS; i++) {
680
     for (int i = 0; i < BLE_MAX_CHARACTERISTICS; i++) {
719
         cyw43_thread_enter();
742
         cyw43_thread_enter();
720
     }
743
     }
721
 
744
 
745
+    return ch;
746
+}
747
+
748
+int8_t ble_write(const uint8_t *service, const uint8_t *characteristic,
749
+                 const uint8_t *buff, uint16_t buff_len) {
750
+    cyw43_thread_enter();
751
+
752
+    if (state != TC_READY) {
753
+        cyw43_thread_exit();
754
+        debug("invalid state for write (%d)", state);
755
+        return -1;
756
+    }
757
+
758
+    int srvc = discover_service(service);
759
+    if (srvc < 0) {
760
+        debug("error discovering service (%d)", srvc);
761
+        return srvc;
762
+    }
763
+
764
+    int ch = discover_characteristic(srvc, characteristic);
765
+    if (ch < 0) {
766
+        debug("error discovering characteristic (%d)", ch);
767
+        return ch;
768
+    }
769
+
722
     if (buff_len > BLE_MAX_VALUE_LEN) {
770
     if (buff_len > BLE_MAX_VALUE_LEN) {
723
         buff_len = BLE_MAX_VALUE_LEN;
771
         buff_len = BLE_MAX_VALUE_LEN;
724
     }
772
     }
768
     cyw43_thread_exit();
816
     cyw43_thread_exit();
769
     return ret;
817
     return ret;
770
 }
818
 }
819
+
820
+int8_t ble_discover(const uint8_t *service, const uint8_t *characteristic) {
821
+    cyw43_thread_enter();
822
+
823
+    if (state != TC_READY) {
824
+        cyw43_thread_exit();
825
+        debug("invalid state for discovery (%d)", state);
826
+        return -1;
827
+    }
828
+
829
+    int srvc = discover_service(service);
830
+    if (srvc < 0) {
831
+        debug("error discovering service (%d)", srvc);
832
+        return srvc;
833
+    }
834
+
835
+    int ch = discover_characteristic(srvc, characteristic);
836
+    if (ch < 0) {
837
+        debug("error discovering characteristic (%d)", ch);
838
+        return ch;
839
+    }
840
+
841
+    cyw43_thread_exit();
842
+    return 0;
843
+}
844
+
845
+int8_t ble_notification_disable(const uint8_t *service, const uint8_t *characteristic) {
846
+    cyw43_thread_enter();
847
+
848
+    if (state != TC_READY) {
849
+        cyw43_thread_exit();
850
+        debug("invalid state for notify (%d)", state);
851
+        return -1;
852
+    }
853
+
854
+    int srvc = discover_service(service);
855
+    if (srvc < 0) {
856
+        debug("error discovering service (%d)", srvc);
857
+        return srvc;
858
+    }
859
+
860
+    int ch = discover_characteristic(srvc, characteristic);
861
+    if (ch < 0) {
862
+        debug("error discovering characteristic (%d)", ch);
863
+        return ch;
864
+    }
865
+
866
+    gatt_client_stop_listening_for_characteristic_value_updates(&services[srvc].chars[ch].n);
867
+
868
+    cyw43_thread_exit();
869
+    return 0;
870
+}
871
+
872
+int8_t ble_notification_enable(const uint8_t *service, const uint8_t *characteristic) {
873
+    cyw43_thread_enter();
874
+
875
+    if (state != TC_READY) {
876
+        cyw43_thread_exit();
877
+        debug("invalid state for notify (%d)", state);
878
+        return -1;
879
+    }
880
+
881
+    int srvc = discover_service(service);
882
+    if (srvc < 0) {
883
+        debug("error discovering service (%d)", srvc);
884
+        return srvc;
885
+    }
886
+
887
+    int ch = discover_characteristic(srvc, characteristic);
888
+    if (ch < 0) {
889
+        debug("error discovering characteristic (%d)", ch);
890
+        return ch;
891
+    }
892
+
893
+    gatt_client_listen_for_characteristic_value_updates(&services[srvc].chars[ch].n,
894
+                                                        hci_event_handler,
895
+                                                        connection_handle,
896
+                                                        &services[srvc].chars[ch].c);
897
+
898
+    gatt_client_write_client_characteristic_configuration(hci_event_handler,
899
+                                                          connection_handle,
900
+                                                          &services[srvc].chars[ch].c,
901
+                                                          GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION);
902
+
903
+    state = TC_W4_NOTIFY_ENABLE;
904
+    cyw43_thread_exit();
905
+
906
+    uint32_t start_time = to_ms_since_boot(get_absolute_time());
907
+    while (1) {
908
+        sleep_ms(1);
909
+        main_loop_hw();
910
+
911
+        uint32_t now = to_ms_since_boot(get_absolute_time());
912
+        if ((now - start_time) >= BLE_NOTY_TIMEOUT_MS) {
913
+            debug("timeout waiting for notify enable");
914
+            cyw43_thread_enter();
915
+            state = TC_READY;
916
+            cyw43_thread_exit();
917
+            return -6;
918
+        }
919
+
920
+        cyw43_thread_enter();
921
+        enum ble_state state_cached = state;
922
+        cyw43_thread_exit();
923
+
924
+        if ((state_cached == TC_NOTIFY_ENABLED) || (state_cached == TC_READY)) {
925
+            break;
926
+        }
927
+    }
928
+
929
+    cyw43_thread_enter();
930
+
931
+    int8_t ret = (state == TC_NOTIFY_ENABLED) ? 0 : -7;
932
+    state = TC_READY;
933
+
934
+    cyw43_thread_exit();
935
+    return ret;
936
+}
937
+
938
+bool ble_notification_ready(void) {
939
+    cyw43_thread_enter();
940
+
941
+    if (state != TC_READY) {
942
+        cyw43_thread_exit();
943
+        debug("invalid state for notify (%d)", state);
944
+        return -1;
945
+    }
946
+
947
+    uint16_t tmp = read_len;
948
+
949
+    cyw43_thread_exit();
950
+    return (tmp > 0);
951
+
952
+}
953
+
954
+uint16_t ble_notification_get(uint8_t *buff, uint16_t buff_len) {
955
+    cyw43_thread_enter();
956
+
957
+    if (state != TC_READY) {
958
+        cyw43_thread_exit();
959
+        debug("invalid state for notify (%d)", state);
960
+        return -1;
961
+    }
962
+
963
+    if (read_len > buff_len) {
964
+        debug("buffer too short (%d < %d)", buff_len, read_len);
965
+        cyw43_thread_exit();
966
+        return -2;
967
+    }
968
+
969
+    memcpy(buff, data_buff, read_len);
970
+
971
+    uint16_t tmp = read_len;
972
+    read_len = 0;
973
+
974
+    cyw43_thread_exit();
975
+    return tmp;
976
+}

+ 2
- 1
src/buttons.c View File

69
 
69
 
70
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
70
         if ((now - buttons[i].last_time) > DEBOUNCE_DELAY_MS) {
71
             if (state != buttons[i].current_state) {
71
             if (state != buttons[i].current_state) {
72
+                //debug("btn %d now %s", i, state ? "pressed" : "released");
73
+
72
                 buttons[i].current_state = state;
74
                 buttons[i].current_state = state;
73
-                debug("btn %d now %s", i, state ? "pressed" : "released");
74
                 if (callback) {
75
                 if (callback) {
75
                     callback(i, state);
76
                     callback(i, state);
76
                 }
77
                 }

+ 8
- 0
src/console.c View File

171
                         bd_addr_to_str(results[i].addr),
171
                         bd_addr_to_str(results[i].addr),
172
                         results[i].type, results[i].rssi,
172
                         results[i].type, results[i].rssi,
173
                         age / 1000.0, results[i].name, info);
173
                         age / 1000.0, results[i].name, info);
174
+
175
+                if (results[i].data_len > 0) {
176
+                    hexdump(results[i].data, results[i].data_len);
177
+                }
178
+
179
+                if (i < (n - 1)) {
180
+                    println();
181
+                }
174
             }
182
             }
175
         }
183
         }
176
     } else if (str_startswith(line, "con ")) {
184
     } else if (str_startswith(line, "con ")) {

+ 2
- 2
src/lcd.c View File

34
 #define LCD_PIN_RST 12
34
 #define LCD_PIN_RST 12
35
 #define LCD_PIN_BL 13
35
 #define LCD_PIN_BL 13
36
 
36
 
37
-#define ST7789_PICO_COLUMN                             240
38
-#define ST7789_PICO_ROW                                ST7789_PICO_COLUMN
37
+#define ST7789_PICO_COLUMN                             LCD_HEIGHT
38
+#define ST7789_PICO_ROW                                LCD_WIDTH
39
 
39
 
40
 #define ST7789_PICO_ACCESS                            (ST7789_ORDER_PAGE_TOP_TO_BOTTOM | \
40
 #define ST7789_PICO_ACCESS                            (ST7789_ORDER_PAGE_TOP_TO_BOTTOM | \
41
                                                        ST7789_ORDER_COLUMN_LEFT_TO_RIGHT | \
41
                                                        ST7789_ORDER_COLUMN_LEFT_TO_RIGHT | \

+ 0
- 7
src/mem.c View File

79
 
79
 
80
 void mem_load_defaults(void) {
80
 void mem_load_defaults(void) {
81
     data_ram.data.wf_count = wf_default_count;
81
     data_ram.data.wf_count = wf_default_count;
82
-    debug("preparing %d default workflows", data_ram.data.wf_count);
83
     for (uint16_t i = 0; i < wf_default_count; i++) {
82
     for (uint16_t i = 0; i < wf_default_count; i++) {
84
         data_ram.data.wf[i] = wf_default_data[i];
83
         data_ram.data.wf[i] = wf_default_data[i];
85
-        debug("\"%s\" by \"%s\"", data_ram.data.wf[i].name, data_ram.data.wf[i].author);
86
     }
84
     }
87
 }
85
 }
88
 
86
 
108
     } else {
106
     } else {
109
         debug("invalid config (0x%02X != 0x%02X)", flash_ptr->version, MEM_VERSION);
107
         debug("invalid config (0x%02X != 0x%02X)", flash_ptr->version, MEM_VERSION);
110
     }
108
     }
111
-
112
-    debug("found %d workflows", data_ram.data.wf_count);
113
-    for (uint16_t i = 0; i < data_ram.data.wf_count; i++) {
114
-        debug("\"%s\" by \"%s\"", data_ram.data.wf[i].name, data_ram.data.wf[i].author);
115
-    }
116
 }
109
 }
117
 
110
 
118
 static void mem_write_flash(void *param) {
111
 static void mem_write_flash(void *param) {

+ 2
- 2
src/state_crafty.c View File

28
 
28
 
29
 #include "menu.h"
29
 #include "menu.h"
30
 
30
 
31
-#define CRAFTY_UPDATE_TIME_MS 1000
31
+#define CRAFTY_UPDATE_TIME_MS 3000
32
 
32
 
33
 static bd_addr_t ble_addr = {0};
33
 static bd_addr_t ble_addr = {0};
34
 static bd_addr_type_t ble_type = 0;
34
 static bd_addr_type_t ble_type = 0;
115
     static uint32_t last = 0;
115
     static uint32_t last = 0;
116
     uint32_t now = to_ms_since_boot(get_absolute_time());
116
     uint32_t now = to_ms_since_boot(get_absolute_time());
117
     if (((now - last) >= CRAFTY_UPDATE_TIME_MS) || (last == 0)) {
117
     if (((now - last) >= CRAFTY_UPDATE_TIME_MS) || (last == 0)) {
118
-        last = now;
119
         menu_run(draw, true);
118
         menu_run(draw, true);
119
+        last = to_ms_since_boot(get_absolute_time());
120
     }
120
     }
121
 
121
 
122
     if (wait_for_disconnect && !ble_is_connected()) {
122
     if (wait_for_disconnect && !ble_is_connected()) {

+ 9
- 2
src/state_scan.c View File

100
 #ifdef MENU_PREFER_VOLCANO
100
 #ifdef MENU_PREFER_VOLCANO
101
             if (dev == DEV_VOLCANO) {
101
             if (dev == DEV_VOLCANO) {
102
                 menu->selection = devs - 1;
102
                 menu->selection = devs - 1;
103
+
103
 #ifdef VOLCANO_AUTO_CONNECT_TIMEOUT_MS
104
 #ifdef VOLCANO_AUTO_CONNECT_TIMEOUT_MS
104
-                auto_connect_time = to_ms_since_boot(get_absolute_time());
105
-                auto_connect_idx = i;
105
+#ifdef VOLCANO_AUTO_CONNECT_WITHIN_MS
106
+                if (to_ms_since_boot(get_absolute_time()) <= VOLCANO_AUTO_CONNECT_WITHIN_MS) {
107
+#endif // VOLCANO_AUTO_CONNECT_WITHIN_MS
108
+                    auto_connect_time = to_ms_since_boot(get_absolute_time());
109
+                    auto_connect_idx = i;
110
+#ifdef VOLCANO_AUTO_CONNECT_WITHIN_MS
111
+                }
112
+#endif // VOLCANO_AUTO_CONNECT_WITHIN_MS
106
 #endif // VOLCANO_AUTO_CONNECT_TIMEOUT_MS
113
 #endif // VOLCANO_AUTO_CONNECT_TIMEOUT_MS
107
             }
114
             }
108
 #endif // MENU_PREFER_VOLCANO
115
 #endif // MENU_PREFER_VOLCANO

+ 9
- 10
src/text.c View File

166
         text_prepare_font(&font);
166
         text_prepare_font(&font);
167
     }
167
     }
168
 
168
 
169
-    int x = 0;
170
-    int width = 240;
169
+    int x_off = 0;
170
+    int width = LCD_WIDTH;
171
 
171
 
172
-    int y = 50;
173
-    int height = MENU_MAX_LINES * (20 + 2);
172
+    int y_off = 50;
173
+    int height = (MENU_MAX_LINES * 20) + ((MENU_MAX_LINES - 1) * 2);
174
 
174
 
175
     struct text_conf text = {
175
     struct text_conf text = {
176
         .text = "",
176
         .text = "",
177
-        .x = x,
178
-        .y = y,
177
+        .x = x_off,
178
+        .y = y_off,
179
         .justify = false,
179
         .justify = false,
180
         .alignment = centered ? MF_ALIGN_CENTER : MF_ALIGN_LEFT,
180
         .alignment = centered ? MF_ALIGN_CENTER : MF_ALIGN_LEFT,
181
         .width = width,
181
         .width = width,
186
         .font = &font,
186
         .font = &font,
187
     };
187
     };
188
 
188
 
189
-    lcd_write_rect(x,
190
-                   y,
191
-                   x + width - 1,
192
-                   y + height - 1,
189
+    lcd_write_rect(x_off, y_off,
190
+                   x_off + width - 1,
191
+                   y_off + height - 1,
193
                    RGB_565(0x00, 0x00, 0x00));
192
                    RGB_565(0x00, 0x00, 0x00));
194
 
193
 
195
     text.text = s;
194
     text.text = s;

+ 37
- 0
src/volcano.c View File

40
     0x5a, 0x26, 0x42, 0x49, 0x43, 0x4b, 0x45, 0x4c,
40
     0x5a, 0x26, 0x42, 0x49, 0x43, 0x4b, 0x45, 0x4c,
41
 };
41
 };
42
 
42
 
43
+int8_t volcano_discover_characteristics(void) {
44
+    uuid_base[3] = UUID_WRITE_SRVC;
45
+    int8_t r;
46
+
47
+    uuid_base2[3] = UUID_TARGET_TEMP;
48
+    r = ble_discover(uuid_base, uuid_base2);
49
+    if (r < 0) {
50
+        return r;
51
+    }
52
+
53
+    uuid_base2[3] = UUID_HEATER_ON;
54
+    r = ble_discover(uuid_base, uuid_base2);
55
+    if (r < 0) {
56
+        return r;
57
+    }
58
+
59
+    uuid_base2[3] = UUID_HEATER_OFF;
60
+    r = ble_discover(uuid_base, uuid_base2);
61
+    if (r < 0) {
62
+        return r;
63
+    }
64
+
65
+    uuid_base2[3] = UUID_PUMP_ON;
66
+    r = ble_discover(uuid_base, uuid_base2);
67
+    if (r < 0) {
68
+        return r;
69
+    }
70
+
71
+    uuid_base2[3] = UUID_PUMP_OFF;
72
+    r = ble_discover(uuid_base, uuid_base2);
73
+    if (r < 0) {
74
+        return r;
75
+    }
76
+
77
+    return 0;
78
+}
79
+
43
 int16_t volcano_get_current_temp(void) {
80
 int16_t volcano_get_current_temp(void) {
44
     uuid_base[3] = UUID_CURRENT_TEMP;
81
     uuid_base[3] = UUID_CURRENT_TEMP;
45
 
82
 

+ 6
- 5
src/workflow.c View File

199
     wf_i = index;
199
     wf_i = index;
200
     step = 0;
200
     step = 0;
201
 
201
 
202
-    // discover characteristics
203
-    volcano_set_pump_state(false);
204
-    volcano_set_heater_state(false);
205
-    volcano_set_target_temp(1850);
206
-
202
+    /*
203
+     * first turn on heater, then do discovery, to save some time.
204
+     * this means we heat for some seconds before changing the setpoint.
205
+     * should not be a problem in practice.
206
+     */
207
     volcano_set_heater_state(true);
207
     volcano_set_heater_state(true);
208
+    volcano_discover_characteristics();
208
 
209
 
209
     do_step();
210
     do_step();
210
 }
211
 }

Loading…
Cancel
Save