Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce Delegate #87

Merged
merged 5 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 76 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions examples/embassy-usb-keyboard/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "embassy-usb-keyboard"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
publish = false

[dependencies]
riot-rs = { path = "../../src/riot-rs", features = ["time", "usb"] }
riot-rs-boards = { path = "../../src/riot-rs-boards" }
embassy-executor = { workspace = true, default-features = false }
embassy-nrf = { workspace = true, default-features = false }
embassy-sync = { workspace = true }
embassy-usb = { workspace = true, features = ["usbd-hid"] }
embassy-time = { workspace = true, default-features = false }
static_cell = { workspace = true }
usbd-hid = { version = "0.6.1"}
16 changes: 16 additions & 0 deletions examples/embassy-usb-keyboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# embassy-usb-keyboard

## About

This application is testing basic
[embassy](https://github.com/embassy-rs/embassy) _USB HID_ usage with RIOT-rs.

## How to run

In this folder, run

laze build -b nrf52840dk run

With the device USB cable connected, pressing Button 1 should send the keycode
0x04 ('a') to the connected computer, and pressing Button 2 should send keycode
0x05 ('b').
5 changes: 5 additions & 0 deletions examples/embassy-usb-keyboard/laze.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
apps:
- name: embassy-usb-keyboard
context: nrf52840dk
selects:
- ?release
135 changes: 135 additions & 0 deletions examples/embassy-usb-keyboard/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(used_with_arg)]

use embassy_time::Duration;
use embassy_usb::class::hid::{self, HidReaderWriter};
use riot_rs::embassy::{make_static, usb::UsbDriver};
use riot_rs::linkme::distributed_slice;
use riot_rs::rt::debug::println;

use usbd_hid::descriptor::KeyboardReport;

mod pins;

// TODO: wrap in macro
use riot_rs::embassy::delegate::Delegate;
static USB_BUILDER_HOOK: Delegate<riot_rs::embassy::usb::UsbBuilder> = Delegate::new();

#[distributed_slice(riot_rs::embassy::usb::USB_BUILDER_HOOKS)]
#[linkme(crate=riot_rs::embassy::linkme)]
static _USB_BUILDER_HOOK: &Delegate<riot_rs::embassy::usb::UsbBuilder> = &USB_BUILDER_HOOK;

#[embassy_executor::task]
async fn usb_keyboard(button_peripherals: pins::Buttons) {
let mut buttons = Buttons::new(button_peripherals);

let config = embassy_usb::class::hid::Config {
report_descriptor: <usbd_hid::descriptor::KeyboardReport as usbd_hid::descriptor::SerializedDescriptor>::desc(),
request_handler: None,
poll_ms: 60,
max_packet_size: 64,
};

let hid_state = make_static!(hid::State::new());
let hid_rw: HidReaderWriter<'static, UsbDriver, 1, 8> = USB_BUILDER_HOOK
.with(|usb_builder| hid::HidReaderWriter::new(usb_builder, hid_state, config))
.await;

let (_hid_reader, mut hid_writer) = hid_rw.split();

loop {
for (i, button) in buttons.get_mut().iter_mut().enumerate() {
if button.is_pressed() {
println!("Button #{} pressed", i + 1);

let report = keyboard_report(KEYCODE_MAPPING[i]);
if let Err(e) = hid_writer.write_serialize(&report).await {
println!("Failed to send report: {:?}", e);
}
let report = keyboard_report(KEY_RELEASED);
if let Err(e) = hid_writer.write_serialize(&report).await {
println!("Failed to send report: {:?}", e);
}
}
}

// Debounce events
embassy_time::Timer::after(Duration::from_millis(50)).await;
}
}

// TODO: macro up this
use riot_rs::embassy::{arch::OptionalPeripherals, Spawner};
#[riot_rs::embassy::distributed_slice(riot_rs::embassy::EMBASSY_TASKS)]
#[linkme(crate = riot_rs::embassy::linkme)]
fn __init_usb_keyboard(spawner: &Spawner, peripherals: &mut OptionalPeripherals) {
spawner
.spawn(usb_keyboard(pins::Buttons::take_from(peripherals).unwrap()))
.unwrap();
}

use crate::buttons::{Buttons, KEY_COUNT};

// Assuming a QWERTY US layout, see https://docs.qmk.fm/#/how_keyboards_work
// and https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
const KC_A: u8 = 0x04;
const KC_C: u8 = 0x06;
const KC_G: u8 = 0x0a;
const KC_T: u8 = 0x17;

const KEY_RELEASED: u8 = 0x00;

fn keyboard_report(keycode: u8) -> KeyboardReport {
KeyboardReport {
keycodes: [keycode, 0, 0, 0, 0, 0],
leds: 0,
modifier: 0,
reserved: 0,
}
}

// Maps physical buttons to keycodes/characters
const KEYCODE_MAPPING: [u8; KEY_COUNT as usize] = [KC_A, KC_C, KC_G, KC_T];

mod buttons {
use embassy_nrf::gpio::{AnyPin, Input, Pin, Pull};

use crate::pins;

pub const KEY_COUNT: u8 = 4;

pub struct Button(Input<'static>);

impl Button {
pub fn new(button: AnyPin) -> Self {
Self(Input::new(button, Pull::Up))
}

pub fn is_pressed(&mut self) -> bool {
self.0.is_low()
}
}

pub struct Buttons([Button; KEY_COUNT as usize]);

impl Buttons {
pub fn new(button_peripherals: pins::Buttons) -> Self {
Self([
Button::new(button_peripherals.btn1.degrade()),
Button::new(button_peripherals.btn2.degrade()),
Button::new(button_peripherals.btn3.degrade()),
Button::new(button_peripherals.btn4.degrade()),
])
}

pub fn get(&self) -> &[Button] {
&self.0
}

pub fn get_mut(&mut self) -> &mut [Button] {
&mut self.0
}
}
}
12 changes: 12 additions & 0 deletions examples/embassy-usb-keyboard/src/pins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use embassy_nrf::peripherals;
use riot_rs::define_peripherals;

#[cfg(builder = "nrf52840dk")]
define_peripherals! {
Buttons {
btn1: P0_11,
btn2: P0_12,
btn3: P0_24,
btn4: P0_25,
}
}
1 change: 1 addition & 0 deletions examples/laze.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ subdirs:
- embassy-http-server
- embassy-net-tcp
- embassy-net-udp
- embassy-usb-keyboard
- hello-world
- minimal
- threading
Loading
Loading