diff --git a/Cargo.toml b/Cargo.toml index a3358ab..57ec3d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ version = "0.1.0" [dependencies] cortex-m = "0.7" cortex-m-rt = "0.7" +cortex-m-rtic = "1.1.2" embedded-hal = { version = "0.2.5", features = ["unproven"] } defmt = "0.3" @@ -14,6 +15,11 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } # We're using a Pico by default on this template rp-pico = "0.5" +rp2040-monotonic = "1.1.0" + +usb-device = "0.2.8" +usbd-serial = "0.1.1" +usbd-hid = "0.5.1" # but you can use any BSP. Uncomment this to use the pro_micro_rp2040 BSP instead # sparkfun-pro-micro-rp2040 = "0.3" diff --git a/src/main.rs b/src/main.rs index 027ffb1..5066952 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,149 +4,200 @@ #![no_std] #![no_main] -use bsp::entry; -use defmt::*; use defmt_rtt as _; -use embedded_hal::digital::v2::OutputPin; + use panic_probe as _; -// Provide an alias for our BSP so we can switch targets quickly. -// Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. -use rp_pico as bsp; -// use sparkfun_pro_micro_rp2040 as bsp; - -use bsp::hal::{ - clocks::{init_clocks_and_plls, Clock}, - pac, - sio::Sio, - watchdog::Watchdog, -}; - mod flipdot; -use crate::flipdot::write_display; -#[entry] -fn main() -> ! { - info!("Program start"); - let mut pac = pac::Peripherals::take().unwrap(); - let core = pac::CorePeripherals::take().unwrap(); - let mut watchdog = Watchdog::new(pac.WATCHDOG); - let sio = Sio::new(pac.SIO); +#[rtic::app(device = rp_pico::hal::pac, peripherals = true, dispatchers = [XIP_IRQ])] +mod app { - // External high-speed crystal on the pico board is 12Mhz - let external_xtal_freq_hz = 12_000_000u32; - let clocks = init_clocks_and_plls( - external_xtal_freq_hz, - pac.XOSC, - pac.CLOCKS, - pac.PLL_SYS, - pac.PLL_USB, - &mut pac.RESETS, - &mut watchdog, - ) - .ok() - .unwrap(); + use embedded_hal::digital::v2::OutputPin; - let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); + use rp_pico::hal; + use rp_pico::hal::*; + use rp_pico::XOSC_CRYSTAL_FREQ; - let pins = bsp::Pins::new( - pac.IO_BANK0, - pac.PADS_BANK0, - sio.gpio_bank0, - &mut pac.RESETS, - ); + // USB Device support + use usb_device::{class_prelude::*, prelude::*}; + // USB Communications Class Device support + use usbd_serial::SerialPort; - let mut led_pin = pins.led.into_push_pull_output(); + use rp2040_monotonic::fugit::ExtU64; + use rp2040_monotonic::*; - let mut row_data_pin = pins.gpio4.into_push_pull_output(); - let mut row_clock_pin = pins.gpio5.into_push_pull_output(); + use crate::flipdot::write_display; - let mut col_data_pin = pins.gpio2.into_push_pull_output(); - let mut col_clock_pin = pins.gpio3.into_push_pull_output(); + #[monotonic(binds = TIMER_IRQ_0, default = true)] + type Monotonic = Rp2040Monotonic; - let mut white_pin = pins.gpio6.into_push_pull_output(); - let mut black_pin = pins.gpio7.into_push_pull_output(); - let mut strobe_pin = pins.gpio8.into_push_pull_output(); + #[shared] + struct Shared { + serial: SerialPort<'static, hal::usb::UsbBus>, + usb_dev: usb_device::device::UsbDevice<'static, hal::usb::UsbBus>, + } - write_display( - &[0; 16], - &mut col_clock_pin, - &mut col_data_pin, - &mut row_clock_pin, - &mut row_data_pin, - &mut strobe_pin, - &mut white_pin, - &mut black_pin, - &mut delay, - ); + #[local] + struct Local { + led_pin: hal::gpio::Pin, + row_data_pin: hal::gpio::Pin, + row_clock_pin: hal::gpio::Pin, + col_data_pin: hal::gpio::Pin, + col_clock_pin: hal::gpio::Pin, + white_pin: hal::gpio::Pin, + black_pin: hal::gpio::Pin, + strobe_pin: hal::gpio::Pin, + delay: cortex_m::delay::Delay, + pattern: bool, + } - let pattern1 = [ - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0100_0000_0101_0101, - 0b1010_1010_1111_0010_1010, - 0b0101_0100_0001_0101_0101, - 0b1010_1010_0001_0010_1010, - 0b0101_0100_1001_0101_0101, - 0b1010_1010_0000_0010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - ]; + #[init(local = [usb_bus: Option> = None])] + fn init(c: init::Context) -> (Shared, Local, init::Monotonics) { + let mut resets = c.device.RESETS; + let mut watchdog = hal::watchdog::Watchdog::new(c.device.WATCHDOG); - let pattern2 = [ - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_0000_0010_1010, - 0b0101_0100_1111_0101_0101, - 0b1010_1010_0001_0010_1010, - 0b0101_0100_0001_0101_0101, - 0b1010_1010_1001_0010_1010, - 0b0101_0100_0000_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - 0b0101_0101_0101_0101_0101, - 0b1010_1010_1010_1010_1010, - ]; + // Configure the clocks - The default is to generate a 125 MHz system clock + let clocks = hal::clocks::init_clocks_and_plls( + XOSC_CRYSTAL_FREQ, + c.device.XOSC, + c.device.CLOCKS, + c.device.PLL_SYS, + c.device.PLL_USB, + &mut resets, + &mut watchdog, + ) + .ok() + .unwrap(); - loop { + let mut delay = + cortex_m::delay::Delay::new(c.core.SYST, clocks.system_clock.freq().to_Hz()); + + let usb_bus: &'static _ = + c.local + .usb_bus + .insert(UsbBusAllocator::new(hal::usb::UsbBus::new( + c.device.USBCTRL_REGS, + c.device.USBCTRL_DPRAM, + clocks.usb_clock, + true, + &mut resets, + ))); + + let serial = SerialPort::new(usb_bus); + + let usb_dev = UsbDeviceBuilder::new(usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST") + .device_class(2) // from: https://www.usb.org/defined-class-codes + .build(); + + let sio = hal::Sio::new(c.device.SIO); + let pins = rp_pico::Pins::new( + c.device.IO_BANK0, + c.device.PADS_BANK0, + sio.gpio_bank0, + &mut resets, + ); + + let mut led_pin = pins.led.into_push_pull_output(); led_pin.set_low().unwrap(); - write_display( - &pattern1, - &mut col_clock_pin, - &mut col_data_pin, - &mut row_clock_pin, - &mut row_data_pin, - &mut strobe_pin, - &mut white_pin, - &mut black_pin, - &mut delay, - ); - delay.delay_ms(1000); - led_pin.set_high().unwrap(); + let row_data_pin = pins.gpio4.into_push_pull_output(); + let row_clock_pin = pins.gpio5.into_push_pull_output(); + + let col_data_pin = pins.gpio2.into_push_pull_output(); + let col_clock_pin = pins.gpio3.into_push_pull_output(); + + let white_pin = pins.gpio6.into_push_pull_output(); + let black_pin = pins.gpio7.into_push_pull_output(); + let strobe_pin = pins.gpio8.into_push_pull_output(); + + let pattern = false; + + update_display::spawn_after(1.secs()).unwrap(); + + ( + Shared { serial, usb_dev }, + Local { + led_pin, + row_data_pin, + row_clock_pin, + col_data_pin, + col_clock_pin, + white_pin, + black_pin, + strobe_pin, + delay, + pattern, + }, + init::Monotonics(Rp2040Monotonic::new(c.device.TIMER)), + ) + } + + #[task(local = [pattern, led_pin, row_data_pin, row_clock_pin, col_data_pin, + col_clock_pin, white_pin, black_pin, strobe_pin, delay])] + fn update_display(cx: update_display::Context) { + let pattern = if *cx.local.pattern { + [ + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0100_0000_0101_0101, + 0b1010_1010_1111_0010_1010, + 0b0101_0100_0001_0101_0101, + 0b1010_1010_0001_0010_1010, + 0b0101_0100_1001_0101_0101, + 0b1010_1010_0000_0010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + ] + } else { + [ + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_0000_0010_1010, + 0b0101_0100_1111_0101_0101, + 0b1010_1010_0001_0010_1010, + 0b0101_0100_0001_0101_0101, + 0b1010_1010_1001_0010_1010, + 0b0101_0100_0000_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + 0b0101_0101_0101_0101_0101, + 0b1010_1010_1010_1010_1010, + ] + }; + + if *cx.local.pattern { + cx.local.led_pin.set_high().unwrap(); + } else { + cx.local.led_pin.set_low().unwrap(); + } + *cx.local.pattern = !*cx.local.pattern; + write_display( - &pattern2, - &mut col_clock_pin, - &mut col_data_pin, - &mut row_clock_pin, - &mut row_data_pin, - &mut strobe_pin, - &mut white_pin, - &mut black_pin, - &mut delay, + &pattern, + cx.local.col_clock_pin, + cx.local.col_data_pin, + cx.local.row_clock_pin, + cx.local.row_data_pin, + cx.local.strobe_pin, + cx.local.white_pin, + cx.local.black_pin, + cx.local.delay, ); - delay.delay_ms(1000); + + update_display::spawn_after(1.secs()).unwrap(); } } - -// End of file