JohnDoneth / hd44780-driver

Implementation of the embedded-hal traits for the HD44780.
MIT License
37 stars 40 forks source link

Requesting example where the loop contains a delay #14

Closed David-OConnor closed 4 years ago

David-OConnor commented 4 years ago

Ie, since the lcd requires consuming a delay, how do you use one later, like in the loop? The current examples don't have a delay in the loop.

How do you use the delay after this line ?

let mut lcd = HD44780::new_i2c(i2c, LCD_I2C_ADDRESS, delay);
JohnDoneth commented 4 years ago

Because the embedded_hal Delay trait requires a mutable reference to self it's not possible to share such a reference without using interior mutability with the help of something like RefCell. Both the HD44780 crate and your code want mutable access to the delay provider. Rust enforces at compile time that two mutable references to the same location do not occur. With RefCell we can avoid this requirement and check at runtime. https://doc.rust-lang.org/book/ch15-05-interior-mutability.html#enforcing-borrowing-rules-at-runtime-with-refcellt

Here is a Rust playground example of doing such that to solve your problem. https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=826e9dbebd5075c1f7dada1c8e96ecba

use core::cell::RefCell;

trait Delay {
    fn delay(&mut self, milli: u32);
}

#[derive(Clone, Copy)]
struct DelayProvider {}

impl Delay for DelayProvider {
    fn delay(&mut self, milli: u32) {
        println!("Delaying for {}ms", milli);
    }
}

fn consumes_ownership<T: Delay>(mut delay: T, milli: u32) {
    delay.delay(milli);
}

fn main() {
    let delay = DelayProvider {};

    let delay: RefCell<DelayProvider> = RefCell::new(delay);

    consumes_ownership(*RefCell::borrow_mut(&delay), 42);
    consumes_ownership(*RefCell::borrow_mut(&delay), 64);
}
David-OConnor commented 4 years ago

Awesome. Was already writing the PR. Took a diff approach, where we never consume delay. It's subjective which approach is more elegant. Adv of yours is we don't have to keep passing delay around. Adv of mine is we can avoid smart pointers, and consuming things that don't need to be consumed.

David-OConnor commented 4 years ago

Working for me with PR merged