Compare commits
1 Commits
da2a8f5bfc
...
wip-1
Author | SHA1 | Date | |
---|---|---|---|
7a3ea61030 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,3 @@
|
|||||||
/.vscode
|
|
||||||
/.embuild
|
/.embuild
|
||||||
/target
|
/target
|
||||||
/Cargo.lock
|
/Cargo.lock
|
26
.vscode/launch.json
vendored
Normal file
26
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "probe-rs-debug",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "probe-rs Test",
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"connectUnderReset": true,
|
||||||
|
"chip": "ESP32S3",
|
||||||
|
"flashingConfig": {
|
||||||
|
"flashingEnabled": true,
|
||||||
|
"haltAfterReset": true
|
||||||
|
},
|
||||||
|
"coreConfigs": [
|
||||||
|
{
|
||||||
|
"coreIndex": 0,
|
||||||
|
"programBinary": "./target/xtensa-esp32s3-espidf/debug/${workspaceFolderBasename}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@@ -11,11 +11,13 @@ name = "renderbug"
|
|||||||
harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors
|
harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = "s"
|
opt-level = 3
|
||||||
|
lto = true
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
debug = true # Symbols are nice and they don't increase the size on Flash
|
debug = true # Symbols are nice and they don't increase the size on Flash
|
||||||
opt-level = "z"
|
opt-level = "z"
|
||||||
|
lto = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "esp-idf-svc/native", "rmt", "smart-leds"]
|
default = ["std", "esp-idf-svc/native", "rmt", "smart-leds"]
|
||||||
@@ -48,6 +50,7 @@ embedded-graphics = { version = "0.8.1", optional = true, features = ["fixed_poi
|
|||||||
ansi_term = "0.12.1"
|
ansi_term = "0.12.1"
|
||||||
num = "0.4.3"
|
num = "0.4.3"
|
||||||
chrono = "0.4.38"
|
chrono = "0.4.38"
|
||||||
|
fugit = "0.3.7"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
embuild = "0.32.0"
|
embuild = "0.32.0"
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
partition_table = "partitions.csv"
|
|
@@ -1,5 +0,0 @@
|
|||||||
# Name, Type, SubType, Offset, Size, Flags
|
|
||||||
# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap
|
|
||||||
nvs, data, nvs, , 0x6000,
|
|
||||||
phy_init, data, phy, , 0x1000,
|
|
||||||
factory, app, factory, , 3M,
|
|
|
13
src/TODO.md
13
src/TODO.md
@@ -1,18 +1,15 @@
|
|||||||
[x] cfg macros
|
[x] cfg macros
|
||||||
[ ] warnings
|
[ ] warnings
|
||||||
[x] rgb crate
|
[x] rgb crate
|
||||||
[x] Layer blending
|
[ ] Layer blending
|
||||||
[x] Refactor idle pattern into test pattern
|
[ ] Refactor idle pattern into test pattern
|
||||||
[x] Wifi
|
[ ] Wifi
|
||||||
[ ] JSON surface map loading
|
[ ] JSON surface map loading
|
||||||
[ ] Weather
|
[ ] Weather
|
||||||
[x] Circadian Rhythm
|
[ ] Circadian Rhythm
|
||||||
[x] NTP
|
[ ] NTP
|
||||||
[ ] Config to only start a subset of tasks on startup
|
[ ] Config to only start a subset of tasks on startup
|
||||||
[ ] Serial CLI
|
[ ] Serial CLI
|
||||||
[ ] Surface blending API
|
[ ] Surface blending API
|
||||||
[ ] Layer blending equations
|
[ ] Layer blending equations
|
||||||
[ ] Surface rotation
|
[ ] Surface rotation
|
||||||
[ ] esp8266 port
|
|
||||||
[ ] event system
|
|
||||||
[ ] threaded schedulers
|
|
18
src/main.rs
18
src/main.rs
@@ -21,31 +21,29 @@ use crate::geometry::Rectangle;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let mut board: DefaultBoard = Board::take();
|
let mut board: DefaultBoard = Board::take();
|
||||||
|
|
||||||
log::info!("🐛 Booting Renderbug!");
|
log::info!("Board: {}", core::any::type_name_of_val(&board));
|
||||||
|
|
||||||
log::info!("📡 Board {}", core::any::type_name_of_val(&board));
|
log::info!("Creating tasks");
|
||||||
|
|
||||||
log::info!("⚙️ Creating tasks");
|
|
||||||
let mut system = board.system_tasks();
|
let mut system = board.system_tasks();
|
||||||
log::info!("⏰ System scheduler: {}", core::any::type_name_of_val(&system));
|
log::info!("System scheduler: {}", core::any::type_name_of_val(&system));
|
||||||
|
|
||||||
log::info!("💡 Creating output");
|
log::info!("Creating output");
|
||||||
let output = board.output();
|
let output = board.output();
|
||||||
log::info!("Output: {}", core::any::type_name_of_val(&output));
|
log::info!("Output: {}", core::any::type_name_of_val(&output));
|
||||||
|
|
||||||
log::info!("🎨 Preparing surfaces");
|
log::info!("Preparing surfaces");
|
||||||
let mut surfaces = board.surfaces();
|
let mut surfaces = board.surfaces();
|
||||||
log::info!("Surface implementation: {}", core::any::type_name_of_val(&output));
|
log::info!("Surface implementation: {}", core::any::type_name_of_val(&output));
|
||||||
|
|
||||||
log::info!("🌌 Creating animations");
|
log::info!("Creating animations");
|
||||||
let mut animations = FixedSizeScheduler::new([
|
let mut animations = FixedSizeScheduler::new([
|
||||||
Box::new(animations::IdleTask::new(&mut surfaces)),
|
Box::new(animations::IdleTask::new(&mut surfaces)),
|
||||||
Box::new(animations::TestPattern::new(surfaces.new_surface(&Rectangle::everything()).unwrap())),
|
//Box::new(animations::TestPattern::new(surfaces.new_surface(&Rectangle::everything()).unwrap())),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
let mut renderer = FixedSizeScheduler::new([Box::new(Renderer::new(output, surfaces))]);
|
let mut renderer = FixedSizeScheduler::new([Box::new(Renderer::new(output, surfaces))]);
|
||||||
|
|
||||||
log::info!("🚌 Starting event bus");
|
log::info!("Starting event bus");
|
||||||
let mut bus = EventBus::new();
|
let mut bus = EventBus::new();
|
||||||
|
|
||||||
log::info!("Ready to rock and roll");
|
log::info!("Ready to rock and roll");
|
||||||
|
@@ -20,7 +20,7 @@ pub trait Select<'a> {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LinearCoordView {
|
pub struct LinearCoordView {
|
||||||
max_x: u8,
|
rect: Rectangle<Virtual>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ pub type LinearCoords = Coordinates<LinearSpace>;
|
|||||||
impl<'a> CoordinateView<'a> for LinearCoordView {
|
impl<'a> CoordinateView<'a> for LinearCoordView {
|
||||||
type Space = LinearSpace;
|
type Space = LinearSpace;
|
||||||
fn next(&mut self) -> Option<(VirtualCoordinates, LinearCoords)> {
|
fn next(&mut self) -> Option<(VirtualCoordinates, LinearCoords)> {
|
||||||
if self.idx as u8 == self.max_x {
|
if self.idx as u8 == self.rect.bottom_right.x {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let virt = VirtualCoordinates::new(self.idx as u8, 0); // FIXME: scale8
|
let virt = VirtualCoordinates::new(self.idx as u8, 0); // FIXME: scale8
|
||||||
@@ -62,7 +62,7 @@ impl<'a> Select<'a> for LinearPixelMapping {
|
|||||||
type View = LinearCoordView;
|
type View = LinearCoordView;
|
||||||
fn select(&'a self, rect: &Rectangle<Virtual>) -> Self::View {
|
fn select(&'a self, rect: &Rectangle<Virtual>) -> Self::View {
|
||||||
LinearCoordView {
|
LinearCoordView {
|
||||||
max_x: rect.bottom_right.x,
|
rect: rect.clone(),
|
||||||
idx: 0,
|
idx: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,24 +107,6 @@ impl<const STRIDE_NUM: usize> StrideMapping<STRIDE_NUM> {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_cyberplague() -> Self {
|
|
||||||
Self::from_json(&[
|
|
||||||
(0, 6, 6, false),
|
|
||||||
(1, 6, 6, true),
|
|
||||||
(2, 6, 6, false),
|
|
||||||
(3, 4, 9, true),
|
|
||||||
(4, 4, 14, false),
|
|
||||||
(5, 0, 17, true),
|
|
||||||
(6, 2, 12, false),
|
|
||||||
(7, 0, 18, true),
|
|
||||||
(8, 4, 14, false),
|
|
||||||
(9, 5, 9, true),
|
|
||||||
(10, 4, 7, false),
|
|
||||||
(11, 5, 6, true),
|
|
||||||
(12, 5, 6, false)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_jar() -> Self {
|
pub fn new_jar() -> Self {
|
||||||
Self::from_json(&[
|
Self::from_json(&[
|
||||||
(0, 0, 17, false),
|
(0, 0, 17, false),
|
||||||
@@ -169,12 +151,6 @@ impl<const STRIDE_NUM: usize> StrideMapping<STRIDE_NUM> {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_albus() -> Self {
|
|
||||||
Self::from_json(&[
|
|
||||||
(0, 0, 50 * 3, false)
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_json(stride_json: &[(u8, u8, u8, bool)]) -> Self {
|
pub fn from_json(stride_json: &[(u8, u8, u8, bool)]) -> Self {
|
||||||
let mut strides = [Stride::default(); STRIDE_NUM];
|
let mut strides = [Stride::default(); STRIDE_NUM];
|
||||||
let stride_count = stride_json.len();
|
let stride_count = stride_json.len();
|
||||||
@@ -215,6 +191,8 @@ impl<const STRIDE_NUM: usize> StrideMapping<STRIDE_NUM> {
|
|||||||
let s = size.take().unwrap();
|
let s = size.take().unwrap();
|
||||||
log::info!("size={:?}", s);
|
log::info!("size={:?}", s);
|
||||||
|
|
||||||
|
log::info!("strides={:?}", strides);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
strides,
|
strides,
|
||||||
pixel_count: physical_idx,
|
pixel_count: physical_idx,
|
||||||
|
@@ -10,10 +10,8 @@ use chrono::Timelike;
|
|||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
|
||||||
use esp_idf_svc::eventloop::{EspSubscription, EspSystemEventLoop, System};
|
use esp_idf_svc::eventloop::{EspSubscription, EspSystemEventLoop, System};
|
||||||
use esp_idf_svc::hal::gpio::Pins;
|
|
||||||
use esp_idf_svc::hal::modem::Modem;
|
use esp_idf_svc::hal::modem::Modem;
|
||||||
use esp_idf_svc::hal::prelude::Peripherals;
|
use esp_idf_svc::hal::prelude::Peripherals;
|
||||||
use esp_idf_svc::hal::rmt::RMT;
|
|
||||||
use esp_idf_svc::hal::task::thread::ThreadSpawnConfiguration;
|
use esp_idf_svc::hal::task::thread::ThreadSpawnConfiguration;
|
||||||
use esp_idf_svc::mqtt::client::EspMqttClient;
|
use esp_idf_svc::mqtt::client::EspMqttClient;
|
||||||
use esp_idf_svc::mqtt::client::EspMqttConnection;
|
use esp_idf_svc::mqtt::client::EspMqttConnection;
|
||||||
@@ -39,26 +37,72 @@ use crate::task::FixedSizeScheduler;
|
|||||||
use crate::task::Task;
|
use crate::task::Task;
|
||||||
use crate::time::Periodically;
|
use crate::time::Periodically;
|
||||||
|
|
||||||
|
pub mod i2s {
|
||||||
|
use esp_idf_svc::hal::i2s::*;
|
||||||
|
use rgb::ComponentBytes;
|
||||||
|
use rgb::Rgb;
|
||||||
|
|
||||||
|
use crate::mappings::*;
|
||||||
|
use crate::buffers::Pixbuf;
|
||||||
|
use crate::render::Output;
|
||||||
|
use crate::render::Sample;
|
||||||
|
|
||||||
|
pub struct I2SOutput<'d> {
|
||||||
|
driver: I2sDriver<'d, I2sTx>,
|
||||||
|
pixbuf: [Rgb<u8>; 310],
|
||||||
|
pixmap: StrideMapping,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> I2SOutput<'d> {
|
||||||
|
fn new(driver: I2sDriver<'d, I2sTx>) -> Self {
|
||||||
|
I2SOutput {
|
||||||
|
driver,
|
||||||
|
pixbuf: Pixbuf::new(),
|
||||||
|
pixmap: StrideMapping::new_jar()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Output for I2SOutput<'d> {
|
||||||
|
fn on_event(&mut self, event: &crate::events::Event) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blank(&mut self) {
|
||||||
|
self.pixbuf.blank();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit(&mut self) {
|
||||||
|
let bytes = self.pixbuf.as_bytes();
|
||||||
|
let mut written = self.driver.preload_data(bytes).unwrap();
|
||||||
|
self.driver.tx_enable().unwrap();
|
||||||
|
while written < bytes.len() {
|
||||||
|
let next = &bytes[written..];
|
||||||
|
written += self.driver.write(next, 0).unwrap();
|
||||||
|
}
|
||||||
|
self.driver.tx_disable().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Sample for I2SOutput<'d> {
|
||||||
|
type Pixel = Rgb<u8>;
|
||||||
|
fn sample(&mut self, rect: &crate::geometry::Rectangle<crate::geometry::Virtual>) -> impl crate::render::PixelView<Pixel = Self::Pixel> {
|
||||||
|
StrideSampler::new(&mut self.pixbuf, self.pixmap.select(rect))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Esp32Board {
|
pub struct Esp32Board {
|
||||||
sys_loop: EspSystemEventLoop,
|
sys_loop: EspSystemEventLoop,
|
||||||
modem: Option<Modem>,
|
modem: Option<Modem>,
|
||||||
pins: Option<Pins>,
|
|
||||||
rmt: Option<RMT>,
|
|
||||||
surfaces: BufferedSurfacePool,
|
surfaces: BufferedSurfacePool,
|
||||||
|
output: Option<<Self as Board>::Output>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Board for Esp32Board {
|
impl Board for Esp32Board {
|
||||||
type Output = StrideOutput<[Rgb<u8>; 310], FastWs2812Esp32Rmt<'static>>;
|
type Output = StrideOutput<[Rgb<u8>; 310], FastWs2812Esp32Rmt<'static>>;
|
||||||
type Surfaces = BufferedSurfacePool;
|
type Surfaces = BufferedSurfacePool;
|
||||||
type Scheduler = FixedSizeScheduler<4>;
|
type Scheduler = FixedSizeScheduler<4>;
|
||||||
|
|
||||||
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 {
|
fn take() -> Self {
|
||||||
// It is necessary to call this function once. Otherwise some patches to the runtime
|
// It is necessary to call this function once. Otherwise some patches to the runtime
|
||||||
@@ -71,25 +115,18 @@ impl Board for Esp32Board {
|
|||||||
let peripherals = Peripherals::take().unwrap();
|
let peripherals = Peripherals::take().unwrap();
|
||||||
let sys_loop = EspSystemEventLoop::take().unwrap();
|
let sys_loop = EspSystemEventLoop::take().unwrap();
|
||||||
|
|
||||||
Esp32Board {
|
let mut chip_id: [u8; 8] = [0; 8];
|
||||||
modem: Some(peripherals.modem),
|
unsafe {
|
||||||
sys_loop: sys_loop.clone(),
|
esp_efuse_mac_get_default(&mut chip_id as *mut u8);
|
||||||
surfaces: 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?}", chip_id);
|
||||||
|
|
||||||
log::info!("Setting up output for chip ID {:x?}", Self::chip_id());
|
|
||||||
|
|
||||||
const POWER_VOLTS : u32 = 5;
|
const POWER_VOLTS : u32 = 5;
|
||||||
const POWER_MA : u32 = 500;
|
const POWER_MA : u32 = 500;
|
||||||
const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA;
|
const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA;
|
||||||
|
let pins = peripherals.pins;
|
||||||
|
|
||||||
let pins = self.pins.take().unwrap();
|
|
||||||
let rmt = self.rmt.take().unwrap();
|
|
||||||
ThreadSpawnConfiguration {
|
ThreadSpawnConfiguration {
|
||||||
pin_to_core: Some(esp_idf_svc::hal::cpu::Core::Core1),
|
pin_to_core: Some(esp_idf_svc::hal::cpu::Core::Core1),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -98,12 +135,12 @@ impl Board for Esp32Board {
|
|||||||
// But the implementation spawns a thread based on the core the driver was created in,
|
// But the implementation spawns a thread based on the core the driver was created in,
|
||||||
// so we create the driver in another thread briefly.
|
// so we create the driver in another thread briefly.
|
||||||
// Fun stuff.
|
// Fun stuff.
|
||||||
let output = match Self::chip_id().to_be_bytes() { // panel test board
|
let output = match chip_id { // panel test board
|
||||||
[72, 202, 67, 89, 145, 204, 0, 0] => {
|
[72, 202, 67, 89, 145, 204, 0, 0] => {
|
||||||
StrideOutput::new(
|
StrideOutput::new(
|
||||||
Pixbuf::new(),
|
Pixbuf::new(),
|
||||||
StrideMapping::new_panel(),
|
StrideMapping::new_panel(),
|
||||||
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(peripherals.rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
||||||
MAX_POWER_MW
|
MAX_POWER_MW
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -111,15 +148,15 @@ impl Board for Esp32Board {
|
|||||||
StrideOutput::new(
|
StrideOutput::new(
|
||||||
Pixbuf::new(),
|
Pixbuf::new(),
|
||||||
StrideMapping::new_jar(),
|
StrideMapping::new_jar(),
|
||||||
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio14).unwrap() }).join().unwrap(),
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(peripherals.rmt.channel0, pins.gpio14).unwrap() }).join().unwrap(),
|
||||||
MAX_POWER_MW
|
MAX_POWER_MW
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
[0x4a, 0xca, 0x43, 0x59, 0x85, 0x58, 0x0, 0x0] => { // Albus the tree
|
[0x4a, 0xca, 0x43, 0x59, 0x85, 0x58, 0x0, 0x0] => { // Albus the tree
|
||||||
StrideOutput::new(
|
StrideOutput::new(
|
||||||
Pixbuf::new(),
|
Pixbuf::new(),
|
||||||
StrideMapping::new_albus(),
|
StrideMapping::new_jar(),
|
||||||
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(peripherals.rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
||||||
MAX_POWER_MW
|
MAX_POWER_MW
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -127,7 +164,7 @@ impl Board for Esp32Board {
|
|||||||
StrideOutput::new(
|
StrideOutput::new(
|
||||||
Pixbuf::new(),
|
Pixbuf::new(),
|
||||||
StrideMapping::new_fairylights(),
|
StrideMapping::new_fairylights(),
|
||||||
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(peripherals.rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
||||||
MAX_POWER_MW
|
MAX_POWER_MW
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@@ -135,23 +172,15 @@ impl Board for Esp32Board {
|
|||||||
StrideOutput::new(
|
StrideOutput::new(
|
||||||
Pixbuf::new(),
|
Pixbuf::new(),
|
||||||
StrideMapping::new_fairylights(),
|
StrideMapping::new_fairylights(),
|
||||||
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(peripherals.rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
||||||
MAX_POWER_MW
|
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(
|
StrideOutput::new(
|
||||||
Pixbuf::new(),
|
Pixbuf::new(),
|
||||||
StrideMapping::new(),
|
StrideMapping::new(),
|
||||||
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
std::thread::spawn(move || { FastWs2812Esp32Rmt::new(peripherals.rmt.channel0, pins.gpio5).unwrap() }).join().unwrap(),
|
||||||
MAX_POWER_MW
|
MAX_POWER_MW
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -160,7 +189,16 @@ impl Board for Esp32Board {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}.set().unwrap();
|
}.set().unwrap();
|
||||||
|
|
||||||
output
|
Esp32Board {
|
||||||
|
modem: Some(peripherals.modem),
|
||||||
|
sys_loop: sys_loop.clone(),
|
||||||
|
surfaces: BufferedSurfacePool::new(),
|
||||||
|
output: Some(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output(&mut self) -> Self::Output {
|
||||||
|
self.output.take().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn surfaces(&mut self) -> Self::Surfaces {
|
fn surfaces(&mut self) -> Self::Surfaces {
|
||||||
@@ -227,9 +265,9 @@ impl CircadianRhythm {
|
|||||||
adjusted_end.hour += 24;
|
adjusted_end.hour += 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_time = (start.hour as u16).wrapping_mul(60);
|
let start_time = start.hour * 60;
|
||||||
let end_time = (end.hour as u16).wrapping_mul(60);
|
let end_time = end.hour * 60;
|
||||||
let now_time = (hour as u16).wrapping_mul(60).wrapping_add(minute as u16);
|
let now_time = hour * 60 + minute;
|
||||||
|
|
||||||
let duration = end_time - start_time;
|
let duration = end_time - start_time;
|
||||||
let cur_duration = now_time - start_time;
|
let cur_duration = now_time - start_time;
|
||||||
@@ -461,8 +499,6 @@ impl Task for WifiTask {
|
|||||||
|
|
||||||
fn stop(&mut self) {
|
fn stop(&mut self) {
|
||||||
log::info!("Stopping wifi");
|
log::info!("Stopping wifi");
|
||||||
self.wifi_sub.take().unwrap();
|
|
||||||
self.ip_sub.take().unwrap();
|
|
||||||
self.disconnect();
|
self.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
44
src/platform/esp32_nostd.rs
Normal file
44
src/platform/esp32_nostd.rs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
use rgb::Rgb;
|
||||||
|
use super::smart_leds_lib::rmt::FastWs2812Esp32Rmt;
|
||||||
|
use super::smart_leds_lib::StrideOutput;
|
||||||
|
|
||||||
|
use crate::task::{FixedSizeScheduler, Task};
|
||||||
|
use crate::buffers::StaticSurfacePool;
|
||||||
|
|
||||||
|
use super::Board;
|
||||||
|
|
||||||
|
pub struct Esp32Board<'a> {
|
||||||
|
output: Option<<Self as Board>::Output>,
|
||||||
|
surfaces: Option<StaticSurfacePool>,
|
||||||
|
tasks: Option<[&'a mut dyn Task; 1]>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Board for Esp32Board<'a> {
|
||||||
|
type Output = StrideOutput<[Rgb<u8>; 310], FastWs2812Esp32Rmt<'a>>;
|
||||||
|
type Surfaces = StaticSurfacePool;
|
||||||
|
type Scheduler = FixedSizeScheduler<0>;
|
||||||
|
fn take() -> Self {
|
||||||
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
//esp_alloc::heap_allocator!(72 * 1024);
|
||||||
|
|
||||||
|
const POWER_VOLTS : u32 = 5;
|
||||||
|
const POWER_MA : u32 = 500;
|
||||||
|
const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA;
|
||||||
|
let pins = peripherals.pins;
|
||||||
|
|
||||||
|
|
||||||
|
Esp32Board { output: None, surfaces: None, tasks: None }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output(&mut self) -> Self::Output {
|
||||||
|
self.output.take().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn surfaces(&mut self) -> Self::Surfaces {
|
||||||
|
self.surfaces.take().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn system_tasks(&mut self) -> Self::Scheduler {
|
||||||
|
FixedSizeScheduler::new([])
|
||||||
|
}
|
||||||
|
}
|
@@ -20,5 +20,4 @@ pub trait Board {
|
|||||||
fn output(&mut self) -> Self::Output;
|
fn output(&mut self) -> Self::Output;
|
||||||
fn surfaces(&mut self) -> Self::Surfaces;
|
fn surfaces(&mut self) -> Self::Surfaces;
|
||||||
fn system_tasks(&mut self) -> Self::Scheduler;
|
fn system_tasks(&mut self) -> Self::Scheduler;
|
||||||
fn chip_id() -> u64;
|
|
||||||
}
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
use smart_leds_trait::SmartLedsWrite;
|
use smart_leds_trait::SmartLedsWrite;
|
||||||
|
|
||||||
use crate::buffers::Pixbuf;
|
use crate::buffers::Pixbuf;
|
||||||
|
use crate::events::Variant;
|
||||||
use crate::render::{HardwarePixel, Output, PixelView, Sample};
|
use crate::render::{HardwarePixel, Output, PixelView, Sample};
|
||||||
use crate::power::brightness_for_mw;
|
use crate::power::brightness_for_mw;
|
||||||
use crate::geometry::*;
|
use crate::geometry::*;
|
||||||
@@ -56,7 +57,7 @@ impl<P: Pixbuf<Pixel=T::Color>, T: FastWrite> Output for StrideOutput<P, T> {
|
|||||||
|
|
||||||
fn on_event(&mut self, event: &crate::events::Event) {
|
fn on_event(&mut self, event: &crate::events::Event) {
|
||||||
match event {
|
match event {
|
||||||
crate::events::Event::PropertyChange("output.brightness", Variant::Byte(new_brightness)) => self.brightness = *new_brightness,
|
crate::events::Event::PropertyChange("output.brightness", new_brightness) => self.brightness = new_brightness.clone().into(),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/task.rs
16
src/task.rs
@@ -42,18 +42,18 @@ impl ScheduledTask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn start(&mut self) {
|
fn start(&mut self) {
|
||||||
match self.state {
|
self.state = match self.state {
|
||||||
ScheduledState::Stopped => self.state = ScheduledState::Start,
|
ScheduledState::Stopped => ScheduledState::Start,
|
||||||
ScheduledState::Stop => self.state = ScheduledState::Running,
|
ScheduledState::Stop => ScheduledState::Running,
|
||||||
_ => ()
|
_ => self.state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&mut self) {
|
fn stop(&mut self) {
|
||||||
match self.state {
|
self.state = match self.state {
|
||||||
ScheduledState::Running => self.state = ScheduledState::Stop,
|
ScheduledState::Running => ScheduledState::Stop,
|
||||||
ScheduledState::Start => self.state = ScheduledState::Stopped,
|
ScheduledState::Start => ScheduledState::Stopped,
|
||||||
_ => ()
|
_ => self.state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Periodically {
|
pub struct Periodically {
|
||||||
last_run: Instant,
|
last_run: Instant,
|
||||||
duration: Duration
|
duration: Duration
|
||||||
|
Reference in New Issue
Block a user