You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.3 KiB
Rust

#![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<DynPin, DynPin, 4, 5>,
layout: Layout<4, 5, 1, ()>,
usb_dev: UsbDevice,
}
#[init(local = [usb_bus: Option<usb_device::bus::UsbBusAllocator<hal::usb::UsbBus>> = 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();
}
}