Fix some stuff and add clock output

This commit is contained in:
2025-11-28 23:53:37 +01:00
parent 6cf860fb34
commit 657c06e978

View File

@@ -7,6 +7,7 @@
//! GP15..GP22 => D0..D7 //! GP15..GP22 => D0..D7
//! GP26 => CE //! GP26 => CE
//! GP27 => OE //! GP27 => OE
//! GP28 => Clock
mod serial; mod serial;
@@ -26,11 +27,12 @@ use embassy_rp::{
flash::{self, FLASH_BASE, Flash}, flash::{self, FLASH_BASE, Flash},
gpio::{Drive, Level, Output, SlewRate}, gpio::{Drive, Level, Output, SlewRate},
multicore::{Stack, spawn_core1}, multicore::{Stack, spawn_core1},
pac::SIO,
peripherals::{FLASH, PIO0, USB}, peripherals::{FLASH, PIO0, USB},
pio::{self, Direction, Pio, ShiftConfig, ShiftDirection, StateMachine, program::pio_asm}, pio::{self, Pio, ShiftConfig, ShiftDirection, StateMachine, program::pio_asm},
usb::{self, Driver}, usb::{self, Driver},
}; };
use embassy_time::Timer; use embassy_time::{Duration, Ticker, Timer};
use embassy_usb::{ use embassy_usb::{
UsbDevice, UsbDevice,
class::cdc_acm::{self, CdcAcmClass}, class::cdc_acm::{self, CdcAcmClass},
@@ -40,9 +42,6 @@ use static_cell::{ConstStaticCell, StaticCell};
use crate::serial::{Link, PacketBuilder}; use crate::serial::{Link, PacketBuilder};
const ADDRESS_PINS: u8 = 15;
const DATA_PINS: u8 = 8;
const ROM_SIZE: usize = 32 * 1024; const ROM_SIZE: usize = 32 * 1024;
const FLASH_SIZE: usize = 2 * 1024 * 1024; const FLASH_SIZE: usize = 2 * 1024 * 1024;
@@ -64,7 +63,8 @@ async fn main(spawner: Spawner) -> ! {
embassy_rp::config::Config::new(defmt::unwrap!(ClockConfig::system_freq(200_000_000))); embassy_rp::config::Config::new(defmt::unwrap!(ClockConfig::system_freq(200_000_000)));
let p = embassy_rp::init(config); let p = embassy_rp::init(config);
let led = unsafe { p.PIN_25.clone_unchecked() }; let mut led = Output::new(p.PIN_25, Level::High);
let clock = Output::new(p.PIN_28, Level::Low);
let mut flash = Flash::<_, _, FLASH_SIZE>::new_blocking(p.FLASH); let mut flash = Flash::<_, _, FLASH_SIZE>::new_blocking(p.FLASH);
@@ -76,27 +76,16 @@ async fn main(spawner: Spawner) -> ! {
let data = pio_asm!(".wrap_target", "out pins, 8", ".wrap"); let data = pio_asm!(".wrap_target", "out pins, 8", ".wrap");
// OR CE and OE and set 4 pindirs // OR CE and OE and set 4 pindirs
let output_enable = pio_asm!( let output_enable = pio_asm!(
".origin 0", ".side_set 4 opt pindirs",
".side_set 4 pindirs", "loop:",
"mov pc, pins side 0xf", "in NULL, 32",
"mov pc, pins side 0x0", "in pins, 2",
"mov pc, pins side 0x0", "mov x, isr",
"mov pc, pins side 0x0" "jmp !x low",
); "high:",
// report pin activity to the cpu "jmp loop side 0x0",
let report_data = pio_asm!( "low:",
"wait_oe:", "jmp loop side 0xf",
"mov y, pins", // read all pins
"mov osr, y", // move into the osr so we can shift them out
"out null, 26", // skipp all pins until CE
"out x, 2", // put CE and OE into x
"jmp x--, wait_oe", // if any of CE and OE are set go back to the start
"mov isr, y", // put the address into the isr
"push",
".wrap_target",
"mov x, pins", // read all pins
"jmp x!=y wait_oe", // if any pins have changed, restart and check oe again
".wrap"
); );
let Pio { let Pio {
@@ -104,7 +93,6 @@ async fn main(spawner: Spawner) -> ! {
mut sm0, mut sm0,
mut sm1, mut sm1,
mut sm2, mut sm2,
mut sm3,
.. ..
} = Pio::new(p.PIO0, Irqs); } = Pio::new(p.PIO0, Irqs);
let output_enable = common.load_program(&output_enable.program); let output_enable = common.load_program(&output_enable.program);
@@ -158,44 +146,13 @@ async fn main(spawner: Spawner) -> ! {
ce_pin.set_schmitt(true); ce_pin.set_schmitt(true);
let mut oe_pin = common.make_pio_pin(p.PIN_27); let mut oe_pin = common.make_pio_pin(p.PIN_27);
oe_pin.set_schmitt(true); oe_pin.set_schmitt(true);
let led_pin = common.make_pio_pin(p.PIN_25);
let address_pins = [
&address_pins[0],
&address_pins[1],
&address_pins[2],
&address_pins[3],
&address_pins[4],
&address_pins[5],
&address_pins[6],
&address_pins[7],
&address_pins[8],
&address_pins[9],
&address_pins[10],
&address_pins[11],
&address_pins[12],
&address_pins[13],
&address_pins[14],
data_pins[0],
data_pins[1],
data_pins[2],
data_pins[3],
data_pins[4],
data_pins[5],
data_pins[6],
data_pins[7],
&common.make_pio_pin(p.PIN_23),
&common.make_pio_pin(p.PIN_24),
&led_pin,
&ce_pin,
&oe_pin,
];
// configure data pio // configure data pio
let mut cfg = pio::Config::default(); let mut cfg = pio::Config::default();
cfg.use_program(&common.load_program(&data.program), &[]); cfg.use_program(&common.load_program(&data.program), &[]);
cfg.set_out_pins(&data_pins[..]); cfg.set_out_pins(&data_pins[..]);
cfg.shift_out = ShiftConfig { cfg.shift_out = ShiftConfig {
threshold: DATA_PINS, threshold: u8::try_from(data_pins.len()).unwrap_or(32),
direction: ShiftDirection::default(), direction: ShiftDirection::default(),
auto_fill: true, auto_fill: true,
}; };
@@ -212,30 +169,12 @@ async fn main(spawner: Spawner) -> ! {
sm2.set_config(&cfg); sm2.set_config(&cfg);
sm2.set_enable(true); sm2.set_enable(true);
// configure address pio
let mut cfg = pio::Config::default();
cfg.use_program(&common.load_program(&report_data.program), &[]);
cfg.set_in_pins(&address_pins[..]);
cfg.shift_in = ShiftConfig {
threshold: ADDRESS_PINS,
direction: ShiftDirection::default(),
auto_fill: true,
};
sm3.set_pin_dirs(Direction::In, &address_pins[..]);
sm3.set_pin_dirs(Direction::Out, &[&led_pin]);
sm3.set_config(&cfg);
sm3.set_enable(true);
spawn_core1( spawn_core1(
p.CORE1, p.CORE1,
unsafe { &mut *addr_of_mut!(CORE1_STACK) }, unsafe { &mut *addr_of_mut!(CORE1_STACK) },
move || core1_loop(sm0, sm3), move || core1_loop(sm0),
); );
// enable the rx not empty interrupt for sm3 on interrupt line 0
// let pio = PIO0;
// pio.irqs(0).inte().modify(|m| m.set_sm3_rxnempty(true));
let driver = Driver::new(p.USB, Irqs); let driver = Driver::new(p.USB, Irqs);
let config = { let config = {
@@ -270,8 +209,9 @@ async fn main(spawner: Spawner) -> ! {
let usb = builder.build(); let usb = builder.build();
spawner.must_spawn(usb_task(usb)); spawner.must_spawn(usb_task(usb));
spawner.must_spawn(clock_task(clock));
let mut led = Output::new(led, Level::Low); led.set_low();
loop { loop {
'outer: { 'outer: {
@@ -319,17 +259,17 @@ async fn main(spawner: Spawner) -> ! {
} }
} }
fn core1_loop<const N1: usize, const N2: usize>( fn core1_loop<const N: usize>(mut data_sm: StateMachine<'_, impl pio::Instance, N>) -> ! {
mut data_sm: StateMachine<'_, impl pio::Instance, N1>, let mut last_address = 0;
mut address_sm: StateMachine<'_, impl pio::Instance, N2>,
) -> ! {
loop { loop {
let address = loop { let address = SIO.gpio_in(0).read();
if let Some(address) = address_sm.rx().try_pull() {
break address;
}
};
let address = (address & 0x7fff) as u16; let address = (address & 0x7fff) as u16;
let address2 = SIO.gpio_in(0).read();
let address2 = (address2 & 0x7fff) as u16;
if address != address2 || address == last_address {
continue;
}
last_address = address;
let data = ROM_DATA[usize::from(address)].load(Ordering::Relaxed); let data = ROM_DATA[usize::from(address)].load(Ordering::Relaxed);
defmt::debug!("replying with {:#04x} @ {:#06x}", data, address); defmt::debug!("replying with {:#04x} @ {:#06x}", data, address);
data_sm.tx().push(u32::from(data)); data_sm.tx().push(u32::from(data));
@@ -342,16 +282,11 @@ async fn usb_task(mut usb: UsbDevice<'static, Driver<'static, USB>>) -> ! {
} }
#[task] #[task]
async fn pio_task( async fn clock_task(mut clock: Output<'static>) -> ! {
mut data_sm: StateMachine<'static, PIO0, 0>, let mut ticker = Ticker::every(Duration::from_millis(250));
mut address_sm: StateMachine<'static, PIO0, 3>,
) -> ! {
loop { loop {
let address = address_sm.rx().wait_pull().await; clock.toggle();
let address = (address & 0x7fff) as u16; ticker.next().await;
let data = ROM_DATA[usize::from(address)].load(Ordering::SeqCst);
defmt::trace!("replying with {:#04x} @ {:#06x}", data, address);
data_sm.tx().try_push(u32::from(data));
} }
} }