Fix some stuff and add clock output
This commit is contained in:
131
src/main.rs
131
src/main.rs
@@ -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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user