icE1usb firmware: Detect A-bit in TS0; report via USB + LED
Scan over every odd E1 frame TS0 byte to check if the A-bit is set,
indicating a remote alarm. If so, set yellow LED and report via the
error flags communicated to the host by USB interrupt transfer.
Change-Id: Ic4f57cf79bd32cf75f81ef3073cb8d4a2d1857d8
diff --git a/firmware/ice40-riscv/icE1usb/e1.c b/firmware/ice40-riscv/icE1usb/e1.c
index 5e57480..f5e367e 100644
--- a/firmware/ice40-riscv/icE1usb/e1.c
+++ b/firmware/ice40-riscv/icE1usb/e1.c
@@ -290,9 +290,11 @@
unsigned int
e1_rx_need_data(unsigned int usb_addr, unsigned int max_frames, unsigned int *pos)
{
+ bool rai_received = false;
+ bool rai_possible = false;
unsigned int ofs;
int tot_frames = 0;
- int n_frames;
+ int n_frames, i;
while (max_frames) {
/* Get some data from the FIFO */
@@ -314,10 +316,34 @@
max_frames -= n_frames;
tot_frames += n_frames;
+ /* While DMA is running: Determine if remote end indicates any alarms */
+ for (i = 0; i < n_frames; i++) {
+ unsigned int frame_nr = ofs + i;
+ /* A bit is present in every odd frame TS0 */
+ if (frame_nr & 1) {
+ uint8_t ts0 = *e1_data_ptr(0, ofs + i, 0);
+ rai_possible = true;
+ if (ts0 & 0x20) {
+ rai_received = true;
+ break;
+ }
+ }
+ }
+
/* Wait for DMA completion */
while (dma_poll());
}
+ if (rai_possible) {
+ if (rai_received) {
+ g_e1.errors.flags |= E1_ERR_F_RAI;
+ e1_platform_led_set(0, E1P_LED_YELLOW, E1P_LED_ST_ON);
+ } else {
+ g_e1.errors.flags &= ~E1_ERR_F_RAI;
+ e1_platform_led_set(0, E1P_LED_YELLOW, E1P_LED_ST_OFF);
+ }
+ }
+
return tot_frames;
}