1
0
Fork 0

optimize: rclk via pio

sd2
radex 2024-05-26 22:01:38 +02:00
parent 589f8a96ae
commit fbbcf0746c
Signed by: radex
SSH Key Fingerprint: SHA256:hvqRXAGG1h89yqnS+cyFTLKQbzjWD4uXIqw7Y+0ws30
5 changed files with 56 additions and 32 deletions

View File

@ -67,6 +67,12 @@ int32_t gfx_decoder_loadNextFrame() {
} }
// insert placeholder for unused last stage (after pixel 19) // insert placeholder for unused last stage (after pixel 19)
sample >>=1; 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; ledBuffer[bi][(ROW_COUNT - 1 - y) * COL_MODULES + xModule] = sample;
} }

View File

@ -49,7 +49,8 @@ void leds_init() {
pinMode(COL_SER, OUTPUT); pinMode(COL_SER, OUTPUT);
pinMode(COL_OE, OUTPUT); pinMode(COL_OE, OUTPUT);
outputEnable(ROW_OE, false); outputEnable(ROW_OE, false);
pinMode(COL_RCLK, OUTPUT); // pinMode(COL_RCLK, OUTPUT);
pinMode(RCLK, OUTPUT);
pinMode(COL_SRCLK, OUTPUT); pinMode(COL_SRCLK, OUTPUT);
pinMode(COL_SRCLR, OUTPUT); pinMode(COL_SRCLR, OUTPUT);
@ -57,18 +58,18 @@ void leds_init() {
pinMode(ROW_SER, OUTPUT); pinMode(ROW_SER, OUTPUT);
pinMode(ROW_OE, OUTPUT); pinMode(ROW_OE, OUTPUT);
outputEnable(ROW_OE, false); outputEnable(ROW_OE, false);
pinMode(ROW_RCLK, OUTPUT); // pinMode(ROW_RCLK, OUTPUT);
pinMode(ROW_SRCLK, OUTPUT); pinMode(ROW_SRCLK, OUTPUT);
pinMode(ROW_SRCLR, OUTPUT); pinMode(ROW_SRCLR, OUTPUT);
// clear output - cols // clear output - cols
clearShiftReg(COL_SRCLK, COL_SRCLR); clearShiftReg(COL_SRCLK, COL_SRCLR);
pulsePin(COL_RCLK); pulsePin(RCLK);
outputEnable(COL_OE, true); outputEnable(COL_OE, true); // this is fine, because we control OE via rows only
// clear output - rows // clear output - rows
clearShiftReg(ROW_SRCLK, ROW_SRCLR); clearShiftReg(ROW_SRCLK, ROW_SRCLR);
pulsePin(ROW_RCLK); pulsePin(RCLK);
} }
void leds_disable() { void leds_disable() {
@ -127,11 +128,8 @@ void leds_render() {
pulsePin(ROW_SRCLK); pulsePin(ROW_SRCLK);
} }
// set row data // set row data using PIO
// NOTE: values are loaded right-left // latch signal is also sent here
// 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
// TODO: Some ideas for future optimization: // TODO: Some ideas for future optimization:
// - see if we can disable px pusher delays on improved electric interface // - see if we can disable px pusher delays on improved electric interface
// - improve outer loop which adds 2us of processing on each loop // - 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 // pio_sm_drain_tx_fifo doesn't seem to do the trick
// if not, we might need to use irqs or something // if not, we might need to use irqs or something
busy_wait_us(4); busy_wait_us(4);
// TODO: Why doesn't this work?!
// latch rows and columns // while (!pio_interrupt_get(pusher_pio, pusher_sm)) {
gpio_set_mask(1 << ROW_RCLK | 1 << COL_RCLK); // tight_loop_contents();
_NOP(); // }
_NOP(); pio_interrupt_clear(pusher_pio, pusher_sm);
gpio_clr_mask(1 << ROW_RCLK | 1 << COL_RCLK);
// show for a certain period // show for a certain period
outputEnable(ROW_OE, true); outputEnable(ROW_OE, true);
@ -196,11 +193,16 @@ void leds_initPusher() {
// data is inverted // data is inverted
gpio_set_outover(dataPin, GPIO_OVERRIDE_INVERT); 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); sm_config_set_sideset_pins(&config, latchPin);
pio_gpio_init(pio, latchPin); pio_gpio_init(pio, latchPin);
pio_sm_set_consecutive_pindirs(pio, sm, latchPin, 1, true); 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 // Load our configuration, and jump to the start of the program
pio_sm_init(pio, sm, offset, &config); pio_sm_init(pio, sm, offset, &config);
pio_sm_set_enabled(pio, sm, true); pio_sm_set_enabled(pio, sm, true);

View File

@ -6,13 +6,14 @@
#define COL_SER 20 #define COL_SER 20
#define COL_OE 21 #define COL_OE 21
#define COL_RCLK 22 // #define COL_RCLK 22
#define RCLK 22
#define COL_SRCLK 26 #define COL_SRCLK 26
#define COL_SRCLR 27 #define COL_SRCLR 27
#define ROW_SER 14 #define ROW_SER 14
#define ROW_OE 13 #define ROW_OE 13
#define ROW_RCLK 12 // #define ROW_RCLK 12
#define ROW_SRCLK 11 #define ROW_SRCLK 11
#define ROW_SRCLR 10 #define ROW_SRCLR 10

View File

@ -7,15 +7,26 @@ public entry_point:
; push 24 bits to the shift registers ; push 24 bits to the shift registers
; also, return latch bit to 0 ; also, return latch bit to 0
set x, 23 side 0 set x, 23 side 0
; ignore the 8 least significant bits
out null, 8
loop: loop:
; lower clock edge ; TODO: check if delays can be lowered with a PCB
nop side 0 ; set bit; lower clock edge
; set bit out pins, 1 side 0 [1]
out pins, 1
; loop; latch bit (rising edge) ; loop; latch bit (rising edge)
; TODO: check if this delay can be lowered with a PCB
jmp x-- loop side 1 [2] jmp x-- loop side 1 [2]
end: 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

View File

@ -20,17 +20,21 @@
static const uint16_t leds_px_pusher_program_instructions[] = { static const uint16_t leds_px_pusher_program_instructions[] = {
// .wrap_target // .wrap_target
0xf037, // 0: set x, 23 side 0 0xf037, // 0: set x, 23 side 0
0x6068, // 1: out null, 8 0x7101, // 1: out pins, 1 side 0 [1]
0xb042, // 2: nop side 0 0x1a41, // 2: jmp x--, 1 side 1 [2]
0x6001, // 3: out pins, 1 0x7028, // 3: out x, 8 side 0
0x1a42, // 4: jmp x--, 2 side 1 [2] 0x0045, // 4: jmp x--, 5
// .wrap // .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 #if !PICO_NO_HARDWARE
static const struct pio_program leds_px_pusher_program = { static const struct pio_program leds_px_pusher_program = {
.instructions = leds_px_pusher_program_instructions, .instructions = leds_px_pusher_program_instructions,
.length = 5, .length = 9,
.origin = -1, .origin = -1,
}; };