build: configure different displays based on cargo configs
This commit is contained in:
		
							
								
								
									
										21
									
								
								Cargo.toml
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								Cargo.toml
									
									
									
									
									
								
							| @@ -18,7 +18,12 @@ debug = true    # Symbols are nice and they don't increase the size on Flash | ||||
| opt-level = "z" | ||||
|  | ||||
| [features] | ||||
| default = ["std", "embassy", "esp-idf-svc/native"] | ||||
| default = ["std", "embassy", "esp-idf-svc/native", "rmt", "smart-leds"] | ||||
|  | ||||
| embedded-graphics = ["dep:embedded-graphics", "ws2812-esp32-rmt-driver/embedded-graphics-core"] | ||||
| smart-leds = ["dep:smart-leds", "dep:smart-leds-trait", "ws2812-esp32-rmt-driver/smart-leds-trait"] | ||||
| spi = ["dep:ws2812-spi"] | ||||
| rmt = ["dep:ws2812-esp32-rmt-driver"] | ||||
|  | ||||
| pio = ["esp-idf-svc/pio"] | ||||
| std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] | ||||
| @@ -30,17 +35,21 @@ embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf- | ||||
| [dependencies] | ||||
| log = { version = "0.4", default-features = false } | ||||
| esp-idf-svc = { version = "0.49", default-features = false } | ||||
| ws2812-esp32-rmt-driver = { version = "*", features = ["embedded-graphics-core", "smart-leds-trait"]} | ||||
| embedded-graphics = { version = "0.8.1", features = ["fixed_point", "defmt"] } | ||||
| hsv = "0.1.1" | ||||
| palette = { version = "0.7.6" } | ||||
| embedded-canvas = "0.3.1" | ||||
| embassy-executor = "0.6.0" | ||||
| running-average = "0.1.0" | ||||
| ws2812-spi = "0.5.0" | ||||
| smart-leds-trait = "0.3.0" | ||||
| rgb = "0.8.50" | ||||
| smart-leds = "0.4.0" | ||||
|  | ||||
| ws2812-esp32-rmt-driver = { version = "*", optional = true } | ||||
|  | ||||
| ws2812-spi = { version = "0.5.0", optional = true } | ||||
|  | ||||
| smart-leds-trait = { version = "0.3.0", optional = true } | ||||
| smart-leds = { version = "0.4.0", optional = true } | ||||
|  | ||||
| embedded-graphics = { version = "0.8.1", optional = true, features = ["fixed_point", "defmt"] } | ||||
|  | ||||
| [build-dependencies] | ||||
| embuild = "0.32.0" | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| [ ] cfg macros | ||||
| [x] cfg macros | ||||
| [ ] warnings | ||||
| [ ] rgb crate | ||||
| [ ] Layer blending | ||||
|   | ||||
| @@ -16,21 +16,7 @@ use crate::render::*; | ||||
| use crate::time::Periodically; | ||||
| use crate::task::Task; | ||||
| use crate::geometry::*; | ||||
|  | ||||
| impl<T: RgbColor> AsMilliwatts for T { | ||||
|     fn as_milliwatts(&self) -> u32 { | ||||
|         const RED_MW : u32   = 16 * 5; //< 16mA @ 5v = 80mW | ||||
|         const GREEN_MW : u32 = 11 * 5; //< 11mA @ 5v = 55mW | ||||
|         const BLUE_MW : u32  = 15 * 5; //< 15mA @ 5v = 75mW | ||||
|         const DARK_MW : u32  =  1 * 5; //<  1mA @ 5v =  5mW | ||||
|  | ||||
|         let red = (self.r() as u32 * RED_MW).wrapping_shr(8); | ||||
|         let green = (self.g() as u32 * GREEN_MW).wrapping_shr(8); | ||||
|         let blue = (self.b() as u32 * BLUE_MW).wrapping_shr(8); | ||||
|  | ||||
|         return red + green + blue + DARK_MW; | ||||
|     } | ||||
| } | ||||
| use crate::platform::DisplayInit; | ||||
|  | ||||
| pub struct EmbeddedDisplay<T, S> | ||||
| where | ||||
| @@ -124,3 +110,39 @@ impl<T: LedPixelShape, S: Surface> Display<S> for EmbeddedDisplay<Ws2812DrawTarg | ||||
|         ).unwrap(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<Shape: LedPixelShape> DisplayInit for Ws2812DrawTarget<'_, Shape> { | ||||
|     fn new_display<S: Surface>() -> impl Display<S> + Task { | ||||
|         let peripherals = Peripherals::take().unwrap(); | ||||
|         let led_pin = peripherals.pins.gpio14; | ||||
|         let channel = peripherals.rmt.channel0; | ||||
|  | ||||
|         const POWER_VOLTS : u32 = 5; | ||||
|         const POWER_MA : u32 = 500; | ||||
|         const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; | ||||
|  | ||||
|         let target = Self::new(channel, led_pin).unwrap(); | ||||
|         return EmbeddedDisplay::<Self, S>::new(target, MAX_POWER_MW); | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct PonderjarMatrix {} | ||||
| impl LedPixelShape for PonderjarMatrix { | ||||
|     fn size() -> Size { | ||||
|         Size::new(17, 17) | ||||
|     } | ||||
|  | ||||
|     fn pixel_index(point: Point) -> Option<usize> { | ||||
|         if (0..Self::size().width as i32).contains(&point.x) && (0..Self::size().height as i32).contains(&point.y) { | ||||
|             if point.y % 2 == 0 { | ||||
|                 Some((point.y as u32 * Self::size().width as u32 + point.x as u32).try_into().unwrap()) | ||||
|             } else { | ||||
|                 Some((point.y as u32 * Self::size().width as u32 - point.x as u32).try_into().unwrap()) | ||||
|             } | ||||
|         } else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub type PonderjarTarget<'a> = Ws2812DrawTarget<'a, PonderjarMatrix>; | ||||
|   | ||||
							
								
								
									
										93
									
								
								src/lib8.rs
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								src/lib8.rs
									
									
									
									
									
								
							| @@ -1,9 +1,8 @@ | ||||
| use palette::convert::FromColorUnclamped; | ||||
| use palette::encoding::srgb::Srgb; | ||||
| use palette::Hsv; | ||||
| use embedded_graphics::pixelcolor::RgbColor; | ||||
| use embedded_graphics::pixelcolor::PixelColor; | ||||
| use embedded_graphics::pixelcolor::raw::RawU8; | ||||
|  | ||||
| use crate::power::AsMilliwatts; | ||||
|  | ||||
| #[derive(PartialEq, Debug, Copy, Clone)] | ||||
| pub struct RGB8 { | ||||
| @@ -22,31 +21,6 @@ impl RGB8 { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl RgbColor for RGB8 { | ||||
|     fn r(&self) -> u8 { self.red } | ||||
|     fn g(&self) -> u8 { self.green } | ||||
|     fn b(&self) -> u8 { self.blue } | ||||
|  | ||||
|     const MAX_R: u8 = 255; | ||||
|     const MAX_G: u8 = 255; | ||||
|     const MAX_B: u8 = 255; | ||||
|  | ||||
|     const BLACK: Self = Self::new(0, 0, 0); | ||||
|     const WHITE: Self = Self::new(255, 255, 255); | ||||
|  | ||||
|     const RED: Self = Self::new(255, 0, 0); | ||||
|     const GREEN: Self = Self::new(0, 255, 0); | ||||
|     const BLUE: Self = Self::new(0, 0, 255); | ||||
|  | ||||
|     const YELLOW: Self = Self::new(255, 0, 0); | ||||
|     const CYAN: Self = Self::new(0, 255, 0); | ||||
|     const MAGENTA: Self = Self::new(0, 0, 255); | ||||
| } | ||||
|  | ||||
| impl PixelColor for RGB8 { | ||||
|     type Raw = RawU8; | ||||
| } | ||||
|  | ||||
| impl FromColorUnclamped<Hsv<Srgb, u8>> for RGB8 { | ||||
|     fn from_color_unclamped(hsv: Hsv<Srgb, u8>) -> RGB8 { | ||||
|         if hsv.saturation == 0 { | ||||
| @@ -70,3 +44,66 @@ impl FromColorUnclamped<Hsv<Srgb, u8>> for RGB8 { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl AsMilliwatts for RGB8 { | ||||
|     fn as_milliwatts(&self) -> u32 { | ||||
|         const RED_MW : u32   = 16 * 5; //< 16mA @ 5v = 80mW | ||||
|         const GREEN_MW : u32 = 11 * 5; //< 11mA @ 5v = 55mW | ||||
|         const BLUE_MW : u32  = 15 * 5; //< 15mA @ 5v = 75mW | ||||
|         const DARK_MW : u32  =  1 * 5; //<  1mA @ 5v =  5mW | ||||
|  | ||||
|         let red = (self.red as u32 * RED_MW).wrapping_shr(8); | ||||
|         let green = (self.green as u32 * GREEN_MW).wrapping_shr(8); | ||||
|         let blue = (self.blue as u32 * BLUE_MW).wrapping_shr(8); | ||||
|  | ||||
|         return red + green + blue + DARK_MW; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature="embedded-graphics")] | ||||
| mod embedded_graphics { | ||||
|     use embedded_graphics::pixelcolor::RgbColor; | ||||
|     use embedded_graphics::pixelcolor::PixelColor; | ||||
|     use embedded_graphics::pixelcolor::raw::RawU8; | ||||
|  | ||||
|     impl RgbColor for RGB8 { | ||||
|         fn r(&self) -> u8 { self.red } | ||||
|         fn g(&self) -> u8 { self.green } | ||||
|         fn b(&self) -> u8 { self.blue } | ||||
|  | ||||
|         const MAX_R: u8 = 255; | ||||
|         const MAX_G: u8 = 255; | ||||
|         const MAX_B: u8 = 255; | ||||
|  | ||||
|         const BLACK: Self = Self::new(0, 0, 0); | ||||
|         const WHITE: Self = Self::new(255, 255, 255); | ||||
|  | ||||
|         const RED: Self = Self::new(255, 0, 0); | ||||
|         const GREEN: Self = Self::new(0, 255, 0); | ||||
|         const BLUE: Self = Self::new(0, 0, 255); | ||||
|  | ||||
|         const YELLOW: Self = Self::new(255, 0, 0); | ||||
|         const CYAN: Self = Self::new(0, 255, 0); | ||||
|         const MAGENTA: Self = Self::new(0, 0, 255); | ||||
|     } | ||||
|  | ||||
|     impl PixelColor for RGB8 { | ||||
|         type Raw = RawU8; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     impl<T: RgbColor> AsMilliwatts for T { | ||||
|         fn as_milliwatts(&self) -> u32 { | ||||
|             const RED_MW : u32   = 16 * 5; //< 16mA @ 5v = 80mW | ||||
|             const GREEN_MW : u32 = 11 * 5; //< 11mA @ 5v = 55mW | ||||
|             const BLUE_MW : u32  = 15 * 5; //< 15mA @ 5v = 75mW | ||||
|             const DARK_MW : u32  =  1 * 5; //<  1mA @ 5v =  5mW | ||||
|  | ||||
|             let red = (self.r() as u32 * RED_MW).wrapping_shr(8); | ||||
|             let green = (self.g() as u32 * GREEN_MW).wrapping_shr(8); | ||||
|             let blue = (self.b() as u32 * BLUE_MW).wrapping_shr(8); | ||||
|  | ||||
|             return red + green + blue + DARK_MW; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										35
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,24 +1,37 @@ | ||||
| use palette::Hsv; | ||||
| use palette::convert::IntoColorUnclamped; | ||||
|  | ||||
| use ws2812_esp32_rmt_driver::lib_smart_leds::Ws2812Esp32Rmt; | ||||
| use ws2812_esp32_rmt_driver::lib_embedded_graphics::Ws2812DrawTarget; | ||||
|  | ||||
| mod power; | ||||
| mod lib8; | ||||
| mod render; | ||||
| mod task; | ||||
| mod time; | ||||
| mod geometry; | ||||
| mod embedded_graphics_lib; | ||||
| mod smart_leds_lib; | ||||
| mod platform; | ||||
|  | ||||
| #[cfg(feature="embedded-graphics")] | ||||
| mod embedded_graphics_lib; | ||||
|  | ||||
| #[cfg(feature="rmt")] | ||||
| #[cfg(feature="embedded-graphics")] | ||||
| use ws2812_esp32_rmt_driver::lib_embedded_graphics::PonderjarTarget; | ||||
|  | ||||
| #[cfg(feature="smart-leds")] | ||||
| mod smart_leds_lib; | ||||
|  | ||||
| #[cfg(feature="rmt")] | ||||
| #[cfg(feature="smart-leds")] | ||||
| use ws2812_esp32_rmt_driver::lib_smart_leds::Ws2812Esp32Rmt; | ||||
|  | ||||
| #[cfg(feature="spi")] | ||||
| #[cfg(feature="smart-leds")] | ||||
| use crate::smart_leds_lib::spi::SPIDisplay; | ||||
|  | ||||
| use crate::time::Periodically; | ||||
| use crate::geometry::{Coordinates, VirtualCoordinates}; | ||||
| use crate::render::{Shader, Surfaces, Surface, SimpleSurface}; | ||||
| use crate::task::Task; | ||||
| use crate::platform::{DisplayInit, PonderjarTarget, SPIDisplay}; | ||||
| use crate::platform::{DisplayInit}; | ||||
|  | ||||
| struct IdleTask<T: Surface> { | ||||
|     frame: u8, | ||||
| @@ -70,8 +83,14 @@ fn main() { | ||||
|     esp_idf_svc::log::EspLogger::initialize_default(); | ||||
|  | ||||
|     log::info!("Setting up display"); | ||||
|     //let mut display = SPIDisplay::new_display::<SimpleSurface>(); | ||||
|     //let mut display = PonderjarTarget::new_display::<SimpleSurface>(); | ||||
|  | ||||
|     #[cfg(feature="spi")] | ||||
|     let mut display = SPIDisplay::new_display::<SimpleSurface>(); | ||||
|  | ||||
|     #[cfg(feature="embedded-graphics")] | ||||
|     let mut display = PonderjarTarget::new_display::<SimpleSurface>(); | ||||
|  | ||||
|     #[cfg(feature="rmt")] | ||||
|     let mut display = Ws2812Esp32Rmt::new_display::<SimpleSurface>(); | ||||
|  | ||||
|     log::info!("Creating runner"); | ||||
|   | ||||
| @@ -1,102 +1,6 @@ | ||||
| use esp_idf_svc::hal::{ | ||||
|     prelude::*, | ||||
|     gpio::AnyIOPin, | ||||
|     spi::{ | ||||
|         config::{Config, DriverConfig}, | ||||
|         Dma, | ||||
|         SpiBusDriver, | ||||
|         SpiDriver, | ||||
|     } | ||||
| }; | ||||
|  | ||||
| use ws2812_spi::Ws2812; | ||||
| use ws2812_esp32_rmt_driver::lib_smart_leds::Ws2812Esp32Rmt; | ||||
| use ws2812_esp32_rmt_driver::lib_embedded_graphics::{LedPixelShape, Ws2812DrawTarget}; | ||||
|  | ||||
| use embedded_graphics::prelude::{Size, Point}; | ||||
|  | ||||
| use crate::smart_leds_lib::SmartLedDisplay; | ||||
| use crate::embedded_graphics_lib::EmbeddedDisplay; | ||||
|  | ||||
| use crate::render::{Surface, Display}; | ||||
| use crate::task::Task; | ||||
|  | ||||
| pub trait DisplayInit { | ||||
|     fn new_display<S: Surface>() -> impl Display<S> + Task; | ||||
| } | ||||
|  | ||||
| impl DisplayInit for Ws2812Esp32Rmt<'_> { | ||||
|     fn new_display<S: Surface>() -> impl Display<S> + Task { | ||||
|         let peripherals = Peripherals::take().unwrap(); | ||||
|         let led_pin = peripherals.pins.gpio14; | ||||
|         let channel = peripherals.rmt.channel0; | ||||
|  | ||||
|         const POWER_VOLTS : u32 = 5; | ||||
|         const POWER_MA : u32 = 500; | ||||
|         const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; | ||||
|  | ||||
|         let target = Self::new(channel, led_pin).unwrap(); | ||||
|         return SmartLedDisplay::new(target, MAX_POWER_MW); | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<Shape: LedPixelShape> DisplayInit for Ws2812DrawTarget<'_, Shape> { | ||||
|     fn new_display<S: Surface>() -> impl Display<S> + Task { | ||||
|         let peripherals = Peripherals::take().unwrap(); | ||||
|         let led_pin = peripherals.pins.gpio14; | ||||
|         let channel = peripherals.rmt.channel0; | ||||
|  | ||||
|         const POWER_VOLTS : u32 = 5; | ||||
|         const POWER_MA : u32 = 500; | ||||
|         const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; | ||||
|  | ||||
|         let target = Self::new(channel, led_pin).unwrap(); | ||||
|         return EmbeddedDisplay::<Self, S>::new(target, MAX_POWER_MW); | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub struct SPIDisplay {} | ||||
| impl DisplayInit for SPIDisplay { | ||||
|     fn new_display<S: Surface>() -> impl Display<S> + Task { | ||||
|         let peripherals = Peripherals::take().unwrap(); | ||||
|  | ||||
|         let driver = SpiDriver::new_without_sclk( | ||||
|             peripherals.spi2, | ||||
|             peripherals.pins.gpio14, | ||||
|             Option::<AnyIOPin>::None, | ||||
|             &DriverConfig::new().dma(Dma::Auto(512)) | ||||
|         ).unwrap(); | ||||
|  | ||||
|         let cfg = Config::new().baudrate(3_200.kHz().into()); | ||||
|  | ||||
|         let spi = SpiBusDriver::new(driver, &cfg).unwrap(); | ||||
|  | ||||
|         const POWER_VOLTS : u32 = 5; | ||||
|         const POWER_MA : u32 = 500; | ||||
|         const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; | ||||
|         let target = Ws2812::new(spi); | ||||
|         return SmartLedDisplay::new(target, MAX_POWER_MW) | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| pub struct PonderjarMatrix {} | ||||
| impl LedPixelShape for PonderjarMatrix { | ||||
|     fn size() -> Size { | ||||
|         Size::new(17, 17) | ||||
|     } | ||||
|  | ||||
|     fn pixel_index(point: Point) -> Option<usize> { | ||||
|         if (0..Self::size().width as i32).contains(&point.x) && (0..Self::size().height as i32).contains(&point.y) { | ||||
|             if point.y % 2 == 0 { | ||||
|                 Some((point.y as u32 * Self::size().width as u32 + point.x as u32).try_into().unwrap()) | ||||
|             } else { | ||||
|                 Some((point.y as u32 * Self::size().width as u32 - point.x as u32).try_into().unwrap()) | ||||
|             } | ||||
|         } else { | ||||
|             None | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub type PonderjarTarget<'a> = Ws2812DrawTarget<'a, PonderjarMatrix>; | ||||
|   | ||||
| @@ -3,11 +3,10 @@ use running_average::RealTimeRunningAverage; | ||||
|  | ||||
| use crate::render::{Surface, SurfacePool, Display, Surfaces}; | ||||
| use crate::task::Task; | ||||
| use crate::power; | ||||
| use crate::power::{brightness_for_mw, AsMilliwatts}; | ||||
| use crate::time::Periodically; | ||||
| use crate::lib8::RGB8; | ||||
| use crate::geometry::*; | ||||
| use crate::power::AsMilliwatts; | ||||
|  | ||||
| use smart_leds::brightness; | ||||
|  | ||||
| @@ -68,20 +67,20 @@ impl<T: SmartLedsWrite<Color = Rgb<u8>>, S: Surface> Display<S> for SmartLedDisp | ||||
|  | ||||
|     fn end_frame(&mut self) { | ||||
|         self.fps.insert(1); | ||||
|         let b = power::brightness_for_mw(self.total_mw, 255, self.max_mw); | ||||
|         let b = brightness_for_mw(self.total_mw, 255, self.max_mw); | ||||
|         self.fps_display.run(|| { | ||||
|             log::info!("FPS: {} frame={} brightness={} mw={}", self.fps.measurement(), self.frame, b, self.total_mw); | ||||
|         }); | ||||
|         self.target.write(brightness(self.pixbuf.iter().cloned(), b)); | ||||
|         let _ = self.target.write(brightness(self.pixbuf.iter().cloned(), b)); | ||||
|     } | ||||
|  | ||||
|     fn render_frame(&mut self) { | ||||
|         for x in 0..self.pixbuf.len() { | ||||
|             let virtCoords = VirtualCoordinates::new(x as u8, 0); | ||||
|             let virt_coords = VirtualCoordinates::new(x as u8, 0); | ||||
|             let mut pixel = RGB8::new(0, 0, 0); | ||||
|             for surface in self.surfaces.iter() { | ||||
|                 surface.with_shader(|shader| { | ||||
|                     pixel = shader.draw(virtCoords.clone()); | ||||
|                     pixel = shader.draw(virt_coords.clone()); | ||||
|                 }) | ||||
|             } | ||||
|             self.total_mw += pixel.as_milliwatts(); | ||||
| @@ -89,3 +88,74 @@ impl<T: SmartLedsWrite<Color = Rgb<u8>>, S: Surface> Display<S> for SmartLedDisp | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(feature="rmt")] | ||||
| pub mod rmt { | ||||
|     use esp_idf_svc::hal::prelude::Peripherals; | ||||
|     use ws2812_esp32_rmt_driver::lib_smart_leds::Ws2812Esp32Rmt; | ||||
|  | ||||
|     use crate::render::{Display, Surface}; | ||||
|     use crate::task::Task; | ||||
|     use crate::smart_leds_lib::SmartLedDisplay; | ||||
|  | ||||
|     use crate::platform::DisplayInit; | ||||
|     impl DisplayInit for Ws2812Esp32Rmt<'_> { | ||||
|         fn new_display<S: Surface>() -> impl Display<S> + Task { | ||||
|             let peripherals = Peripherals::take().unwrap(); | ||||
|             let led_pin = peripherals.pins.gpio14; | ||||
|             let channel = peripherals.rmt.channel0; | ||||
|  | ||||
|             const POWER_VOLTS : u32 = 5; | ||||
|             const POWER_MA : u32 = 500; | ||||
|             const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; | ||||
|  | ||||
|             let target = Self::new(channel, led_pin).unwrap(); | ||||
|             return SmartLedDisplay::new(target, MAX_POWER_MW); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| #[cfg(feature="spi")] | ||||
| pub mod spi { | ||||
|     use ws2812_spi::Ws2812; | ||||
|  | ||||
|     use crate::render::{Display, Surface}; | ||||
|     use crate::task::Task; | ||||
|     use crate::smart_leds_lib::SmartLedDisplay; | ||||
|  | ||||
|     use esp_idf_svc::hal::{ | ||||
|         prelude::*, | ||||
|         gpio::AnyIOPin, | ||||
|         spi::{ | ||||
|             config::{Config, DriverConfig}, | ||||
|             Dma, | ||||
|             SpiBusDriver, | ||||
|             SpiDriver, | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     pub struct SPIDisplay {} | ||||
|     impl DisplayInit for SPIDisplay { | ||||
|         fn new_display<S: Surface>() -> impl Display<S> + Task { | ||||
|             let peripherals = Peripherals::take().unwrap(); | ||||
|  | ||||
|             let driver = SpiDriver::new_without_sclk( | ||||
|                 peripherals.spi2, | ||||
|                 peripherals.pins.gpio14, | ||||
|                 Option::<AnyIOPin>::None, | ||||
|                 &DriverConfig::new().dma(Dma::Auto(512)) | ||||
|             ).unwrap(); | ||||
|  | ||||
|             let cfg = Config::new().baudrate(3_200.kHz().into()); | ||||
|  | ||||
|             let spi = SpiBusDriver::new(driver, &cfg).unwrap(); | ||||
|  | ||||
|             const POWER_VOLTS : u32 = 5; | ||||
|             const POWER_MA : u32 = 500; | ||||
|             const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; | ||||
|             let target = Ws2812::new(spi); | ||||
|             return SmartLedDisplay::new(target, MAX_POWER_MW) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user