Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for 7.3 Inch HAT (F) #191

Merged
merged 3 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?;
| [7.5 Inch B/W HD (A)](https://www.waveshare.com/product/displays/e-paper/epaper-1/7.5inch-hd-e-paper-hat.htm) | Black, White | ✕ | ✕ | ✔ | ✔ |
| [7.5 Inch B/W V2 (A)](https://www.waveshare.com/product/7.5inch-e-paper-hat.htm) [[1](#1-75-inch-bw-v2-a)] | Black, White | ✕ | ✕ | ✔ | ✔ |
| [7.5 Inch B/W (A)](https://www.waveshare.com/product/7.5inch-e-paper-hat.htm) | Black, White | ✕ | ✕ | ✔ | ✔ |
| [7.3 Inch HAT (F)](https://www.waveshare.com/product/7.3inch-e-paper-hat-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ |
| [5.83 Inch B/W/R (b)](https://www.waveshare.com/5.83inch-e-Paper-B.htm) | Black, White, Red | ✕ | Not officially | ✔ | ✔ |
| [5.65 Inch 7 Color (F)](https://www.waveshare.com/5.65inch-e-paper-module-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ |
| [4.2 Inch B/W (A)](https://www.waveshare.com/product/4.2inch-e-paper-module.htm) | Black, White | ✕ | Not officially [[2](#2-42-inch-e-ink-blackwhite---partial-refresh)] | ✔ | ✔ |
Expand Down
2 changes: 1 addition & 1 deletion src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub enum TriColor {
Chromatic,
}

/// For the 5in65 7 Color Display
/// For the 7 Color Displays
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum OctColor {
/// Black Color
Expand Down
55 changes: 55 additions & 0 deletions src/epd7in3f/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::traits;

#[allow(dead_code, clippy::upper_case_acronyms)]
#[derive(Clone, Copy, Debug)]
pub(crate) enum Command {
Ox00 = 0x00,
Ox01 = 0x01,

PowerOff = 0x02,

Ox03 = 0x03,

PowerOn = 0x04,

Ox05 = 0x05,
Ox06 = 0x06,

DeepSleep = 0x07,

Ox08 = 0x08,

DataStartTransmission = 0x10,

DataFresh = 0x12,

IPC = 0x13,

Ox30 = 0x30,

TSE = 0x41,

Ox50 = 0x50,
Ox60 = 0x60,
Ox61 = 0x61,

Ox82 = 0x82,
Ox84 = 0x84,

CMDH = 0xAA,

AGID = 0x86,

CCSET = 0xE0,

OxE3 = 0xE3,

TSSET = 0xE6,
}

impl traits::Command for Command {
/// Returns the address of the command
fn address(self) -> u8 {
self as u8
}
}
275 changes: 275 additions & 0 deletions src/epd7in3f/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
//! A simple Driver for the Waveshare 7.3inch e-Paper HAT (F) Display via SPI
//!
//! # References
//!
//! - [Datasheet](https://www.waveshare.com/wiki/7.3inch_e-Paper_HAT_(F))
//! - [Waveshare C driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_7in3f.c)
//! - [Waveshare Python driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in3f.py)

use embedded_hal::{
delay::DelayNs,
digital::{InputPin, OutputPin},
spi::SpiDevice,
};

use crate::{
buffer_len,
color::OctColor,
interface::DisplayInterface,
traits::{InternalWiAdditions, WaveshareDisplay},
};

use self::command::Command;

mod command;

/// Full size buffer for use with the 7in3f EPD
#[cfg(feature = "graphics")]
pub type Display7in3f = crate::graphics::Display<
WIDTH,
HEIGHT,
false,
{ buffer_len(WIDTH as usize, HEIGHT as usize * 4) },
OctColor,
>;

/// Width of the display
pub const WIDTH: u32 = 800;
/// Height of the display
pub const HEIGHT: u32 = 480;
/// Default Background Color
pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White;
/// Default mode of writing data (single byte vs blockwise)
const SINGLE_BYTE_WRITE: bool = true;

/// Epd57n3f driver
pub struct Epd7in3f<SPI, BUSY, DC, RST, DELAY> {
/// Connection Interface
interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
/// Background Color
color: OctColor,
}

impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
for Epd7in3f<SPI, BUSY, DC, RST, DELAY>
where
SPI: SpiDevice,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
DELAY: DelayNs,
{
fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
self.interface.reset(delay, 20_000, 2_000);
self.wait_busy_low(delay);
delay.delay_ms(30);

self.cmd_with_data(spi, Command::CMDH, &[0x49, 0x55, 0x20, 0x08, 0x09, 0x18])?;
self.cmd_with_data(spi, Command::Ox01, &[0x3F, 0x00, 0x32, 0x2A, 0x0E, 0x2A])?;
self.cmd_with_data(spi, Command::Ox00, &[0x5F, 0x69])?;
self.cmd_with_data(spi, Command::Ox03, &[0x00, 0x54, 0x00, 0x44])?;
self.cmd_with_data(spi, Command::Ox05, &[0x40, 0x1F, 0x1F, 0x2C])?;
self.cmd_with_data(spi, Command::Ox06, &[0x6F, 0x1F, 0x1F, 0x22])?;
self.cmd_with_data(spi, Command::Ox08, &[0x6F, 0x1F, 0x1F, 0x22])?;
self.cmd_with_data(spi, Command::IPC, &[0x00, 0x04])?;
self.cmd_with_data(spi, Command::Ox30, &[0x3C])?;
self.cmd_with_data(spi, Command::TSE, &[0x00])?;
self.cmd_with_data(spi, Command::Ox50, &[0x3F])?;
self.cmd_with_data(spi, Command::Ox60, &[0x02, 0x00])?;
self.cmd_with_data(spi, Command::Ox61, &[0x03, 0x20, 0x01, 0xE0])?;
self.cmd_with_data(spi, Command::Ox82, &[0x1E])?;
self.cmd_with_data(spi, Command::Ox84, &[0x00])?;
self.cmd_with_data(spi, Command::AGID, &[0x00])?;
self.cmd_with_data(spi, Command::OxE3, &[0x2F])?;
self.cmd_with_data(spi, Command::CCSET, &[0x00])?;
self.cmd_with_data(spi, Command::TSSET, &[0x00])
}
}

impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
for Epd7in3f<SPI, BUSY, DC, RST, DELAY>
where
SPI: SpiDevice,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
DELAY: DelayNs,
{
type DisplayColor = OctColor;

fn new(
spi: &mut SPI,
busy: BUSY,
dc: DC,
rst: RST,
delay: &mut DELAY,
delay_us: Option<u32>,
) -> Result<Self, <SPI>::Error>
where
Self: Sized,
{
let interface = DisplayInterface::new(busy, dc, rst, delay_us);
let color = DEFAULT_BACKGROUND_COLOR;

let mut epd = Epd7in3f { interface, color };

epd.init(spi, delay)?;

Ok(epd)
}

fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), <SPI>::Error> {
self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])
}

fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
self.init(spi, delay)
}

fn set_background_color(&mut self, color: Self::DisplayColor) {
self.color = color;
}

fn background_color(&self) -> &Self::DisplayColor {
&self.color
}

fn width(&self) -> u32 {
WIDTH
}

fn height(&self) -> u32 {
HEIGHT
}

fn update_frame(
&mut self,
spi: &mut SPI,
buffer: &[u8],
delay: &mut DELAY,
) -> Result<(), <SPI>::Error> {
self.wait_until_idle(spi, delay)?;
self.cmd_with_data(spi, Command::DataStartTransmission, buffer)
}

fn update_partial_frame(
&mut self,
_spi: &mut SPI,
_delay: &mut DELAY,
_buffer: &[u8],
_x: u32,
_y: u32,
_width: u32,
_height: u32,
) -> Result<(), <SPI>::Error> {
unimplemented!()
}

fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
self.command(spi, Command::PowerOn)?;
self.wait_busy_low(delay);

self.cmd_with_data(spi, Command::DataFresh, &[0x00])?;
self.wait_busy_low(delay);

self.cmd_with_data(spi, Command::PowerOff, &[0x00])?;
self.wait_busy_low(delay);

Ok(())
}

fn update_and_display_frame(
&mut self,
spi: &mut SPI,
buffer: &[u8],
delay: &mut DELAY,
) -> Result<(), <SPI>::Error> {
self.update_frame(spi, buffer, delay)?;
self.display_frame(spi, delay)
}

fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
let bg = OctColor::colors_byte(self.color, self.color);

self.wait_busy_low(delay);
self.command(spi, Command::DataStartTransmission)?;
self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?;

self.display_frame(spi, delay)
}

fn set_lut(
&mut self,
_spi: &mut SPI,
_delay: &mut DELAY,
_refresh_rate: Option<crate::traits::RefreshLut>,
) -> Result<(), <SPI>::Error> {
unimplemented!()
}

fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
self.wait_busy_low(delay);
Ok(())
}
}

impl<SPI, BUSY, DC, RST, DELAY> Epd7in3f<SPI, BUSY, DC, RST, DELAY>
where
SPI: SpiDevice,
BUSY: InputPin,
DC: OutputPin,
RST: OutputPin,
DELAY: DelayNs,
{
fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
self.interface.cmd(spi, command)
}

fn cmd_with_data(
&mut self,
spi: &mut SPI,
command: Command,
data: &[u8],
) -> Result<(), SPI::Error> {
self.interface.cmd_with_data(spi, command, data)
}

fn wait_busy_low(&mut self, delay: &mut DELAY) {
self.interface.wait_until_idle(delay, true);
}

/// Show 7 blocks of color, used for quick testing
pub fn show_7block(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
let color_7 = [
OctColor::Black,
OctColor::White,
OctColor::Green,
OctColor::Blue,
OctColor::Red,
OctColor::Yellow,
OctColor::Orange,
OctColor::White,
];

self.command(spi, Command::DataStartTransmission)?;
for _ in 0..240 {
for color in color_7.iter().take(4) {
for _ in 0..100 {
self.interface
.data(spi, &[OctColor::colors_byte(*color, *color)])?;
}
}
}

for _ in 0..240 {
for color in color_7.iter().skip(4) {
for _ in 0..100 {
self.interface
.data(spi, &[OctColor::colors_byte(*color, *color)])?;
}
}
}

self.display_frame(spi, delay)
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ pub mod epd4in2;
pub mod epd5in65f;
pub mod epd5in83_v2;
pub mod epd5in83b_v2;
pub mod epd7in3f;
pub mod epd7in5;
pub mod epd7in5_hd;
pub mod epd7in5_v2;
Expand Down