diff --git a/firmware/src/boards/cynthion_d11/fpga.c b/firmware/src/boards/cynthion_d11/fpga.c index ce5f944..7c2dbab 100644 --- a/firmware/src/boards/cynthion_d11/fpga.c +++ b/firmware/src/boards/cynthion_d11/fpga.c @@ -10,6 +10,7 @@ #include "apollo_board.h" #include "jtag.h" +#include "fpga.h" /* @@ -68,4 +69,7 @@ void trigger_fpga_reconfiguration(void) gpio_set_pin_level(FPGA_PROGRAM, true); gpio_set_pin_direction(FPGA_PROGRAM, GPIO_DIRECTION_IN); + + // Update internal state. + fpga_online = true; } diff --git a/firmware/src/boards/cynthion_d11/fpga_adv.c b/firmware/src/boards/cynthion_d11/fpga_adv.c index 329d5d0..9588d2f 100644 --- a/firmware/src/boards/cynthion_d11/fpga_adv.c +++ b/firmware/src/boards/cynthion_d11/fpga_adv.c @@ -7,6 +7,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include "fpga_adv.h" #include "usb_switch.h" #include "apollo_board.h" @@ -23,6 +24,9 @@ #define TIMEOUT 100UL static uint32_t last_phy_adv = 0; +// Allow deferred switching of the USB port. +static bool defer_hand_off = false; + // Create a reference to our SERCOM object. typedef Sercom sercom_t; static sercom_t *sercom = SERCOM1; @@ -107,9 +111,12 @@ void fpga_adv_init(void) void fpga_adv_task(void) { #ifdef BOARD_HAS_USB_SWITCH - // Take over USB after timeout - if (board_millis() - last_phy_adv >= TIMEOUT) { + // Take over USB after timeout + if (fpga_requesting_port() == false) { take_over_usb(); + } else if (defer_hand_off) { + hand_off_usb(); + defer_hand_off = false; } #endif } @@ -120,12 +127,26 @@ void fpga_adv_task(void) void honor_fpga_adv(void) { #ifdef BOARD_HAS_USB_SWITCH - if (board_millis() - last_phy_adv < TIMEOUT) { + if (fpga_requesting_port()) { hand_off_usb(); + } else { + defer_hand_off = true; } #endif } +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + return board_millis() - last_phy_adv < TIMEOUT; +#else + return false; +#endif +} + #ifdef BOARD_HAS_USB_SWITCH /** diff --git a/firmware/src/boards/cynthion_d11/led.c b/firmware/src/boards/cynthion_d11/led.c index a8e4fac..01aa054 100644 --- a/firmware/src/boards/cynthion_d11/led.c +++ b/firmware/src/boards/cynthion_d11/led.c @@ -19,10 +19,13 @@ #include "led.h" +#include "fpga.h" +#include "fpga_adv.h" +#include "usb_switch.h" /** Store the current LED blink pattern. */ -static blink_pattern_t blink_pattern = BLINK_IDLE; +static led_pattern_t led_pattern = LED_IDLE; /** @@ -116,16 +119,16 @@ static void display_led_number(uint8_t number) /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. */ -void led_set_blink_pattern(blink_pattern_t pattern) +void led_set_pattern(led_pattern_t pattern) { - blink_pattern = pattern; + led_pattern = pattern; leds_off(); // Values of 0 to 31 should be set immediately as static patterns. - if (blink_pattern < 32) { + if (led_pattern < 32) { for (int i = 0; i < 5; i++) { - if (blink_pattern & (1 << i)) { + if (led_pattern & (1 << i)) { display_led_number(i); } } @@ -134,36 +137,45 @@ void led_set_blink_pattern(blink_pattern_t pattern) /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void) +void led_task(void) { static uint32_t start_ms = 0; static uint8_t active_led = 0; static bool count_up = true; // Values of 0 to 31 define static patterns only. - if (blink_pattern < 32) { + if (led_pattern < 32) { return; } - // Blink every interval ms - if ( board_millis() - start_ms < blink_pattern) return; // not enough time - start_ms += blink_pattern; + // When the device is idle, use the following scheme for LEDs: + // - LED A: power indication (always on in Apollo) + // - LED B: FPGA allowed online (indicates PROGRAM toggle) + // - LED C: FPGA has requested CONTROL port + // - LED D: USB switched to FPGA + // - LED E: flashing patterns (e.g. fault indication) + if (led_pattern == LED_IDLE) { + led_set(LED_A, true); + led_set(LED_B, fpga_is_online()); + led_set(LED_C, fpga_requesting_port()); + led_set(LED_D, fpga_controls_usb_port()); + led_set(LED_E, false); + return; + } - switch (blink_pattern) { + // Blink every interval ms + if ( board_millis() - start_ms < led_pattern) return; // not enough time + start_ms += led_pattern; - // Standard blink pattern for when the device is idle. - // Indicates that the device's JTAG lines are un-pulled. - case BLINK_IDLE: - led_toggle(LED_E); - break; + switch (led_pattern) { // Blink patterns for when the device is being used for JTAG // operation. When these are on, the uC is driving the JTAG lines, // so the JTAG header probably shouldn't used to drive the lines. - case BLINK_JTAG_CONNECTED: - case BLINK_JTAG_UPLOADING: + case LED_JTAG_CONNECTED: + case LED_JTAG_UPLOADING: // Sweep back and forth. if (active_led == 0xFF) { @@ -182,7 +194,7 @@ void heartbeat_task(void) // Blink patterns for when the device is being used for SPI flash access. // When these are displayed, - case BLINK_FLASH_CONNECTED: + case LED_FLASH_CONNECTED: if (active_led == 5) { active_led = 0; diff --git a/firmware/src/boards/cynthion_d21/fpga.c b/firmware/src/boards/cynthion_d21/fpga.c index 17a1151..929345a 100644 --- a/firmware/src/boards/cynthion_d21/fpga.c +++ b/firmware/src/boards/cynthion_d21/fpga.c @@ -9,6 +9,7 @@ #include #include "jtag.h" +#include "fpga.h" // List of pins used for FPGA interfacing. enum { @@ -73,4 +74,7 @@ void trigger_fpga_reconfiguration(void) gpio_set_pin_level(PIN_PROG, true); gpio_set_pin_direction(PIN_PROG, GPIO_DIRECTION_IN); + + // Update internal state. + fpga_online = true; } diff --git a/firmware/src/boards/cynthion_d21/fpga_adv.c b/firmware/src/boards/cynthion_d21/fpga_adv.c index b2c85f9..5a62561 100644 --- a/firmware/src/boards/cynthion_d21/fpga_adv.c +++ b/firmware/src/boards/cynthion_d21/fpga_adv.c @@ -6,6 +6,7 @@ * Copyright (c) 2023 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ +#include /** * Initialize FPGA_ADV receive-only serial port @@ -27,3 +28,11 @@ void fpga_adv_task(void) void honor_fpga_adv(void) { } + +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void) +{ + return false; +} diff --git a/firmware/src/boards/cynthion_d21/led.c b/firmware/src/boards/cynthion_d21/led.c index 05470c3..3625281 100644 --- a/firmware/src/boards/cynthion_d21/led.c +++ b/firmware/src/boards/cynthion_d21/led.c @@ -22,7 +22,7 @@ /** Store the current LED blink pattern. */ -static blink_pattern_t blink_pattern = BLINK_IDLE; +static led_pattern_t led_pattern = LED_IDLE; /** @@ -103,16 +103,16 @@ static void display_led_number(uint8_t number) /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. */ -void led_set_blink_pattern(blink_pattern_t pattern) +void led_set_pattern(led_pattern_t pattern) { - blink_pattern = pattern; + led_pattern = pattern; leds_off(); // Values of 0 to 31 should be set immediately as static patterns. - if (blink_pattern < 32) { + if (led_pattern < 32) { for (int i = 0; i < 5; i++) { - if (blink_pattern & (1 << i)) { + if (led_pattern & (1 << i)) { display_led_number(i); } } @@ -121,36 +121,36 @@ void led_set_blink_pattern(blink_pattern_t pattern) /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void) +void led_task(void) { static uint32_t start_ms = 0; static uint8_t active_led = 0; static bool count_up = true; // Values of 0 to 31 define static patterns only. - if (blink_pattern < 32) { + if (led_pattern < 32) { return; } // Blink every interval ms - if ( board_millis() - start_ms < blink_pattern) return; // not enough time - start_ms += blink_pattern; + if ( board_millis() - start_ms < led_pattern) return; // not enough time + start_ms += led_pattern; - switch (blink_pattern) { + switch (led_pattern) { // Standard blink pattern for when the device is idle. // Indicates that the device's JTAG lines are un-pulled. - case BLINK_IDLE: + case LED_IDLE: led_toggle(LED_E); break; // Blink patterns for when the device is being used for JTAG // operation. When these are on, the uC is driving the JTAG lines, // so the JTAG header probably shouldn't used to drive the lines. - case BLINK_JTAG_CONNECTED: - case BLINK_JTAG_UPLOADING: + case LED_JTAG_CONNECTED: + case LED_JTAG_UPLOADING: // Sweep back and forth. if (active_led == 0xFF) { @@ -169,7 +169,7 @@ void heartbeat_task(void) // Blink patterns for when the device is being used for SPI flash access. // When these are displayed, - case BLINK_FLASH_CONNECTED: + case LED_FLASH_CONNECTED: if (active_led == 5) { active_led = 0; diff --git a/firmware/src/boards/daisho/fpga_adv.c b/firmware/src/boards/daisho/fpga_adv.c index b2c85f9..5a62561 100644 --- a/firmware/src/boards/daisho/fpga_adv.c +++ b/firmware/src/boards/daisho/fpga_adv.c @@ -6,6 +6,7 @@ * Copyright (c) 2023 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ +#include /** * Initialize FPGA_ADV receive-only serial port @@ -27,3 +28,11 @@ void fpga_adv_task(void) void honor_fpga_adv(void) { } + +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void) +{ + return false; +} diff --git a/firmware/src/boards/daisho/led.c b/firmware/src/boards/daisho/led.c index 0ce2bc8..a6d30ac 100644 --- a/firmware/src/boards/daisho/led.c +++ b/firmware/src/boards/daisho/led.c @@ -21,15 +21,15 @@ /** Store the current LED blink pattern. */ -static blink_pattern_t blink_pattern = BLINK_IDLE; +static led_pattern_t led_pattern = LED_IDLE; /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. */ -void led_set_blink_pattern(blink_pattern_t pattern) +void led_set_pattern(led_pattern_t pattern) { - blink_pattern = pattern; + led_pattern = pattern; leds_off(); } @@ -91,18 +91,18 @@ void leds_off(void) /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void) +void led_task(void) { static uint32_t start_ms = 0; // Blink every interval ms - if ( board_millis() - start_ms < blink_pattern) { + if ( board_millis() - start_ms < led_pattern) { return; // not enough time } - start_ms += blink_pattern; + start_ms += led_pattern; led_toggle(LED_STATUS); } diff --git a/firmware/src/boards/qtpy/fpga.c b/firmware/src/boards/qtpy/fpga.c index 59aecc0..82c8de9 100644 --- a/firmware/src/boards/qtpy/fpga.c +++ b/firmware/src/boards/qtpy/fpga.c @@ -10,6 +10,7 @@ #include "apollo_board.h" #include "jtag.h" +#include "fpga.h" // List of pins used for FPGA interfacing. @@ -80,4 +81,7 @@ void trigger_fpga_reconfiguration(void) gpio_set_pin_level(PIN_PROG, true); gpio_set_pin_direction(PIN_PROG, GPIO_DIRECTION_IN); + + // Update internal state. + fpga_online = true; } diff --git a/firmware/src/boards/qtpy/fpga_adv.c b/firmware/src/boards/qtpy/fpga_adv.c index b2c85f9..5a62561 100644 --- a/firmware/src/boards/qtpy/fpga_adv.c +++ b/firmware/src/boards/qtpy/fpga_adv.c @@ -6,6 +6,7 @@ * Copyright (c) 2023 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ +#include /** * Initialize FPGA_ADV receive-only serial port @@ -27,3 +28,11 @@ void fpga_adv_task(void) void honor_fpga_adv(void) { } + +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void) +{ + return false; +} diff --git a/firmware/src/boards/qtpy/led.c b/firmware/src/boards/qtpy/led.c index 68a1c13..4ca10b6 100644 --- a/firmware/src/boards/qtpy/led.c +++ b/firmware/src/boards/qtpy/led.c @@ -22,15 +22,15 @@ /** Store the current LED blink pattern. */ -static blink_pattern_t blink_pattern = BLINK_IDLE; +static led_pattern_t led_pattern = LED_IDLE; /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. */ -void led_set_blink_pattern(blink_pattern_t pattern) +void led_set_pattern(led_pattern_t pattern) { - blink_pattern = pattern; + led_pattern = pattern; leds_off(); } @@ -105,31 +105,31 @@ static void display_led_number(uint8_t number) /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void) +void led_task(void) { static uint32_t start_ms = 0; static uint8_t active_led = 0; static bool count_up = true; // Blink every interval ms - if ( board_millis() - start_ms < blink_pattern) return; // not enough time - start_ms += blink_pattern; + if ( board_millis() - start_ms < led_pattern) return; // not enough time + start_ms += led_pattern; - switch (blink_pattern) { + switch (led_pattern) { // Standard blink pattern for when the device is idle. // Indicates that the device's JTAG lines are un-pulled. - case BLINK_IDLE: + case LED_IDLE: led_toggle(LED_E); break; // Blink patterns for when the device is being used for JTAG // operation. When these are on, the uC is driving the JTAG lines, // so the JTAG header probably shouldn't used to drive the lines. - case BLINK_JTAG_CONNECTED: - case BLINK_JTAG_UPLOADING: + case LED_JTAG_CONNECTED: + case LED_JTAG_UPLOADING: // Sweep back and forth. if (active_led == 0xFF) { @@ -148,7 +148,7 @@ void heartbeat_task(void) // Blink patterns for when the device is being used for SPI flash access. // When these are displayed, - case BLINK_FLASH_CONNECTED: + case LED_FLASH_CONNECTED: if (active_led == 5) { active_led = 0; diff --git a/firmware/src/boards/samd11_xplained/fpga.c b/firmware/src/boards/samd11_xplained/fpga.c index 17a1151..929345a 100644 --- a/firmware/src/boards/samd11_xplained/fpga.c +++ b/firmware/src/boards/samd11_xplained/fpga.c @@ -9,6 +9,7 @@ #include #include "jtag.h" +#include "fpga.h" // List of pins used for FPGA interfacing. enum { @@ -73,4 +74,7 @@ void trigger_fpga_reconfiguration(void) gpio_set_pin_level(PIN_PROG, true); gpio_set_pin_direction(PIN_PROG, GPIO_DIRECTION_IN); + + // Update internal state. + fpga_online = true; } diff --git a/firmware/src/boards/samd11_xplained/fpga_adv.c b/firmware/src/boards/samd11_xplained/fpga_adv.c index b2c85f9..5a62561 100644 --- a/firmware/src/boards/samd11_xplained/fpga_adv.c +++ b/firmware/src/boards/samd11_xplained/fpga_adv.c @@ -6,6 +6,7 @@ * Copyright (c) 2023 Great Scott Gadgets * SPDX-License-Identifier: BSD-3-Clause */ +#include /** * Initialize FPGA_ADV receive-only serial port @@ -27,3 +28,11 @@ void fpga_adv_task(void) void honor_fpga_adv(void) { } + +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void) +{ + return false; +} diff --git a/firmware/src/boards/samd11_xplained/led.c b/firmware/src/boards/samd11_xplained/led.c index 0ce2bc8..a6d30ac 100644 --- a/firmware/src/boards/samd11_xplained/led.c +++ b/firmware/src/boards/samd11_xplained/led.c @@ -21,15 +21,15 @@ /** Store the current LED blink pattern. */ -static blink_pattern_t blink_pattern = BLINK_IDLE; +static led_pattern_t led_pattern = LED_IDLE; /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. */ -void led_set_blink_pattern(blink_pattern_t pattern) +void led_set_pattern(led_pattern_t pattern) { - blink_pattern = pattern; + led_pattern = pattern; leds_off(); } @@ -91,18 +91,18 @@ void leds_off(void) /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void) +void led_task(void) { static uint32_t start_ms = 0; // Blink every interval ms - if ( board_millis() - start_ms < blink_pattern) { + if ( board_millis() - start_ms < led_pattern) { return; // not enough time } - start_ms += blink_pattern; + start_ms += led_pattern; led_toggle(LED_STATUS); } diff --git a/firmware/src/debug_spi.c b/firmware/src/debug_spi.c index cf09c34..c2fb5b7 100644 --- a/firmware/src/debug_spi.c +++ b/firmware/src/debug_spi.c @@ -200,7 +200,7 @@ bool handle_take_configuration_spi(uint8_t rhport, tusb_control_request_t const* #endif // ... and set a blink pattern accordingly. - led_set_blink_pattern(BLINK_FLASH_CONNECTED); + led_set_pattern(LED_FLASH_CONNECTED); return tud_control_xfer(rhport, request, NULL, 0); } @@ -217,7 +217,7 @@ bool handle_release_configuration_spi(uint8_t rhport, tusb_control_request_t con gpio_set_pin_pull_mode(PIN_FLASH_CS, GPIO_PULL_UP); #endif - led_set_blink_pattern(BLINK_IDLE); + led_set_pattern(LED_IDLE); return tud_control_xfer(rhport, request, NULL, 0); } diff --git a/firmware/src/fpga.c b/firmware/src/fpga.c index 90e9527..d0aea32 100644 --- a/firmware/src/fpga.c +++ b/firmware/src/fpga.c @@ -12,6 +12,7 @@ extern uint8_t jtag_out_buffer[256]; +bool fpga_online = false; /* * ECP5 opcode that enables offline configuration mode @@ -36,4 +37,15 @@ void force_fpga_offline(void) jtag_go_to_state(STATE_RUN_TEST_IDLE); jtag_wait_time(2); jtag_deinit(); + + // Update internal state. + fpga_online = false; +} + +/* + * True after FPGA reconfiguration, false after forcing FPGA offline. + */ +bool fpga_is_online(void) +{ + return fpga_online; } diff --git a/firmware/src/fpga.h b/firmware/src/fpga.h index e4bb9c3..e1637f3 100644 --- a/firmware/src/fpga.h +++ b/firmware/src/fpga.h @@ -10,6 +10,8 @@ #ifndef __FPGA_H__ #define __FPGA_H__ +extern bool fpga_online; + /** * Sets up the I/O pins needed to configure the FPGA. */ @@ -32,4 +34,9 @@ void trigger_fpga_reconfiguration(void); */ void force_fpga_offline(void); +/* + * True after FPGA reconfiguration, false after forcing FPGA offline. + */ +bool fpga_is_online(void); + #endif diff --git a/firmware/src/fpga_adv.h b/firmware/src/fpga_adv.h index 6e9b5ab..1585230 100644 --- a/firmware/src/fpga_adv.h +++ b/firmware/src/fpga_adv.h @@ -25,5 +25,9 @@ void fpga_adv_task(void); */ void honor_fpga_adv(void); +/** + * True if we received an advertisement message within the last time window. + */ +bool fpga_requesting_port(void); #endif diff --git a/firmware/src/jtag.c b/firmware/src/jtag.c index 88a1ef6..0d798d9 100644 --- a/firmware/src/jtag.c +++ b/firmware/src/jtag.c @@ -20,6 +20,10 @@ #include "jtag.h" #include "uart.h" #include "spi.h" +#include "fpga.h" + +#define ISC_ENABLE 0xC6 +#define ISC_DISABLE 0x26 // JTAG comms buffers. @@ -109,6 +113,16 @@ bool handle_jtag_request_set_out_buffer(uint8_t rhport, tusb_control_request_t c return false; } + // HACK: check the buffer for commands that affect the FPGA configuration state. + if (request->wLength == 1) { + if (jtag_out_buffer[0] == ISC_ENABLE) { + fpga_online = false; + } + if (jtag_out_buffer[0] == ISC_DISABLE) { + fpga_online = true; + } + } + // Copy the relevant data into our OUT buffer. return tud_control_xfer(rhport, request, jtag_out_buffer, request->wLength); } @@ -191,7 +205,7 @@ bool handle_jtag_get_state(uint8_t rhport, tusb_control_request_t const* request */ bool handle_jtag_start(uint8_t rhport, tusb_control_request_t const* request) { - led_set_blink_pattern(BLINK_JTAG_CONNECTED); + led_set_pattern(LED_JTAG_CONNECTED); jtag_init(); return tud_control_xfer(rhport, request, NULL, 0); @@ -203,7 +217,7 @@ bool handle_jtag_start(uint8_t rhport, tusb_control_request_t const* request) */ bool handle_jtag_stop(uint8_t rhport, tusb_control_request_t const* request) { - led_set_blink_pattern(BLINK_IDLE); + led_set_pattern(LED_IDLE); jtag_deinit(); return tud_control_xfer(rhport, request, NULL, 0); diff --git a/firmware/src/led.h b/firmware/src/led.h index c643089..b5d1243 100644 --- a/firmware/src/led.h +++ b/firmware/src/led.h @@ -22,21 +22,21 @@ * with different semantic meanings. */ typedef enum { - BLINK_IDLE = 500, - BLINK_JTAG_CONNECTED = 150, - BLINK_JTAG_UPLOADING = 50, + LED_IDLE = 500, + LED_JTAG_CONNECTED = 150, + LED_JTAG_UPLOADING = 50, - BLINK_FLASH_CONNECTED = 130, -} blink_pattern_t; + LED_FLASH_CONNECTED = 130, +} led_pattern_t; /** - * Sets the active LED blink pattern. + * Sets the active LED pattern. * - * See @ref blink_pattern_t for the meaning of the pattern argument. + * See @ref led_pattern_t for the meaning of the pattern argument. */ -void led_set_blink_pattern(blink_pattern_t pattern); +void led_set_pattern(led_pattern_t pattern); /** @@ -76,8 +76,8 @@ void led_set(led_t led, bool on); /** - * Task that handles blinking the heartbeat LED. + * Task that handles LED updates. */ -void heartbeat_task(void); +void led_task(void); #endif diff --git a/firmware/src/main.c b/firmware/src/main.c index ab3bfba..88f0b25 100644 --- a/firmware/src/main.c +++ b/firmware/src/main.c @@ -85,7 +85,7 @@ int main(void) while (1) { tud_task(); // tinyusb device task console_task(); - heartbeat_task(); + led_task(); button_task(); fpga_adv_task(); } diff --git a/firmware/src/usb_switch.c b/firmware/src/usb_switch.c index 2b38d54..190f92c 100644 --- a/firmware/src/usb_switch.c +++ b/firmware/src/usb_switch.c @@ -63,3 +63,16 @@ void take_over_usb(void) switch_state = SWITCH_MCU; #endif } + + +/** + * True if the USB switch handed over the port to the FPGA. + */ +bool fpga_controls_usb_port(void) +{ +#ifdef BOARD_HAS_USB_SWITCH + return switch_state == SWITCH_FPGA; +#else + return false; +#endif +} diff --git a/firmware/src/usb_switch.h b/firmware/src/usb_switch.h index 7049ae2..d17f36b 100644 --- a/firmware/src/usb_switch.h +++ b/firmware/src/usb_switch.h @@ -10,6 +10,7 @@ #ifndef __USB_SWITCH_H__ #define __USB_SWITCH_H__ +#include /** * Hand off shared USB port to FPGA. @@ -21,5 +22,8 @@ void hand_off_usb(void); */ void take_over_usb(void); - +/** + * True if the USB switch handed over the port to the FPGA. + */ +bool fpga_controls_usb_port(void); #endif diff --git a/firmware/src/vendor.c b/firmware/src/vendor.c index 6c20f9f..f027704 100644 --- a/firmware/src/vendor.c +++ b/firmware/src/vendor.c @@ -116,7 +116,7 @@ bool handle_get_id_request(uint8_t rhport, tusb_control_request_t const* request */ bool handle_set_led_pattern(uint8_t rhport, tusb_control_request_t const* request) { - led_set_blink_pattern(request->wValue); + led_set_pattern(request->wValue); return tud_control_xfer(rhport, request, NULL, 0); }