Files
kb-firmware/src/main.rs

223 lines
5.8 KiB
Rust

#![no_std]
#![no_main]
use core::sync::atomic::{AtomicBool, Ordering};
use defmt::{info, warn};
use embassy_executor::Spawner;
use embassy_futures::join::join;
use embassy_rp::{bind_interrupts, gpio::{Input, Level, Output, Pull}, peripherals::USB, usb::{Driver, InterruptHandler}};
use embassy_time::{Duration, Timer};
use embassy_usb::{Builder, Config, Handler, class::hid::{HidReaderWriter, ReportId, RequestHandler, State}, control::OutResponse};
use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
use {defmt_rtt as _, panic_probe as _};
pub struct Debouncer<'a> {
input: Input<'a>,
debounce: Duration,
}
impl<'a> Debouncer<'a> {
pub fn new(input: Input<'a>, debounce: Duration) -> Self {
Self { input, debounce }
}
pub async fn debounce_low(&mut self) -> Level {
loop {
let l1 = self.input.get_level();
self.input.wait_for_low().await;
Timer::after(self.debounce).await;
let l2 = self.input.get_level();
if l1 != l2 {
break l2;
}
}
}
pub async fn debounce_high(&mut self) -> Level {
loop {
let l1 = self.input.get_level();
self.input.wait_for_high().await;
Timer::after(self.debounce).await;
let l2 = self.input.get_level();
if l1 != l2 {
break l2;
}
}
}
}
bind_interrupts!(struct Irqs {
USBCTRL_IRQ => InterruptHandler<USB>;
});
#[embassy_executor::main]
async fn main(_spawner: Spawner) -> () {
let p = embassy_rp::init(Default::default());
let driver = Driver::new(p.USB, Irqs);
let mut config = Config::new(0x1234, 0xabcd);
config.manufacturer = Some("Lukrecja");
config.product = Some("kb-prototype");
config.serial_number = Some("00000000");
config.composite_with_iads = false;
config.device_class = 0x00;
config.device_sub_class = 0x00;
config.device_protocol = 0x00;
let mut config_descriptor = [0; 256];
let mut bos_descriptor = [0; 256];
let mut msos_descriptor = [0; 256];
let mut control_buf = [0; 64];
let mut request_handler = KbRequestHandler {};
let mut device_handler = KbDeviceHandler::new();
let mut state = State::new();
let mut builder = Builder::new(
driver,
config,
&mut config_descriptor,
&mut bos_descriptor,
&mut msos_descriptor,
&mut control_buf,
);
builder.handler(&mut device_handler);
let config = embassy_usb::class::hid::Config {
report_descriptor: KeyboardReport::desc(),
request_handler: None,
poll_ms: 60,
max_packet_size: 64,
};
let hid = HidReaderWriter::<_, 1, 8>::new(&mut builder, &mut state, config);
let mut usb = builder.build();
let usb_fut = usb.run();
let mut led = Output::new(p.PIN_25, Level::Low);
let mut switch_input = Debouncer::new(Input::new(p.PIN_0, Pull::Up), Duration::from_millis(20));
switch_input.input.set_schmitt(true);
let (reader, mut writer) = hid.split();
let in_fut = async {
loop {
defmt::info!("waiting for low");
led.set_low();
switch_input.debounce_low().await;
info!("got low");
led.set_high();
let report = KeyboardReport {
keycodes: [4, 0, 0, 0, 0, 0],
leds: 0,
modifier: 0,
reserved: 0,
};
match writer.write_serialize(&report).await {
Ok(()) => info!("report sent"),
Err(e) => warn!("failed to send: {:?}", e),
};
switch_input.debounce_high().await;
info!("got high");
let report = KeyboardReport {
keycodes: [0, 0, 0, 0, 0, 0],
leds: 0,
modifier: 0,
reserved: 0,
};
match writer.write_serialize(&report).await {
Ok(()) => info!("report sent"),
Err(e) => warn!("failed to send: {:?}", e),
};
}
};
let out_fut = async {
reader.run(false, &mut request_handler).await;
};
join(usb_fut, join(in_fut, out_fut)).await;
}
struct KbRequestHandler {}
impl RequestHandler for KbRequestHandler {
fn get_report(&mut self, _id: ReportId, _buf: &mut [u8]) -> Option<usize> {
info!("get report");
None
}
fn set_report(&mut self, _id: ReportId, data: &[u8]) -> OutResponse {
info!("set report: {=[u8]}", data);
OutResponse::Accepted
}
fn set_idle_ms(&mut self, _id: Option<ReportId>, dur: u32) {
info!("set idle rate to {}", dur);
}
fn get_idle_ms(&mut self, _id: Option<ReportId>) -> Option<u32> {
info!("get idle rate");
None
}
}
struct KbDeviceHandler {
configured: AtomicBool,
}
impl KbDeviceHandler {
fn new() -> Self {
Self {
configured: AtomicBool::new(false),
}
}
}
impl Handler for KbDeviceHandler {
fn enabled(&mut self, enabled: bool) {
self.configured.store(false, Ordering::Relaxed);
if enabled {
info!("device enabled");
} else {
info!("device disabled");
}
}
fn reset(&mut self) {
self.configured.store(false, Ordering::Relaxed);
info!("bus reset, Vbus current limit is 100mA");
}
fn addressed(&mut self, addr: u8) {
self.configured.store(false, Ordering::Relaxed);
info!("USB address set to: {}", addr);
}
fn configured(&mut self, configured: bool) {
self.configured.store(configured, Ordering::Relaxed);
if configured {
info!("device configured")
} else {
info!("device no longer configured");
}
}
}