Skip to content

Commit 744940c

Browse files
add: driver for epd7in3e
1 parent 48458e1 commit 744940c

3 files changed

Lines changed: 316 additions & 0 deletions

File tree

src/epd7in3e/command.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use crate::traits;
2+
3+
#[allow(dead_code, clippy::upper_case_acronyms)]
4+
#[derive(Clone, Copy, Debug)]
5+
pub(crate) enum Command {
6+
Ox00 = 0x00,
7+
Ox01 = 0x01,
8+
9+
PowerOff = 0x02,
10+
11+
Ox03 = 0x03,
12+
13+
PowerOn = 0x04,
14+
15+
Ox05 = 0x05,
16+
Ox06 = 0x06,
17+
18+
DeepSleep = 0x07,
19+
20+
Ox08 = 0x08,
21+
22+
DataStartTransmission = 0x10,
23+
24+
DataFresh = 0x12,
25+
26+
Ox30 = 0x30,
27+
28+
Ox50 = 0x50,
29+
Ox60 = 0x60,
30+
Ox61 = 0x61,
31+
32+
Ox84 = 0x84,
33+
34+
CMDH = 0xAA,
35+
36+
OxE3 = 0xE3,
37+
}
38+
39+
impl traits::Command for Command {
40+
/// Returns the address of the command
41+
fn address(self) -> u8 {
42+
self as u8
43+
}
44+
}

src/epd7in3e/mod.rs

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
//! A simple Driver for the Waveshare 7.3inch e-Paper HAT (E) Display via SPI
2+
//!
3+
//! # References
4+
//!
5+
//! - [Datasheet](https://www.waveshare.com/wiki/7.3inch_e-Paper_HAT_(E))
6+
//! - [Waveshare Python driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in3e.py)
7+
8+
use embedded_hal::{
9+
delay::DelayNs,
10+
digital::{InputPin, OutputPin},
11+
spi::SpiDevice,
12+
};
13+
14+
use crate::{
15+
buffer_len,
16+
color::OctColor,
17+
interface::DisplayInterface,
18+
traits::{InternalWiAdditions, WaveshareDisplay},
19+
};
20+
21+
use self::command::Command;
22+
23+
mod command;
24+
25+
/// Full size buffer for use with the 7in3e EPD
26+
#[cfg(feature = "graphics")]
27+
pub type Display7in3e = crate::graphics::Display<
28+
WIDTH,
29+
HEIGHT,
30+
false,
31+
{ buffer_len(WIDTH as usize, HEIGHT as usize * 4) },
32+
OctColor,
33+
>;
34+
35+
/// Width of the display
36+
pub const WIDTH: u32 = 800;
37+
/// Height of the display
38+
pub const HEIGHT: u32 = 480;
39+
/// Default Background Color
40+
pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White;
41+
/// Default mode of writing data (single byte vs blockwise)
42+
const SINGLE_BYTE_WRITE: bool = true;
43+
44+
/// Epd7in3e driver
45+
pub struct Epd7in3e<SPI, BUSY, DC, RST, DELAY> {
46+
/// Connection Interface
47+
interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
48+
/// Background Color
49+
color: OctColor,
50+
}
51+
52+
impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
53+
for Epd7in3e<SPI, BUSY, DC, RST, DELAY>
54+
where
55+
SPI: SpiDevice,
56+
BUSY: InputPin,
57+
DC: OutputPin,
58+
RST: OutputPin,
59+
DELAY: DelayNs,
60+
{
61+
fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
62+
self.interface.reset(delay, 20_000, 2_000);
63+
self.wait_busy_low(delay);
64+
delay.delay_ms(30);
65+
66+
self.cmd_with_data(spi, Command::CMDH, &[0x49, 0x55, 0x20, 0x08, 0x09, 0x18])?;
67+
self.cmd_with_data(spi, Command::Ox01, &[0x3F])?;
68+
self.cmd_with_data(spi, Command::Ox00, &[0x5F, 0x69])?;
69+
self.cmd_with_data(spi, Command::Ox03, &[0x00, 0x54, 0x00, 0x44])?;
70+
self.cmd_with_data(spi, Command::Ox05, &[0x40, 0x1F, 0x1F, 0x2C])?;
71+
self.cmd_with_data(spi, Command::Ox06, &[0x6F, 0x1F, 0x17, 0x49])?;
72+
self.cmd_with_data(spi, Command::Ox08, &[0x6F, 0x1F, 0x1F, 0x22])?;
73+
self.cmd_with_data(spi, Command::Ox30, &[0x03])?;
74+
self.cmd_with_data(spi, Command::Ox50, &[0x3F])?;
75+
self.cmd_with_data(spi, Command::Ox60, &[0x02, 0x00])?;
76+
self.cmd_with_data(spi, Command::Ox61, &[0x03, 0x20, 0x01, 0xE0])?;
77+
self.cmd_with_data(spi, Command::Ox84, &[0x01])?;
78+
self.cmd_with_data(spi, Command::OxE3, &[0x2F])?;
79+
self.wait_busy_low(delay);
80+
81+
Ok(())
82+
}
83+
}
84+
85+
impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
86+
for Epd7in3e<SPI, BUSY, DC, RST, DELAY>
87+
where
88+
SPI: SpiDevice,
89+
BUSY: InputPin,
90+
DC: OutputPin,
91+
RST: OutputPin,
92+
DELAY: DelayNs,
93+
{
94+
type DisplayColor = OctColor;
95+
96+
fn new(
97+
spi: &mut SPI,
98+
busy: BUSY,
99+
dc: DC,
100+
rst: RST,
101+
delay: &mut DELAY,
102+
delay_us: Option<u32>,
103+
) -> Result<Self, <SPI>::Error>
104+
where
105+
Self: Sized,
106+
{
107+
let interface = DisplayInterface::new(busy, dc, rst, delay_us);
108+
let color = DEFAULT_BACKGROUND_COLOR;
109+
110+
let mut epd = Epd7in3e { interface, color };
111+
112+
epd.init(spi, delay)?;
113+
114+
Ok(epd)
115+
}
116+
117+
fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), <SPI>::Error> {
118+
self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])
119+
}
120+
121+
fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
122+
self.init(spi, delay)
123+
}
124+
125+
fn set_background_color(&mut self, color: Self::DisplayColor) {
126+
self.color = color;
127+
}
128+
129+
fn background_color(&self) -> &Self::DisplayColor {
130+
&self.color
131+
}
132+
133+
fn width(&self) -> u32 {
134+
WIDTH
135+
}
136+
137+
fn height(&self) -> u32 {
138+
HEIGHT
139+
}
140+
141+
fn update_frame(
142+
&mut self,
143+
spi: &mut SPI,
144+
buffer: &[u8],
145+
delay: &mut DELAY,
146+
) -> Result<(), <SPI>::Error> {
147+
self.wait_until_idle(spi, delay)?;
148+
self.cmd_with_data(spi, Command::DataStartTransmission, buffer)
149+
}
150+
151+
fn update_partial_frame(
152+
&mut self,
153+
_spi: &mut SPI,
154+
_delay: &mut DELAY,
155+
_buffer: &[u8],
156+
_x: u32,
157+
_y: u32,
158+
_width: u32,
159+
_height: u32,
160+
) -> Result<(), <SPI>::Error> {
161+
unimplemented!()
162+
}
163+
164+
fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
165+
self.command(spi, Command::PowerOn)?;
166+
self.wait_busy_low(delay);
167+
168+
self.cmd_with_data(spi, Command::DataFresh, &[0x00])?;
169+
self.wait_busy_low(delay);
170+
171+
self.cmd_with_data(spi, Command::PowerOff, &[0x00])?;
172+
self.wait_busy_low(delay);
173+
174+
Ok(())
175+
}
176+
177+
fn update_and_display_frame(
178+
&mut self,
179+
spi: &mut SPI,
180+
buffer: &[u8],
181+
delay: &mut DELAY,
182+
) -> Result<(), <SPI>::Error> {
183+
self.update_frame(spi, buffer, delay)?;
184+
self.display_frame(spi, delay)
185+
}
186+
187+
fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
188+
let bg = OctColor::colors_byte(self.color, self.color);
189+
190+
self.wait_busy_low(delay);
191+
self.command(spi, Command::DataStartTransmission)?;
192+
self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?;
193+
194+
self.display_frame(spi, delay)
195+
}
196+
197+
fn set_lut(
198+
&mut self,
199+
_spi: &mut SPI,
200+
_delay: &mut DELAY,
201+
_refresh_rate: Option<crate::traits::RefreshLut>,
202+
) -> Result<(), <SPI>::Error> {
203+
unimplemented!()
204+
}
205+
206+
fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), <SPI>::Error> {
207+
self.wait_busy_low(delay);
208+
Ok(())
209+
}
210+
}
211+
212+
impl<SPI, BUSY, DC, RST, DELAY> Epd7in3e<SPI, BUSY, DC, RST, DELAY>
213+
where
214+
SPI: SpiDevice,
215+
BUSY: InputPin,
216+
DC: OutputPin,
217+
RST: OutputPin,
218+
DELAY: DelayNs,
219+
{
220+
fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
221+
self.interface.cmd(spi, command)
222+
}
223+
224+
fn cmd_with_data(
225+
&mut self,
226+
spi: &mut SPI,
227+
command: Command,
228+
data: &[u8],
229+
) -> Result<(), SPI::Error> {
230+
self.interface.cmd_with_data(spi, command, data)
231+
}
232+
233+
fn wait_busy_low(&mut self, delay: &mut DELAY) {
234+
self.interface.wait_until_idle(delay, true);
235+
}
236+
237+
/// Show 7 blocks of color, used for quick testing
238+
pub fn show_7block(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
239+
let color_7 = [
240+
OctColor::Black,
241+
OctColor::White,
242+
OctColor::Green,
243+
OctColor::Blue,
244+
OctColor::Red,
245+
OctColor::Yellow,
246+
OctColor::Orange,
247+
OctColor::White,
248+
];
249+
250+
self.command(spi, Command::DataStartTransmission)?;
251+
for _ in 0..240 {
252+
for color in color_7.iter().take(4) {
253+
for _ in 0..100 {
254+
self.interface
255+
.data(spi, &[OctColor::colors_byte(*color, *color)])?;
256+
}
257+
}
258+
}
259+
260+
for _ in 0..240 {
261+
for color in color_7.iter().skip(4) {
262+
for _ in 0..100 {
263+
self.interface
264+
.data(spi, &[OctColor::colors_byte(*color, *color)])?;
265+
}
266+
}
267+
}
268+
269+
self.display_frame(spi, delay)
270+
}
271+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ pub mod epd4in2;
9797
pub mod epd5in65f;
9898
pub mod epd5in83_v2;
9999
pub mod epd5in83b_v2;
100+
pub mod epd7in3e;
100101
pub mod epd7in3f;
101102
pub mod epd7in5;
102103
pub mod epd7in5_hd;

0 commit comments

Comments
 (0)