Skip to content

Commit d1d711f

Browse files
committed
pbio/sys/hmi_pup: Add green light for USB connection.
Makes it easy to see that a host has (automatically) opened a connection. BLE advertising stops automatically.
1 parent aca95a4 commit d1d711f

File tree

4 files changed

+77
-38
lines changed

4 files changed

+77
-38
lines changed

lib/pbio/include/pbio/protocol.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,12 @@ typedef enum {
341341
* @since Pybricks Profile v1.5.0
342342
*/
343343
PBIO_PYBRICKS_STATUS_BATTERY_HIGH_TEMP_WARNING = 11,
344+
/**
345+
* Hub is connected to a host (like Pybricks Code) via USB.
346+
*
347+
* @since Pybricks Profile v1.5.0
348+
*/
349+
PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED = 12,
344350
/** Total number of indications. */
345351
NUM_PBIO_PYBRICKS_STATUS,
346352
} pbio_pybricks_status_flags_t;

lib/pbio/sys/core.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <pbdrv/bluetooth.h>
77
#include <pbdrv/watchdog.h>
8+
#include <pbdrv/usb.h>
89

910
#include <pbio/busy_count.h>
1011
#include <pbio/main.h>
@@ -38,10 +39,13 @@ PROCESS_THREAD(pbsys_system_process, ev, data) {
3839
pbsys_program_stop_poll();
3940
pbsys_status_light_poll();
4041

41-
// Revisit: Use pbio/sys/host callback to indicate connection changes.
42-
if (!pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE)) {
42+
// Revisit: Move to HMI process running parallel to user code.
43+
if (!pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_PYBRICKS)) {
4344
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
4445
}
46+
if (!pbdrv_usb_connection_is_active()) {
47+
pbsys_status_clear(PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED);
48+
}
4549

4650
// keep the hub from resetting itself
4751
pbdrv_watchdog_update();

lib/pbio/sys/hmi_pup.c

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include <pbdrv/bluetooth.h>
1616
#include <pbdrv/led.h>
17+
#include <pbdrv/usb.h>
1718

1819
#include <pbio/button.h>
1920
#include <pbio/busy_count.h>
@@ -133,13 +134,25 @@ void pbsys_hmi_init(void) {
133134
void pbsys_hmi_deinit(void) {
134135
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
135136
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
137+
pbsys_status_clear(PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED);
136138

137139
#if PBIO_CONFIG_LIGHT_MATRIX
138140
pbio_busy_count_up();
139141
pbio_os_process_start(&boot_animation_process, boot_animation_process_boot_thread, (void *)false);
140142
#endif
141143
}
142144

145+
/**
146+
* Tests if the BLE or USB connection has changed.
147+
*
148+
* @return @c true if the system status is different from the driver status. @c false if unchanged.
149+
*/
150+
static bool host_connection_changed(void) {
151+
return
152+
pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_PYBRICKS) != pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED) ||
153+
pbdrv_usb_connection_is_active() != pbsys_status_test(PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED);
154+
}
155+
143156
/**
144157
* The HMI is a loop running the following steps:
145158
*
@@ -168,28 +181,36 @@ static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
168181
light_matrix_show_idle_ui(100);
169182
#endif
170183

171-
// Initialize Bluetooth depending on current state.
172-
if (pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE)) {
173-
DEBUG_PRINT("Connected: yes\n");
184+
// Update USB state.
185+
DEBUG_PRINT("USB Connected: ");
186+
if (pbdrv_usb_connection_is_active()) {
187+
DEBUG_PRINT("Yes.\n");
188+
pbsys_status_set(PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED);
189+
} else {
190+
DEBUG_PRINT("No.\n");
191+
pbsys_status_clear(PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED);
192+
}
193+
194+
// Update BLE state.
195+
DEBUG_PRINT("BLE Connected: ");
196+
if (pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_PYBRICKS)) {
197+
DEBUG_PRINT("Yes.\n");
174198
pbsys_status_set(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
175-
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
176-
// No need to stop advertising since this is automatic.
177199
} else {
178-
// Not connected right now.
179-
DEBUG_PRINT("Connected: No\n");
200+
DEBUG_PRINT("No.\n");
180201
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
202+
}
181203

182-
// Enable or disable advertising depending on user setting.
183-
bool do_advertise = pbsys_storage_settings_bluetooth_enabled_get();
184-
DEBUG_PRINT("Advertising is configured to be: %s. \n", do_advertise ? "on" : "off");
185-
if (do_advertise) {
186-
pbsys_status_set(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
187-
} else {
188-
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
189-
}
190-
pbdrv_bluetooth_start_advertising(do_advertise);
191-
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_await_advertise_or_scan_command(&sub, NULL));
204+
// Advertise if BLE enabled and there is no host connection.
205+
bool advertise = pbsys_storage_settings_bluetooth_enabled_get() && !pbsys_host_is_connected();
206+
DEBUG_PRINT("BLE Advertising: %s. \n", advertise ? "on" : "off");
207+
if (advertise) {
208+
pbsys_status_set(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
209+
} else {
210+
pbsys_status_clear(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING);
192211
}
212+
pbdrv_bluetooth_start_advertising(advertise);
213+
PBIO_OS_AWAIT(state, &sub, pbdrv_bluetooth_await_advertise_or_scan_command(&sub, NULL));
193214

194215
// Buttons could be pressed at the end of the user program, so wait for
195216
// a release and then a new press, or until we have to exit early.
@@ -221,24 +242,24 @@ static pbio_error_t run_ui(pbio_os_state_t *state, pbio_os_timer_t *timer) {
221242
// Wait for button press, external program start, or connection change.
222243
pbdrv_button_get_pressed() ||
223244
pbsys_main_program_start_is_requested() ||
224-
pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE) != pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED);
245+
host_connection_changed();
225246
}));
226247

227248
// Became connected or disconnected, so go back to handle it.
228-
if (pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE) != pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED)) {
249+
if (host_connection_changed()) {
229250
DEBUG_PRINT("Connection changed.\n");
230251
continue;
231252
}
232253

233-
// External progran request takes precedence over buttons.
254+
// External program request takes precedence over buttons.
234255
if (pbsys_main_program_start_is_requested()) {
235256
DEBUG_PRINT("Start program from Pybricks Code.\n");
236257
break;
237258
}
238259

239260
#if PBSYS_CONFIG_HMI_PUP_BLUETOOTH_BUTTON
240-
// Toggle Bluetooth enable setting if Bluetooth button pressed. Only if disconnected.
241-
if ((pbdrv_button_get_pressed() & PBSYS_CONFIG_HMI_PUP_BLUETOOTH_BUTTON) && !pbdrv_bluetooth_is_connected(PBDRV_BLUETOOTH_CONNECTION_LE)) {
261+
// Toggle Bluetooth enable setting if Bluetooth button pressed. Only when disconnected.
262+
if ((pbdrv_button_get_pressed() & PBSYS_CONFIG_HMI_PUP_BLUETOOTH_BUTTON) && !pbsys_host_is_connected()) {
242263
pbsys_storage_settings_bluetooth_enabled_set(!pbsys_storage_settings_bluetooth_enabled_get());
243264
DEBUG_PRINT("Toggling Bluetooth to: %s. \n", pbsys_storage_settings_bluetooth_enabled_get() ? "on" : "off");
244265
continue;

lib/pbio/sys/light.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ typedef enum {
2929
} pbsys_status_light_indication_warning_t;
3030

3131
typedef enum {
32-
PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_NONE,
33-
PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_ADVERTISING,
34-
PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_CONNECTED_IDLE,
35-
} pbsys_status_light_indication_ble_t;
32+
PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_NONE,
33+
PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_ADVERTISING,
34+
PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_CONNECTED,
35+
PBSYS_STATUS_LIGHT_INDICATION_USB_ACTIVE_BLE_ANY,
36+
} pbsys_status_light_indication_usb_ble_t;
3637

3738
/** A single element of a status light indication pattern. */
3839
typedef struct {
@@ -95,12 +96,12 @@ pbsys_status_light_indication_pattern_warning[] = {
9596

9697
static const pbsys_status_light_indication_pattern_element_t *const
9798
pbsys_status_light_indication_pattern_ble[] = {
98-
[PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_NONE] =
99+
[PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_NONE] =
99100
(const pbsys_status_light_indication_pattern_element_t[]) {
100101
PBSYS_STATUS_LIGHT_INDICATION_PATTERN_FOREVER(PBIO_COLOR_NONE),
101102
},
102103
// Two blue blinks, pause, then repeat.
103-
[PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_ADVERTISING] =
104+
[PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_ADVERTISING] =
104105
(const pbsys_status_light_indication_pattern_element_t[]) {
105106
{ .color = PBIO_COLOR_BLUE, .duration = 2 },
106107
{ .color = PBIO_COLOR_BLACK, .duration = 2 },
@@ -109,10 +110,15 @@ pbsys_status_light_indication_pattern_ble[] = {
109110
PBSYS_STATUS_LIGHT_INDICATION_PATTERN_REPEAT
110111
},
111112
// Blue, always on.
112-
[PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_CONNECTED_IDLE] =
113+
[PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_CONNECTED] =
113114
(const pbsys_status_light_indication_pattern_element_t[]) {
114115
PBSYS_STATUS_LIGHT_INDICATION_PATTERN_FOREVER(PBIO_COLOR_BLUE),
115116
},
117+
// Green, always on.
118+
[PBSYS_STATUS_LIGHT_INDICATION_USB_ACTIVE_BLE_ANY] =
119+
(const pbsys_status_light_indication_pattern_element_t[]) {
120+
PBSYS_STATUS_LIGHT_INDICATION_PATTERN_FOREVER(PBIO_COLOR_GREEN),
121+
},
116122
};
117123

118124
typedef struct {
@@ -198,23 +204,25 @@ void pbsys_status_light_handle_status_change(void) {
198204
warning_indication = PBSYS_STATUS_LIGHT_INDICATION_WARNING_LOW_VOLTAGE;
199205
}
200206

201-
// BLE pattern precedence.
202-
pbsys_status_light_indication_ble_t ble_indication = PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_NONE;
203-
if (pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING)) {
204-
ble_indication = PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_ADVERTISING;
207+
// USB/BLE pattern precedence.
208+
pbsys_status_light_indication_usb_ble_t usb_ble_indication = PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_NONE;
209+
if (pbsys_status_test(PBIO_PYBRICKS_STATUS_USB_HOST_CONNECTED)) {
210+
usb_ble_indication = PBSYS_STATUS_LIGHT_INDICATION_USB_ACTIVE_BLE_ANY;
211+
} else if (pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_ADVERTISING)) {
212+
usb_ble_indication = PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_ADVERTISING;
205213
} else if (pbsys_status_test(PBIO_PYBRICKS_STATUS_BLE_HOST_CONNECTED)
206214
#if !PBSYS_CONFIG_STATUS_LIGHT_BLUETOOTH
207215
// Hubs without Bluetooth light show idle state only when program not running.
208216
&& !pbsys_status_test(PBIO_PYBRICKS_STATUS_USER_PROGRAM_RUNNING)
209217
#endif
210218
) {
211-
ble_indication = PBSYS_STATUS_LIGHT_INDICATION_BLUETOOTH_BLE_CONNECTED_IDLE;
219+
usb_ble_indication = PBSYS_STATUS_LIGHT_INDICATION_USB_NONE_BLE_CONNECTED;
212220
}
213221

214222
// If the indication changed, then reset the indication pattern to the
215223
// beginning. Reset both so that patterns with the same length stay in sync.
216-
if (ble_pattern_state->indication != ble_indication || warning_pattern_state->indication != warning_indication) {
217-
ble_pattern_state->indication = ble_indication;
224+
if (ble_pattern_state->indication != usb_ble_indication || warning_pattern_state->indication != warning_indication) {
225+
ble_pattern_state->indication = usb_ble_indication;
218226
ble_pattern_state->pattern_index = ble_pattern_state->pattern_count = 0;
219227

220228
warning_pattern_state->indication = warning_indication;

0 commit comments

Comments
 (0)