Skip to content

Commit 4276780

Browse files
authored
feat(beepy): add a mediocre i2c_puppet driver (#155)
Depends on #154. This branch adds a simple driver for the `i2c_puppet` firmware on the Beepy RP2040. It allows controlling the status LED and reading keypresses. Key input can be read by sending a message to the driver service to subscribe to keypresses. The driver task tracks a list of subscriptions (channels) and broadcasts each keystroke to all subscribers. In addition, the status LED and backlight can be controlled by sending messages to the driver task. The keyboard driver is in a new `mnemos-beepy` crate in `platforms` that contains drivers for the Beepy hardware that are implemented using cross-platform driver service definitions. Right now, this is just the `i2c_puppet` driver, which is implemented against the kernel's cross-platform `I2cService` interface. However, in the future, if we can write a generic driver interface for SPI in the kernel crate, we could move the SHARP display driver into `mnemos-beepy` as well. Currently, the way the keyboard is implemented is pretty bad: we poll the keyboard for new keystrokes periodically, as long as at least one task is subscribed. This is wildly inefficient and we should instead have the `i2c_puppet` send us an interrupt when new keystrokes are ready. However, this will require code for configuring the D1 to actually generate interrupts on GPIO pins, which we haven't written yet. I'll add this in a later branch and rewrite the keyboard driver to use that. Keyboard input isn't actually wired up to anything yet --- we just run a task that logs all keypresses. A subsequent branch will actually make the forth shell handle keyboard input.
1 parent ec43a31 commit 4276780

File tree

13 files changed

+764
-128
lines changed

13 files changed

+764
-128
lines changed

Cargo.lock

Lines changed: 25 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ members = [
1919

2020
# platforms
2121
"platforms/allwinner-d1/core",
22+
"platforms/beepy",
2223
]
2324

2425
exclude = ["platforms/pomelo"]
@@ -34,3 +35,7 @@ rev = "cbcfc62a6ea3646fb43f2c159cfdc19b3d932004"
3435
[patch.crates-io.cordyceps]
3536
git = "https://github.com/hawkw/mycelium.git"
3637
rev = "cbcfc62a6ea3646fb43f2c159cfdc19b3d932004"
38+
39+
[patch.crates-io.bbq10kbd]
40+
git = "https://github.com/hawkw/bbq10kbd"
41+
branch = "eliza/async"

platforms/allwinner-d1/boards/Cargo.lock

Lines changed: 26 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

platforms/allwinner-d1/boards/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ git = "https://github.com/tokio-rs/tracing"
5656
features = ["attributes"]
5757
default-features = false
5858

59+
[dependencies.mnemos-beepy]
60+
path = "../../beepy"
61+
5962
### patches ###
6063

6164
[patch.crates-io.maitake]
@@ -72,3 +75,8 @@ rev = "cbcfc62a6ea3646fb43f2c159cfdc19b3d932004"
7275

7376
[patch.crates-io.mnemos-alloc]
7477
path = "../../../source/alloc"
78+
79+
# NOTE: keep this patch in sync with the one in the main kernel workspace!
80+
[patch.crates-io.bbq10kbd]
81+
git = "https://github.com/hawkw/bbq10kbd"
82+
branch = "eliza/async"

platforms/allwinner-d1/boards/src/beepy.rs

Lines changed: 0 additions & 102 deletions
This file was deleted.

platforms/allwinner-d1/boards/src/bin/mq-pro.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use mnemos_d1_core::{
1111
timer::Timers,
1212
Ram, D1,
1313
};
14+
use mnemos_beepy::i2c_puppet::{I2cPuppetClient, I2cPuppetServer, HsvColor};
1415

1516
const HEAP_SIZE: usize = 384 * 1024 * 1024;
1617

@@ -62,8 +63,42 @@ fn main() -> ! {
6263
})
6364
.unwrap();
6465

65-
// Initialize Beepy peripherals.
66-
mnemos_d1::beepy::initialize(&d1);
66+
d1.initialize_sharp_display();
67+
68+
let i2c_puppet_up = d1.kernel.initialize(async move {
69+
d1.kernel.sleep(Duration::from_secs(2)).await;
70+
I2cPuppetServer::register(d1.kernel, Default::default()).await.expect("failed to register i2c_puppet driver!");
71+
}).unwrap();
72+
73+
d1.kernel.initialize(
74+
async move {
75+
// i2c_puppet demo: print each keypress to the console.
76+
i2c_puppet_up.await.unwrap();
77+
let mut i2c_puppet = I2cPuppetClient::from_registry(d1.kernel).await;
78+
tracing::info!("got i2c puppet client");
79+
80+
let mut keys = i2c_puppet.subscribe_to_keys().await.expect("can't get keys");
81+
tracing::info!("got key subscription");
82+
while let Ok(key) = keys.next_char().await {
83+
tracing::info!(?key, "got keypress");
84+
}
85+
}
86+
).unwrap();
87+
88+
d1.kernel.initialize(async move {
89+
// walk through the HSV color space. maybe eventually we'll use the RGB
90+
// LED to display useful information, but this is fun for now.
91+
let mut hue = 0;
92+
93+
let mut i2c_puppet = I2cPuppetClient::from_registry(d1.kernel).await;
94+
95+
i2c_puppet.toggle_led(true).await.expect("can't turn on LED");
96+
loop {
97+
i2c_puppet.set_led_color(HsvColor::from_hue(hue)).await.expect("can't set color");
98+
hue = hue.wrapping_add(1);
99+
d1.kernel.sleep(Duration::from_millis(50)).await;
100+
}
101+
}).unwrap();
67102

68103
d1.run()
69104
}

platforms/allwinner-d1/boards/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
extern crate alloc;
44

5-
pub mod beepy;
6-
75
use core::{panic::PanicInfo, ptr::NonNull};
86
use kernel::mnemos_alloc::heap::{MnemosAlloc, SingleThreadedLinkedListAllocator};
97
use mnemos_d1_core::{Ram, D1};

platforms/allwinner-d1/core/src/drivers/twi.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,6 @@ impl I2c0 {
348348
tracing::trace!("starting I2C transaction");
349349
let mut guard = self.isr.lock(self.twi);
350350

351-
// reset the TWI engine.
352-
guard.twi.twi_srst.write(|w| w.soft_rst().set_bit());
353-
guard.twi.twi_efr.reset();
354-
355351
let mut started = false;
356352
while let Ok(Transfer {
357353
buf,
@@ -416,12 +412,6 @@ impl I2c0 {
416412
}
417413
// transaction ended!
418414
tracing::debug!("I2C transaction ended");
419-
420-
let guard = self.isr.lock(self.twi);
421-
guard.twi.twi_cntr.modify(|_r, w| {
422-
w.m_stp().set_bit();
423-
w
424-
});
425415
}
426416
}
427417

@@ -501,7 +491,6 @@ impl TwiData {
501491
twi.twi_cntr.modify(|_cntr_r, cntr_w| {
502492
self.state = match (self.state, status) {
503493
(State::Idle, _) => {
504-
// TODO: send a STOP?
505494
cntr_w.m_stp().set_bit();
506495
State::Idle
507496
}

platforms/beepy/Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "mnemos-beepy"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies.mnemos]
9+
path = "../../source/kernel"
10+
default-features = false
11+
features = ["tracing-02"]
12+
13+
[dependencies.bbq10kbd]
14+
version = "0.1.0"
15+
features = ["embedded-hal-async"]
16+
17+
[dependencies.uuid]
18+
version = "1.1.2"
19+
default-features = false
20+
features = ["serde"]
21+
22+
# tracing 0.2
23+
[dependencies.tracing]
24+
git = "https://github.com/tokio-rs/tracing"
25+
# branch = "master"
26+
features = ["attributes"]
27+
default-features = false
28+
29+
[dependencies.futures]
30+
version = "0.3.21"
31+
features = ["async-await"]
32+
default-features = false

0 commit comments

Comments
 (0)