From 594b87bda927d2f9693783db506c63471b7e38da Mon Sep 17 00:00:00 2001 From: Sylvain Munaut Date: Mon, 29 Apr 2024 22:37:45 +0200 Subject: [PATCH] icE1usb fw: Rework the way LEDs are used and updated Signed-off-by: Sylvain Munaut Change-Id: Ib3215a676716cc60e27c5857e4559135928a8cf7 --- firmware/ice40-riscv/icE1usb/e1.c | 96 ++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/firmware/ice40-riscv/icE1usb/e1.c b/firmware/ice40-riscv/icE1usb/e1.c index 6baee16..17c1786 100644 --- a/firmware/ice40-riscv/icE1usb/e1.c +++ b/firmware/ice40-riscv/icE1usb/e1.c @@ -270,6 +270,11 @@ struct e1_state { } linemon; struct e1_error_count errors; + + struct { + enum e1_platform_led_state green; + enum e1_platform_led_state yellow; + } led; }; static struct e1_state g_e1[NUM_E1_PORTS]; @@ -326,6 +331,76 @@ _e1_update_cr_val(int port) } } +static void +_e1_update_leds(int port) +{ + struct e1_state *e1 = _get_state(port); + + enum e1_platform_led_state green; + enum e1_platform_led_state yellow; + + /* + * Green Yellow Condition + * OFF / LOS + * BLINK OFF LOF + * BLINK ON LOF + AIS + * ON OFF ALIGNED + * ON ON ALIGNED + RAI + */ + + /* Compute expected state */ + if (e1->errors.flags & E1_ERR_F_LOS) { + green = E1P_LED_ST_OFF; + yellow = E1P_LED_ST_OFF; + } else if (e1->errors.flags & E1_ERR_F_ALIGN_ERR) { + green = E1P_LED_ST_BLINK; + yellow = (e1->errors.flags & E1_ERR_F_AIS) ? E1P_LED_ST_ON : E1P_LED_ST_OFF; + } else { + green = E1P_LED_ST_ON; + yellow = (e1->errors.flags & E1_ERR_F_RAI) ? E1P_LED_ST_ON : E1P_LED_ST_OFF; + } + + /* Update actual leds */ + if (e1->led.green != green) + e1_platform_led_set(port, E1P_LED_GREEN, green); + + if (e1->led.yellow != yellow) + e1_platform_led_set(port, E1P_LED_YELLOW, yellow); + + e1->led.green = green; + e1->led.yellow = yellow; + + /* Update the shared RGB led */ + if (port == (NUM_E1_PORTS - 1)) + { + static bool c_ok = true, c_flow = false; + bool n_ok = false, n_flow = false; + + for (int port=0; porterrors.flags & E1_ERR_F_ALIGN_ERR); + n_flow |= (e1->rx.state != IDLE); + n_flow |= (e1->tx.state != IDLE); + } + + if (n_ok != c_ok) { + if (n_ok) + led_color(0, 48, 0); // Green + else + led_color(48, 0, 0); // Red + } + + if (n_flow != c_flow) { + led_blink(n_flow, 200, 1000); + led_breathe(n_flow, 100, 200); + } + + c_ok = n_ok; + c_flow = n_flow; + } +} + void e1_init(int port, uint16_t rx_cr, uint16_t tx_cr) { @@ -490,13 +565,10 @@ e1_rx_need_data(int port, unsigned int usb_addr, unsigned int max_frames, unsign } if (rai_possible) { - if (rai_received) { + if (rai_received) e1->errors.flags |= E1_ERR_F_RAI; - e1_platform_led_set(port, E1P_LED_YELLOW, E1P_LED_ST_ON); - } else { + else e1->errors.flags &= ~E1_ERR_F_RAI; - e1_platform_led_set(port, E1P_LED_YELLOW, E1P_LED_ST_OFF); - } } return tot_frames; @@ -561,10 +633,8 @@ e1_poll(int port) uint32_t bd; unsigned int ofs; - /* HACK: LED link status */ + /* Update error flags */ if (e1_regs->rx.csr & E1_RX_SR_ALIGNED) { - e1_platform_led_set(port, E1P_LED_GREEN, E1P_LED_ST_ON); - led_color(0, 48, 0); e1->errors.flags &= ~( E1_ERR_F_LOS | E1_ERR_F_AIS | @@ -572,14 +642,13 @@ e1_poll(int port) E1_ERR_F_ALIGN_ERR ); } else { - e1_platform_led_set(port, E1P_LED_GREEN, E1P_LED_ST_BLINK); - e1_platform_led_set(port, E1P_LED_YELLOW, E1P_LED_ST_OFF); - led_color(48, 0, 0); e1->errors.flags |= E1_ERR_F_ALIGN_ERR; e1->errors.flags &= ~E1_ERR_F_RAI; - /* TODO: completely off if rx tick counter not incrementing */ } + /* Update leds */ + _e1_update_leds(port); + /* Active ? */ if ((e1->rx.state == IDLE) && (e1->tx.state == IDLE)) return; @@ -605,9 +674,6 @@ e1_poll(int port) if (e1->tx.state == STARTING) { if (e1f_unseen_frames(&e1->tx.fifo) < (16 * 5)) return; - /* HACK: LED flow status */ - led_blink(true, 200, 1000); - led_breathe(true, 100, 200); } /* Handle RX */