Skip to content

Commit 2939dfd

Browse files
committed
Loopback test device: improved LED feedback
1 parent ac4dfb2 commit 2939dfd

File tree

2 files changed

+41
-25
lines changed

2 files changed

+41
-25
lines changed

test-devices/loopback-stm32/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,8 @@ Two alternate interfaces are implemented:
5050

5151
The device can be put into suspend mode by the host. It will go into a low-power mode. This is indicated by the user LED turning off. The power LED will stay on. The device can be woken up by the host.
5252

53-
A MacBook with macOS usually puts the device into suspend mode about 1 minuate after is has gone to sleep if it is not connected to a power supply. The device will wake up when the MacBook is woken up.
53+
To put the device into suspended mode, put the host computer to sleep or supended mode. To wake it up, wake up the host computer.
5454

55-
On Windows and Linux, the device is put to sleep immediately when the computer is put to sleep or suspended.
5655

5756

5857
## Building the firmware

test-devices/loopback-stm32/src/main.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,16 @@ int echo_buffer_len;
3838
int num_echos;
3939

4040

41-
// Blink durations
42-
enum {
43-
BLINK_NOT_MOUNTED = 250,
44-
BLINK_MOUNTED = 1000,
45-
};
41+
static bool is_blinking = true;
42+
static uint32_t led_on_until = 0;
43+
static uint32_t blink_toogle_at = 0;
44+
static bool is_blink_on = true;
4645

47-
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
46+
static inline bool has_expired(uint32_t deadline, uint32_t now) {
47+
return (int32_t)(now - deadline) >= 0;
48+
}
4849

50+
static void led_busy(void);
4951
static void led_blinking_task(void);
5052
static void loopback_init(void);
5153
static void loopback_check_rx(void);
@@ -93,6 +95,7 @@ void loopback_check_tx(void) {
9395
n = max_size;
9496

9597
cust_vendor_start_transmit_fifo(EP_LOOPBACK_TX, &loopback_fifo, n);
98+
led_busy();
9699
}
97100
}
98101

@@ -110,6 +113,7 @@ void loopback_check_rx(void) {
110113
void echo_update_state(void) {
111114
if (num_echos > 0) {
112115
cust_vendor_start_transmit(EP_ECHO_TX, echo_buffer, echo_buffer_len);
116+
led_busy();
113117
} else {
114118
cust_vendor_prepare_recv(EP_ECHO_RX, echo_buffer, sizeof(echo_buffer));
115119
}
@@ -129,6 +133,7 @@ void cust_vendor_rx_cb(uint8_t ep_addr, uint32_t recv_bytes) {
129133
echo_buffer_len = recv_bytes;
130134
echo_update_state();
131135
}
136+
led_busy();
132137
}
133138

134139
// Invoked when last tx transfer finished
@@ -139,8 +144,10 @@ void cust_vendor_tx_cb(uint8_t ep_addr, uint32_t sent_bytes) {
139144

140145
// check ZLP
141146
if ((sent_bytes & (bulk_packet_size - 1)) == 0
142-
&& !cust_vendor_is_transmitting(ep_addr))
147+
&& !cust_vendor_is_transmitting(ep_addr)) {
143148
cust_vendor_start_transmit(EP_LOOPBACK_TX, NULL, 0);
149+
led_busy();
150+
}
144151

145152
} else if (ep_addr == EP_ECHO_TX) {
146153
num_echos--;
@@ -153,6 +160,7 @@ void cust_vendor_intf_open_cb(uint8_t intf) {
153160
bulk_packet_size = cust_vendor_packet_size(EP_LOOPBACK_RX);
154161
loopback_check_rx();
155162
echo_update_state();
163+
led_busy();
156164
}
157165

158166
// Invoked when an alternate interface has been selected
@@ -162,6 +170,7 @@ void cust_vendor_alt_intf_selected_cb(uint8_t intf, uint8_t alt) {
162170
loopback_check_rx();
163171
if (alt == 0)
164172
echo_update_state();
173+
led_busy();
165174
}
166175

167176
void cust_vendor_halt_cleared_cb(uint8_t ep_addr) {
@@ -183,6 +192,7 @@ void cust_vendor_halt_cleared_cb(uint8_t ep_addr) {
183192
default:
184193
break;
185194
}
195+
led_busy();
186196
}
187197

188198

@@ -209,27 +219,31 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
209219
if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 0) {
210220
// save value from wValue
211221
saved_value = request->wValue;
222+
led_busy();
212223
return tud_control_status(rhport, request);
213224
}
214225
break;
215226

216227
case REQUEST_SAVE_DATA:
217228
if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 4) {
218229
// receive into `saved_value`
230+
led_busy();
219231
return tud_control_xfer(rhport, request, &saved_value, 4);
220232
}
221233
break;
222234

223235
case REQUEST_SEND_DATA:
224236
if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wLength == 4) {
225237
// transmit from `saved_value`
238+
led_busy();
226239
return tud_control_xfer(rhport, request, &saved_value, 4);
227240
}
228241
break;
229242

230243
case REQUEST_RESET_BUFFERS:
231244
if (request->bmRequestType_bit.direction == TUSB_DIR_OUT && request->wLength == 0) {
232245
reset_buffers();
246+
led_busy();
233247
return tud_control_status(rhport, request);
234248
}
235249
break;
@@ -238,6 +252,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
238252
if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wLength == 1) {
239253
uint8_t intf_num = request->wIndex & 0xff;
240254
if (intf_num < 4) {
255+
led_busy();
241256
// return inteface number
242257
return tud_control_xfer(rhport, request, &intf_num, 1);
243258
}
@@ -247,6 +262,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
247262
// Microsoft WCID descriptor (for automatic WinUSB installation)
248263
case WCID_VENDOR_CODE:
249264
if (request->bmRequestType_bit.direction == TUSB_DIR_IN && request->wIndex == 0x0004) {
265+
led_busy();
250266
// transmit WCID feature descriptor
251267
int len = sizeof(wcid_feature_desc);
252268
if (len >= request->wLength)
@@ -274,12 +290,7 @@ usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) {
274290

275291
// Invoked when device is mounted
276292
void tud_mount_cb(void) {
277-
blink_interval_ms = BLINK_MOUNTED;
278-
}
279-
280-
// Invoked when device is unmounted
281-
void tud_umount_cb(void) {
282-
blink_interval_ms = BLINK_NOT_MOUNTED;
293+
is_blinking = false;
283294
}
284295

285296
// Invoked when usb bus is suspended
@@ -293,15 +304,21 @@ void tud_suspend_cb(bool remote_wakeup_en) {
293304

294305
// --- LED blinking ---
295306

296-
void led_blinking_task(void) {
297-
static uint32_t start_ms = 0;
298-
static bool led_state = false;
299-
300-
// Blink every interval ms
301-
if ( board_millis() - start_ms < blink_interval_ms)
302-
return; // interval not elapsed yet
303-
start_ms += blink_interval_ms;
307+
void led_busy(void) {
308+
led_on_until = board_millis() + 100;
309+
board_led_write(true);
310+
}
304311

305-
board_led_write(led_state);
306-
led_state = 1 - led_state; // toggle
312+
void led_blinking_task(void) {
313+
uint32_t now = board_millis();
314+
if (is_blinking) {
315+
if (has_expired(blink_toogle_at, now)) {
316+
is_blink_on = !is_blink_on;
317+
blink_toogle_at = now + 250;
318+
}
319+
board_led_write(is_blink_on && (now & 7) == 0);
320+
321+
} else if (has_expired(led_on_until, now)) {
322+
board_led_write((now & 3) == 0);
323+
}
307324
}

0 commit comments

Comments
 (0)