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
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();
|
|
}
|
|
}
|