#![no_main]
#![no_std]
// set the panic handler
use panic_halt as _;
use core::convert::Infallible;
use embedded_hal::digital::v2::{InputPin, OutputPin};
use generic_array::typenum::{U4, U6};
use hal::gpio::{gpioa, gpiob, Floating, Input, Output, PullUp, PushPull};
use hal::prelude::*;
use hal::serial;
use hal::usb;
use hal::{stm32, timers};
use keyberon::action::{k, l, m, Action, Action::*};
use keyberon::debounce::Debouncer;
use keyberon::impl_heterogenous_array;
use keyberon::key_code::KbHidReport;
use keyberon::key_code::KeyCode::*;
use keyberon::layout::{Event, Layout};
use keyberon::matrix::{Matrix, PressedKeys};
use nb::block;
use rtic::app;
use stm32f0xx_hal as hal;
use usb_device::bus::UsbBusAllocator;
use usb_device::class::UsbClass as _;
use usb_device::device::UsbDeviceState;
type UsbClass = keyberon::Class<'static, usb::UsbBusType, ()>;
type UsbDevice = keyberon::Device<'static, usb::UsbBusType>;
pub struct Cols(
gpioa::PA15 >,
gpiob::PB3 >,
gpiob::PB4 >,
gpiob::PB5 >,
gpiob::PB8 >,
gpiob::PB9 >,
);
impl_heterogenous_array! {
Cols,
dyn InputPin,
U6,
[0, 1, 2, 3, 4, 5]
}
pub struct Rows(
gpiob::PB0>,
gpiob::PB1>,
gpiob::PB2>,
gpiob::PB10>,
);
impl_heterogenous_array! {
Rows,
dyn OutputPin,
U4,
[0, 1, 2, 3]
}
const CUT: Action = m(&[LShift, Delete]);
const COPY: Action = m(&[LCtrl, Insert]);
const PASTE: Action = m(&[LShift, Insert]);
const L2_ENTER: Action = HoldTap {
timeout: 200,
hold: &l(2),
tap: &k(Enter),
};
const L1_SP: Action = HoldTap {
timeout: 200,
hold: &l(1),
tap: &k(Space),
};
const CSPACE: Action = m(&[LCtrl, Space]);
macro_rules! s {
($k:ident) => {
m(&[LShift, $k])
};
}
macro_rules! a {
($k:ident) => {
m(&[RAlt, $k])
};
}
#[rustfmt::skip]
pub static LAYERS: keyberon::layout::Layers = &[
&[
&[k(Tab), k(Q), k(W), k(E), k(R), k(T), k(Y), k(U), k(I), k(O), k(P), k(LBracket)],
&[k(RBracket),k(A), k(S), k(D), k(F), k(G), k(H), k(J), k(K), k(L), k(SColon),k(Quote) ],
&[k(Equal), k(Z), k(X), k(C), k(V), k(B), k(N), k(M), k(Comma),k(Dot), k(Slash), k(Bslash) ],
&[Trans, Trans,k(LGui),k(LAlt),L1_SP,k(LCtrl),k(RShift),L2_ENTER,k(RAlt),k(BSpace),Trans, Trans ],
], &[
&[Trans, k(Pause),Trans, k(PScreen),Trans, Trans,Trans, Trans, k(Delete),Trans, Trans, Trans ],
&[Trans, Trans, k(NumLock),k(Insert), k(Escape),Trans,k(CapsLock),k(Left),k(Down), k(Up), k(Right),Trans ],
&[k(NonUsBslash),k(Undo), CUT, COPY, PASTE, Trans,Trans, k(Home),k(PgDown),k(PgUp),k(End), Trans ],
&[Trans, Trans, Trans, Trans, Trans, Trans,Trans, Trans, Trans, Trans, Trans, Trans ],
], &[
&[s!(Grave),s!(Kb1),s!(Kb2),s!(Kb3),s!(Kb4),s!(Kb5),s!(Kb6),s!(Kb7),s!(Kb8),s!(Kb9),s!(Kb0),s!(Minus)],
&[ k(Grave), k(Kb1), k(Kb2), k(Kb3), k(Kb4), k(Kb5), k(Kb6), k(Kb7), k(Kb8), k(Kb9), k(Kb0), k(Minus)],
&[a!(Grave),a!(Kb1),a!(Kb2),a!(Kb3),a!(Kb4),a!(Kb5),a!(Kb6),a!(Kb7),a!(Kb8),a!(Kb9),a!(Kb0),a!(Minus)],
&[Trans, Trans, Trans, Trans, CSPACE, Trans, Trans, Trans, Trans, Trans, Trans, Trans ],
], &[
&[k(F1),k(F2),k(F3),k(F4),k(F5),k(F6),k(F7),k(F8),k(F9),k(F10),k(F11),k(F12)],
&[Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans, Trans, Trans ],
&[Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans, Trans, Trans ],
&[Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans,Trans, Trans, Trans ],
],
];
#[app(device = crate::hal::pac, peripherals = true)]
const APP: () = {
struct Resources {
usb_dev: UsbDevice,
usb_class: UsbClass,
matrix: Matrix,
debouncer: Debouncer>,
layout: Layout,
timer: timers::Timer,
transpose: fn(Event) -> Event,
tx: serial::Tx,
rx: serial::Rx,
}
#[init]
fn init(mut c: init::Context) -> init::LateResources {
static mut USB_BUS: Option> = None;
let mut rcc = c
.device
.RCC
.configure()
.hsi48()
.enable_crs(c.device.CRS)
.sysclk(48.mhz())
.pclk(24.mhz())
.freeze(&mut c.device.FLASH);
let gpioa = c.device.GPIOA.split(&mut rcc);
let gpiob = c.device.GPIOB.split(&mut rcc);
let usb = usb::Peripheral {
usb: c.device.USB,
pin_dm: gpioa.pa11,
pin_dp: gpioa.pa12,
};
*USB_BUS = Some(usb::UsbBusType::new(usb));
let usb_bus = USB_BUS.as_ref().unwrap();
let usb_class = keyberon::new_class(usb_bus, ());
let usb_dev = keyberon::new_device(usb_bus);
let mut timer = timers::Timer::tim3(c.device.TIM3, 1.khz(), &mut rcc);
timer.listen(timers::Event::TimeOut);
let pb12: &gpiob::PB12 > = &gpiob.pb12;
let is_left = pb12.is_low().unwrap();
let transpose = if is_left {
transpose_left
} else {
transpose_right
};
let (pa9, pa10) = (gpioa.pa9, gpioa.pa10);
let (tx, rx) = cortex_m::interrupt::free(move |cs| {
(pa9.into_alternate_af1(cs), pa10.into_alternate_af1(cs))
});
let (tx, rx) =
serial::Serial::usart1(c.device.USART1, (tx, rx), 115_200.bps(), &mut rcc).split();
let pa15 = gpioa.pa15;
let matrix = cortex_m::interrupt::free(move |cs| {
Matrix::new(
Cols(
pa15.into_pull_up_input(cs),
gpiob.pb3.into_pull_up_input(cs),
gpiob.pb4.into_pull_up_input(cs),
gpiob.pb5.into_pull_up_input(cs),
gpiob.pb8.into_pull_up_input(cs),
gpiob.pb9.into_pull_up_input(cs),
),
Rows(
gpiob.pb0.into_push_pull_output(cs),
gpiob.pb1.into_push_pull_output(cs),
gpiob.pb2.into_push_pull_output(cs),
gpiob.pb10.into_push_pull_output(cs),
),
)
});
init::LateResources {
usb_dev,
usb_class,
timer,
debouncer: Debouncer::new(PressedKeys::default(), PressedKeys::default(), 5),
matrix: matrix.unwrap(),
layout: Layout::new(LAYERS),
transpose,
tx,
rx,
}
}
#[task(binds = USB, priority = 4, resources = [usb_dev, usb_class])]
fn usb_rx(c: usb_rx::Context) {
if c.resources.usb_dev.poll(&mut [c.resources.usb_class]) {
c.resources.usb_class.poll();
}
}
#[task(priority = 3, resources = [usb_dev, usb_class])]
fn handle_report(mut c: handle_report::Context, report: KbHidReport) {
if !c
.resources
.usb_class
.lock(|k| k.device_mut().set_keyboard_report(report.clone()))
{
return;
}
if c.resources.usb_dev.lock(|d| d.state()) != UsbDeviceState::Configured {
return;
}
while let Ok(0) = c.resources.usb_class.lock(|k| k.write(report.as_bytes())) {}
}
#[task(
binds = TIM3,
priority = 2,
spawn = [handle_report],
resources = [matrix, debouncer, layout, timer, &transpose, tx],
)]
fn tick(c: tick::Context) {
c.resources.timer.wait().unwrap();
for event in c
.resources
.debouncer
.events(c.resources.matrix.get().unwrap())
.map(c.resources.transpose)
{
for &b in &ser(event) {
block!(c.resources.tx.write(b)).unwrap();
}
c.spawn
.handle_report(c.resources.layout.event(event).collect())
.unwrap();
}
c.spawn
.handle_report(c.resources.layout.tick().collect())
.unwrap();
}
#[task(binds = USART1, priority = 1, spawn = [handle_report], resources = [layout, rx])]
fn rx(mut c: rx::Context) {
static mut BUF: [u8; 4] = [0; 4];
for b in &mut BUF[..] {
*b = nb::block!(c.resources.rx.read()).unwrap();
}
if let Ok(event) = de(&BUF[..]) {
c.spawn
.handle_report(c.resources.layout.lock(|l| l.event(event).collect()))
.unwrap();
}
}
extern "C" {
fn CEC_CAN();
}
};
fn transpose_left(e: Event) -> Event {
e
}
fn transpose_right(e: Event) -> Event {
match e {
Event::Press(x, y) => Event::Press(11 - x, y),
Event::Release(x, y) => Event::Release(11 - x, y),
}
}
fn de(bytes: &[u8]) -> Result {
match bytes {
&[b'P', x, y, b'\n'] => Ok(Event::Press(x as usize, y as usize)),
&[b'R', x, y, b'\n'] => Ok(Event::Release(x as usize, y as usize)),
_ => Err(()),
}
}
fn ser(e: Event) -> [u8; 4] {
match e {
Event::Press(x, y) => [b'P', x as u8, y as u8, b'\n'],
Event::Release(x, y) => [b'R', x as u8, y as u8, b'\n'],
}
}