mirror of https://github.com/radex/radmatrix.git
Compare commits
2 Commits
a2f703c2e1
...
73b3760f68
Author | SHA1 | Date |
---|---|---|
radex | 73b3760f68 | |
radex | 90d9d64e12 |
|
@ -8,7 +8,8 @@
|
|||
#include <string.h> // memset
|
||||
// NOTE: This was changed from the original checkout
|
||||
// #include "RP2040.h" // hw_set_bits
|
||||
#include "hardware/address_mapped.h" // hw_set_bits
|
||||
#include "hardware/address_mapped.h" // hw_set_bit
|
||||
#include "cmsis_gcc.h" // NOTE: this was added for _DMB() to build
|
||||
#include "can2040.h" // can2040_setup
|
||||
#include "hardware/regs/dreq.h" // DREQ_PIO0_RX1
|
||||
#include "hardware/structs/dma.h" // dma_hw
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
#include <Arduino.h>
|
||||
#include "config.h"
|
||||
#include "can.h"
|
||||
|
||||
static void can2040_callback(struct can2040 *cd, uint32_t notify, struct can2040_msg *msg) {
|
||||
}
|
||||
|
||||
static void canbus_pio_irq_handler() {
|
||||
can2040_pio_irq_handler(&canbus);
|
||||
}
|
||||
|
||||
void canbus_setup() {
|
||||
uint32_t pio_num = 1;
|
||||
can2040_setup(&canbus, pio_num);
|
||||
can2040_callback_config(&canbus, can2040_callback);
|
||||
|
||||
irq_set_exclusive_handler(PIO1_IRQ_0, canbus_pio_irq_handler);
|
||||
irq_set_priority(PIO1_IRQ_0, 1);
|
||||
irq_set_enabled(PIO1_IRQ_0, true);
|
||||
|
||||
can2040_start(&canbus, CPU_CLOCK_HZ, CAN_BITRATE, CAN_PIN_RX, CAN_PIN_TX);
|
||||
}
|
||||
|
||||
unsigned long canbus_last_heartbeat_at = 0;
|
||||
int canbus_heartbeat_interval = 1000;
|
||||
void canbus_heartbeat();
|
||||
|
||||
void canbus_loop() {
|
||||
auto now = millis();
|
||||
if (canbus_last_heartbeat_at + canbus_heartbeat_interval < now) {
|
||||
canbus_last_heartbeat_at = now;
|
||||
// add some jitter to reduce collision likelihood
|
||||
canbus_heartbeat_interval = 1000 + random(-200, 200);
|
||||
canbus_heartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
void canbus_heartbeat() {
|
||||
int device_id = 224;
|
||||
int msg_kind = 31;
|
||||
int msg_type = 31;
|
||||
|
||||
// {kind:5}{device:8}{type:5}{reserved:11}
|
||||
uint32_t id = CAN2040_ID_EFF | ((msg_kind << (8 + 5)) | (device_id << 5) | msg_type) << 11;
|
||||
|
||||
can2040_msg msg = {
|
||||
.id = id,
|
||||
.dlc = 0,
|
||||
};
|
||||
auto result = can2040_transmit(&canbus, &msg);
|
||||
if (result != 0) {
|
||||
Serial.println("CAN: heartbeat failed");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#ifndef _can_h
|
||||
#define _can_h
|
||||
|
||||
extern "C" {
|
||||
#include "can2040.h"
|
||||
}
|
||||
|
||||
static struct can2040 canbus;
|
||||
|
||||
void canbus_setup();
|
||||
void canbus_loop();
|
||||
|
||||
#endif
|
|
@ -48,6 +48,12 @@
|
|||
#define ROW_SRCLK 18
|
||||
// #define ROW_SRCLR 15
|
||||
|
||||
#define COL_SER_INVERTED false // double inverted
|
||||
#define COL_OE_INVERTED true
|
||||
#define COL_RCLK_INVERTED true
|
||||
#define COL_SRCLK_INVERTED true
|
||||
#define COL_SRCLR_INVERTED false
|
||||
|
||||
// --- screen settings ---
|
||||
|
||||
#define ROW_MODULES 2
|
||||
|
@ -71,6 +77,7 @@
|
|||
#define CPU_CLOCK_HZ 125000000.0f
|
||||
#define SD_CARD_BAUD_RATE 10 * 1000 * 1000
|
||||
#define REFERENCE_VOLTAGE 3.3f // for ADC
|
||||
#define CAN_BITRATE 500000
|
||||
|
||||
// --- debug settings ---
|
||||
|
||||
|
|
|
@ -141,6 +141,23 @@ void leds_init() {
|
|||
pinMode(ROW_SRCLK, OUTPUT);
|
||||
pinMode(ROW_SRCLR, OUTPUT);
|
||||
|
||||
// set pin inversion
|
||||
#if COL_SER_INVERTED
|
||||
gpio_set_outover(COL_SER, GPIO_OVERRIDE_INVERT);
|
||||
#endif
|
||||
#if COL_OE_INVERTED
|
||||
gpio_set_outover(COL_OE, GPIO_OVERRIDE_INVERT);
|
||||
#endif
|
||||
#if COL_RCLK_INVERTED
|
||||
gpio_set_outover(COL_RCLK, GPIO_OVERRIDE_INVERT);
|
||||
#endif
|
||||
#if COL_SRCLK_INVERTED
|
||||
gpio_set_outover(COL_SRCLK, GPIO_OVERRIDE_INVERT);
|
||||
#endif
|
||||
#if COL_SRCLR_INVERTED
|
||||
gpio_set_outover(COL_SRCLR, GPIO_OVERRIDE_INVERT);
|
||||
#endif
|
||||
|
||||
// clear output
|
||||
clearShiftReg(COL_SRCLK, COL_SRCLR);
|
||||
clearShiftReg(ROW_SRCLK, ROW_SRCLR);
|
||||
|
@ -238,18 +255,15 @@ void leds_initPusher() {
|
|||
pio_gpio_init(pio, COL_SER);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, COL_SER, 1, true);
|
||||
|
||||
// data is inverted
|
||||
gpio_set_outover(COL_SER, GPIO_OVERRIDE_INVERT);
|
||||
|
||||
// Set sideset (SRCLK) pin, connect to pad, set as output
|
||||
sm_config_set_sideset_pins(&config, COL_SRCLK);
|
||||
pio_gpio_init(pio, COL_SRCLK);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, COL_SRCLK, 1, true);
|
||||
|
||||
// Set SET (RCLK) pin, connect to pad, set as output
|
||||
sm_config_set_set_pins(&config, ROW_RCLK, 1);
|
||||
pio_gpio_init(pio, ROW_RCLK);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, ROW_RCLK, 1, true);
|
||||
sm_config_set_set_pins(&config, COL_RCLK, 1);
|
||||
pio_gpio_init(pio, COL_RCLK);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, COL_RCLK, 1, true);
|
||||
|
||||
// Load our configuration, and jump to the start of the program
|
||||
pio_sm_init(pio, sm, offset, &config);
|
||||
|
@ -269,9 +283,8 @@ void leds_initRowSelector() {
|
|||
// Shift OSR to the right, autopull
|
||||
sm_config_set_out_shift(&config, true, true, 32);
|
||||
|
||||
// Set OUT and SET (data) pin, connect to pad, set as output
|
||||
// Set OUT/MOV (data) pin, connect to pad, set as output
|
||||
sm_config_set_out_pins(&config, ROW_SER, 1);
|
||||
sm_config_set_set_pins(&config, ROW_SER, 1);
|
||||
pio_gpio_init(pio, ROW_SER);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, ROW_SER, 1, true);
|
||||
|
||||
|
@ -280,6 +293,11 @@ void leds_initRowSelector() {
|
|||
pio_gpio_init(pio, ROW_SRCLK);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, ROW_SRCLK, 1, true);
|
||||
|
||||
// Set SET (RCLK) pin, connect to pad, set as output
|
||||
sm_config_set_set_pins(&config, ROW_RCLK, 1);
|
||||
pio_gpio_init(pio, ROW_RCLK);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, ROW_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);
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
.define public irq_did_latch 0
|
||||
.define public irq_row_selected 1
|
||||
.define public irq_delaying 2
|
||||
.define public irq_delaying 0
|
||||
.define public irq_px_pushed 1
|
||||
.define public irq_rclk_sync 2
|
||||
.define public irq_did_latch 3
|
||||
|
||||
; TODO: check if delays can be lowered with a PCB
|
||||
.define public srclk_0_delay 1
|
||||
.define public srclk_1_delay 2
|
||||
.define public rclk_1_delay 3
|
||||
|
||||
.program leds_px_pusher
|
||||
.side_set 1 opt
|
||||
.define public srclk_0_delay 1
|
||||
.define public srclk_1_delay 2
|
||||
entry_point:
|
||||
.wrap_target
|
||||
; get 32 bits from fifo (not required with autopull, useful for debug)
|
||||
|
@ -29,13 +29,13 @@ end:
|
|||
; MSB=1 indicates end of row
|
||||
jmp !x entry_point
|
||||
end_of_row:
|
||||
; pixels pushed - can begin row selection
|
||||
irq set irq_px_pushed
|
||||
; wait until previous row's delay is complete
|
||||
; (irq will be 0 on first row by default)
|
||||
wait 0 irq irq_delaying
|
||||
; wait until row is selected, and clear flag
|
||||
wait 1 irq irq_row_selected
|
||||
; signal that we're about to latch the row onto display
|
||||
irq set irq_did_latch
|
||||
; synchronize ROW_RCLK and COL_RCLK - note that the delays MUST be the same
|
||||
wait 1 irq irq_rclk_sync
|
||||
; clock RCLK (latch onto register output stage)
|
||||
set pins, 1 [rclk_1_delay]
|
||||
set pins, 0
|
||||
|
@ -44,22 +44,31 @@ end_of_row:
|
|||
|
||||
.program leds_row_selector
|
||||
.side_set 1 opt
|
||||
.define public srclk_0_delay 1
|
||||
.define public srclk_1_delay 2
|
||||
entry_point:
|
||||
.wrap_target
|
||||
; wait until pixels are pushed
|
||||
; (NOTE: This can happen in parallel if ROW_SER and COL_SER are separate)
|
||||
wait 1 irq irq_px_pushed
|
||||
; LSB=1 indicates first (bottom) row, ergo, high SER for the first pulse
|
||||
out pins, 1 side 0 [srclk_0_delay]
|
||||
; The rest of the word indicates number of extra SRCLK pulses
|
||||
out x, 31
|
||||
loop:
|
||||
; pulse SRCLK x times
|
||||
; set SER=0 after first pulse
|
||||
nop side 1 [srclk_1_delay]
|
||||
set pins, 0 side 0 [srclk_0_delay]
|
||||
; set SER=0 after first pulse
|
||||
mov pins, null side 0 [srclk_0_delay]
|
||||
jmp x-- loop
|
||||
end:
|
||||
; signal that row is selected and wait until acknowledged
|
||||
; some delay so that in the worst case scenario we don't start changing rows before RCLK latch
|
||||
irq wait irq_row_selected [4]
|
||||
; synchronize ROW_RCLK and COL_RCLK - note that the delays MUST be the same
|
||||
irq wait irq_rclk_sync
|
||||
; clock RCLK (latch onto register output stage)
|
||||
set pins, 1 [rclk_1_delay]
|
||||
; signal that rclk had latched (delay/oe can begin)
|
||||
irq set irq_did_latch
|
||||
set pins, 0
|
||||
.wrap
|
||||
|
||||
.program leds_delay
|
||||
|
|
|
@ -8,11 +8,10 @@
|
|||
#include "hardware/pio.h"
|
||||
#endif
|
||||
|
||||
#define irq_did_latch 0
|
||||
#define irq_row_selected 1
|
||||
#define irq_delaying 2
|
||||
#define srclk_0_delay 1
|
||||
#define srclk_1_delay 2
|
||||
#define irq_delaying 0
|
||||
#define irq_px_pushed 1
|
||||
#define irq_rclk_sync 2
|
||||
#define irq_did_latch 3
|
||||
#define rclk_1_delay 3
|
||||
|
||||
// -------------- //
|
||||
|
@ -22,6 +21,9 @@
|
|||
#define leds_px_pusher_wrap_target 0
|
||||
#define leds_px_pusher_wrap 9
|
||||
|
||||
#define leds_px_pusher_srclk_0_delay 1
|
||||
#define leds_px_pusher_srclk_1_delay 2
|
||||
|
||||
static const uint16_t leds_px_pusher_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0xf037, // 0: set x, 23 side 0
|
||||
|
@ -29,9 +31,9 @@ static const uint16_t leds_px_pusher_program_instructions[] = {
|
|||
0x1a41, // 2: jmp x--, 1 side 1 [2]
|
||||
0x7028, // 3: out x, 8 side 0
|
||||
0x0020, // 4: jmp !x, 0
|
||||
0x2042, // 5: wait 0 irq, 2
|
||||
0x20c1, // 6: wait 1 irq, 1
|
||||
0xc000, // 7: irq nowait 0
|
||||
0xc001, // 5: irq nowait 1
|
||||
0x2040, // 6: wait 0 irq, 0
|
||||
0x20c2, // 7: wait 1 irq, 2
|
||||
0xe301, // 8: set pins, 1 [3]
|
||||
0xe000, // 9: set pins, 0
|
||||
// .wrap
|
||||
|
@ -57,23 +59,30 @@ static inline pio_sm_config leds_px_pusher_program_get_default_config(uint offse
|
|||
// ----------------- //
|
||||
|
||||
#define leds_row_selector_wrap_target 0
|
||||
#define leds_row_selector_wrap 5
|
||||
#define leds_row_selector_wrap 9
|
||||
|
||||
#define leds_row_selector_srclk_0_delay 1
|
||||
#define leds_row_selector_srclk_1_delay 2
|
||||
|
||||
static const uint16_t leds_row_selector_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x7101, // 0: out pins, 1 side 0 [1]
|
||||
0x603f, // 1: out x, 31
|
||||
0xba42, // 2: nop side 1 [2]
|
||||
0xf100, // 3: set pins, 0 side 0 [1]
|
||||
0x0042, // 4: jmp x--, 2
|
||||
0xc421, // 5: irq wait 1 [4]
|
||||
0x20c1, // 0: wait 1 irq, 1
|
||||
0x7101, // 1: out pins, 1 side 0 [1]
|
||||
0x603f, // 2: out x, 31
|
||||
0xba42, // 3: nop side 1 [2]
|
||||
0xb103, // 4: mov pins, null side 0 [1]
|
||||
0x0043, // 5: jmp x--, 3
|
||||
0xc022, // 6: irq wait 2
|
||||
0xe301, // 7: set pins, 1 [3]
|
||||
0xc003, // 8: irq nowait 3
|
||||
0xe000, // 9: set pins, 0
|
||||
// .wrap
|
||||
};
|
||||
|
||||
#if !PICO_NO_HARDWARE
|
||||
static const struct pio_program leds_row_selector_program = {
|
||||
.instructions = leds_row_selector_program_instructions,
|
||||
.length = 6,
|
||||
.length = 10,
|
||||
.origin = -1,
|
||||
};
|
||||
|
||||
|
@ -97,11 +106,11 @@ static inline pio_sm_config leds_row_selector_program_get_default_config(uint of
|
|||
|
||||
static const uint16_t leds_delay_program_instructions[] = {
|
||||
// .wrap_target
|
||||
0x20c0, // 0: wait 1 irq, 0
|
||||
0xc002, // 1: irq nowait 2
|
||||
0x20c3, // 0: wait 1 irq, 3
|
||||
0xc000, // 1: irq nowait 0
|
||||
0x6020, // 2: out x, 32
|
||||
0x1043, // 3: jmp x--, 3 side 0
|
||||
0xd842, // 4: irq clear 2 side 1
|
||||
0xd840, // 4: irq clear 0 side 1
|
||||
// .wrap
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@ void setup() {
|
|||
init_audio();
|
||||
leds_initRenderer();
|
||||
|
||||
#if CAN_ENABLED
|
||||
canbus_setup();
|
||||
#endif
|
||||
|
||||
#if SD_HAS_DETECTION
|
||||
while (!isSDCardInserted()) {
|
||||
Serial.println("SD card not connected, waiting...");
|
||||
|
@ -100,4 +104,8 @@ void loop() {
|
|||
nextSong();
|
||||
}
|
||||
}
|
||||
|
||||
#if CAN_ENABLED
|
||||
canbus_loop();
|
||||
#endif
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue