-
Notifications
You must be signed in to change notification settings - Fork 140
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
679 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
//! SPI Commands for the Waveshare 2.13" v2 | ||
use crate::traits; | ||
|
||
/// EPD2in13 v2 | ||
/// | ||
/// Should rarely (never?) be needed directly. | ||
/// | ||
/// For more infos about the addresses and what they are doing look into the pdfs | ||
#[allow(dead_code)] | ||
#[allow(non_camel_case_types)] | ||
#[derive(Copy, Clone)] | ||
pub(crate) enum Command { | ||
/// Driver Output control | ||
/// 3 Databytes: | ||
/// A[7:0] | ||
/// 0.. A[8] | ||
/// 0.. B[2:0] | ||
/// Default: Set A[8:0] = 0x127 and B[2:0] = 0x0 | ||
DRIVER_OUTPUT_CONTROL = 0x01, | ||
|
||
GATE_DRIVING_VOLTAGE_CTRL = 0x03, | ||
SOURCE_DRIVING_VOLTAGE_CTRL = 0x04, | ||
|
||
/// Booster Soft start control | ||
/// 3 Databytes: | ||
/// 1.. A[6:0] | ||
/// 1.. B[6:0] | ||
/// 1.. C[6:0] | ||
/// Default: A[7:0] = 0xCF, B[7:0] = 0xCE, C[7:0] = 0x8D | ||
BOOSTER_SOFT_START_CONTROL = 0x0C, | ||
GATE_SCAN_START_POSITION = 0x0F, | ||
//TODO: useful? | ||
// GATE_SCAN_START_POSITION = 0x0F, | ||
/// Deep Sleep Mode Control | ||
/// 1 Databyte: | ||
/// 0.. A[0] | ||
/// Values: | ||
/// A[0] = 0: Normal Mode (POR) | ||
/// A[0] = 1: Enter Deep Sleep Mode | ||
DEEP_SLEEP_MODE = 0x10, | ||
// /// Data Entry mode setting | ||
DATA_ENTRY_MODE_SETTING = 0x11, | ||
|
||
SW_RESET = 0x12, | ||
|
||
TEMPERATURE_SENSOR_CONTROL_WRITE = 0x1A, | ||
TEMPERATURE_SENSOR_CONTROL_READ = 0x1B, | ||
|
||
MASTER_ACTIVATION = 0x20, | ||
|
||
DISPLAY_UPDATE_CONTROL_1 = 0x21, | ||
|
||
DISPLAY_UPDATE_CONTROL_2 = 0x22, | ||
|
||
WRITE_RAM = 0x24, | ||
READ_RAM = 0x27, | ||
|
||
VCOM_SENSE = 0x28, | ||
|
||
WRITE_VCOM_REGISTER = 0x2C, | ||
|
||
WRITE_LUT_REGISTER = 0x32, | ||
|
||
WRITE_REGISTER_TO_DISPLAY_OPT = 0x37, | ||
WRITE_REGISTER_FOR_USER_ID = 0x38, | ||
|
||
SET_DUMMY_LINE_PERIOD = 0x3A, | ||
|
||
SET_GATE_LINE_WIDTH = 0x3B, | ||
|
||
BORDER_WAVEFORM_CONTROL = 0x3C, | ||
|
||
SET_RAM_X_ADDRESS_START_END_POSITION = 0x44, | ||
|
||
SET_RAM_Y_ADDRESS_START_END_POSITION = 0x45, | ||
|
||
SET_RAM_X_ADDRESS_COUNTER = 0x4E, | ||
|
||
SET_RAM_Y_ADDRESS_COUNTER = 0x4F, | ||
|
||
SET_ANALOG_BLOCK_CONTROL = 0x74, | ||
|
||
SET_DIGITAL_BLOCK_CONTROL = 0x7E, | ||
|
||
NOP = 0x7F, | ||
} | ||
|
||
pub(crate) enum DataEntryModeIncr { | ||
X_DECR_Y_DECR = 0x0, | ||
X_INCR_Y_DECR = 0x1, | ||
X_DECR_Y_INCR = 0x2, | ||
X_INCR_Y_INCR = 0x3 | ||
} | ||
|
||
pub (crate) enum DataEntryModeDir { | ||
X_DIR = 0x0, | ||
Y_DIR = 0x4, | ||
} | ||
|
||
impl traits::Command for Command { | ||
/// Returns the address of the command | ||
fn address(self) -> u8 { | ||
self as u8 | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::Command; | ||
use crate::traits::Command as CommandTrait; | ||
|
||
#[test] | ||
fn command_addr() { | ||
assert_eq!(Command::DRIVER_OUTPUT_CONTROL.address(), 0x01); | ||
|
||
assert_eq!(Command::SET_RAM_X_ADDRESS_COUNTER.address(), 0x4E); | ||
|
||
assert_eq!(Command::NOP.address(), 0xFF); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
#[rustfmt::skip] | ||
// Original Waveforms from Waveshare | ||
pub(crate) const LUT_FULL_UPDATE: [u8; 70] =[ | ||
0x80,0x60,0x40,0x00,0x00,0x00,0x00, // LUT0: BB: VS 0 ~7 | ||
0x10,0x60,0x20,0x00,0x00,0x00,0x00, // LUT1: BW: VS 0 ~7 | ||
0x80,0x60,0x40,0x00,0x00,0x00,0x00, // LUT2: WB: VS 0 ~7 | ||
0x10,0x60,0x20,0x00,0x00,0x00,0x00, // LUT3: WW: VS 0 ~7 | ||
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // LUT4: VCOM: VS 0 ~7 | ||
|
||
0x03,0x03,0x00,0x00,0x02, // TP0 A~D RP0 | ||
0x09,0x09,0x00,0x00,0x02, // TP1 A~D RP1 | ||
0x03,0x03,0x00,0x00,0x02, // TP2 A~D RP2 | ||
0x00,0x00,0x00,0x00,0x00, // TP3 A~D RP3 | ||
0x00,0x00,0x00,0x00,0x00, // TP4 A~D RP4 | ||
0x00,0x00,0x00,0x00,0x00, // TP5 A~D RP5 | ||
0x00,0x00,0x00,0x00,0x00, // TP6 A~D RP6 | ||
|
||
// 0x15,0x41,0xA8,0x32,0x30,0x0A, | ||
]; | ||
|
||
#[rustfmt::skip] | ||
pub(crate) const LUT_PARTIAL_UPDATE: [u8; 70] =[ | ||
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // LUT0: BB: VS 0 ~7 | ||
0x80,0x00,0x00,0x00,0x00,0x00,0x00, // LUT1: BW: VS 0 ~7 | ||
0x40,0x00,0x00,0x00,0x00,0x00,0x00, // LUT2: WB: VS 0 ~7 | ||
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // LUT3: WW: VS 0 ~7 | ||
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // LUT4: VCOM: VS 0 ~7 | ||
|
||
0x0A,0x00,0x00,0x00,0x00, // TP0 A~D RP0 | ||
0x00,0x00,0x00,0x00,0x00, // TP1 A~D RP1 | ||
0x00,0x00,0x00,0x00,0x00, // TP2 A~D RP2 | ||
0x00,0x00,0x00,0x00,0x00, // TP3 A~D RP3 | ||
0x00,0x00,0x00,0x00,0x00, // TP4 A~D RP4 | ||
0x00,0x00,0x00,0x00,0x00, // TP5 A~D RP5 | ||
0x00,0x00,0x00,0x00,0x00, // TP6 A~D RP6 | ||
|
||
// 0x15,0x41,0xA8,0x32,0x30,0x0A, | ||
]; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
use crate::epd2in13_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; | ||
use crate::graphics::{Display, DisplayRotation}; | ||
use embedded_graphics::pixelcolor::BinaryColor; | ||
use embedded_graphics::prelude::*; | ||
|
||
/// Full size buffer for use with the 2in13 v2 EPD | ||
/// | ||
/// Can also be manually constructed: | ||
/// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH / 8 * HEIGHT]` | ||
pub struct Display2in13 { | ||
buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], | ||
rotation: DisplayRotation, | ||
} | ||
|
||
impl Default for Display2in13 { | ||
fn default() -> Self { | ||
Display2in13 { | ||
buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); | ||
WIDTH as usize * HEIGHT as usize / 8], | ||
rotation: DisplayRotation::default(), | ||
} | ||
} | ||
} | ||
|
||
impl DrawTarget<BinaryColor> for Display2in13 { | ||
type Error = core::convert::Infallible; | ||
|
||
fn draw_pixel(&mut self, pixel: Pixel<BinaryColor>) -> Result<(), Self::Error> { | ||
self.draw_helper(WIDTH, HEIGHT, pixel) | ||
} | ||
|
||
fn size(&self) -> Size { | ||
Size::new(WIDTH, HEIGHT) | ||
} | ||
} | ||
|
||
impl Display for Display2in13 { | ||
fn buffer(&self) -> &[u8] { | ||
&self.buffer | ||
} | ||
|
||
fn get_mut_buffer(&mut self) -> &mut [u8] { | ||
&mut self.buffer | ||
} | ||
|
||
fn set_rotation(&mut self, rotation: DisplayRotation) { | ||
self.rotation = rotation; | ||
} | ||
|
||
fn rotation(&self) -> DisplayRotation { | ||
self.rotation | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::color::{Black, Color}; | ||
use crate::epd2in13_v2; | ||
use crate::graphics::{Display, DisplayRotation}; | ||
use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; | ||
|
||
// test buffer length | ||
#[test] | ||
fn graphics_size() { | ||
let display = Display2in13::default(); | ||
assert_eq!(display.buffer().len(), 48000); | ||
} | ||
|
||
// test default background color on all bytes | ||
#[test] | ||
fn graphics_default() { | ||
let display = Display2in13::default(); | ||
for &byte in display.buffer() { | ||
assert_eq!(byte, epd2in13_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); | ||
} | ||
} | ||
|
||
#[test] | ||
fn graphics_rotation_0() { | ||
let mut display = Display2in13::default(); | ||
|
||
let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) | ||
.into_styled(PrimitiveStyle::with_stroke(Black, 1)) | ||
.draw(&mut display); | ||
|
||
let buffer = display.buffer(); | ||
|
||
assert_eq!(buffer[0], Color::Black.get_byte_value()); | ||
|
||
for &byte in buffer.iter().skip(1) { | ||
assert_eq!(byte, epd2in13_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); | ||
} | ||
} | ||
|
||
#[test] | ||
fn graphics_rotation_90() { | ||
let mut display = Display2in13::default(); | ||
display.set_rotation(DisplayRotation::Rotate90); | ||
|
||
let _ = Line::new(Point::new(0, 792), Point::new(0, 799)) | ||
.into_styled(PrimitiveStyle::with_stroke(Black, 1)) | ||
.draw(&mut display); | ||
|
||
let buffer = display.buffer(); | ||
|
||
assert_eq!(buffer[0], Color::Black.get_byte_value()); | ||
|
||
for &byte in buffer.iter().skip(1) { | ||
assert_eq!(byte, epd2in13_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); | ||
} | ||
} | ||
|
||
#[test] | ||
fn graphics_rotation_180() { | ||
let mut display = Display2in13::default(); | ||
display.set_rotation(DisplayRotation::Rotate180); | ||
|
||
let _ = Line::new(Point::new(792, 479), Point::new(799, 479)) | ||
.into_styled(PrimitiveStyle::with_stroke(Black, 1)) | ||
.draw(&mut display); | ||
|
||
let buffer = display.buffer(); | ||
|
||
assert_eq!(buffer[0], Color::Black.get_byte_value()); | ||
|
||
for &byte in buffer.iter().skip(1) { | ||
assert_eq!(byte, epd2in13_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); | ||
} | ||
} | ||
|
||
#[test] | ||
fn graphics_rotation_270() { | ||
let mut display = Display2in13::default(); | ||
display.set_rotation(DisplayRotation::Rotate270); | ||
|
||
let _ = Line::new(Point::new(479, 0), Point::new(479, 7)) | ||
.into_styled(PrimitiveStyle::with_stroke(Black, 1)) | ||
.draw(&mut display); | ||
|
||
let buffer = display.buffer(); | ||
|
||
assert_eq!(buffer[0], Color::Black.get_byte_value()); | ||
|
||
for &byte in buffer.iter().skip(1) { | ||
assert_eq!(byte, epd2in13_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); | ||
} | ||
} | ||
} |
Oops, something went wrong.