rust-embedded / embedded-hal

A Hardware Abstraction Layer (HAL) for embedded systems
Apache License 2.0
2.01k stars 200 forks source link

Requesting a PullUp Input pin #148

Open TyberiusPrime opened 5 years ago

TyberiusPrime commented 5 years ago

Dear embeded-hal Gurus,

I'd like my function to accept a Vec<Box<dyn SomeTraitThatSaysInputWithPullUp>> (I'm building as simple key matrix).

Is there any way to specify such currently?

Rahix commented 5 years ago

Your question is very unspecific, which is probably the reason no one could answer it.

  1. Your title seemingly has no connection to the question you asked. Can you clarify this?
  2. Neither Vec nor Box are available on most embedded devices as both require an allocator. Why do you need a Vec<Box<_>>?
  3. Can you post some code of what you tried doing that did not end up working? Ideally, including the error messages you got.

You might also want to read https://stackoverflow.com/help/how-to-ask to have a higher chance of someone helping you.

TyberiusPrime commented 5 years ago

My apologies, I did not notice the markdown eating my code sample and have edited the post accordingly.

Let me post what I'm doing using stm32f1xx_hal right now to read in a key-matrix.


pub struct Matrix {
    sinks_pa: Vec<PAx<Input<PullUp>>>;
    sinks_pb: Vec<PBx<Input<PullUp>>>;
    sources_pa: Vec<PAx<Output<OpenDrain>>>,
    sources_pb: Vec<PBx<Output<OpenDrain>>>,
    output: SmallBitVec,
}
...

Now the way stm32f1xx-hal works I can only 'downgrade' pins up to the port level, and I need to accept multiple arguments to accept them all. Accordingly, my read_matrix() function has every loop twice:

  pub fn read_matrix(&mut self) -> &SmallBitVec {
        self.output.clear();
        for source in self.sources_pa.iter_mut() {
            source.set_high().ok();
        }
        for source in self.sources_pb.iter_mut() {
            source.set_high().ok();
        }

        for source in self.sources_pa.iter_mut() {
            source.set_low().ok();
            Self::read_row(&mut self.output, &self.sinks_pa, &self.sinks_pb);
            source.set_high().ok();
        }
        for source in self.sources_pb.iter_mut() {
            source.set_low().ok();
            Self::read_row(&mut self.output, &self.sinks_pa, &self.sinks_pb);
            source.set_high().ok();
        }
        &self.output
    }

Apart from that this is the easiest and most straight forward way to implement a key matrix, in an alloc environment. My project needs alloc any way.

There are two macro based crates for this task, one reads the matrix every time you want to read out any one pin (https://crates.io/crates/keypad), the other ( https://crates.io/crates/keymatrix ) has essential no documentation and appears to be 'wasting' a u8 per pin.

Basically, all I want to say is 'give me a trait object to an Input Pin with a PullUp. Any input pin. And I fail to see how to specify this in embedded_hal.

hannobraun commented 5 years ago

I don't have a solution for the problem at hand, but I'd like to provide some context about the underlying problem.

This style of representing pin types, generating one type per pin plus downgrade for some flexibility, is used by many HALs, but I believe it is the wrong approach. It is not flexible enough, and not as safe as it could be. The issue reported here demonstrates the lack of flexibility.

I've written previously about what I think is a better approach: https://github.com/nrf-rs/nrf52-hal/issues/8

It's already implemented this way in lpc8xx-hal, and I'll change it in nrf52-hal too, once I find the time.