1
0
Fork 0
sd2
radex 2024-05-24 18:01:23 +02:00
parent 76eef53dd0
commit f2a2b931f8
Signed by: radex
SSH Key Fingerprint: SHA256:hvqRXAGG1h89yqnS+cyFTLKQbzjWD4uXIqw7Y+0ws30
3 changed files with 109 additions and 17 deletions

View File

@ -2,11 +2,21 @@
#include "hardware/gpio.h"
#include "mbed_wait_api.h"
#include "pico/multicore.h"
#include "hardware/pio.h"
#include "leds.h"
#include "leds.pio.h"
PIO pusher_pio = pio0;
uint pusher_sm = 255; // invalid
// NOTE: RCLK, SRCLK capture on *rising* edge
inline void pulsePin(uint8_t pin) {
gpio_put(pin, HIGH);
// there are glitches without this (maybe just due to breadboard...)
_NOP();
_NOP();
_NOP();
gpio_put(pin, LOW);
}
@ -37,6 +47,7 @@ void leds_init() {
// set up col pins
pinMode(COL_SER, OUTPUT);
pinMode(COL_OE, OUTPUT);
outputEnable(ROW_OE, false);
pinMode(COL_RCLK, OUTPUT);
pinMode(COL_SRCLK, OUTPUT);
pinMode(COL_SRCLR, OUTPUT);
@ -44,6 +55,7 @@ void leds_init() {
// set up row pins
pinMode(ROW_SER, OUTPUT);
pinMode(ROW_OE, OUTPUT);
outputEnable(ROW_OE, false);
pinMode(ROW_RCLK, OUTPUT);
pinMode(ROW_SRCLK, OUTPUT);
pinMode(ROW_SRCLR, OUTPUT);
@ -70,10 +82,10 @@ void main2() {
}
}
void leds_initPusher();
void leds_initRenderer() {
// launch core1
// NOTE: For some reason, without delay, core1 doesn't start?
// delay(500);
leds_initPusher();
multicore_reset_core1();
multicore_launch_core1(main2);
}
@ -94,10 +106,12 @@ void leds_render() {
// we want to keep the matrix on during update (except during latch). At low brightness phases,
// we want it off to actually be dim
bool brightPhase = brightnessPhase >= 2;
// digitalWrite(ROW_OE, !brightPhase);
digitalWrite(ROW_OE, !brightPhase);
// next row
pulsePin(ROW_SRCLK);
gpio_put(ROW_SRCLK, HIGH);
busy_wait_us_32(1);
gpio_put(ROW_SRCLK, LOW);
// only one row
digitalWrite(ROW_SER, LOW);
@ -111,29 +125,26 @@ void leds_render() {
pulsePin(ROW_SRCLK);
}
// clear columns
clearShiftReg(COL_SRCLK, COL_SRCLR);
// set row data
size_t rowOffset = y * COL_COUNT;
for (int x = 0; x < COL_COUNT; x++) {
// get value
// NOTE: values are loaded right-left
uint8_t pxValue = framebuffer[y * ROW_COUNT + x];
// apply brightness
bool gotLight = (pxValue >> (4 + brightnessPhase)) & 1;
// set value (note: inverted logic)
gpio_put(COL_SER, !gotLight);
// push value
pulsePin(COL_SRCLK);
uint8_t pxValue = framebuffer[rowOffset + x];
// we use 7/8 stages on shift registers + 1 is unused
int moduleX = x % 20;
if (moduleX == 0) {
pulsePin(COL_SRCLK);
pio_sm_put_blocking(pusher_pio, pusher_sm, 0);
}
if (moduleX == 6 || moduleX == 13 || moduleX == 19) {
pulsePin(COL_SRCLK);
pio_sm_put_blocking(pusher_pio, pusher_sm, 0);
}
// apply brightness
bool gotLight = (pxValue >> (4 + brightnessPhase)) & 1;
// push value
pio_sm_put_blocking(pusher_pio, pusher_sm, gotLight);
}
// disable columns before latch
@ -152,3 +163,34 @@ void leds_render() {
// next brightness phase
brightnessPhase = (brightnessPhase + 1) % 4;
}
void leds_initPusher() {
PIO pio = pusher_pio;
uint sm = pio_claim_unused_sm(pio, true);
pusher_sm = sm;
uint offset = pio_add_program(pio, &leds_px_pusher_program);
uint dataPin = COL_SER;
uint latchPin = COL_SRCLK;
pio_sm_config config = leds_px_pusher_program_get_default_config(offset);
sm_config_set_clkdiv_int_frac(&config, 1, 0);
// Set OUT (data) pin, connect to pad, set as output
sm_config_set_out_pins(&config, dataPin, 1);
pio_gpio_init(pio, dataPin);
pio_sm_set_consecutive_pindirs(pio, sm, dataPin, 1, true);
// data is inverted
gpio_set_outover(dataPin, GPIO_OVERRIDE_INVERT);
// Set SET (latch) 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);
// 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);
}

8
firmware/src/leds.pio Normal file
View File

@ -0,0 +1,8 @@
.program leds_px_pusher
.side_set 1 opt
.wrap_target
public entry_point:
pull side 0
out pins, 1
nop side 1 [1]
.wrap

42
firmware/src/leds.pio.h Normal file
View File

@ -0,0 +1,42 @@
// -------------------------------------------------- //
// This file is autogenerated by pioasm; do not edit! //
// -------------------------------------------------- //
#pragma once
#if !PICO_NO_HARDWARE
#include "hardware/pio.h"
#endif
// -------------- //
// leds_px_pusher //
// -------------- //
#define leds_px_pusher_wrap_target 0
#define leds_px_pusher_wrap 2
#define leds_px_pusher_offset_entry_point 0u
static const uint16_t leds_px_pusher_program_instructions[] = {
// .wrap_target
0x90a0, // 0: pull block side 0
0x6001, // 1: out pins, 1
0xb942, // 2: nop side 1 [1]
// .wrap
};
#if !PICO_NO_HARDWARE
static const struct pio_program leds_px_pusher_program = {
.instructions = leds_px_pusher_program_instructions,
.length = 3,
.origin = -1,
};
static inline pio_sm_config leds_px_pusher_program_get_default_config(uint offset) {
pio_sm_config c = pio_get_default_sm_config();
sm_config_set_wrap(&c, offset + leds_px_pusher_wrap_target, offset + leds_px_pusher_wrap);
sm_config_set_sideset(&c, 2, true, false);
return c;
}
#endif