HAL
This commit is contained in:
parent
0bab1d52a5
commit
c90c10cf7a
6 changed files with 165 additions and 70 deletions
27
Cargo.lock
generated
27
Cargo.lock
generated
|
|
@ -767,6 +767,7 @@ dependencies = [
|
||||||
"mipidsi",
|
"mipidsi",
|
||||||
"panic-probe",
|
"panic-probe",
|
||||||
"rgb",
|
"rgb",
|
||||||
|
"tinytga",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -808,6 +809,12 @@ version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
|
checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mipidsi"
|
name = "mipidsi"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
|
@ -841,6 +848,16 @@ version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "7.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
|
|
@ -1271,6 +1288,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinytga"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "477839bd612acb4d0551915eaf6eef8cc1b3a9dd58e18e9c2b746c78614a25d5"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-graphics",
|
||||||
|
"nom",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.19.0"
|
version = "1.19.0"
|
||||||
|
|
|
||||||
|
|
@ -48,3 +48,4 @@ embedded-hal-bus = "0.3.0"
|
||||||
embassy-futures = "0.1.2"
|
embassy-futures = "0.1.2"
|
||||||
heapless = "0.8.0"
|
heapless = "0.8.0"
|
||||||
rgb = "0.8.52"
|
rgb = "0.8.52"
|
||||||
|
tinytga = "0.5.0"
|
||||||
|
|
|
||||||
27
firmware/src/art.rs
Normal file
27
firmware/src/art.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
use embedded_graphics::{image::Image, pixelcolor::Rgb888, prelude::*};
|
||||||
|
use tinytga::Tga;
|
||||||
|
|
||||||
|
pub struct Hal {
|
||||||
|
image_data: Tga<'static, Rgb888>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hal {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
image_data: Tga::from_slice(include_bytes!("assets/hal.tga")).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drawable for Hal {
|
||||||
|
type Color = Rgb888;
|
||||||
|
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn draw<D>(&self, target: &mut D) -> Result<Self::Output, D::Error>
|
||||||
|
where
|
||||||
|
D: DrawTarget<Color = Self::Color>,
|
||||||
|
{
|
||||||
|
Image::new(&self.image_data, Point::zero()).draw(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
firmware/src/assets/hal.tga
Normal file
BIN
firmware/src/assets/hal.tga
Normal file
Binary file not shown.
101
firmware/src/led_matrix.rs
Normal file
101
firmware/src/led_matrix.rs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
use core::convert::Infallible;
|
||||||
|
|
||||||
|
use embassy_rp::{peripherals::PIO0, pio_programs::ws2812::PioWs2812};
|
||||||
|
use embedded_graphics::{
|
||||||
|
Pixel,
|
||||||
|
pixelcolor::Rgb888,
|
||||||
|
prelude::{DrawTarget, OriginDimensions, Point, RgbColor, Size},
|
||||||
|
};
|
||||||
|
use rgb::RGB8;
|
||||||
|
|
||||||
|
// Sourced from the `smart-leds` crate
|
||||||
|
const GAMMA8: [u8; 256] = [
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||||
|
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14,
|
||||||
|
14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27,
|
||||||
|
27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46,
|
||||||
|
47, 48, 49, 50, 50, 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, 69, 70, 72,
|
||||||
|
73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, 90, 92, 93, 95, 96, 98, 99, 101, 102, 104,
|
||||||
|
105, 107, 109, 110, 112, 114, 115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137,
|
||||||
|
138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
|
||||||
|
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213, 215, 218, 220,
|
||||||
|
223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub fn gamma(color: Rgb888) -> Rgb888 {
|
||||||
|
Rgb888::new(
|
||||||
|
GAMMA8[color.r() as usize],
|
||||||
|
GAMMA8[color.g() as usize],
|
||||||
|
GAMMA8[color.b() as usize],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Serpentine {
|
||||||
|
pub size: Size,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serpentine {
|
||||||
|
fn map(&self, mut p: Point) -> Option<usize> {
|
||||||
|
if p.x < 0 || p.x as u32 >= self.size.width || p.y < 0 || p.y as u32 >= self.size.height {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.y % 2 == 0 {
|
||||||
|
p.x = self.size.width as i32 - 1 - p.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(p.y as usize * self.size.width as usize + p.x as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LedMatrix<'d> {
|
||||||
|
buffer: [RGB8; 320],
|
||||||
|
layout: Serpentine,
|
||||||
|
pio: PioWs2812<'d, PIO0, 0, 320>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> LedMatrix<'d> {
|
||||||
|
pub fn new(layout: Serpentine, pio: PioWs2812<'d, PIO0, 0, 320>) -> Self {
|
||||||
|
Self {
|
||||||
|
buffer: [RGB8::default(); 320],
|
||||||
|
layout,
|
||||||
|
pio,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn sync(&mut self) {
|
||||||
|
self.pio.write(&self.buffer).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> DrawTarget for LedMatrix<'d> {
|
||||||
|
type Color = Rgb888;
|
||||||
|
|
||||||
|
type Error = Infallible;
|
||||||
|
|
||||||
|
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = Pixel<Self::Color>>,
|
||||||
|
{
|
||||||
|
for Pixel(point, color) in pixels {
|
||||||
|
if let Some(x) = self.layout.map(point).and_then(|i| self.buffer.get_mut(i)) {
|
||||||
|
let color = gamma(color);
|
||||||
|
// Map to 0-64 for brightness limiting
|
||||||
|
*x = RGB8::new(
|
||||||
|
color.r().div_ceil(2),
|
||||||
|
color.g().div_ceil(2),
|
||||||
|
color.b().div_ceil(2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> OriginDimensions for LedMatrix<'d> {
|
||||||
|
fn size(&self) -> Size {
|
||||||
|
self.layout.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::convert::Infallible;
|
mod art;
|
||||||
|
mod led_matrix;
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::select::select_array;
|
use embassy_futures::select::select_array;
|
||||||
|
|
@ -19,7 +20,9 @@ use heapless::String;
|
||||||
use mipidsi::interface::SpiInterface;
|
use mipidsi::interface::SpiInterface;
|
||||||
use mipidsi::models::ST7789;
|
use mipidsi::models::ST7789;
|
||||||
use mipidsi::options::Orientation;
|
use mipidsi::options::Orientation;
|
||||||
use rgb::RGB8;
|
|
||||||
|
use crate::art::Hal;
|
||||||
|
use crate::led_matrix::{LedMatrix, Serpentine};
|
||||||
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
|
@ -128,6 +131,7 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
led_surface.clear(Rgb888::BLACK).ok();
|
led_surface.clear(Rgb888::BLACK).ok();
|
||||||
|
/*
|
||||||
Rectangle::new(Point::zero(), led_surface.size())
|
Rectangle::new(Point::zero(), led_surface.size())
|
||||||
.into_styled(
|
.into_styled(
|
||||||
PrimitiveStyleBuilder::new()
|
PrimitiveStyleBuilder::new()
|
||||||
|
|
@ -138,6 +142,9 @@ async fn main(spawner: Spawner) -> ! {
|
||||||
)
|
)
|
||||||
.draw(&mut led_surface)
|
.draw(&mut led_surface)
|
||||||
.ok();
|
.ok();
|
||||||
|
*/
|
||||||
|
let hal = Hal::new();
|
||||||
|
hal.draw(&mut led_surface).ok();
|
||||||
led_surface.sync().await;
|
led_surface.sync().await;
|
||||||
|
|
||||||
let mut render = |f_keys: [bool; 4]| {
|
let mut render = |f_keys: [bool; 4]| {
|
||||||
|
|
@ -184,71 +191,3 @@ async fn dfu_button(mut btn_y: Input<'static>) {
|
||||||
btn_y.wait_for_falling_edge().await;
|
btn_y.wait_for_falling_edge().await;
|
||||||
reset_to_usb_boot(0, 0);
|
reset_to_usb_boot(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Serpentine {
|
|
||||||
size: Size,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serpentine {
|
|
||||||
fn map(&self, mut p: Point) -> Option<usize> {
|
|
||||||
if p.x < 0 || p.x as u32 >= self.size.width || p.y < 0 || p.y as u32 >= self.size.height {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if p.y % 2 == 0 {
|
|
||||||
p.x = self.size.width as i32 - 1 - p.x;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(p.y as usize * self.size.width as usize + p.x as usize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LedMatrix<'d> {
|
|
||||||
buffer: [RGB8; 320],
|
|
||||||
layout: Serpentine,
|
|
||||||
pio: PioWs2812<'d, PIO0, 0, 320>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d> LedMatrix<'d> {
|
|
||||||
fn new(layout: Serpentine, pio: PioWs2812<'d, PIO0, 0, 320>) -> Self {
|
|
||||||
Self {
|
|
||||||
buffer: [RGB8::default(); 320],
|
|
||||||
layout,
|
|
||||||
pio,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn sync(&mut self) {
|
|
||||||
self.pio.write(&self.buffer).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d> DrawTarget for LedMatrix<'d> {
|
|
||||||
type Color = Rgb888;
|
|
||||||
|
|
||||||
type Error = Infallible;
|
|
||||||
|
|
||||||
fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error>
|
|
||||||
where
|
|
||||||
I: IntoIterator<Item = Pixel<Self::Color>>,
|
|
||||||
{
|
|
||||||
for Pixel(point, color) in pixels {
|
|
||||||
if let Some(x) = self.layout.map(point).and_then(|i| self.buffer.get_mut(i)) {
|
|
||||||
// Map to 0-64 for brightness limiting
|
|
||||||
*x = RGB8::new(
|
|
||||||
color.r().div_ceil(4),
|
|
||||||
color.g().div_ceil(4),
|
|
||||||
color.b().div_ceil(4),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'d> OriginDimensions for LedMatrix<'d> {
|
|
||||||
fn size(&self) -> Size {
|
|
||||||
self.layout.size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue