Add communication between keyboard halves

This commit is contained in:
2023-05-09 18:10:43 +02:00
parent 2b66c022f7
commit c39893a067
8 changed files with 278 additions and 31 deletions

View File

@ -6,19 +6,26 @@ use embassy_rp::{
gpio::{AnyPin, Input, Pin, Pull},
pio::PioInstanceBase,
};
use embassy_sync::pubsub::{ImmediatePublisher, PubSubChannel, Subscriber};
use embassy_time::{Duration, Timer};
use futures::{select_biased, FutureExt};
use log::{debug, error, info, warn};
use static_cell::StaticCell;
use tgnt::{button::Button, layer::Layer};
use tgnt::{
button::{Button, Modifier},
keys::Key,
layer::Layer,
};
use crate::{
lights::Lights,
usb::keyboard::KB_REPORT,
util::CS,
ws2812::{Rgb, Ws2812},
};
pub struct KeyboardConfig {
/// Which board is this.
pub half: Half,
/// Array of input pins of each switch
pub pins: [AnyPin; SWITCH_COUNT],
/// Array of LED indices of each switch
@ -28,6 +35,8 @@ pub struct KeyboardConfig {
}
struct State {
/// Which board is this.
half: Half,
current_layer: AtomicU16,
layers: &'static [Layer],
/// Array of LED indices of each switch
@ -35,13 +44,54 @@ struct State {
lights: Lights<PioInstanceBase<1>, SWITCH_COUNT>,
}
/// A keyboard half.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Half {
Left,
Right,
}
#[derive(Clone, Debug)]
pub struct Event {
pub source: Half,
pub kind: EventKind,
}
#[derive(Clone, Debug)]
pub enum EventKind {
PressKey(Key),
ReleaseKey(Key),
PressModifier(Modifier),
ReleaseModifier(Modifier),
SetLayer(u16),
}
pub const KB_SUBSCRIBERS: usize = 2;
pub const ACTUAL_KB_SUBSCRIBERS: usize = KB_SUBSCRIBERS + 1;
const KB_EVENT_CAP: usize = 128;
static KB_EVENTS: PubSubChannel<CS, Event, KB_EVENT_CAP, ACTUAL_KB_SUBSCRIBERS, 0> =
PubSubChannel::new();
pub struct KbEvents {
subscriber: Subscriber<'static, CS, Event, KB_EVENT_CAP, ACTUAL_KB_SUBSCRIBERS, 0>,
publisher: ImmediatePublisher<'static, CS, Event, KB_EVENT_CAP, ACTUAL_KB_SUBSCRIBERS, 0>,
}
pub struct KbEventsTx<'a> {
publisher:
&'a mut ImmediatePublisher<'static, CS, Event, KB_EVENT_CAP, ACTUAL_KB_SUBSCRIBERS, 0>,
}
pub struct KbEventsRx<'a> {
subscriber: &'a mut Subscriber<'static, CS, Event, KB_EVENT_CAP, ACTUAL_KB_SUBSCRIBERS, 0>,
}
impl KeyboardConfig {
pub async fn create(self) {
pub async fn create(self) -> Option<[KbEvents; KB_SUBSCRIBERS]> {
let spawner = Spawner::for_current_executor().await;
if self.layers.is_empty() {
error!("no layers defined");
return;
return None;
}
info!(
@ -51,6 +101,7 @@ impl KeyboardConfig {
static STATE: StaticCell<State> = StaticCell::new();
let state = STATE.init_with(|| State {
half: self.half,
current_layer: AtomicU16::new(0),
layers: Box::leak(self.layers.into_boxed_slice()),
lights: Lights::new(self.led_driver),
@ -72,6 +123,51 @@ impl KeyboardConfig {
break;
}
}
spawner.must_spawn(layer_switch_task(
KbEvents {
publisher: KB_EVENTS.immediate_publisher(),
subscriber: KB_EVENTS.subscriber().unwrap(),
},
state,
));
Some([(); KB_SUBSCRIBERS].map(|_| KbEvents {
publisher: KB_EVENTS.immediate_publisher(),
subscriber: KB_EVENTS.subscriber().unwrap(),
}))
}
}
impl KbEvents {
pub async fn send(&mut self, event: Event) {
self.publisher.publish_immediate(event);
}
pub async fn recv(&mut self) -> Event {
self.subscriber.next_message_pure().await
}
pub fn split(&mut self) -> (KbEventsRx, KbEventsTx) {
let tx = KbEventsTx {
publisher: &mut self.publisher,
};
let rx = KbEventsRx {
subscriber: &mut self.subscriber,
};
(rx, tx)
}
}
impl KbEventsRx<'_> {
pub async fn recv(&mut self) -> Event {
self.subscriber.next_message_pure().await
}
}
impl KbEventsTx<'_> {
pub fn send(&mut self, event: Event) {
self.publisher.publish_immediate(event);
}
}
@ -83,6 +179,7 @@ const SWITCH_COUNT: usize = 18;
async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> ! {
let _pin_nr = pin.pin();
let mut pin = Input::new(pin, Pull::Up);
let events = KB_EVENTS.immediate_publisher();
loop {
// pins are pull-up, so when the switch is pressed they are brought low.
pin.wait_for_low().await;
@ -124,20 +221,26 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> !
}
};
let ev = |kind| Event {
source: state.half,
kind,
};
use EventKind::*;
match button {
&Button::Key(key) => {
KB_REPORT.lock().await.press_key(key);
events.publish_immediate(ev(PressKey(key)));
state.lights.update(set_led(Rgb::new(0, 150, 0))).await;
wait_for_release.await;
KB_REPORT.lock().await.release_key(key);
events.publish_immediate(ev(ReleaseKey(key)));
state.lights.update(set_led(Rgb::new(0, 0, 0))).await;
continue;
}
&Button::Mod(modifier) => {
KB_REPORT.lock().await.press_modifier(modifier);
events.publish_immediate(ev(PressModifier(modifier)));
state.lights.update(set_led(Rgb::new(100, 100, 0))).await;
wait_for_release.await;
KB_REPORT.lock().await.release_modifier(modifier);
events.publish_immediate(ev(ReleaseModifier(modifier)));
state.lights.update(set_led(Rgb::new(0, 0, 0))).await;
continue;
}
@ -145,19 +248,19 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> !
state.lights.update(set_led(Rgb::new(100, 100, 0))).await;
select_biased! {
_ = Timer::after(MOD_TAP_TIME).fuse() => {
KB_REPORT.lock().await.press_modifier(modifier);
events.publish_immediate(ev(PressModifier(modifier)));
state.lights.update(set_led(Rgb::new(0, 0, 150))).await;
pin.wait_for_high().await;
KB_REPORT.lock().await.release_modifier(modifier);
events.publish_immediate(ev(ReleaseModifier(modifier)));
state.lights.update(set_led(Rgb::new(0, 0, 0))).await;
debug!("switch {switch_num} button {button:?} released");
continue;
}
_ = wait_for_release.fuse() => {
KB_REPORT.lock().await.press_key(key);
events.publish_immediate(ev(PressKey(key)));
state.lights.update(set_led(Rgb::new(0, 150, 0))).await;
Timer::after(Duration::from_millis(10)).await;
KB_REPORT.lock().await.release_key(key);
events.publish_immediate(ev(ReleaseKey(key)));
state.lights.update(set_led(Rgb::new(0, 0, 0))).await;
continue;
}
@ -165,12 +268,12 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> !
}
Button::NextLayer => {
let next_layer = (current_layer + 1) % layer_count;
state.current_layer.store(next_layer, Ordering::Relaxed);
events.publish_immediate(ev(SetLayer(next_layer)));
debug!("switched to layer {next_layer}");
}
Button::PrevLayer => {
let prev_layer = current_layer.checked_sub(1).unwrap_or(layer_count - 1);
state.current_layer.store(prev_layer, Ordering::Relaxed);
events.publish_immediate(ev(SetLayer(prev_layer)));
debug!("switched to layer {prev_layer}");
}
Button::None => {}
@ -181,6 +284,16 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> !
}
}
#[embassy_executor::task]
async fn layer_switch_task(mut events: KbEvents, state: &'static State) {
loop {
let event = events.recv().await;
if let EventKind::SetLayer(new_layer) = event.kind {
state.current_layer.store(new_layer, Ordering::Relaxed);
}
}
}
/// Random functions for testing
#[allow(dead_code)]
pub mod test {