2024-07-02 15:57:29 +00:00
|
|
|
use epd_waveshare::{epd7in3f::Epd7in3f, prelude::WaveshareDisplay};
|
|
|
|
use linux_embedded_hal::spidev::SpiModeFlags;
|
|
|
|
use linux_embedded_hal::spidev::SpidevOptions;
|
2024-07-03 23:33:04 +00:00
|
|
|
use linux_embedded_hal::{CdevPin, Delay, SpidevDevice};
|
2024-07-28 04:01:57 +00:00
|
|
|
use tracing::instrument;
|
2024-07-28 04:06:23 +00:00
|
|
|
use tracing::{debug, warn};
|
2024-07-02 15:57:29 +00:00
|
|
|
|
|
|
|
use anyhow::Result;
|
2024-07-18 20:51:07 +00:00
|
|
|
use linux_embedded_hal::gpio_cdev::{Chip, LineRequestFlags};
|
2024-07-02 15:57:29 +00:00
|
|
|
|
2024-07-30 14:20:18 +00:00
|
|
|
use crate::imageproc::DitheredImage;
|
2024-07-29 17:51:51 +00:00
|
|
|
|
2024-07-27 19:11:44 +00:00
|
|
|
pub trait EInkPanel {
|
2024-07-30 14:20:18 +00:00
|
|
|
fn display(&mut self, buf: &DitheredImage) -> Result<()>;
|
2024-07-27 19:11:44 +00:00
|
|
|
}
|
|
|
|
|
2024-07-16 23:55:59 +00:00
|
|
|
pub struct Wrapper {
|
2024-07-02 15:57:29 +00:00
|
|
|
spi: SpidevDevice,
|
|
|
|
gpiochip: Chip,
|
|
|
|
delay: Delay,
|
2024-07-18 20:51:07 +00:00
|
|
|
panel: Epd7in3f<SpidevDevice, CdevPin, CdevPin, CdevPin, Delay>,
|
2024-07-02 15:57:29 +00:00
|
|
|
}
|
|
|
|
|
2024-07-16 23:55:59 +00:00
|
|
|
impl Wrapper {
|
2024-07-27 19:11:44 +00:00
|
|
|
pub fn new() -> Result<Self> {
|
2024-07-02 15:57:29 +00:00
|
|
|
let mut spi = SpidevDevice::open("/dev/spidev0.0")?;
|
|
|
|
let spi_options = SpidevOptions::new()
|
|
|
|
.bits_per_word(8)
|
|
|
|
.max_speed_hz(10_000_000)
|
|
|
|
.mode(SpiModeFlags::SPI_MODE_0)
|
|
|
|
.build();
|
|
|
|
spi.configure(&spi_options)?;
|
|
|
|
|
|
|
|
let mut gpiochip = Chip::new("/dev/gpiochip0")?;
|
|
|
|
let busy_pin = CdevPin::new(gpiochip.get_line(24)?.request(
|
|
|
|
LineRequestFlags::INPUT,
|
|
|
|
0,
|
|
|
|
"frametool",
|
|
|
|
)?)?;
|
|
|
|
let dc_pin = CdevPin::new(gpiochip.get_line(25)?.request(
|
|
|
|
LineRequestFlags::OUTPUT,
|
|
|
|
0,
|
|
|
|
"frametool",
|
|
|
|
)?)?;
|
|
|
|
let rst_pin = CdevPin::new(gpiochip.get_line(17)?.request(
|
|
|
|
LineRequestFlags::OUTPUT,
|
|
|
|
0,
|
|
|
|
"frametool",
|
|
|
|
)?)?;
|
|
|
|
let mut delay = Delay {};
|
|
|
|
let panel = Epd7in3f::new(&mut spi, busy_pin, dc_pin, rst_pin, &mut delay, None)?;
|
|
|
|
|
2024-07-27 19:11:44 +00:00
|
|
|
Ok(Self {
|
2024-07-02 15:57:29 +00:00
|
|
|
spi,
|
|
|
|
gpiochip,
|
|
|
|
delay,
|
2024-07-18 20:51:07 +00:00
|
|
|
panel,
|
2024-07-02 15:57:29 +00:00
|
|
|
})
|
|
|
|
}
|
2024-07-27 19:11:44 +00:00
|
|
|
pub fn test(&mut self) -> Result<()> {
|
|
|
|
self.panel.show_7block(&mut self.spi, &mut self.delay)?;
|
|
|
|
self.panel.sleep(&mut self.spi, &mut self.delay)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EInkPanel for Wrapper {
|
2024-07-28 04:01:57 +00:00
|
|
|
#[instrument(skip_all)]
|
2024-07-30 14:20:18 +00:00
|
|
|
fn display(&mut self, img: &DitheredImage) -> Result<()> {
|
2024-07-29 17:51:51 +00:00
|
|
|
let buf = img.into_display_buffer();
|
2024-07-18 20:51:07 +00:00
|
|
|
self.panel
|
2024-07-29 17:51:51 +00:00
|
|
|
.update_and_display_frame(&mut self.spi, &buf, &mut self.delay)?;
|
2024-07-27 19:11:44 +00:00
|
|
|
debug!("Finished updating frame");
|
2024-07-17 05:24:11 +00:00
|
|
|
self.panel.sleep(&mut self.spi, &mut self.delay)?;
|
2024-07-27 19:11:44 +00:00
|
|
|
debug!("Display entered sleep mode");
|
2024-07-17 05:24:11 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2024-07-27 19:11:44 +00:00
|
|
|
}
|
|
|
|
|
2024-07-29 17:51:51 +00:00
|
|
|
/// A Fake EInk display for testing purposes.
|
|
|
|
/// Saves the output as `display.bmp`
|
2024-07-27 19:11:44 +00:00
|
|
|
pub struct FakeEInk();
|
|
|
|
impl EInkPanel for FakeEInk {
|
2024-07-30 14:20:18 +00:00
|
|
|
fn display(&mut self, img: &DitheredImage) -> Result<()> {
|
2024-07-29 17:51:51 +00:00
|
|
|
warn!("Fake display was called: saving to display.bmp");
|
|
|
|
img.into_rgbimage().save("display.bmp");
|
|
|
|
|
2024-07-02 15:57:29 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|