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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions