Add led drivers
This commit is contained in:
parent
c1b98bb7d0
commit
e023814626
4 changed files with 275 additions and 12 deletions
15
.zed/tasks.json
Normal file
15
.zed/tasks.json
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Project tasks configuration. See https://zed.dev/docs/tasks for documentation.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"label": "cargo run --release [roleplay-microcontroller]",
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["run", "--release"],
|
||||||
|
"use_new_terminal": false,
|
||||||
|
"allow_concurrent_runs": false,
|
||||||
|
"reveal": "always",
|
||||||
|
"hide": "never",
|
||||||
|
"shell": "system"
|
||||||
|
}
|
||||||
|
]
|
||||||
67
Cargo.lock
generated
67
Cargo.lock
generated
|
|
@ -107,7 +107,7 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f377753756ec12e76b52d2dd657437be0448cc9736402ffadd0b8b8b9602c8a1"
|
checksum = "f377753756ec12e76b52d2dd657437be0448cc9736402ffadd0b8b8b9602c8a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-sync",
|
"embassy-sync 0.6.2",
|
||||||
"embedded-io",
|
"embedded-io",
|
||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
"futures-intrusive",
|
"futures-intrusive",
|
||||||
|
|
@ -215,7 +215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12"
|
checksum = "41fea5ef5bed4d3468dfd44f5c9fa4cda8f54c86d4fb4ae683eacf9d39e2ea12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-sync",
|
"embassy-sync 0.6.2",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embedded-hal 0.2.7",
|
"embedded-hal 0.2.7",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
|
|
@ -262,7 +262,7 @@ checksum = "ed041cc19a603d657124fddefdcbe5ef8bd60e77d972793ebb57de93394f5949"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-net-driver",
|
"embassy-net-driver",
|
||||||
"embassy-sync",
|
"embassy-sync 0.6.2",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
"embedded-nal-async",
|
"embedded-nal-async",
|
||||||
|
|
@ -291,6 +291,20 @@ dependencies = [
|
||||||
"heapless",
|
"heapless",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embassy-sync"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cef1a8a1ea892f9b656de0295532ac5d8067e9830d49ec75076291fd6066b136"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"critical-section",
|
||||||
|
"embedded-io-async",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-util",
|
||||||
|
"heapless",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-time"
|
name = "embassy-time"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
@ -499,7 +513,7 @@ dependencies = [
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-embedded-hal",
|
"embassy-embedded-hal",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
"embassy-sync",
|
"embassy-sync 0.6.2",
|
||||||
"embedded-can",
|
"embedded-can",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
"embedded-hal-async",
|
"embedded-hal-async",
|
||||||
|
|
@ -537,7 +551,7 @@ dependencies = [
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
"embassy-sync",
|
"embassy-sync 0.6.2",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embassy-time-driver",
|
"embassy-time-driver",
|
||||||
"embassy-time-queue-utils",
|
"embassy-time-queue-utils",
|
||||||
|
|
@ -612,7 +626,7 @@ dependencies = [
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-net-driver",
|
"embassy-net-driver",
|
||||||
"embassy-sync",
|
"embassy-sync 0.6.2",
|
||||||
"embedded-io",
|
"embedded-io",
|
||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
"enumset",
|
"enumset",
|
||||||
|
|
@ -874,7 +888,9 @@ dependencies = [
|
||||||
"bleps",
|
"bleps",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
|
"embassy-futures",
|
||||||
"embassy-net",
|
"embassy-net",
|
||||||
|
"embassy-sync 0.7.0",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embedded-io",
|
"embedded-io",
|
||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
|
|
@ -885,8 +901,10 @@ dependencies = [
|
||||||
"esp-wifi",
|
"esp-wifi",
|
||||||
"heapless",
|
"heapless",
|
||||||
"log",
|
"log",
|
||||||
|
"smart-leds",
|
||||||
"smoltcp",
|
"smoltcp",
|
||||||
"static_cell",
|
"static_cell",
|
||||||
|
"ws2812-spi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1081,6 +1099,15 @@ version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rgb"
|
||||||
|
version = "0.8.50"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "riscv"
|
name = "riscv"
|
||||||
version = "0.12.1"
|
version = "0.12.1"
|
||||||
|
|
@ -1163,6 +1190,24 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smart-leds"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "66df34e571fa9993fa6f99131a374d58ca3d694b75f9baac93458fe0d6057bf0"
|
||||||
|
dependencies = [
|
||||||
|
"smart-leds-trait",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smart-leds-trait"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edeb89c73244414bb0568611690dd095b2358b3fda5bae65ad784806cca00157"
|
||||||
|
dependencies = [
|
||||||
|
"rgb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smoltcp"
|
name = "smoltcp"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
@ -1502,6 +1547,16 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ws2812-spi"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2fd98e2b649252eced2ec3aa8d5048e7d2ac294276b0567939bbf47741f9934"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
"smart-leds-trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtensa-lx"
|
name = "xtensa-lx"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
|
|
||||||
16
Cargo.toml
16
Cargo.toml
|
|
@ -4,8 +4,18 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "uwu"
|
name = "m5stamp_c3_ws2812"
|
||||||
path = "./src/bin/main.rs"
|
path = "./src/bin/main.rs"
|
||||||
|
test = false
|
||||||
|
doctest = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "m5stamp_c3_ws2812"
|
||||||
|
path = "./src/lib.rs"
|
||||||
|
test = false
|
||||||
|
doctest = false
|
||||||
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-net = { version = "0.6.0", features = [
|
embassy-net = { version = "0.6.0", features = [
|
||||||
|
|
@ -52,6 +62,10 @@ esp-wifi = { version = "0.13.0", features = [
|
||||||
] }
|
] }
|
||||||
heapless = { version = "0.8.0", default-features = false }
|
heapless = { version = "0.8.0", default-features = false }
|
||||||
static_cell = { version = "2.1.0", features = ["nightly"] }
|
static_cell = { version = "2.1.0", features = ["nightly"] }
|
||||||
|
smart-leds = "0.4.0"
|
||||||
|
ws2812-spi = "0.5.0"
|
||||||
|
embassy-futures = "0.1.1"
|
||||||
|
embassy-sync = "0.7.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
# Rust debug is too slow.
|
# Rust debug is too slow.
|
||||||
|
|
|
||||||
189
src/bin/main.rs
189
src/bin/main.rs
|
|
@ -1,12 +1,25 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
use core::pin::Pin;
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_futures::select::{Either, select};
|
||||||
|
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
|
||||||
|
use embassy_sync::channel::{Channel, Sender};
|
||||||
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
|
use esp_hal::gpio::{Input, InputConfig, Pull};
|
||||||
|
use esp_hal::peripherals::GPIO;
|
||||||
|
use esp_hal::spi::master::{Config, Spi};
|
||||||
|
use esp_hal::time::Rate;
|
||||||
use esp_hal::timer::systimer::SystemTimer;
|
use esp_hal::timer::systimer::SystemTimer;
|
||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use smart_leds::RGB8;
|
||||||
|
use smart_leds::SmartLedsWrite;
|
||||||
|
use static_cell::StaticCell;
|
||||||
|
use ws2812_spi::Ws2812;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||||
|
|
@ -15,8 +28,11 @@ fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
static CHANNEL: StaticCell<Channel<NoopRawMutex, i32, 2>> = StaticCell::new();
|
||||||
|
|
||||||
#[esp_hal_embassy::main]
|
#[esp_hal_embassy::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
|
let channel = CHANNEL.init(Channel::new());
|
||||||
// generator version: 0.3.1
|
// generator version: 0.3.1
|
||||||
|
|
||||||
esp_println::logger::init_logger_from_env();
|
esp_println::logger::init_logger_from_env();
|
||||||
|
|
@ -39,13 +55,176 @@ async fn main(spawner: Spawner) {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// TODO: Spawn some tasks
|
spawner
|
||||||
let _ = spawner;
|
.spawn(listen_rotary_encoder(
|
||||||
|
RotaryEncoderConfig {
|
||||||
|
clk: Input::new(
|
||||||
|
peripherals.GPIO8,
|
||||||
|
InputConfig::default().with_pull(Pull::Up),
|
||||||
|
),
|
||||||
|
ot: Input::new(
|
||||||
|
peripherals.GPIO10,
|
||||||
|
InputConfig::default().with_pull(Pull::Up),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
channel.sender(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut led_strip = {
|
||||||
|
let spi = Spi::new(
|
||||||
|
peripherals.SPI2,
|
||||||
|
Config::default().with_frequency(Rate::from_mhz(3)),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.with_mosi(peripherals.GPIO4);
|
||||||
|
Ws2812::new(spi)
|
||||||
|
};
|
||||||
|
|
||||||
|
let colors = [
|
||||||
|
RGB8 { r: 0, g: 255, b: 0 },
|
||||||
|
RGB8 { r: 255, g: 0, b: 0 },
|
||||||
|
RGB8 { r: 255, g: 0, b: 0 },
|
||||||
|
RGB8 {
|
||||||
|
r: 0,
|
||||||
|
g: 255,
|
||||||
|
b: 255,
|
||||||
|
},
|
||||||
|
RGB8 {
|
||||||
|
r: 255,
|
||||||
|
g: 0,
|
||||||
|
b: 255,
|
||||||
|
},
|
||||||
|
RGB8 {
|
||||||
|
r: 255,
|
||||||
|
g: 255,
|
||||||
|
b: 0,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let mut color_idx = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
info!("Hello world!");
|
let delta = channel.receive().await;
|
||||||
Timer::after(Duration::from_secs(1)).await;
|
color_idx += delta;
|
||||||
|
// led_strip
|
||||||
|
// .write([
|
||||||
|
// colors[color_idx % colors.len()],
|
||||||
|
// colors[(color_idx + 1) % colors.len()],
|
||||||
|
// colors[(color_idx + 2) % colors.len()],
|
||||||
|
// colors[(color_idx + 3) % colors.len()],
|
||||||
|
// ])
|
||||||
|
// .unwrap();
|
||||||
|
//
|
||||||
|
|
||||||
|
let cnt = 4;
|
||||||
|
|
||||||
|
led_strip
|
||||||
|
.write((0..cnt).map(|it| {
|
||||||
|
if it <= (color_idx % cnt) {
|
||||||
|
RGB8 {
|
||||||
|
r: 255,
|
||||||
|
g: 50,
|
||||||
|
b: 00,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RGB8 { r: 0, g: 0, b: 0 }
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-beta.0/examples/src/bin
|
// for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/esp-hal-v1.0.0-beta.0/examples/src/bin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Throttler<'a> {
|
||||||
|
input: Input<'a>,
|
||||||
|
throttle: Duration,
|
||||||
|
last_fire: Option<Instant>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Throttler<'a> {
|
||||||
|
pub fn new(input: Input<'a>, throttle: Duration) -> Self {
|
||||||
|
Self {
|
||||||
|
input,
|
||||||
|
throttle,
|
||||||
|
last_fire: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn wait_for(&mut self) {
|
||||||
|
if let Some(allow_next_fire) = self
|
||||||
|
.last_fire
|
||||||
|
.and_then(|last_fire| last_fire.checked_add(self.throttle))
|
||||||
|
{
|
||||||
|
Timer::at(allow_next_fire).await;
|
||||||
|
}
|
||||||
|
self.input.wait_for_falling_edge().await;
|
||||||
|
self.last_fire = Some(Instant::now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RotaryEncoderConfig<'a, 'b> {
|
||||||
|
clk: Input<'a>,
|
||||||
|
ot: Input<'b>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
enum RotaryState {
|
||||||
|
Clk,
|
||||||
|
Ot,
|
||||||
|
}
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn listen_rotary_encoder(
|
||||||
|
mut config: RotaryEncoderConfig<'static, 'static>,
|
||||||
|
channel: Sender<'static, NoopRawMutex, i32, 2>,
|
||||||
|
) {
|
||||||
|
info!("Waiting for rotary.");
|
||||||
|
|
||||||
|
let mut state: Option<RotaryState> = None;
|
||||||
|
|
||||||
|
let mut clk_input = Throttler::new(config.clk, Duration::from_millis(50));
|
||||||
|
let mut ot_input = Throttler::new(config.ot, Duration::from_millis(50));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let clk = async {
|
||||||
|
clk_input.wait_for().await;
|
||||||
|
};
|
||||||
|
|
||||||
|
let ot = async {
|
||||||
|
ot_input.wait_for().await;
|
||||||
|
};
|
||||||
|
|
||||||
|
let next_state = match select(clk, ot).await {
|
||||||
|
Either::First(_) => (RotaryState::Clk),
|
||||||
|
Either::Second(_) => (RotaryState::Ot),
|
||||||
|
};
|
||||||
|
|
||||||
|
//info!("State: {next_state:?}");
|
||||||
|
|
||||||
|
match (state, next_state) {
|
||||||
|
(None, RotaryState::Ot) => {
|
||||||
|
if clk_input.input.is_high() {
|
||||||
|
state = Some(RotaryState::Ot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(None, RotaryState::Clk) => {
|
||||||
|
if ot_input.input.is_high() {
|
||||||
|
state = Some(RotaryState::Clk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(RotaryState::Clk), RotaryState::Ot) => {
|
||||||
|
info!("Clk -> Ot");
|
||||||
|
state = None;
|
||||||
|
channel.send(1).await;
|
||||||
|
}
|
||||||
|
(Some(RotaryState::Ot), RotaryState::Clk) => {
|
||||||
|
info!("Ot -> Clk");
|
||||||
|
state = None;
|
||||||
|
channel.send(-1).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
(Some(RotaryState::Ot), RotaryState::Ot)
|
||||||
|
| (Some(RotaryState::Clk), RotaryState::Clk) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue