From 2a953464fd5a399d5f728de7ac72b647ced41e7f Mon Sep 17 00:00:00 2001 From: radex Date: Sun, 26 May 2024 23:00:49 +0200 Subject: [PATCH] optimize: use irq to signal readiness --- firmware/src/gfx_decoder.cpp | 1 + firmware/src/leds.cpp | 19 ++++++++----------- firmware/src/leds.h | 1 + firmware/src/leds.pio | 5 ++--- firmware/src/leds.pio.h | 6 +++--- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/firmware/src/gfx_decoder.cpp b/firmware/src/gfx_decoder.cpp index eaff6a0..b438366 100644 --- a/firmware/src/gfx_decoder.cpp +++ b/firmware/src/gfx_decoder.cpp @@ -78,6 +78,7 @@ int32_t gfx_decoder_loadNextFrame() { } } } + ledBufferReady = true; // copy to framebuffer // TODO: mutex? double buffer? or something... diff --git a/firmware/src/leds.cpp b/firmware/src/leds.cpp index c881153..7b5c23b 100644 --- a/firmware/src/leds.cpp +++ b/firmware/src/leds.cpp @@ -36,6 +36,7 @@ uint8_t brightnessPhaseDelays[COLOR_BITS] = {0, 1, 6, 20, 60}; // NOTE: Alignment required to allow 4-byte reads uint8_t framebuffer[ROW_COUNT * COL_COUNT] __attribute__((aligned(32))) = {0}; +bool ledBufferReady = false; uint32_t ledBuffer[8][ROW_COUNT * COL_MODULES] = {0}; void leds_init() { @@ -93,6 +94,11 @@ void leds_initRenderer() { } void leds_render() { + if (!ledBufferReady) { + outputEnable(ROW_OE, false); + return; + } + // brightness phase bool brightPhase = brightnessPhase >= 3; auto buffer = ledBuffer[brightnessPhase + 3]; @@ -134,25 +140,16 @@ void leds_render() { // - see if we can disable px pusher delays on improved electric interface // - improve outer loop which adds 2us of processing on each loop // - change busy wait into some kind of interrupt-based thing so that processing can continue - // - latch row and clock simultaneously, avoid disabling output // - DMA? for (int xModule = 0; xModule < COL_MODULES; xModule++) { uint32_t pxValues = buffer[bufferOffset + xModule]; pio_sm_put_blocking(pusher_pio, pusher_sm, pxValues); } - // wait for all data to be shifted out - while (!pio_sm_is_tx_fifo_empty(pusher_pio, pusher_sm)) { + // wait until pushing and RCLK latch are done + while (!pio_interrupt_get(pusher_pio, 0)) { tight_loop_contents(); } - // TODO: Is there an API to wait for PIO to actually become idle? - // pio_sm_drain_tx_fifo doesn't seem to do the trick - // if not, we might need to use irqs or something - busy_wait_us(4); - // TODO: Why doesn't this work?! - // while (!pio_interrupt_get(pusher_pio, pusher_sm)) { - // tight_loop_contents(); - // } pio_interrupt_clear(pusher_pio, pusher_sm); // show for a certain period diff --git a/firmware/src/leds.h b/firmware/src/leds.h index f443b63..7ea0485 100644 --- a/firmware/src/leds.h +++ b/firmware/src/leds.h @@ -33,6 +33,7 @@ void leds_loop(); void leds_render(); extern uint8_t framebuffer[ROW_COUNT * COL_COUNT]; +extern bool ledBufferReady; extern uint32_t ledBuffer[8][ROW_COUNT * COL_MODULES]; #endif diff --git a/firmware/src/leds.pio b/firmware/src/leds.pio index b7299b9..b3c4b5e 100644 --- a/firmware/src/leds.pio +++ b/firmware/src/leds.pio @@ -6,7 +6,7 @@ public entry_point: ; pull ; push 24 bits to the shift registers ; also, return latch bit to 0 - set x, 23 side 0 + set x, 23 side 0 loop: ; TODO: check if delays can be lowered with a PCB ; set bit; lower clock edge @@ -23,10 +23,9 @@ end: .wrap end_of_row: ; indicate to main processor that row was processed + irq set 0 ; clock RCLK (latch onto register output stage) set pins, 1 [3] set pins, 0 - irq wait 0 rel - ; wait for next row jmp entry_point diff --git a/firmware/src/leds.pio.h b/firmware/src/leds.pio.h index d7b559d..c5eb55d 100644 --- a/firmware/src/leds.pio.h +++ b/firmware/src/leds.pio.h @@ -25,9 +25,9 @@ static const uint16_t leds_px_pusher_program_instructions[] = { 0x7028, // 3: out x, 8 side 0 0x0045, // 4: jmp x--, 5 // .wrap - 0xe301, // 5: set pins, 1 [3] - 0xe000, // 6: set pins, 0 - 0xc030, // 7: irq wait 0 rel + 0xc000, // 5: irq nowait 0 + 0xe301, // 6: set pins, 1 [3] + 0xe000, // 7: set pins, 0 0x0000, // 8: jmp 0 };