Switch to layer matrix instead of layer list
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
|||||||
target
|
target
|
||||||
|
*.pc
|
||||||
|
|||||||
@ -46,9 +46,10 @@ fn memory() {
|
|||||||
|
|
||||||
fn serialize_layout(ron_path: &str, postcard_path: &str) {
|
fn serialize_layout(ron_path: &str, postcard_path: &str) {
|
||||||
println!("cargo:rerun-if-changed={ron_path}");
|
println!("cargo:rerun-if-changed={ron_path}");
|
||||||
|
println!("cargo:rerun-if-changed={postcard_path}");
|
||||||
|
|
||||||
let layers = fs::read_to_string(ron_path).expect("Failed to read .ron");
|
let layers = fs::read_to_string(ron_path).expect("Failed to read .ron");
|
||||||
let layers: Vec<Layer> = ron::from_str(&layers).expect("Failed to deserialize .ron");
|
let layers: Vec<Vec<Layer>> = ron::from_str(&layers).expect("Failed to deserialize .ron");
|
||||||
|
|
||||||
let serialized = postcard::to_stdvec(&layers).expect("Failed to serialize layers");
|
let serialized = postcard::to_stdvec(&layers).expect("Failed to serialize layers");
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
|
[
|
||||||
Layer(
|
Layer(
|
||||||
buttons: [
|
buttons: [
|
||||||
// Row 1
|
// Row 1
|
||||||
@ -25,7 +26,7 @@
|
|||||||
// Thumbpad
|
// Thumbpad
|
||||||
Key(Backspace),
|
Key(Backspace),
|
||||||
Key(Space),
|
Key(Space),
|
||||||
HoldLayer(1),
|
Layer(Peek, Right, 1),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Layer(
|
Layer(
|
||||||
@ -54,7 +55,7 @@
|
|||||||
// Thumbpad
|
// Thumbpad
|
||||||
Key(Backspace),
|
Key(Backspace),
|
||||||
Key(Space),
|
Key(Space),
|
||||||
HoldLayer(1),
|
Layer(Peek, Right, 1),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Layer(
|
Layer(
|
||||||
@ -83,7 +84,97 @@
|
|||||||
// Thumbpad
|
// Thumbpad
|
||||||
Key(Backspace),
|
Key(Backspace),
|
||||||
Key(Space),
|
Key(Space),
|
||||||
HoldLayer(1),
|
Layer(Peek, Right, 1),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
[ // gaming row
|
||||||
|
Layer(
|
||||||
|
buttons: [
|
||||||
|
// Row 1
|
||||||
|
Key(Escape),
|
||||||
|
Key(Q),
|
||||||
|
Key(W),
|
||||||
|
Key(E),
|
||||||
|
Key(R),
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
Mod(LShift),
|
||||||
|
Key(A),
|
||||||
|
Key(S),
|
||||||
|
Key(D),
|
||||||
|
Key(F),
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
Mod(LCtrl),
|
||||||
|
Key(Z),
|
||||||
|
Key(X),
|
||||||
|
Key(C),
|
||||||
|
Key(V),
|
||||||
|
|
||||||
|
// Thumbpad
|
||||||
|
Key(Backspace),
|
||||||
|
Key(Space),
|
||||||
|
Layer(Peek, Right, 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Layer(
|
||||||
|
buttons: [
|
||||||
|
// Row 1
|
||||||
|
Key(D1),
|
||||||
|
Key(D2),
|
||||||
|
Key(D3),
|
||||||
|
Key(D4),
|
||||||
|
Key(D5),
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
Key(D6),
|
||||||
|
Key(D7),
|
||||||
|
Key(D8),
|
||||||
|
Key(D9),
|
||||||
|
Key(D0),
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Thumbpad
|
||||||
|
Key(Backspace),
|
||||||
|
Key(Space),
|
||||||
|
Layer(Peek, Right, 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Layer(
|
||||||
|
buttons: [
|
||||||
|
// Row 1
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Thumbpad
|
||||||
|
Key(Backspace),
|
||||||
|
Key(Space),
|
||||||
|
Layer(Peek, Right, 1),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
@ -54,7 +54,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
neopixel.write(&[Rgb::new(0xFF, 0x00, 0x00)]).await;
|
neopixel.write(&[Rgb::new(0xFF, 0x00, 0x00)]).await;
|
||||||
|
|
||||||
let layers = include_bytes!("layers.pc");
|
let layers = include_bytes!("layers.pc");
|
||||||
let Ok(layers): Result<Vec<Layer>, _> = postcard::from_bytes(layers) else {
|
let Ok(layers): Result<Vec<Vec<Layer>>, _> = postcard::from_bytes(layers) else {
|
||||||
log::error!("Failed to deserialize layer config");
|
log::error!("Failed to deserialize layer config");
|
||||||
stall().await
|
stall().await
|
||||||
};
|
};
|
||||||
|
|||||||
28
lib/src/atomics.rs
Normal file
28
lib/src/atomics.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use atomic_polyfill::{AtomicU32, Ordering};
|
||||||
|
|
||||||
|
pub struct AtomicCoord {
|
||||||
|
inner: AtomicU32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AtomicCoord {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
AtomicCoord {
|
||||||
|
inner: AtomicU32::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&self, ordering: Ordering) -> (u16, u16) {
|
||||||
|
let [a, b, c, d] = self.inner.load(ordering).to_ne_bytes();
|
||||||
|
let x = u16::from_ne_bytes([a, b]);
|
||||||
|
let y = u16::from_ne_bytes([c, d]);
|
||||||
|
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn store(&self, x: u16, y: u16, ordering: Ordering) {
|
||||||
|
let [a, b] = x.to_ne_bytes();
|
||||||
|
let [c, d] = y.to_ne_bytes();
|
||||||
|
let xy = u32::from_ne_bytes([a, b, c, d]);
|
||||||
|
self.inner.store(xy, ordering);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
mod lights;
|
mod lights;
|
||||||
|
|
||||||
use core::sync::atomic::{AtomicU16, Ordering};
|
use core::sync::atomic::Ordering;
|
||||||
|
|
||||||
use alloc::{boxed::Box, vec::Vec};
|
use alloc::{boxed::Box, vec::Vec};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
@ -12,9 +12,13 @@ use embassy_sync::pubsub::{ImmediatePublisher, PubSubChannel, Subscriber};
|
|||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use tgnt::{button::Button, layer::Layer};
|
use tgnt::{
|
||||||
|
button::{Button, LayerDir, LayerShift},
|
||||||
|
layer::Layer,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
atomics::AtomicCoord,
|
||||||
event::{
|
event::{
|
||||||
switch::{Event, EventKind},
|
switch::{Event, EventKind},
|
||||||
Half,
|
Half,
|
||||||
@ -32,14 +36,16 @@ pub struct KeyboardConfig {
|
|||||||
/// Array of LED indices of each switch
|
/// Array of LED indices of each switch
|
||||||
pub led_map: [usize; SWITCH_COUNT],
|
pub led_map: [usize; SWITCH_COUNT],
|
||||||
pub led_driver: Ws2812<PIO1>,
|
pub led_driver: Ws2812<PIO1>,
|
||||||
pub layers: Vec<Layer>,
|
/// Matrix of layers. Stored as rows of columns.
|
||||||
|
pub layers: Vec<Vec<Layer>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
/// Which board is this.
|
/// Which board is this.
|
||||||
half: Half,
|
half: Half,
|
||||||
current_layer: AtomicU16,
|
current_layer: AtomicCoord,
|
||||||
layers: &'static [Layer],
|
layer_cols: usize,
|
||||||
|
layers: &'static [Vec<Layer>],
|
||||||
/// Array of LED indices of each switch
|
/// Array of LED indices of each switch
|
||||||
led_map: [usize; SWITCH_COUNT],
|
led_map: [usize; SWITCH_COUNT],
|
||||||
lights: Lights<PIO1, SWITCH_COUNT>,
|
lights: Lights<PIO1, SWITCH_COUNT>,
|
||||||
@ -81,20 +87,23 @@ impl KeyboardConfig {
|
|||||||
static STATE: StaticCell<State> = StaticCell::new();
|
static STATE: StaticCell<State> = StaticCell::new();
|
||||||
let state = STATE.init_with(|| State {
|
let state = STATE.init_with(|| State {
|
||||||
half: self.half,
|
half: self.half,
|
||||||
current_layer: AtomicU16::new(0),
|
current_layer: AtomicCoord::new(),
|
||||||
|
layer_cols: self.layers.iter().map(|row| row.len()).max().unwrap_or(0),
|
||||||
layers: Box::leak(self.layers.into_boxed_slice()),
|
layers: Box::leak(self.layers.into_boxed_slice()),
|
||||||
lights: Lights::new(self.led_driver),
|
lights: Lights::new(self.led_driver),
|
||||||
led_map: self.led_map,
|
led_map: self.led_map,
|
||||||
});
|
});
|
||||||
|
|
||||||
for (i, layer) in state.layers.iter().enumerate() {
|
for (y, row) in state.layers.iter().enumerate() {
|
||||||
|
for (x, layer) in row.iter().enumerate() {
|
||||||
if layer.buttons.len() != SWITCH_COUNT {
|
if layer.buttons.len() != SWITCH_COUNT {
|
||||||
warn!(
|
warn!(
|
||||||
"layer {i} defines {} buttons, but there are {SWITCH_COUNT} switches",
|
"layer ({x}, {y}) defines {} buttons, but there are {SWITCH_COUNT} switches",
|
||||||
layer.buttons.len(),
|
layer.buttons.len(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i, pin) in self.pins.into_iter().enumerate() {
|
for (i, pin) in self.pins.into_iter().enumerate() {
|
||||||
if spawner.spawn(switch_task(i, pin, state)).is_err() {
|
if spawner.spawn(switch_task(i, pin, state)).is_err() {
|
||||||
@ -176,21 +185,19 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> !
|
|||||||
// TODO: do we need debouncing?
|
// TODO: do we need debouncing?
|
||||||
|
|
||||||
// get current layer
|
// get current layer
|
||||||
let mut current_layer = state.current_layer.load(Ordering::Relaxed);
|
let (x, y) = state.current_layer.load(Ordering::Relaxed);
|
||||||
let layer_count = state.layers.len() as u16;
|
|
||||||
if current_layer >= layer_count {
|
let Some(Layer { buttons }) = state.layers.get(usize::from(y))
|
||||||
error!("current layer was out of bounds for some reason ({current_layer})");
|
.and_then(|row| row.get(usize::from(x))) else {
|
||||||
current_layer = 0;
|
// currently layer is null, do nothing
|
||||||
}
|
pin.wait_for_high().await;
|
||||||
let Some(Layer { buttons }) = state.layers.get(usize::from(current_layer)) else {
|
|
||||||
error!("current layer was out of bounds for some reason ({current_layer})");
|
|
||||||
state.current_layer.store(0, Ordering::Relaxed);
|
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
// and current button
|
// and current button
|
||||||
let Some(button) = buttons.get(switch_num) else {
|
let Some(button) = buttons.get(switch_num) else {
|
||||||
warn!("no button defined for switch {switch_num}");
|
warn!("no button defined for switch {switch_num}");
|
||||||
|
pin.wait_for_high().await;
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -223,30 +230,43 @@ async fn switch_task(switch_num: usize, pin: AnyPin, state: &'static State) -> !
|
|||||||
|
|
||||||
#[embassy_executor::task]
|
#[embassy_executor::task]
|
||||||
async fn layer_switch_task(mut events: KbEvents, state: &'static State) {
|
async fn layer_switch_task(mut events: KbEvents, state: &'static State) {
|
||||||
let layer_count = state.layers.len() as u16;
|
let col_count = state.layer_cols as u16;
|
||||||
let Some(last_layer) = layer_count.checked_sub(1) else {
|
let row_count = state.layers.len() as u16;
|
||||||
|
let Some(last_row) = row_count.checked_sub(1) else {
|
||||||
|
error!("no layers specified");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(last_col) = col_count.checked_sub(1) else {
|
||||||
error!("no layers specified");
|
error!("no layers specified");
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
use LayerDir::*;
|
||||||
|
use LayerShift::*;
|
||||||
|
|
||||||
let event = events.recv().await;
|
let event = events.recv().await;
|
||||||
let layer = state.current_layer.load(Ordering::Relaxed);
|
let (x, y) = state.current_layer.load(Ordering::Relaxed);
|
||||||
let new_layer = match event.kind {
|
let (nx, ny) = match event.kind {
|
||||||
EventKind::Press { button } => match button {
|
EventKind::Press { button } => match button {
|
||||||
Button::NextLayer => layer.wrapping_add(1) % layer_count,
|
Button::Layer(_, Up, n) => (x, y.checked_sub(n).unwrap_or(last_row)),
|
||||||
Button::PrevLayer => layer.checked_sub(1).unwrap_or(last_layer),
|
Button::Layer(_, Down, n) => (x, y.wrapping_add(n) % row_count),
|
||||||
Button::HoldLayer(l) => layer.wrapping_add(l) % layer_count,
|
Button::Layer(_, Left, n) => (x.checked_sub(n).unwrap_or(last_col), y),
|
||||||
|
Button::Layer(_, Right, n) => (x.wrapping_add(n) % col_count, y),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
},
|
},
|
||||||
EventKind::Release { button, .. } => match button {
|
EventKind::Release { button, .. } => match button {
|
||||||
Button::HoldLayer(l) => layer.checked_sub(l).unwrap_or(last_layer),
|
Button::Layer(Peek, Up, n) => (x, y.wrapping_add(n) % row_count),
|
||||||
|
Button::Layer(Peek, Down, n) => (x, y.checked_sub(n).unwrap_or(last_row)),
|
||||||
|
Button::Layer(Peek, Left, n) => (x.wrapping_add(n) % col_count, y),
|
||||||
|
Button::Layer(Peek, Right, n) => (x.checked_sub(n).unwrap_or(last_col), y),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
state.current_layer.store(new_layer, Ordering::Relaxed);
|
state.current_layer.store(nx, ny, Ordering::Relaxed);
|
||||||
debug!("switched to layer {new_layer}");
|
debug!("switched to layer ({nx}, {ny})");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,3 @@
|
|||||||
use core::cmp::min;
|
|
||||||
|
|
||||||
use atomic_polyfill::Ordering;
|
|
||||||
use embassy_futures::yield_now;
|
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
use futures::{select_biased, FutureExt};
|
use futures::{select_biased, FutureExt};
|
||||||
use tgnt::button::Button;
|
use tgnt::button::Button;
|
||||||
@ -149,6 +145,8 @@ async fn handle_event(
|
|||||||
Button::Mod(..) => LightState::Solid(Rgb::new(0, 0, 150)),
|
Button::Mod(..) => LightState::Solid(Rgb::new(0, 0, 150)),
|
||||||
Button::ModTap(..) => LightState::Solid(Rgb::new(0, 0, 150)),
|
Button::ModTap(..) => LightState::Solid(Rgb::new(0, 0, 150)),
|
||||||
Button::Compose(..) => LightState::Solid(Rgb::new(0, 100, 100)),
|
Button::Compose(..) => LightState::Solid(Rgb::new(0, 100, 100)),
|
||||||
|
Button::Layer(..) => LightState::Solid(Rgb::new(120, 0, 120)),
|
||||||
|
/*
|
||||||
Button::NextLayer | Button::PrevLayer => {
|
Button::NextLayer | Button::PrevLayer => {
|
||||||
yield_now().await; // dirty hack to make sure layer_switch_task gets to run first
|
yield_now().await; // dirty hack to make sure layer_switch_task gets to run first
|
||||||
let layer = state.current_layer.load(Ordering::Relaxed);
|
let layer = state.current_layer.load(Ordering::Relaxed);
|
||||||
@ -182,6 +180,7 @@ async fn handle_event(
|
|||||||
}
|
}
|
||||||
LightState::Solid(Rgb::new(100, 0, 100))
|
LightState::Solid(Rgb::new(100, 0, 100))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
_ => LightState::Solid(Rgb::new(150, 0, 0)),
|
_ => LightState::Solid(Rgb::new(150, 0, 0)),
|
||||||
},
|
},
|
||||||
EventKind::Release { .. } => LightState::FadeBy(0.85),
|
EventKind::Release { .. } => LightState::FadeBy(0.85),
|
||||||
|
|||||||
@ -134,16 +134,12 @@ pub async fn keypress_handler(
|
|||||||
};
|
};
|
||||||
|
|
||||||
match button {
|
match button {
|
||||||
Button::ModTap(_, _) => {
|
Button::ModTap(..) => {
|
||||||
debug!("adding modtap to queue");
|
debug!("adding modtap to queue");
|
||||||
// add event to queue
|
// add event to queue
|
||||||
insert(queue, button);
|
insert(queue, button);
|
||||||
}
|
}
|
||||||
Button::Mod(m) => {
|
Button::Mod(..) | Button::Key(..) => {
|
||||||
// if events in queue, also add to queue maybe?
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
Button::Key(_) => {
|
|
||||||
if queue.is_empty() {
|
if queue.is_empty() {
|
||||||
debug!("sending key now");
|
debug!("sending key now");
|
||||||
// otherwise, send immediately
|
// otherwise, send immediately
|
||||||
@ -195,11 +191,7 @@ pub async fn keypress_handler(
|
|||||||
slow_release(output, &button).await;
|
slow_release(output, &button).await;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Button::Mod(m) => {
|
Button::Mod(..) | Button::Key(..) => {
|
||||||
debug!("mod not implemented yet");
|
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
Button::Key(_) => {
|
|
||||||
// if this press event was in queue, resolve all ModTaps before in queue as Mods
|
// if this press event was in queue, resolve all ModTaps before in queue as Mods
|
||||||
// otherwise, just resolve this
|
// otherwise, just resolve this
|
||||||
if let Some(position_in_queue) = position_in_queue {
|
if let Some(position_in_queue) = position_in_queue {
|
||||||
|
|||||||
@ -23,10 +23,11 @@ pub mod usb;
|
|||||||
#[cfg(target_arch = "arm")]
|
#[cfg(target_arch = "arm")]
|
||||||
pub mod ws2812;
|
pub mod ws2812;
|
||||||
|
|
||||||
|
pub mod atomics;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
|
pub mod keypress_handler;
|
||||||
pub mod logger;
|
pub mod logger;
|
||||||
pub mod neopixel;
|
pub mod neopixel;
|
||||||
pub mod rgb;
|
pub mod rgb;
|
||||||
pub mod rtt;
|
pub mod rtt;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod keypress_handler;
|
|
||||||
|
|||||||
@ -50,6 +50,7 @@ async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut even
|
|||||||
let (mut rx, mut tx) = uart.split();
|
let (mut rx, mut tx) = uart.split();
|
||||||
let (mut events_rx, mut events_tx) = events.split();
|
let (mut events_rx, mut events_tx) = events.split();
|
||||||
|
|
||||||
|
/// The header of a UART packet.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug, NoUninit, AnyBitPattern)]
|
#[derive(Clone, Copy, Debug, NoUninit, AnyBitPattern)]
|
||||||
struct Header {
|
struct Header {
|
||||||
@ -78,11 +79,14 @@ async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut even
|
|||||||
|
|
||||||
if calculated_crc != crc {
|
if calculated_crc != crc {
|
||||||
log::error!("invalid uart header crc: {header:x?}");
|
log::error!("invalid uart header crc: {header:x?}");
|
||||||
buf.remove(0); // pop the first byte and hope we find a good packet header
|
buf.remove(0); // drop the first byte and hope we find a good packet header
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!("got uart header {header:x?}");
|
log::trace!(
|
||||||
|
"reading from uart, header={header:?}, bytes_received={}",
|
||||||
|
rest.len()
|
||||||
|
);
|
||||||
|
|
||||||
let len = usize::from(header.len);
|
let len = usize::from(header.len);
|
||||||
if rest.len() >= len {
|
if rest.len() >= len {
|
||||||
|
|||||||
@ -48,7 +48,7 @@ fn serialize_layout(ron_path: &str, postcard_path: &str) {
|
|||||||
println!("cargo:rerun-if-changed={ron_path}");
|
println!("cargo:rerun-if-changed={ron_path}");
|
||||||
|
|
||||||
let layers = fs::read_to_string(ron_path).expect("Failed to read .ron");
|
let layers = fs::read_to_string(ron_path).expect("Failed to read .ron");
|
||||||
let layers: Vec<Layer> = ron::from_str(&layers).expect("Failed to deserialize .ron");
|
let layers: Vec<Vec<Layer>> = ron::from_str(&layers).expect("Failed to deserialize .ron");
|
||||||
|
|
||||||
let serialized = postcard::to_stdvec(&layers).expect("Failed to serialize layers");
|
let serialized = postcard::to_stdvec(&layers).expect("Failed to serialize layers");
|
||||||
|
|
||||||
|
|||||||
111
right/layers.ron
111
right/layers.ron
@ -1,4 +1,5 @@
|
|||||||
[
|
[
|
||||||
|
[
|
||||||
Layer(
|
Layer(
|
||||||
buttons: [
|
buttons: [
|
||||||
// Row 1
|
// Row 1
|
||||||
@ -23,7 +24,7 @@
|
|||||||
Key(Z),
|
Key(Z),
|
||||||
|
|
||||||
// Thumbpad
|
// Thumbpad
|
||||||
HoldLayer(1),
|
Layer(Peek, Right, 1),
|
||||||
Key(Return),
|
Key(Return),
|
||||||
Key(Delete),
|
Key(Delete),
|
||||||
],
|
],
|
||||||
@ -31,14 +32,14 @@
|
|||||||
Layer(
|
Layer(
|
||||||
buttons: [
|
buttons: [
|
||||||
// Row 1
|
// Row 1
|
||||||
Key(PrintScreen),
|
Compose(O, A, None), // å
|
||||||
Key(D7),
|
Key(D7),
|
||||||
Key(D8),
|
Key(D8),
|
||||||
Key(D9),
|
Key(D9),
|
||||||
Key(D0),
|
Key(D0),
|
||||||
|
|
||||||
// Row 2
|
// Row 2
|
||||||
None,
|
Compose(Apostrophe, A, None), // ä
|
||||||
ModTap(D4, RCtrl),
|
ModTap(D4, RCtrl),
|
||||||
ModTap(D5, RShift),
|
ModTap(D5, RShift),
|
||||||
ModTap(D6, RAlt),
|
ModTap(D6, RAlt),
|
||||||
@ -46,14 +47,74 @@
|
|||||||
Mod(RMod),
|
Mod(RMod),
|
||||||
|
|
||||||
// Row 3
|
// Row 3
|
||||||
None,
|
Compose(Apostrophe, A, None), // ö
|
||||||
Key(D1),
|
Key(D1),
|
||||||
Key(D2),
|
Key(D2),
|
||||||
Key(D3),
|
Key(D3),
|
||||||
None,
|
None,
|
||||||
|
|
||||||
// Thumbpad
|
// Thumbpad
|
||||||
HoldLayer(1),
|
Layer(Peek, Right, 1),
|
||||||
|
Key(Return),
|
||||||
|
Key(Delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Layer(
|
||||||
|
buttons: [
|
||||||
|
// Row 1
|
||||||
|
Key(F1),
|
||||||
|
Key(F4),
|
||||||
|
Key(F7),
|
||||||
|
Key(F10),
|
||||||
|
Layer(Move, Down, 1),
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
Key(F2),
|
||||||
|
ModTap(F5, RCtrl),
|
||||||
|
ModTap(F8, RShift),
|
||||||
|
ModTap(F11, RAlt),
|
||||||
|
Mod(RMod),
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
Key(F3),
|
||||||
|
Key(F6),
|
||||||
|
Key(F9),
|
||||||
|
Key(F12),
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Thumbpad
|
||||||
|
Layer(Peek, Right, 1),
|
||||||
|
Key(Return),
|
||||||
|
Key(Delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
[ // gaming row
|
||||||
|
Layer(
|
||||||
|
buttons: [
|
||||||
|
// Row 1
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Thumbpad
|
||||||
|
Layer(Peek, Right, 1),
|
||||||
Key(Return),
|
Key(Return),
|
||||||
Key(Delete),
|
Key(Delete),
|
||||||
],
|
],
|
||||||
@ -69,10 +130,10 @@
|
|||||||
|
|
||||||
// Row 2
|
// Row 2
|
||||||
None,
|
None,
|
||||||
Mod(RCtrl),
|
None,
|
||||||
Mod(RShift),
|
None,
|
||||||
Mod(RAlt),
|
None,
|
||||||
Mod(RMod),
|
None,
|
||||||
|
|
||||||
// Row 3
|
// Row 3
|
||||||
None,
|
None,
|
||||||
@ -82,9 +143,39 @@
|
|||||||
None,
|
None,
|
||||||
|
|
||||||
// Thumbpad
|
// Thumbpad
|
||||||
HoldLayer(1),
|
Layer(Peek, Right, 1),
|
||||||
Key(Return),
|
Key(Return),
|
||||||
Key(Delete),
|
Key(Delete),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Layer(
|
||||||
|
buttons: [
|
||||||
|
// Row 1
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Layer(Move, Up, 1),
|
||||||
|
|
||||||
|
// Row 2
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Row 3
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
|
||||||
|
// Thumbpad
|
||||||
|
Layer(Peek, Right, 1),
|
||||||
|
Key(Return),
|
||||||
|
Key(Delete),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
//Timer::after(Duration::from_millis(3000)).await;
|
//Timer::after(Duration::from_millis(3000)).await;
|
||||||
|
|
||||||
let layers = include_bytes!("layers.pc");
|
let layers = include_bytes!("layers.pc");
|
||||||
let Ok(layers): Result<Vec<Layer>, _> = postcard::from_bytes(layers) else {
|
let Ok(layers): Result<Vec<Vec<Layer>>, _> = postcard::from_bytes(layers) else {
|
||||||
log::error!("Failed to deserialize layer config");
|
log::error!("Failed to deserialize layer config");
|
||||||
stall().await
|
stall().await
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user