Skip to content

How to impl SpiDevice on multiple Word sizes #737

@dbristow-otc

Description

@dbristow-otc

I'm working on a driver and I have an issue that is the opposite of that in #637 - I would like to preferably write to a SpiDevice<u16>, falling back to a SpiDevice<u8> if the SpiBus doesn't implement u16. I've tried a few different things, and I almost have an Autoref-Based specialization implemented, but I can't actually get it to use the SpiDevice<u16> trait. I've also tried using the nightly min_specialization feature, but the compiler just reports 'conflicting implementation'.

Below is a MVP of what I'm trying to do:

use embedded_hal::spi::{ErrorType, SpiDevice};

struct Wrap<'a, T>(&'a mut T);

trait ViaU16<E: ErrorType> {
    fn write_word(&mut self, word: u16) -> Result<(), <E as ErrorType>::Error>;
}

// writes the u16 directly to the SpiBus
impl<T: SpiDevice<u16>> ViaU16<T> for &mut Wrap<'_, T> {
    fn write_word(&mut self, word: u16) -> Result<(), <T as ErrorType>::Error>{
        self.0.write(&[word])
    }
}

trait ViaU8<E: ErrorType> {
    fn write_word(&mut self, word: u16) -> Result<(), <E as ErrorType>::Error>;
}

// Converts the u16 to a big-endian u8 slice before writing to the SpiBus
impl<T: SpiDevice<u8>> ViaU8<T> for Wrap<'_, T> {
    fn write_word(&mut self, word: u16) -> Result<(), <T as ErrorType>::Error>{
        self.0.write(&word.to_be_bytes())
    }
}

pub struct Device<SPI> {
    pub spi: SPI,
}

impl<SPI: SpiDevice> Device<SPI> {
    fn transmit(&mut self) -> Result<(), SPI::Error> {
        (&mut &mut Wrap(&mut self.spi)).write_word(0xABCD)
    }
}

The code above will always execute the impl SpiDevice<u8> and always skips the impl SpiDevice<u16> code. I was wondering that I need to open up SpiDevice to SpiDevice<Word> in my impl<SPI: SpiDevice> Device, but that creates a new problem where trait bound 'SPI: SpiDevice' is not satisfied.

Any leads on how to do this, or does embedded_hal not have the ability to use generic word sizes?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions