diff --git a/Cargo.toml b/Cargo.toml index f10aa7f..395d359 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,15 @@ version = "0.1.0" authors = ["Wesley Moore "] [dependencies] + +[dependencies.embedded-hal] +features = ["unproven"] +version = "0.2.2" + +[dependencies.embedded-graphics] +optional = true +version = "0.4.4" + +[features] +default = ["graphics"] +graphics = ["embedded-graphics"] diff --git a/README.md b/README.md index 13077a0..210f204 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ The library has been tested and confirmed working on these devices: ## Credits +* [Waveshare EPD driver](https://github.com/caemor/epd-waveshare) * [SSD1306 OLED display driver](https://github.com/jamwaffles/ssd1306) * [SSD1322 OLED display driver](https://github.com/edarc/ssd1322) * [Pimoroni Python library for the Inky pHAT and Inky wHAT e-paper displays](https://github.com/pimoroni/inky) diff --git a/src/interface.rs b/src/interface.rs new file mode 100644 index 0000000..820e243 --- /dev/null +++ b/src/interface.rs @@ -0,0 +1,81 @@ +use hal; + +// Section 15.2 of the HINK-E0213A07 data sheet says to hold for 10ms +const RESET_DELAY_MS: u8 = 10; + +struct DisplayInterface { + /// SPI + spi: SPI, + /// CS for SPI + cs: CS, + /// Low for busy, Wait until display is ready! + busy: BUSY, + /// Data/Command Control Pin (High for data, Low for command) + dc: DC, + /// Pin for Reseting + reset: RESET, +} + +impl DisplayInterface +where + SPI: hal::blocking::spi::Write, + CS: hal::digital::OutputPin, + BUSY: hal::digital::InputPin, + DC: hal::digital::OutputPin, + RESET: hal::digital::OutputPin, +{ + pub fn new(spi: SPI, cs: CS, busy: BUSY, dc: DC, reset: RESET) -> Self { + Self { + spi, + cs, + busy, + dc, + reset, + } + } + + fn reset>(&mut self, delay: &mut D) { + self.reset.set_low(); + delay.delay_ms(RESET_DELAY_MS); + self.reset.set_high(); + delay.delay_ms(RESET_DELAY_MS); + } + + fn send_command(&mut self, command: u8) -> Result<(), SPI::Error> { + self.dc.set_low(); + self.write(&[command])?; + self.dc.set_high(); + + Ok(()) + } + + fn send_data(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.dc.set_high(); + self.write(data) + } + + fn write(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + // Select the controller with chip select (CS) + self.cs.set_low(); + + // Linux has a default limit of 4096 bytes per SPI transfer + // https://github.com/torvalds/linux/blob/ccda4af0f4b92f7b4c308d3acc262f4a7e3affad/drivers/spi/spidev.c#L93 + if cfg!(target_os = "linux") { + for data_chunk in data.chunks(4096) { + self.spi.write(data_chunk)?; + } + } else { + self.spi.write(data)?; + } + + // Release the controller + self.cs.set_high(); + + Ok(()) + } + + + fn busy_wait(&self) { + while self.busy.is_high() {} + } +} diff --git a/src/lib.rs b/src/lib.rs index 31e1bb2..91cbf93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,7 @@ +extern crate embedded_hal as hal; + +mod interface; + #[cfg(test)] mod tests { #[test]