From b6029778e075964a95ef6864dfd4231e1c40d02a Mon Sep 17 00:00:00 2001 From: Victoria Fischer Date: Sat, 3 Jan 2026 14:47:12 +0100 Subject: [PATCH] graphics: display: update figments api to drop pixel spaces --- src/graphics/display.rs | 54 +++++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/graphics/display.rs b/src/graphics/display.rs index 010d8f0..88dd885 100644 --- a/src/graphics/display.rs +++ b/src/graphics/display.rs @@ -5,29 +5,29 @@ use alloc::sync::Arc; //use super::{Output}; use figments_render::{ - gamma::{GammaCurve, WithGamma}, output::{Brightness, GammaCorrected, OutputAsync}, power::AsMilliwatts, smart_leds::PowerManagedWriterAsync + gamma::{GammaCurve, WithGamma}, output::{Brightness, GammaCorrected, Output, OutputAsync}, power::AsMilliwatts, smart_leds::PowerManagedWriter }; -use smart_leds::SmartLedsWriteAsync; +use smart_leds::{SmartLedsWrite, SmartLedsWriteAsync}; pub const NUM_PIXELS: usize = 178; -// FIXME: We need a way to specify a different buffer format from the 'native' hardware output, due to sometimes testing with GRB strips instead of RGB -pub struct BikeOutput { - pixbuf: [T::Color; NUM_PIXELS], - writer: PowerManagedWriterAsync, +#[derive(Debug)] +pub struct BikeOutput { + pixbuf: [Color; NUM_PIXELS], + writer: PowerManagedWriter, controls: DisplayControls } -impl GammaCorrected for BikeOutput where T::Color: PixelBlend> + PixelFormat + Debug + WithGamma + Default + Clone, T::Error: Debug { +impl GammaCorrected for BikeOutput { fn set_gamma(&mut self, gamma: GammaCurve) { self.writer.controls().set_gamma(gamma); } } -impl>> BikeOutput where T::Error: core::fmt::Debug { +impl BikeOutput { pub fn new(target: T, max_mw: u32, controls: DisplayControls) -> Self { Self { pixbuf: [Default::default(); NUM_PIXELS], - writer: PowerManagedWriterAsync::new(target, max_mw), + writer: PowerManagedWriter::new(target, max_mw), controls } } @@ -37,12 +37,30 @@ impl>> BikeOutput where T::Error: core } } -impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, SegmentSpace> for BikeOutput where T::Color: PixelSink + PixelBlend> + Default + Clone + Debug + 'static + AsMilliwatts + PixelFormat + WithGamma, [T::Color; NUM_PIXELS]: AsMilliwatts + WithGamma + Copy, T::Error: core::fmt::Debug { - async fn commit_async(&mut self) -> Result<(), T::Error> { +impl<'a, T: SmartLedsWrite + 'a> Output<'a, SegmentSpace> for BikeOutput where T::Color: AsMilliwatts + Copy + Fract8Ops + WithGamma + Default + Debug + 'a + 'static { + type Error = T::Error; + + type Controls = DisplayControls; + + fn commit(&mut self) -> Result<(), Self::Error> { + self.writer.controls().set_brightness(self.controls.brightness()); + self.writer.controls().set_on(self.controls.is_on()); + critical_section::with(|_| { + self.writer.write(&self.pixbuf) + }) + } + + fn controls(&self) -> Option<&Self::Controls> { + Some(&self.controls) + } +} + +impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, SegmentSpace> for BikeOutput where T::Color: 'static + Copy + Fract8Ops + WithGamma + Default + Debug + AsMilliwatts + 'a { + async fn commit_async(&mut self) -> Result<(), T::Error> where T: SmartLedsWriteAsync { self.writer.controls().set_brightness(self.controls.brightness()); self.writer.controls().set_on(self.controls.is_on()); // TODO: We should grab the power used here and somehow feed it back into the telemetry layer, probably just via another atomic u32 - self.writer.write(&self.pixbuf).await + self.writer.write_async(&self.pixbuf).await } //type HardwarePixel = T::Color; @@ -54,8 +72,8 @@ impl<'a, T: SmartLedsWriteAsync + 'a> OutputAsync<'a, SegmentSpace> for BikeOutp } } -impl<'a, T: SmartLedsWriteAsync> Sample<'a, SegmentSpace> for BikeOutput where T::Color: 'a + Debug + PixelFormat, [T::Color; NUM_PIXELS]: Sample<'a, SegmentSpace, Output = T::Color> { - type Output = T::Color; +impl<'a, T, Color> Sample<'a, SegmentSpace> for BikeOutput where Color: 'a, [Color; NUM_PIXELS]: Sample<'a, SegmentSpace, Output = Color> { + type Output = Color; fn sample(&mut self, rect: &Rectangle) -> impl Iterator, &'a mut Self::Output)> { self.pixbuf.sample(rect) @@ -76,7 +94,7 @@ pub struct Segment { length: usize, } -impl<'a, T: PixelFormat> Sample<'a, SegmentSpace> for [T; NUM_PIXELS] where T: 'static { +impl<'a, T> Sample<'a, SegmentSpace> for [T; NUM_PIXELS] where T: 'static { type Output = T; fn sample(&mut self, rect: &Rectangle) -> impl Iterator, &'a mut Self::Output)> { @@ -98,19 +116,19 @@ impl CoordinateSpace for SegmentSpace { type Data = usize; } -pub struct SegmentIter<'a, Format: PixelFormat> { +pub struct SegmentIter<'a, Format> { pixbuf: &'a mut [Format; NUM_PIXELS], cur: Coordinates, end: Coordinates, } -impl<'a, Format: PixelFormat + Debug> Debug for SegmentIter<'a, Format> { +impl<'a, Format: Debug> Debug for SegmentIter<'a, Format> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("BikeIter").field("cur", &self.cur).field("end", &self.end).finish() } } -impl<'a, Format: PixelFormat> Iterator for SegmentIter<'a, Format> { +impl<'a, Format> Iterator for SegmentIter<'a, Format> { type Item = (Coordinates, &'a mut Format); fn next(&mut self) -> Option {