Skip to content

Miscellaneous improvements#30

Open
sajattack wants to merge 4 commits into
masterfrom
misc-improvements
Open

Miscellaneous improvements#30
sajattack wants to merge 4 commits into
masterfrom
misc-improvements

Conversation

@sajattack
Copy link
Copy Markdown
Owner

  • better error typing
  • more docs
  • make buffer size const generic

- better error typing
- more docs
- make buffer size const generic
@sajattack sajattack force-pushed the misc-improvements branch from 16516ce to 0cf898e Compare June 4, 2025 02:19
@sajattack sajattack mentioned this pull request Jun 4, 2025
Copy link
Copy Markdown

@jbeaurivage jbeaurivage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have two minor comments, but otherwise this looks pretty good!

Comment thread src/lib.rs
{
if let Some(rst) = &mut self.rst {
rst.set_high().map_err(|_| ())?;
rst.set_high().map_err(|e| Error::Gpio(e))?;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend implementing From<embedded_hal::digital::Error> for Error (likewise for embedded_hal::spi::Error) to avoid manually mapping errors everywhere.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having some trouble figuring out how to do this with the generics on the Error. I think they help avoid dyn

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, looks like you can't have both From implementations because they would overlap if SE == GE. In that case I'd recommend only implementing From<GE> for Error<SE, GE>, and using map_err for the one occurrence where Error::Spi appears :)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although it might be beneficial to change the error type to this:

/// Errors
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error<SE, GE>
where
    SE: embedded_hal::spi::Error,
    GE: embedded_hal::digital::Error,
{
    Spi(SE),
    Gpio(GE),
}

Copy link
Copy Markdown

@ianrrees ianrrees Jul 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, yeah this is awkward because the SPI and GPIO error types could be the same...

I'd suggest not making Error generic across the types, instead have the Spi variant contain an spi::ErrorKind and the Gpio variant contain a digital::ErrorKind.

Then, a couple functions could tell the compiler how to interpret the results of calls that return the generic SPI/GPIO Results:

enum Error {
    Spi(spi::ErrorKind),
    Gpio(digital::ErrorKind),
}

/// Translates digital Result types to ours
fn digital<T, D: digital::Error>(digital_res: Result<T, D>) -> Result<T, Error> {
    digital_res.map_err(|e| Error::Gpio(e.kind()))
}

/// Translates SPI Result types to ours
fn spi<T, S: spi::Error>(spi_res: Result<T, S>) -> Result<T, Error> {
    spi_res.map_err(|e| Error::Spi(e.kind()))
}

// This way, you can do something like
fn demo_method(&mut self) -> Result<(), Error> {
    digital(rst.set_high())?;
}

Comment thread src/lib.rs
Comment on lines +241 to +246

/// Write multiple pixels, trading ram size for speed
pub fn write_pixels_buffered<P: IntoIterator<Item = u16>>(
&mut self,
colors: P,
) -> Result<(), ()> {
) -> Result<(), Error<SE, GE>> {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't necessarily think one approach is better than the other, but the users could fine-tune the buffer size more if the *_buffered methods took the const generic parameter instead of the top-level struct. Also, users that don't want to use the buffered methods wouldn't have to specify a fake buffer size just to satisfy the API.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was considering that, but there were some weird dependency issues between methods calling eachother. I'll look at it more carefully and report back later.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no way to add the generics to the function signature of the embedded_graphics functions afaict
image

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, then it seems like this suggestion isn't viable. Apologies!

@jbeaurivage
Copy link
Copy Markdown

Oh also I'd suggest optionally supporting defmt to display your error type

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants