1use core::time::Duration;
2use embedded_graphics::{
3 pixelcolor::BinaryColor,
4 prelude::{Dimensions, Point, Size},
5 primitives::Rectangle,
6};
7use embedded_hal::digital::{InputPin, OutputPin};
8use embedded_hal_async::{delay::DelayNs, digital::Wait, spi::SpiBus};
9
10use crate::{
11 buffer::{binary_buffer_length, BinaryBuffer},
12 Epd, EpdHw, Error,
13};
14
15pub const LUT_FULL_UPDATE: [u8; 30] = [
19 0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
21];
22pub const LUT_PARTIAL_UPDATE: [u8; 30] = [
27 0x10, 0x18, 0x18, 0x08, 0x18, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x44, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29];
30
31pub const DISPLAY_HEIGHT: u16 = 296;
33pub const DISPLAY_WIDTH: u16 = 128;
35pub const RECOMMENDED_MIN_FULL_REFRESH_INTERVAL: Duration = Duration::from_secs(180);
37pub const RECOMMENDED_MAX_FULL_REFRESH_INTERVAL: Duration = Duration::from_secs(24 * 60 * 60);
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
41pub enum Command {
42 DriverOutputControl = 0x01,
44 BoosterSoftStartControl = 0x0C,
46 DeepSleepMode = 0x10,
48 DataEntryModeSetting = 0x11,
50 SwReset = 0x12,
52 TemperatureSensorControl = 0x1A,
54 MasterActivation = 0x20,
57 DisplayUpdateControl1 = 0x21,
59 DisplayUpdateControl2 = 0x22,
61 WriteRam = 0x24,
63 WriteVcom = 0x2C,
65 WriteLut = 0x32,
67 SetDummyLinePeriod = 0x3A,
69 SetGateLineWidth = 0x3B,
71 BorderWaveformControl = 0x3C,
74 SetRamXStartEnd = 0x44,
76 SetRamYStartEnd = 0x45,
78 SetRamX = 0x4E,
80 SetRamY = 0x4F,
82 Noop = 0xFF,
84}
85
86const DRIVER_OUTPUT_INIT_DATA: [u8; 3] = [0x27, 0x01, 0x00];
94const BOOSTER_SOFT_START_INIT_DATA: [u8; 3] = [0xCF, 0xCE, 0x8D];
98
99impl Command {
100 fn register(&self) -> u8 {
101 *self as u8
102 }
103}
104
105pub struct Epd2in9<HW>
111where
112 HW: EpdHw,
113{
114 hw: HW,
115}
116
117impl<HW> Epd2in9<HW>
118where
119 HW: EpdHw,
120{
121 pub fn new(hw: HW) -> Self {
122 Epd2in9 { hw }
123 }
124
125 pub async fn set_border(&mut self, color: BinaryColor) -> Result<(), HW::Error> {
127 let border_setting: u8 = match color {
128 BinaryColor::Off => 0x40, BinaryColor::On => 0x50, };
131 self.send(Command::BorderWaveformControl, &[border_setting])
132 .await
133 }
134}
135
136impl<HW> Epd<HW> for Epd2in9<HW>
137where
138 HW: EpdHw,
139{
140 type Command = Command;
141 type Buffer = BinaryBuffer<
142 { binary_buffer_length(Size::new(DISPLAY_WIDTH as u32, DISPLAY_HEIGHT as u32)) },
143 >;
144
145 async fn init(&mut self, lut: &[u8]) -> Result<(), HW::Error> {
146 if lut.len() != 30 {
147 Err(Error::InvalidArgument)?
148 }
149
150 self.hw.reset().set_high()?;
152
153 self.send(Command::SwReset, &[]).await?;
155
156 self.send(Command::DriverOutputControl, &DRIVER_OUTPUT_INIT_DATA)
157 .await?;
158 self.send(
159 Command::BoosterSoftStartControl,
160 &BOOSTER_SOFT_START_INIT_DATA,
161 )
162 .await?;
163 self.send(Command::DataEntryModeSetting, &[0b11]).await?;
165
166 self.send(Command::WriteVcom, &[0xA8]).await?;
168 self.send(Command::SetDummyLinePeriod, &[0x1A]).await?;
170 self.send(Command::SetGateLineWidth, &[0x08]).await?;
172
173 self.send(Command::WriteLut, lut).await?;
174
175 Ok(())
176 }
177
178 async fn clear(&mut self) -> Result<(), HW::Error> {
179 self.send(Command::DisplayUpdateControl1, &[0x90]).await?;
182 self.update_display().await?;
183 self.send(Command::DisplayUpdateControl1, &[0x01]).await?;
185
186 Ok(())
187 }
188
189 async fn reset(&mut self) -> Result<(), HW::Error> {
190 self.hw.reset().set_low()?;
192 self.hw.delay().delay_ms(10).await;
193 self.hw.reset().set_high()?;
194 self.hw.delay().delay_ms(10).await;
195 Ok(())
196 }
197
198 async fn sleep(&mut self) -> Result<(), <HW as EpdHw>::Error> {
199 self.send(Command::DeepSleepMode, &[0x01]).await
200 }
201
202 async fn wake(&mut self) -> Result<(), <HW as EpdHw>::Error> {
203 self.reset().await
204
205 }
207
208 async fn display_buffer(&mut self, buffer: &Self::Buffer) -> Result<(), <HW as EpdHw>::Error> {
209 let buffer_bounds = buffer.bounding_box();
210 self.set_window(buffer_bounds).await?;
211 self.set_cursor(buffer_bounds.top_left).await?;
212 self.write_image(buffer.data()).await?;
213
214 Ok(())
215 }
216
217 async fn set_window(&mut self, shape: Rectangle) -> Result<(), <HW as EpdHw>::Error> {
221 let x_start = shape.top_left.x;
222 let x_end = x_start + shape.size.width as i32;
223 if x_start % 8 != 0 || x_end % 8 != 0 {
224 Err(Error::InvalidArgument)?
225 }
226 let x_start_byte = (x_start >> 3) as u8;
227 let x_end_byte = (x_end >> 8) as u8;
228 self.send(Command::SetRamXStartEnd, &[x_start_byte, x_end_byte])
229 .await?;
230
231 let y_start = shape.top_left.y;
232 let y_end = y_start + shape.size.height as i32;
233 let y_start_low = (y_start & 0xFF) as u8;
234 let y_start_high = ((y_start >> 8) & 0xFF) as u8;
235 let y_end_low = (y_end & 0xFF) as u8;
236 let y_end_high = ((y_end >> 8) & 0xFF) as u8;
237 self.send(
238 Command::SetRamYStartEnd,
239 &[y_start_low, y_start_high, y_end_low, y_end_high],
240 )
241 .await?;
242
243 Ok(())
244 }
245
246 async fn set_cursor(&mut self, position: Point) -> Result<(), <HW as EpdHw>::Error> {
250 if position.x % 8 != 0 {
251 Err(Error::InvalidArgument)?
252 }
253 self.send(Command::SetRamX, &[(position.x >> 3) as u8])
254 .await?;
255 let y_low = (position.y & 0xFF) as u8;
256 let y_high = ((position.y >> 8) & 0xFF) as u8;
257 self.send(Command::SetRamY, &[y_low, y_high]).await?;
258 Ok(())
259 }
260
261 async fn update_display(&mut self) -> Result<(), <HW as EpdHw>::Error> {
262 self.send(Command::DisplayUpdateControl2, &[0x04]).await?;
266 self.send(Command::MasterActivation, &[]).await?;
267 self.send(Command::Noop, &[]).await?;
268 Ok(())
269 }
270
271 async fn write_image(&mut self, image: &[u8]) -> Result<(), <HW as EpdHw>::Error> {
272 self.send(Command::WriteRam, image).await
273 }
274
275 async fn send(&mut self, command: Command, data: &[u8]) -> Result<(), HW::Error> {
276 self.wait_if_busy().await?;
277
278 self.hw.cs().set_low()?;
279 self.hw.dc().set_low()?;
280 self.hw.spi().write(&[command.register()]).await?;
281
282 if !data.is_empty() {
283 self.hw.dc().set_high()?;
284 self.hw.spi().write(data).await?;
285 }
286
287 self.hw.cs().set_high()?;
288 Ok(())
289 }
290
291 async fn wait_if_busy(&mut self) -> Result<(), HW::Error> {
292 let busy = self.hw.busy();
293 if busy.is_low().unwrap() {
294 busy.wait_for_high().await?;
295 }
296 Ok(())
297 }
298}
299
300