#![no_std] #![no_main] use keyberon::key_code::KbHidReport; use panic_halt as _; pub use sparkfun_pro_micro_rp2040::hal; mod layout; use hal::gpio::DynPin; use hal::usb::UsbBus; use keyberon::debounce::Debouncer; use keyberon::layout::Layout; use keyberon::matrix::Matrix; use hal::timer::Alarm; use hal::timer::Alarm0; use usb_device::bus::UsbBusAllocator; use usb_device::class::UsbClass as _; hal::bsp_pins!( Gpio0 { name: tx0 }, Gpio1 { name: rx0 }, Gpio2 { name: gpio2 }, Gpio3 { name: gpio3 }, Gpio4 { name: gpio4 }, Gpio5 { name: gpio5 }, Gpio6 { name: gpio6 }, Gpio7 { name: gpio7 }, Gpio8 { name: tx1 }, Gpio9 { name: rx1 }, Gpio16 { name: sda }, Gpio17 { name: scl }, Gpio20 { name: cipo }, Gpio21 { name: ncs }, Gpio22 { name: sck }, Gpio23 { name: copi }, Gpio25 { name: led }, Gpio26 { name: adc0 }, Gpio27 { name: adc1 }, Gpio28 { name: adc2 }, Gpio29 { name: adc3 }, ); type UsbClass = keyberon::Class<'static, UsbBus, ()>; type UsbDevice = usb_device::device::UsbDevice<'static, UsbBus>; const POLL_RATE: u32 = 100; #[rtic::app(device = sparkfun_pro_micro_rp2040::hal::pac, peripherals = true)] mod app { use fugit::MicrosDurationU32; use super::*; #[shared] struct Shared { usb_class: UsbClass, alarm: Alarm0, } #[local] struct Local { debouncer: Debouncer<[[bool; 4]; 5]>, matrix: Matrix, layout: Layout<4, 5, 1, ()>, usb_dev: UsbDevice, } #[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::new(c.device.WATCHDOG); // configure clocks let clocks = hal::clocks::init_clocks_and_plls( sparkfun_pro_micro_rp2040::XOSC_CRYSTAL_FREQ, c.device.XOSC, c.device.CLOCKS, c.device.PLL_SYS, c.device.PLL_USB, &mut resets, &mut watchdog, ) .ok() .unwrap(); 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 usb_class = keyberon::new_class(usb_bus, ()); let usb_dev = keyberon::new_device(usb_bus); let sio = hal::Sio::new(c.device.SIO); let pins = rp2040_hal::gpio::Pins::new( c.device.IO_BANK0, c.device.PADS_BANK0, sio.gpio_bank0, &mut resets, ); let mut timer = hal::Timer::new(c.device.TIMER, &mut resets); let mut alarm = timer.alarm_0().unwrap(); let _ = alarm.schedule(MicrosDurationU32::from_ticks(POLL_RATE)); alarm.enable_interrupt(); let matrix = Matrix::new( [ pins.gpio22.into_pull_up_input().into(), pins.gpio20.into_pull_up_input().into(), pins.gpio23.into_pull_up_input().into(), pins.gpio21.into_pull_up_input().into(), ], [ pins.gpio5.into_push_pull_output().into(), pins.gpio6.into_push_pull_output().into(), pins.gpio7.into_push_pull_output().into(), pins.gpio8.into_push_pull_output().into(), pins.gpio9.into_push_pull_output().into(), ], ); ( Shared { usb_class, alarm }, Local { usb_dev, matrix: matrix.unwrap(), debouncer: Debouncer::new( [[false; 4]; 5], [[false; 4]; 5], (5000u32 / POLL_RATE) as u16, ), layout: Layout::new(&crate::layout::LAYERS), }, init::Monotonics(), ) } #[task(binds = USBCTRL_IRQ, priority = 3, local = [usb_dev], shared = [ usb_class])] fn usb_rx(mut c: usb_rx::Context) { c.shared .usb_class .lock(|usb_class| super::usb_poll(&mut c.local.usb_dev, usb_class)); } #[task(binds = TIMER_IRQ_0, priority = 1, local = [debouncer, matrix, layout], shared = [usb_class, alarm])] fn tick(mut c: tick::Context) { for event in c.local.debouncer.events(c.local.matrix.get().unwrap()) { c.local.layout.event(event); } let report: KbHidReport = c.local.layout.keycodes().collect(); if c.shared .usb_class .lock(|k| k.device_mut().set_keyboard_report(report.clone())) { while let Ok(0) = c.shared.usb_class.lock(|k| k.write(report.as_bytes())) {} } c.shared.alarm.lock(|a| { a.clear_interrupt(); let _ = a.schedule(MicrosDurationU32::from_ticks(POLL_RATE)); }); } #[idle] fn idle(_cx: idle::Context) -> ! { loop { cortex_m::asm::nop(); } } } fn usb_poll(usb_dev: &mut UsbDevice, keyboard: &mut UsbClass) { if usb_dev.poll(&mut [keyboard]) { keyboard.poll(); } }