Skip to content

Commit c33265f

Browse files
feat: add LED activity indication for data transmission
- Blue LED blinks when scanning for devices (not connected) - Solid green LED when connected but idle - Flickering green LED when connected and data is actively flowing - Added data activity tracking to BLE HID notification handler - 20ms LED toggle rate for responsive visual feedback - 100ms activity window for immediate response to data flow changes The LED now provides real-time visual feedback of the bridge connection status and data transmission activity. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 86eca17 commit c33265f

5 files changed

Lines changed: 116 additions & 12 deletions

File tree

app/src/ble_hid.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,15 @@ static uint8_t hogp_notify_cb(struct bt_hogp *hogp,
154154
} else {
155155
k_sem_take(&ep_write_sem, K_FOREVER);
156156
// printk("Report %u sent directly to USB", report_id);
157+
158+
/* Trigger data activity callback for LED indication */
159+
if (data_received_callback) {
160+
data_received_callback(data, size);
161+
}
162+
163+
/* Also directly trigger transport layer data activity */
164+
extern void ble_transport_mark_data_activity(void);
165+
ble_transport_mark_data_activity();
157166
}
158167
}
159168

app/src/ble_transport.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ static bool bridging_started = false;
3333
static bool hid_client_ready = false;
3434
static bool hid_discovery_complete = false;
3535

36+
/* Data activity tracking for LED indication */
37+
static bool data_activity = false;
38+
static int64_t last_data_time = 0;
39+
3640
/* HID Bridge callbacks */
3741
static ble_data_callback_t hid_data_callback = NULL;
3842
static ble_ready_callback_t hid_ready_callback = NULL;
@@ -154,6 +158,7 @@ int ble_transport_send_nus_data(const uint8_t *data, uint16_t len)
154158
LOG_ERR("BLE Transport send failed: %d", err);
155159
} else {
156160
LOG_INF("BLE Transport send successful");
161+
data_activity = true; // Mark data activity for LED indication
157162
}
158163
return err;
159164
}
@@ -189,6 +194,7 @@ int ble_transport_send_hid_data(const uint8_t *data, uint16_t len)
189194
LOG_ERR("BLE Transport HID send failed: %d", err);
190195
} else {
191196
LOG_INF("BLE Transport HID send successful");
197+
data_activity = true; // Mark data activity for LED indication
192198
}
193199
return err;
194200
}
@@ -232,6 +238,11 @@ static void ble_nus_data_received_cb(const uint8_t *data, uint16_t len)
232238
LOG_INF("PACKET STRUCTURE: Type=0x%02x, Length=%d", data[0], len);
233239
}
234240

241+
// Mark data activity for LED indication
242+
data_activity = true;
243+
last_data_time = k_uptime_get();
244+
LOG_INF("=== DATA ACTIVITY MARKED ===");
245+
235246
// Bridge NUS data directly to USB CDC
236247
if (usb_cdc_send_callback) {
237248
usb_cdc_send_callback(data, len);
@@ -289,6 +300,11 @@ static void ble_hid_data_received_cb(const uint8_t *data, uint16_t len)
289300
LOG_INF("HID PACKET STRUCTURE: Type=0x%02x, Length=%d", data[0], len);
290301
}
291302

303+
// Mark data activity for LED indication
304+
data_activity = true;
305+
last_data_time = k_uptime_get();
306+
LOG_INF("=== DATA ACTIVITY MARKED ===");
307+
292308
// Bridge HID data directly to USB HID
293309
if (hid_data_callback) {
294310
LOG_INF("Calling USB HID callback with %d bytes", len);
@@ -373,3 +389,32 @@ static void ble_central_disconnected_cb(struct bt_conn *conn, uint8_t reason)
373389

374390
LOG_INF("BLE Central disconnected - resetting both NUS and HID bridge states");
375391
}
392+
393+
bool ble_transport_is_connected(void)
394+
{
395+
return nus_client_ready || hid_client_ready;
396+
}
397+
398+
bool ble_transport_has_data_activity(void)
399+
{
400+
// Check if we've had data activity within the last 100ms
401+
int64_t current_time = k_uptime_get();
402+
if (data_activity && (current_time - last_data_time) < 100) {
403+
LOG_DBG("BLE data activity detected (time diff: %lld ms)", current_time - last_data_time);
404+
return true;
405+
}
406+
407+
// Reset if it's been too long
408+
if ((current_time - last_data_time) >= 100) {
409+
data_activity = false;
410+
}
411+
412+
return false;
413+
}
414+
415+
void ble_transport_mark_data_activity(void)
416+
{
417+
data_activity = true;
418+
last_data_time = k_uptime_get();
419+
LOG_INF("=== DATA ACTIVITY MARKED (DIRECT) ===");
420+
}

app/src/ble_transport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ int ble_transport_register_usb_hid_callback(ble_data_callback_t cb);
3030
int ble_transport_send_nus_data(const uint8_t *data, uint16_t len);
3131
bool ble_transport_is_nus_ready(void);
3232

33+
/* Connection status */
34+
bool ble_transport_is_connected(void);
35+
bool ble_transport_has_data_activity(void);
36+
3337
/* Future HID Transport functions (for later integration) */
3438
int ble_transport_register_hid_data_callback(ble_data_callback_t cb);
3539
int ble_transport_register_hid_ready_callback(ble_ready_callback_t cb);

app/src/main.c

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,22 @@ int main(void)
8888

8989
LOG_INF("Starting USB ↔ BLE bridge (NUS + HID)");
9090

91-
// LED for status indication
92-
const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
91+
// LED status indication system
92+
const struct gpio_dt_spec led_blue = GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios); // Blue LED
93+
const struct gpio_dt_spec led_green = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); // Green LED
9394
static int led_counter = 0;
95+
static bool data_activity = false;
96+
97+
// Configure LEDs
98+
if (!gpio_is_ready_dt(&led_blue) || !gpio_is_ready_dt(&led_green)) {
99+
LOG_ERR("LED devices not ready");
100+
} else {
101+
gpio_pin_configure_dt(&led_blue, GPIO_OUTPUT);
102+
gpio_pin_configure_dt(&led_green, GPIO_OUTPUT);
103+
// Start with blue LED on (scanning state)
104+
gpio_pin_set_dt(&led_blue, 1);
105+
gpio_pin_set_dt(&led_green, 0);
106+
}
94107

95108
for (;;) {
96109
/* USB CDC ↔ BLE NUS Bridge */
@@ -105,6 +118,7 @@ int main(void)
105118
if (bytes_read > 0) { // Data received from CDC
106119
cdc_buffer[cdc_pos] = c;
107120
cdc_pos++;
121+
data_activity = true; // Mark data activity
108122

109123
// Send complete command when we get newline
110124
if (c == '\n' || c == '\r' || cdc_pos >= UART_BUF_SIZE) {
@@ -125,11 +139,43 @@ int main(void)
125139
}
126140
}
127141

128-
// Toggle LED every 1000 iterations (roughly every second)
142+
// LED status system
129143
led_counter++;
130-
if (led_counter >= 1000) {
131-
(void)gpio_pin_toggle(led0.port, led0.pin);
132-
led_counter = 0;
144+
145+
// Check BLE connection status and data activity
146+
bool is_connected = ble_transport_is_connected();
147+
bool ble_data_activity = ble_transport_has_data_activity();
148+
149+
// Debug logging every second
150+
if (led_counter % 1000 == 0) {
151+
LOG_INF("LED: connected=%d, usb_data=%d, ble_data=%d", is_connected, data_activity, ble_data_activity);
152+
}
153+
154+
if (is_connected && (data_activity || ble_data_activity)) {
155+
// Connected with data activity: Green flicker
156+
if (led_counter % 20 == 0) { // Very fast flicker every 20ms
157+
gpio_pin_toggle_dt(&led_green);
158+
}
159+
// Turn off blue LED
160+
gpio_pin_set_dt(&led_blue, 0);
161+
162+
} else if (is_connected) {
163+
// Connected but no data: Solid green
164+
gpio_pin_set_dt(&led_green, 1);
165+
gpio_pin_set_dt(&led_blue, 0);
166+
167+
} else {
168+
// Not connected: Blue blink (scanning)
169+
gpio_pin_set_dt(&led_green, 0);
170+
if (led_counter >= 500) { // Slow blink every 500ms
171+
gpio_pin_toggle_dt(&led_blue);
172+
led_counter = 0;
173+
}
174+
}
175+
176+
// Reset data activity flag periodically
177+
if (led_counter % 100 == 0) {
178+
data_activity = false;
133179
}
134180

135181
// Small delay to prevent busy waiting

app/src/usb_hid.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ LOG_MODULE_REGISTER(usb_mouse, LOG_LEVEL_INF);
2525
* GLOBAL VARIABLES
2626
* ============================================================================ */
2727

28-
/* LED for status indication */
29-
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
28+
/* LED for status indication (blue LED) */
29+
static const struct gpio_dt_spec led2 = GPIO_DT_SPEC_GET(DT_ALIAS(led2), gpios);
3030

3131
/* USB HID device and semaphore - accessible to BLE module for direct sending */
3232
const struct device *hid_dev;
@@ -153,13 +153,13 @@ int usb_init(void)
153153
/* Initialize USB endpoint semaphore */
154154
k_sem_init(&ep_write_sem, 0, 1);
155155

156-
/* Configure status LED */
157-
if (!gpio_is_ready_dt(&led0)) {
158-
LOG_ERR("LED device %s is not ready", led0.port->name);
156+
/* Configure status blue LED */
157+
if (!gpio_is_ready_dt(&led2)) {
158+
LOG_ERR("LED device %s is not ready", led2.port->name);
159159
return -ENODEV;
160160
}
161161

162-
ret = gpio_pin_configure_dt(&led0, GPIO_OUTPUT);
162+
ret = gpio_pin_configure_dt(&led2, GPIO_OUTPUT);
163163
if (ret < 0) {
164164
LOG_ERR("Failed to configure the LED pin, error: %d", ret);
165165
return ret;

0 commit comments

Comments
 (0)