143 lines
5.7 KiB
Rust
143 lines
5.7 KiB
Rust
use esp_idf_svc::{eventloop::EspSystemEventLoop, hal::{gpio::Pins, modem::Modem, prelude::Peripherals, rmt::RMT, task::thread::ThreadSpawnConfiguration}, nvs::EspDefaultNvsPartition, sys::esp_efuse_mac_get_default};
|
|
use rgb::Rgb;
|
|
|
|
use crate::{buffers::{BufferedSurfacePool, Pixbuf}, mappings::StrideMapping, platform::{smart_leds_lib::{rmt::FastWs2812Esp32Rmt, StrideOutput}, Board}, task::FixedSizeScheduler};
|
|
|
|
use super::{mqtt::MqttTask, wifi::WifiTask};
|
|
|
|
pub struct Esp32Board {
|
|
sys_loop: EspSystemEventLoop,
|
|
modem: Option<Modem>,
|
|
pins: Option<Pins>,
|
|
rmt: Option<RMT>,
|
|
surfaces: Option<BufferedSurfacePool>,
|
|
}
|
|
|
|
impl Board for Esp32Board {
|
|
type Output = StrideOutput<[Rgb<u8>; 310], FastWs2812Esp32Rmt<'static>>;
|
|
type Surfaces = BufferedSurfacePool;
|
|
type Scheduler = FixedSizeScheduler<2>;
|
|
|
|
fn chip_id() -> u64 {
|
|
let mut chip_id: [u8; 8] = [0; 8];
|
|
unsafe {
|
|
esp_efuse_mac_get_default(&mut chip_id as *mut u8);
|
|
}
|
|
return u64::from_be_bytes(chip_id);
|
|
}
|
|
|
|
fn take() -> Self {
|
|
// It is necessary to call this function once. Otherwise some patches to the runtime
|
|
// implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
|
|
esp_idf_svc::sys::link_patches();
|
|
|
|
// Bind the log crate to the ESP Logging facilities
|
|
esp_idf_svc::log::EspLogger::initialize_default();
|
|
|
|
let peripherals = Peripherals::take().unwrap();
|
|
let sys_loop = EspSystemEventLoop::take().unwrap();
|
|
|
|
Esp32Board {
|
|
modem: Some(peripherals.modem),
|
|
sys_loop: sys_loop,
|
|
surfaces: Some(BufferedSurfacePool::new()),
|
|
pins: Some(peripherals.pins),
|
|
rmt: Some(peripherals.rmt)
|
|
}
|
|
}
|
|
|
|
fn output(&mut self) -> Self::Output {
|
|
|
|
log::info!("Setting up output for chip ID {:x?}", Self::chip_id());
|
|
|
|
const POWER_VOLTS : u32 = 5;
|
|
const POWER_MA : u32 = 500;
|
|
const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA;
|
|
|
|
let pins = self.pins.take().unwrap();
|
|
let rmt = self.rmt.take().unwrap();
|
|
ThreadSpawnConfiguration {
|
|
pin_to_core: Some(esp_idf_svc::hal::cpu::Core::Core1),
|
|
..Default::default()
|
|
}.set().unwrap();
|
|
// Wifi driver creates too many interrupts on core0, so we need to use RMT on core1.
|
|
// But the implementation spawns a thread based on the core the driver was created in,
|
|
// so we create the driver in another thread briefly.
|
|
// Fun stuff.
|
|
let output = match Self::chip_id().to_be_bytes() { // panel test board
|
|
[72, 202, 67, 89, 145, 204, 0, 0] => {
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new_panel(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
|
MAX_POWER_MW
|
|
)
|
|
},
|
|
[0x8C, 0xAA, 0xB5, 0x83, 0x5f, 0x74, 0x0, 0x0] => { //ponderjar
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new_jar(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio14).unwrap() }).join().unwrap(),
|
|
MAX_POWER_MW
|
|
)
|
|
},
|
|
[0x4a, 0xca, 0x43, 0x59, 0x85, 0x58, 0x0, 0x0] => { // Albus the tree
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new_albus(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
|
POWER_VOLTS * 2_400
|
|
)
|
|
},
|
|
[0x48, 0xca, 0x43, 0x59, 0x9d, 0x48, 0x0, 0x0] => { // kitchen cabinets
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new_fairylights(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
|
MAX_POWER_MW
|
|
)
|
|
},
|
|
[0x48, 0xca, 0x43, 0x59, 0x9e, 0xdc, 0x0, 0x0] => { // front window
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new_fairylights(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
|
MAX_POWER_MW
|
|
)
|
|
},
|
|
[0xfc, 0xf5, 0xc4, 0x05, 0xb8, 0x30, 0x0, 0x0] => { // cyberplague
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new_cyberplague(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio13).unwrap() }).join().unwrap(),
|
|
MAX_POWER_MW
|
|
)
|
|
},
|
|
_ => {
|
|
StrideOutput::new(
|
|
Pixbuf::new(),
|
|
StrideMapping::new(),
|
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
|
MAX_POWER_MW
|
|
)
|
|
}
|
|
};
|
|
ThreadSpawnConfiguration {
|
|
..Default::default()
|
|
}.set().unwrap();
|
|
|
|
output
|
|
}
|
|
|
|
fn surfaces(&mut self) -> Self::Surfaces {
|
|
self.surfaces.take().unwrap()
|
|
}
|
|
|
|
fn system_tasks(&mut self) -> Self::Scheduler {
|
|
let nvs = EspDefaultNvsPartition::take().unwrap();
|
|
FixedSizeScheduler::new([
|
|
Box::new(WifiTask::new(self.modem.take().unwrap(), self.sys_loop.clone(), &nvs)),
|
|
Box::new(MqttTask::new())
|
|
])
|
|
}
|
|
} |