diff --git a/firmware/src/gfx_decoder.cpp b/firmware/src/gfx_decoder.cpp index 2d7b619..eaff6a0 100644 --- a/firmware/src/gfx_decoder.cpp +++ b/firmware/src/gfx_decoder.cpp @@ -67,6 +67,12 @@ int32_t gfx_decoder_loadNextFrame() { } // insert placeholder for unused last stage (after pixel 19) sample >>=1; + // shift to LSB position + sample >>=8; + // MSB=1 indicates end of row + if (xModule == COL_MODULES - 1) { + sample |= 0x80000000; + } ledBuffer[bi][(ROW_COUNT - 1 - y) * COL_MODULES + xModule] = sample; } diff --git a/firmware/src/leds.cpp b/firmware/src/leds.cpp index a7a1302..c881153 100644 --- a/firmware/src/leds.cpp +++ b/firmware/src/leds.cpp @@ -49,7 +49,8 @@ void leds_init() { pinMode(COL_SER, OUTPUT); pinMode(COL_OE, OUTPUT); outputEnable(ROW_OE, false); - pinMode(COL_RCLK, OUTPUT); + // pinMode(COL_RCLK, OUTPUT); + pinMode(RCLK, OUTPUT); pinMode(COL_SRCLK, OUTPUT); pinMode(COL_SRCLR, OUTPUT); @@ -57,18 +58,18 @@ void leds_init() { pinMode(ROW_SER, OUTPUT); pinMode(ROW_OE, OUTPUT); outputEnable(ROW_OE, false); - pinMode(ROW_RCLK, OUTPUT); + // pinMode(ROW_RCLK, OUTPUT); pinMode(ROW_SRCLK, OUTPUT); pinMode(ROW_SRCLR, OUTPUT); // clear output - cols clearShiftReg(COL_SRCLK, COL_SRCLR); - pulsePin(COL_RCLK); - outputEnable(COL_OE, true); + pulsePin(RCLK); + outputEnable(COL_OE, true); // this is fine, because we control OE via rows only // clear output - rows clearShiftReg(ROW_SRCLK, ROW_SRCLR); - pulsePin(ROW_RCLK); + pulsePin(RCLK); } void leds_disable() { @@ -127,11 +128,8 @@ void leds_render() { pulsePin(ROW_SRCLK); } - // set row data - // NOTE: values are loaded right-left - // Optimized implementation: use PIO, avoid division, modulo, etc... - // we use 7/8 stages of each shift register + 1 is unused so we need to do - // silly shit + // set row data using PIO + // latch signal is also sent here // TODO: Some ideas for future optimization: // - see if we can disable px pusher delays on improved electric interface // - improve outer loop which adds 2us of processing on each loop @@ -151,12 +149,11 @@ void leds_render() { // 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); - - // latch rows and columns - gpio_set_mask(1 << ROW_RCLK | 1 << COL_RCLK); - _NOP(); - _NOP(); - gpio_clr_mask(1 << ROW_RCLK | 1 << COL_RCLK); + // 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 outputEnable(ROW_OE, true); @@ -196,11 +193,16 @@ void leds_initPusher() { // data is inverted gpio_set_outover(dataPin, GPIO_OVERRIDE_INVERT); - // Set SET (latch) pin, connect to pad, set as output + // Set sideset (SRCLK) pin, connect to pad, set as output sm_config_set_sideset_pins(&config, latchPin); pio_gpio_init(pio, latchPin); pio_sm_set_consecutive_pindirs(pio, sm, latchPin, 1, true); + // Set SET (RCLK) pin, connect to pad, set as output + sm_config_set_set_pins(&config, RCLK, 1); + pio_gpio_init(pio, RCLK); + pio_sm_set_consecutive_pindirs(pio, sm, RCLK, 1, true); + // Load our configuration, and jump to the start of the program pio_sm_init(pio, sm, offset, &config); pio_sm_set_enabled(pio, sm, true); diff --git a/firmware/src/leds.h b/firmware/src/leds.h index f884621..f443b63 100644 --- a/firmware/src/leds.h +++ b/firmware/src/leds.h @@ -6,13 +6,14 @@ #define COL_SER 20 #define COL_OE 21 -#define COL_RCLK 22 +// #define COL_RCLK 22 +#define RCLK 22 #define COL_SRCLK 26 #define COL_SRCLR 27 #define ROW_SER 14 #define ROW_OE 13 -#define ROW_RCLK 12 +// #define ROW_RCLK 12 #define ROW_SRCLK 11 #define ROW_SRCLR 10 diff --git a/firmware/src/leds.pio b/firmware/src/leds.pio index 34c47d5..b7299b9 100644 --- a/firmware/src/leds.pio +++ b/firmware/src/leds.pio @@ -7,15 +7,26 @@ public entry_point: ; push 24 bits to the shift registers ; also, return latch bit to 0 set x, 23 side 0 - ; ignore the 8 least significant bits - out null, 8 loop: - ; lower clock edge - nop side 0 - ; set bit - out pins, 1 + ; TODO: check if delays can be lowered with a PCB + ; set bit; lower clock edge + out pins, 1 side 0 [1] ; loop; latch bit (rising edge) - ; TODO: check if this delay can be lowered with a PCB jmp x-- loop side 1 [2] end: -.wrap + ; ignore unused bits + ; load MSBs into x + ; lower clock edge + out x, 8 side 0 + ; MSB=1 indicates end of row + jmp x-- end_of_row + .wrap +end_of_row: + ; indicate to main processor that row was processed + ; 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 cf7fe9a..d7b559d 100644 --- a/firmware/src/leds.pio.h +++ b/firmware/src/leds.pio.h @@ -20,17 +20,21 @@ static const uint16_t leds_px_pusher_program_instructions[] = { // .wrap_target 0xf037, // 0: set x, 23 side 0 - 0x6068, // 1: out null, 8 - 0xb042, // 2: nop side 0 - 0x6001, // 3: out pins, 1 - 0x1a42, // 4: jmp x--, 2 side 1 [2] + 0x7101, // 1: out pins, 1 side 0 [1] + 0x1a41, // 2: jmp x--, 1 side 1 [2] + 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 + 0x0000, // 8: jmp 0 }; #if !PICO_NO_HARDWARE static const struct pio_program leds_px_pusher_program = { .instructions = leds_px_pusher_program_instructions, - .length = 5, + .length = 9, .origin = -1, };