diff --git a/src/main.rs b/src/main.rs index 17b3d36..7c51707 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ //! GP15..GP22 => D0..D7 //! GP26 => CE //! GP27 => OE +//! GP28 => Clock mod serial; @@ -26,11 +27,12 @@ use embassy_rp::{ flash::{self, FLASH_BASE, Flash}, gpio::{Drive, Level, Output, SlewRate}, multicore::{Stack, spawn_core1}, + pac::SIO, 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}, }; -use embassy_time::Timer; +use embassy_time::{Duration, Ticker, Timer}; use embassy_usb::{ UsbDevice, class::cdc_acm::{self, CdcAcmClass}, @@ -40,9 +42,6 @@ use static_cell::{ConstStaticCell, StaticCell}; use crate::serial::{Link, PacketBuilder}; -const ADDRESS_PINS: u8 = 15; -const DATA_PINS: u8 = 8; - const ROM_SIZE: usize = 32 * 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))); 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); @@ -76,27 +76,16 @@ async fn main(spawner: Spawner) -> ! { let data = pio_asm!(".wrap_target", "out pins, 8", ".wrap"); // OR CE and OE and set 4 pindirs let output_enable = pio_asm!( - ".origin 0", - ".side_set 4 pindirs", - "mov pc, pins side 0xf", - "mov pc, pins side 0x0", - "mov pc, pins side 0x0", - "mov pc, pins side 0x0" - ); - // report pin activity to the cpu - let report_data = pio_asm!( - "wait_oe:", - "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" + ".side_set 4 opt pindirs", + "loop:", + "in NULL, 32", + "in pins, 2", + "mov x, isr", + "jmp !x low", + "high:", + "jmp loop side 0x0", + "low:", + "jmp loop side 0xf", ); let Pio { @@ -104,7 +93,6 @@ async fn main(spawner: Spawner) -> ! { mut sm0, mut sm1, mut sm2, - mut sm3, .. } = Pio::new(p.PIO0, Irqs); let output_enable = common.load_program(&output_enable.program); @@ -158,44 +146,13 @@ async fn main(spawner: Spawner) -> ! { ce_pin.set_schmitt(true); let mut oe_pin = common.make_pio_pin(p.PIN_27); 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 let mut cfg = pio::Config::default(); cfg.use_program(&common.load_program(&data.program), &[]); cfg.set_out_pins(&data_pins[..]); cfg.shift_out = ShiftConfig { - threshold: DATA_PINS, + threshold: u8::try_from(data_pins.len()).unwrap_or(32), direction: ShiftDirection::default(), auto_fill: true, }; @@ -212,30 +169,12 @@ async fn main(spawner: Spawner) -> ! { sm2.set_config(&cfg); 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( p.CORE1, 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 config = { @@ -270,8 +209,9 @@ async fn main(spawner: Spawner) -> ! { let usb = builder.build(); spawner.must_spawn(usb_task(usb)); + spawner.must_spawn(clock_task(clock)); - let mut led = Output::new(led, Level::Low); + led.set_low(); loop { 'outer: { @@ -319,17 +259,17 @@ async fn main(spawner: Spawner) -> ! { } } -fn core1_loop( - mut data_sm: StateMachine<'_, impl pio::Instance, N1>, - mut address_sm: StateMachine<'_, impl pio::Instance, N2>, -) -> ! { +fn core1_loop(mut data_sm: StateMachine<'_, impl pio::Instance, N>) -> ! { + let mut last_address = 0; loop { - let address = loop { - if let Some(address) = address_sm.rx().try_pull() { - break address; - } - }; + let address = SIO.gpio_in(0).read(); 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); defmt::debug!("replying with {:#04x} @ {:#06x}", data, address); data_sm.tx().push(u32::from(data)); @@ -342,16 +282,11 @@ async fn usb_task(mut usb: UsbDevice<'static, Driver<'static, USB>>) -> ! { } #[task] -async fn pio_task( - mut data_sm: StateMachine<'static, PIO0, 0>, - mut address_sm: StateMachine<'static, PIO0, 3>, -) -> ! { +async fn clock_task(mut clock: Output<'static>) -> ! { + let mut ticker = Ticker::every(Duration::from_millis(250)); loop { - let address = address_sm.rx().wait_pull().await; - let address = (address & 0x7fff) as u16; - 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)); + clock.toggle(); + ticker.next().await; } }