OFTIDOHYR5GXVY3ON52BR3WJ4WWQY3SV3NBEWOVQJ3QM523EZKZQC stm32f3xx-hal = { version = "^0.9", features = ["stm32f303x8"] }
embassy = { git = "https://github.com/embassy-rs/embassy.git", features = ["defmt", "nightly"] }embassy-stm32 = { git = "https://github.com/embassy-rs/embassy.git", features = ["time-driver-any", "stm32f303cb", "unstable-pac", "memory-x"] }tinyvec = { version = "^1.6", features = ["alloc"] }# https://github.com/embassy-rs/embassy/pull/709usb-device = "^0.2"usbd-hid = "^0.6"
[toolchain]channel = "nightly"
#![no_main]#![no_std]#![feature(type_alias_impl_trait)]use ashtoret as _; // global logger + panicking-behavior + memory layoutuse defmt::*;use embassy::executor::Spawner;use embassy::time::{Duration, Timer};use embassy_stm32::{gpio::{Level, Output, Speed},Peripherals,};use ashtoret::keyboards::{moonlander::Moonlander, Keyboard};#[embassy::main]async fn main(_spawner: Spawner, p: Peripherals) {let keyboard = Moonlander::init(p);keyboard.run()}
pub struct Hid {}
use embassy::time::{Duration, Timer};use embassy_stm32::gpio::{AnyPin, Input, Output};type MatrixArray<const COLS: usize, const ROWS: usize> = [[bool; COLS]; ROWS];pub enum ScanKind<const COLS: usize, const ROWS: usize, T> {Direct([[Input<'static, AnyPin>; COLS]; ROWS]),Row2Col {row_pins: [Output<'static, AnyPin>; ROWS],col_pins: [Input<'static, AnyPin>; COLS],},Custom(T),}#[derive(Copy, Clone, Default, Debug, defmt::Format)]pub enum KeyEvent {Pressed(u16),Released(u16),#[default]Nop,}// TODO: Bitstuffingpub struct Matrix<const COLS: usize, const ROWS: usize, T> {state: MatrixArray<COLS, ROWS>,prev_state: MatrixArray<COLS, ROWS>,pins: ScanKind<COLS, ROWS, T>,debounce: Option<Duration>,scan_fn: Option<fn(&ScanKind<COLS, ROWS, T>) -> MatrixArray<COLS, ROWS>>,}impl<const COLS: usize, const ROWS: usize, T> Matrix<{ COLS }, { ROWS }, T> {pub fn new(pins: ScanKind<COLS, ROWS, T>) -> Self {Self {state: [[false; COLS]; ROWS],prev_state: [[false; COLS]; ROWS],pins,debounce: None,scan_fn: None,}}pub fn with_debounce(mut self, time: Duration) -> Self {self.debounce = Some(time);self}pub fn with_custom_scan(mut self,scan_fn: fn(&ScanKind<COLS, ROWS, T>) -> MatrixArray<COLS, ROWS>,) -> Self {self.scan_fn = Some(scan_fn);self}fn raw_update(&mut self) -> tinyvec::TinyVec<[KeyEvent; 6]> {core::mem::swap(&mut self.prev_state, &mut self.state);self.state = if let Some(custom_scan) = self.scan_fn {custom_scan(&self.pins)} else {// Note: Not needed for the Moonlander, as it implements a custom scanning routinetodo!()};let mut vec = tinyvec::TinyVec::new();for (idx, (key, prev_key)) in self.state.iter().flatten().zip(self.prev_state.iter().flatten()).enumerate(){if let Some(event) = if *key && !prev_key {Some(KeyEvent::Pressed(idx as u16))} else if !key && *prev_key {Some(KeyEvent::Released(idx as u16))} else {None} {vec.push(event)}}vec}pub async fn update(&mut self) -> Option<tinyvec::TinyVec<[KeyEvent; 6]>> {let changes = self.raw_update();if let Some(debounce) = self.debounce&& !changes.is_empty() {Timer::after(debounce).await;if self.raw_update().is_empty() {Some(changes)} else {None}} else {Some(changes)}}}
use crate::drivers::SharedBus;use embassy_stm32::i2c::{self, I2c};pub struct Mcp23018<T: i2c::Instance> {i2c: SharedBus<I2c<'static, T>>,}impl<T: i2c::Instance> Mcp23018<T> {pub fn new() -> Self {todo!()}}
use embassy::blocking_mutex::NoopMutex;pub mod hid;pub mod matrix;pub mod mcp23018;pub type SharedBus<T> = &'static NoopMutex<T>;
use crate::drivers::mcp23018::Mcp23018;use embassy_stm32::gpio::{AnyPin, Input, Output};use embassy_stm32::peripherals::I2C1;pub struct MatrixScanner {pub row_pins: [Output<'static, AnyPin>; 6],pub col_pins: [Input<'static, AnyPin>; 7],pub right_side: Mcp23018<I2C1>,}pub fn scan_matrix(pins: &MatrixScanner) -> [[bool; super::MATRIX_COLS]; super::MATRIX_ROWS] {todo!()}
mod matrix;use crate::drivers::matrix::{Matrix, ScanKind};use crate::drivers::mcp23018::Mcp23018;use crate::keyboards::moonlander::matrix::MatrixScanner;use crate::keyboards::Keyboard;use embassy_stm32::Peripherals;pub const MATRIX_COLS: usize = 7;pub const MATRIX_ROWS: usize = 12;pub struct Moonlander {matrix: Matrix<MATRIX_COLS, MATRIX_ROWS, MatrixScanner>,}impl Keyboard for Moonlander {fn init(p: Peripherals) -> Self {let matrix = Matrix::new(ScanKind::Custom(MatrixScanner {row_pins: outputs![p.PB10, p.PB11, p.PB12, p.PB13, p.PB14, p.PB15],col_pins: inputs![p.PA0, p.PA1, p.PA2, p.PA3, p.PA6, p.PA7, p.PB0,],right_side: Mcp23018::new(),})).with_custom_scan(|scanner| {if let ScanKind::Custom(scanner) = scanner {matrix::scan_matrix(scanner)} else {unreachable!()}});Self { matrix }}fn run(self) -> ! {cortex_m::asm::udf()}}
use embassy_stm32::Peripherals;pub trait Keyboard {fn init(p: Peripherals) -> Self;fn run(self) -> !;}pub mod moonlander;
#![feature(let_chains)]#![feature(alloc_error_handler)]#[macro_export]macro_rules! outputs {($($pin:expr),* $(,)?) => {{use embassy_stm32::gpio::{Level, Output, Speed, Pin};[$(Output::new($pin.degrade(), Level::Low, Speed::High),)*]}}}#[macro_export]macro_rules! inputs {($($pin:expr),* $(,)?) => {{use embassy_stm32::gpio::{Input, Pull, Pin};