Removed #[allow(non_camel_case_types)] to fix issues
parent
0567da80c0
commit
ba1b90e2f3
|
|
@ -103,7 +103,7 @@ where
|
||||||
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
|
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::DRIVER_OUTPUT_CONTROL,
|
Command::DriverOutputControl,
|
||||||
&[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00],
|
&[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
@ -114,26 +114,26 @@ where
|
||||||
//TODO: test
|
//TODO: test
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::BOOSTER_SOFT_START_CONTROL,
|
Command::BoosterSoftStartControl,
|
||||||
&[0xD7, 0xD6, 0x9D],
|
&[0xD7, 0xD6, 0x9D],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// One Databyte with value 0xA8 for 7V VCOM
|
// One Databyte with value 0xA8 for 7V VCOM
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[0xA8])?;
|
.cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8])?;
|
||||||
|
|
||||||
// One Databyte with default value 0x1A for 4 dummy lines per gate
|
// One Databyte with default value 0x1A for 4 dummy lines per gate
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::SET_DUMMY_LINE_PERIOD, &[0x1A])?;
|
.cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A])?;
|
||||||
|
|
||||||
// One Databyte with default value 0x08 for 2us per line
|
// One Databyte with default value 0x08 for 2us per line
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::SET_GATE_LINE_WIDTH, &[0x08])?;
|
.cmd_with_data(spi, Command::SetGateLineWidth, &[0x08])?;
|
||||||
|
|
||||||
// One Databyte with default value 0x03
|
// One Databyte with default value 0x03
|
||||||
// -> address: x increment, y increment, address counter is updated in x direction
|
// -> address: x increment, y increment, address counter is updated in x direction
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DATA_ENTRY_MODE_SETTING, &[0x03])?;
|
.cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?;
|
||||||
|
|
||||||
self.set_lut(spi, None)?;
|
self.set_lut(spi, None)?;
|
||||||
|
|
||||||
|
|
@ -194,7 +194,7 @@ where
|
||||||
// 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode
|
// 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode
|
||||||
//TODO: is 0x00 needed here or would 0x01 be even more efficient?
|
//TODO: is 0x00 needed here or would 0x01 be even more efficient?
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x00])?;
|
.cmd_with_data(spi, Command::DeepSleepMode, &[0x00])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +202,7 @@ where
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.use_full_frame(spi)?;
|
self.use_full_frame(spi)?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;
|
.cmd_with_data(spi, Command::WriteRam, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,7 +221,7 @@ where
|
||||||
self.set_ram_counter(spi, x, y)?;
|
self.set_ram_counter(spi, x, y)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;
|
.cmd_with_data(spi, Command::WriteRam, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,9 +230,9 @@ where
|
||||||
// enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version)
|
// enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version)
|
||||||
//TODO: test control_1 or control_2 with default value 0xFF (from the datasheet)
|
//TODO: test control_1 or control_2 with default value 0xFF (from the datasheet)
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xC4])?;
|
.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::MASTER_ACTIVATION)?;
|
self.interface.cmd(spi, Command::MasterActivation)?;
|
||||||
// MASTER Activation should not be interupted to avoid currption of panel images
|
// MASTER Activation should not be interupted to avoid currption of panel images
|
||||||
// therefore a terminate command is send
|
// therefore a terminate command is send
|
||||||
self.interface.cmd(spi, Command::NOP)?;
|
self.interface.cmd(spi, Command::NOP)?;
|
||||||
|
|
@ -252,7 +252,7 @@ where
|
||||||
// clear the ram with the background color
|
// clear the ram with the background color
|
||||||
let color = self.background_color.get_byte_value();
|
let color = self.background_color.get_byte_value();
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::WRITE_RAM)?;
|
self.interface.cmd(spi, Command::WriteRam)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color, WIDTH / 8 * HEIGHT)?;
|
.data_x_times(spi, color, WIDTH / 8 * HEIGHT)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -321,14 +321,14 @@ where
|
||||||
// aren't relevant
|
// aren't relevant
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_X_ADDRESS_START_END_POSITION,
|
Command::SetRamXAddressStartEndPosition,
|
||||||
&[(start_x >> 3) as u8, (end_x >> 3) as u8],
|
&[(start_x >> 3) as u8, (end_x >> 3) as u8],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// 2 Databytes: A[7:0] & 0..A[8] for each - start and end
|
// 2 Databytes: A[7:0] & 0..A[8] for each - start and end
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_Y_ADDRESS_START_END_POSITION,
|
Command::SetRamYAddressStartEndPosition,
|
||||||
&[
|
&[
|
||||||
start_y as u8,
|
start_y as u8,
|
||||||
(start_y >> 8) as u8,
|
(start_y >> 8) as u8,
|
||||||
|
|
@ -349,12 +349,12 @@ where
|
||||||
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
|
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
|
||||||
// aren't relevant
|
// aren't relevant
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?;
|
.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?;
|
||||||
|
|
||||||
// 2 Databytes: A[7:0] & 0..A[8]
|
// 2 Databytes: A[7:0] & 0..A[8]
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_Y_ADDRESS_COUNTER,
|
Command::SetRamYAddressCounter,
|
||||||
&[y as u8, (y >> 8) as u8],
|
&[y as u8, (y >> 8) as u8],
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -365,7 +365,7 @@ where
|
||||||
assert!(buffer.len() == 30);
|
assert!(buffer.len() == 30);
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)?;
|
.cmd_with_data(spi, Command::WriteLutRegister, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,35 +2,34 @@
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
|
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
DATA_START_TRANSMISSION_2 = 0x13,
|
DataStartTransmission2 = 0x13,
|
||||||
|
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
LUT_WHITE_TO_WHITE = 0x21,
|
LutWhiteToWhite = 0x21,
|
||||||
LUT_BLACK_TO_WHITE = 0x22,
|
LutBlackToWhite = 0x22,
|
||||||
LUT_G0 = 0x23,
|
LutG0 = 0x23,
|
||||||
LUT_G1 = 0x24,
|
LutG1 = 0x24,
|
||||||
LUT_RED_VCOM = 0x25,
|
LutRedVcom = 0x25,
|
||||||
LUT_RED0 = 0x26,
|
LutRed0 = 0x26,
|
||||||
LUT_RED1 = 0x27,
|
LutRed1 = 0x27,
|
||||||
|
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
TEMPERATURE_SENSOR_SELECTION = 0x41,
|
TemperatureSensorSelection = 0x41,
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
RESOLUTION_SETTING = 0x61,
|
ResolutionSetting = 0x61,
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
POWER_SAVING = 0xE3,
|
PowerSaving = 0xE3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
|
||||||
|
|
@ -56,29 +56,29 @@ where
|
||||||
|
|
||||||
// set the power settings
|
// set the power settings
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_SETTING, &[0x07, 0x00, 0x08, 0x00])?;
|
.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x00, 0x08, 0x00])?;
|
||||||
|
|
||||||
// start the booster
|
// start the booster
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x07, 0x07, 0x07])?;
|
.cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x07])?;
|
||||||
|
|
||||||
// power on
|
// power on
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
delay.delay_ms(5);
|
delay.delay_ms(5);
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
// set the panel settings
|
// set the panel settings
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xCF])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0xCF])?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?;
|
self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?;
|
||||||
|
|
||||||
// PLL
|
// PLL
|
||||||
self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x39])?;
|
self.cmd_with_data(spi, Command::PllControl, &[0x39])?;
|
||||||
|
|
||||||
// set resolution
|
// set resolution
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x0E])?;
|
self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0E])?;
|
||||||
|
|
||||||
self.set_lut(spi, None)?;
|
self.set_lut(spi, None)?;
|
||||||
|
|
||||||
|
|
@ -112,7 +112,7 @@ where
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
for b in black {
|
for b in black {
|
||||||
let expanded = expand_bits(*b);
|
let expanded = expand_bits(*b);
|
||||||
|
|
@ -127,7 +127,7 @@ where
|
||||||
chromatic: &[u8],
|
chromatic: &[u8],
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data(spi, chromatic)?;
|
self.interface.data(spi, chromatic)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -164,19 +164,19 @@ where
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating
|
.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x00])?; // VCOM to 0V
|
.cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // VCOM to 0V
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_SETTING, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast
|
.cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
//NOTE: The example code has a 1s delay here
|
//NOTE: The example code has a 1s delay here
|
||||||
|
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +210,7 @@ where
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
for b in buffer {
|
for b in buffer {
|
||||||
// Two bits per pixel
|
// Two bits per pixel
|
||||||
|
|
@ -225,7 +225,7 @@ where
|
||||||
let nbits = WIDTH * (HEIGHT / 8);
|
let nbits = WIDTH * (HEIGHT / 8);
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data_x_times(spi, color, nbits)?;
|
self.interface.data_x_times(spi, color, nbits)?;
|
||||||
|
|
||||||
//NOTE: Example code has a delay here
|
//NOTE: Example code has a delay here
|
||||||
|
|
@ -247,7 +247,7 @@ where
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -265,7 +265,7 @@ where
|
||||||
|
|
||||||
// Clear the black
|
// Clear the black
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
// Uses 2 bits per pixel
|
// Uses 2 bits per pixel
|
||||||
self.interface
|
self.interface
|
||||||
|
|
@ -273,7 +273,7 @@ where
|
||||||
|
|
||||||
// Clear the red
|
// Clear the red
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color, WIDTH * HEIGHT / 8)?;
|
.data_x_times(spi, color, WIDTH * HEIGHT / 8)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -285,19 +285,19 @@ where
|
||||||
_refresh_rate: Option<RefreshLUT>,
|
_refresh_rate: Option<RefreshLUT>,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::LUT_FOR_VCOM, LUT_VCOM0)?;
|
.cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, LUT_WHITE_TO_WHITE)?;
|
.cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE)?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, LUT_BLACK_TO_WHITE)?;
|
.cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE)?;
|
||||||
self.interface.cmd_with_data(spi, Command::LUT_G0, LUT_G1)?;
|
self.interface.cmd_with_data(spi, Command::LutG0, LUT_G1)?;
|
||||||
self.interface.cmd_with_data(spi, Command::LUT_G1, LUT_G2)?;
|
self.interface.cmd_with_data(spi, Command::LutG1, LUT_G2)?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::LUT_RED_VCOM, LUT_RED_VCOM)?;
|
.cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM)?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::LUT_RED0, LUT_RED0)?;
|
.cmd_with_data(spi, Command::LutRed0, LUT_RED0)?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::LUT_RED1, LUT_RED1)?;
|
.cmd_with_data(spi, Command::LutRed1, LUT_RED1)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -340,7 +340,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::RESOLUTION_SETTING)?;
|
self.command(spi, Command::ResolutionSetting)?;
|
||||||
|
|
||||||
self.send_data(spi, &[w as u8])?;
|
self.send_data(spi, &[w as u8])?;
|
||||||
self.send_data(spi, &[(h >> 8) as u8])?;
|
self.send_data(spi, &[(h >> 8) as u8])?;
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,32 @@
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
|
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
DATA_START_TRANSMISSION_2 = 0x13,
|
DataStartTransmission2 = 0x13,
|
||||||
|
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
LUT_WHITE_TO_WHITE = 0x21,
|
LutWhiteToWhite = 0x21,
|
||||||
LUT_BLACK_TO_WHITE = 0x22,
|
LutBlackToWhite = 0x22,
|
||||||
LUT_WHITE_TO_BLACK = 0x23,
|
LutWhiteToBlack = 0x23,
|
||||||
LUT_BLACK_TO_BLACK = 0x24,
|
LutBlackToBlack = 0x24,
|
||||||
|
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
TEMPERATURE_SENSOR_SELECTION = 0x41,
|
TemperatureSensorSelection = 0x41,
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
RESOLUTION_SETTING = 0x61,
|
ResolutionSetting = 0x61,
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
POWER_SAVING = 0xE3,
|
PowerSaving = 0xE3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
|
||||||
|
|
@ -57,20 +57,20 @@ where
|
||||||
self.interface.reset(delay, 2);
|
self.interface.reset(delay, 2);
|
||||||
|
|
||||||
// start the booster
|
// start the booster
|
||||||
self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?;
|
self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?;
|
||||||
|
|
||||||
// power on
|
// power on
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
delay.delay_ms(5);
|
delay.delay_ms(5);
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
// set the panel settings
|
// set the panel settings
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x0f, 0x0d])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0x0f, 0x0d])?;
|
||||||
|
|
||||||
// set resolution
|
// set resolution
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x77])?;
|
self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77])?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +97,7 @@ where
|
||||||
|
|
||||||
fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> {
|
fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, black)?;
|
self.cmd_with_data(spi, Command::DataStartTransmission1, black)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -108,7 +108,7 @@ where
|
||||||
chromatic: &[u8],
|
chromatic: &[u8],
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, chromatic)?;
|
self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -145,9 +145,9 @@ where
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xa5])?;
|
self.cmd_with_data(spi, Command::DeepSleep, &[0xa5])?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +182,7 @@ where
|
||||||
// Clear the chromatic layer
|
// Clear the chromatic layer
|
||||||
let color = self.color.get_byte_value();
|
let color = self.color.get_byte_value();
|
||||||
|
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_2)?;
|
self.command(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -202,7 +202,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -220,11 +220,11 @@ where
|
||||||
let color = DEFAULT_BACKGROUND_COLOR.get_byte_value();
|
let color = DEFAULT_BACKGROUND_COLOR.get_byte_value();
|
||||||
|
|
||||||
// Clear the black
|
// Clear the black
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_1)?;
|
self.command(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
||||||
|
|
||||||
// Clear the chromatic
|
// Clear the chromatic
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_2)?;
|
self.command(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -276,7 +276,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::RESOLUTION_SETTING)?;
|
self.command(spi, Command::ResolutionSetting)?;
|
||||||
|
|
||||||
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
// | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
|
||||||
// | HRES[7:3] | 0 | 0 | 0 |
|
// | HRES[7:3] | 0 | 0 | 0 |
|
||||||
|
|
|
||||||
|
|
@ -9,51 +9,50 @@ use bit_field::BitField;
|
||||||
///
|
///
|
||||||
/// For more infos about the addresses and what they are doing look into the pdfs
|
/// For more infos about the addresses and what they are doing look into the pdfs
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
DRIVER_OUTPUT_CONTROL = 0x01,
|
DriverOutputControl = 0x01,
|
||||||
GATE_DRIVING_VOLTAGE_CTRL = 0x03,
|
GateDrivingVoltageCtrl = 0x03,
|
||||||
SOURCE_DRIVING_VOLTAGE_CTRL = 0x04,
|
SourceDrivingVoltageCtrl = 0x04,
|
||||||
BOOSTER_SOFT_START_CONTROL = 0x0C,
|
BoosterSoftStartControl = 0x0C,
|
||||||
GATE_SCAN_START_POSITION = 0x0F,
|
GateScanStartPosition = 0x0F,
|
||||||
DEEP_SLEEP_MODE = 0x10,
|
DeepSleepMode = 0x10,
|
||||||
DATA_ENTRY_MODE_SETTING = 0x11,
|
DataEntryModeSetting = 0x11,
|
||||||
SW_RESET = 0x12,
|
SwReset = 0x12,
|
||||||
HV_READY_DETECTION = 0x14,
|
HvReadyDetection = 0x14,
|
||||||
VCI_DETECTION = 0x15,
|
VciDetection = 0x15,
|
||||||
TEMPERATURE_SENSOR_CONTROL_WRITE = 0x1A,
|
TemperatureSensorControlWrite = 0x1A,
|
||||||
TEMPERATURE_SENSOR_CONTROL_READ = 0x1B,
|
TemperatureSensorControlRead = 0x1B,
|
||||||
TEMPERATURE_SENSOR_EXT_CONTROL_WRITE = 0x1C,
|
TemperatureSensorExtControlWrite = 0x1C,
|
||||||
MASTER_ACTIVATION = 0x20,
|
MasterActivation = 0x20,
|
||||||
DISPLAY_UPDATE_CONTROL_1 = 0x21,
|
DisplayUpdateControl1 = 0x21,
|
||||||
DISPLAY_UPDATE_CONTROL_2 = 0x22,
|
DisplayUpdateControl2 = 0x22,
|
||||||
WRITE_RAM = 0x24,
|
WriteRam = 0x24,
|
||||||
WRITE_RAM_RED = 0x26,
|
WriteRamRed = 0x26,
|
||||||
READ_RAM = 0x27,
|
ReadRam = 0x27,
|
||||||
VCOM_SENSE = 0x28,
|
VcomSense = 0x28,
|
||||||
VCOM_SENSE_DURATION = 0x29,
|
VcomSenseDuration = 0x29,
|
||||||
PROGRAM_VCOM_OPT = 0x2A,
|
ProgramVcomOpt = 0x2A,
|
||||||
WRITE_VCOM_REGISTER = 0x2C,
|
WriteVcomRegister = 0x2C,
|
||||||
OTP_REGISTER_READ = 0x2D,
|
OtpRegisterRead = 0x2D,
|
||||||
STATUS_BIT_READ = 0x2F,
|
StatusBitRead = 0x2F,
|
||||||
PROGRAM_WS_OTP = 0x30,
|
ProgramWsOtp = 0x30,
|
||||||
LOAD_WS_OTP = 0x31,
|
LoadWsOtp = 0x31,
|
||||||
WRITE_LUT_REGISTER = 0x32,
|
WriteLutRegister = 0x32,
|
||||||
PROGRAM_OTP_SELECTION = 0x36,
|
ProgramOtpSelection = 0x36,
|
||||||
WRITE_OTP_SELECTION = 0x37,
|
WriteOtpSelection = 0x37,
|
||||||
SET_DUMMY_LINE_PERIOD = 0x3A,
|
SetDummyLinePeriod = 0x3A,
|
||||||
SET_GATE_LINE_WIDTH = 0x3B,
|
SetGateLineWidth = 0x3B,
|
||||||
BORDER_WAVEFORM_CONTROL = 0x3C,
|
BorderWaveformControl = 0x3C,
|
||||||
READ_RAM_OPTION = 0x41,
|
ReadRamOption = 0x41,
|
||||||
SET_RAM_X_ADDRESS_START_END_POSITION = 0x44,
|
SetRamXAddressStartEndPosition = 0x44,
|
||||||
SET_RAM_Y_ADDRESS_START_END_POSITION = 0x45,
|
SetRamYAddressStartEndPosition = 0x45,
|
||||||
AUTO_WRITE_RED_RAM_REGULAR_PATTERN = 0x46,
|
AutoWriteRedRamRegularPattern = 0x46,
|
||||||
AUTO_WRITE_BW_RAM_REGULAR_PATTERN = 0x47,
|
AutoWriteBwRamRegularPattern = 0x47,
|
||||||
SET_RAM_X_ADDRESS_COUNTER = 0x4E,
|
SetRamXAddressCounter = 0x4E,
|
||||||
SET_RAM_Y_ADDRESS_COUNTER = 0x4F,
|
SetRamYAddressCounter = 0x4F,
|
||||||
SET_ANALOG_BLOCK_CONTROL = 0x74,
|
SetAnalogBlockControl = 0x74,
|
||||||
SET_DIGITAL_BLOCK_CONTROL = 0x7E,
|
SetDigitalBlockControl = 0x7E,
|
||||||
|
|
||||||
NOP = 0x7F,
|
NOP = 0x7F,
|
||||||
}
|
}
|
||||||
|
|
@ -135,32 +134,30 @@ impl DisplayUpdateControl2 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub(crate) enum DataEntryModeIncr {
|
pub(crate) enum DataEntryModeIncr {
|
||||||
X_DECR_Y_DECR = 0x0,
|
XDecrYDecr = 0x0,
|
||||||
X_INCR_Y_DECR = 0x1,
|
XIncrYDecr = 0x1,
|
||||||
X_DECR_Y_INCR = 0x2,
|
XDecrYIncr = 0x2,
|
||||||
X_INCR_Y_INCR = 0x3,
|
XIncrYIncr = 0x3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub(crate) enum DataEntryModeDir {
|
pub(crate) enum DataEntryModeDir {
|
||||||
X_DIR = 0x0,
|
XDir = 0x0,
|
||||||
Y_DIR = 0x4,
|
YDir = 0x4,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum BorderWaveFormVBD {
|
pub(crate) enum BorderWaveFormVBD {
|
||||||
GS = 0x0,
|
GS = 0x0,
|
||||||
FIX_LEVEL = 0x1,
|
FixLevel = 0x1,
|
||||||
VCOM = 0x2,
|
VCOM = 0x2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum BorderWaveFormFixLevel {
|
pub(crate) enum BorderWaveFormFixLevel {
|
||||||
VSS = 0x0,
|
VSS = 0x0,
|
||||||
|
|
@ -170,7 +167,6 @@ pub(crate) enum BorderWaveFormFixLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum BorderWaveFormGS {
|
pub(crate) enum BorderWaveFormGS {
|
||||||
LUT0 = 0x0,
|
LUT0 = 0x0,
|
||||||
|
|
@ -194,17 +190,16 @@ impl BorderWaveForm {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum DeepSleepMode {
|
pub enum DeepSleepMode {
|
||||||
// Sleeps and keeps access to RAM and controller
|
// Sleeps and keeps access to RAM and controller
|
||||||
NORMAL = 0x00,
|
Normal = 0x00,
|
||||||
|
|
||||||
// Sleeps without access to RAM/controller but keeps RAM content
|
// Sleeps without access to RAM/controller but keeps RAM content
|
||||||
MODE_1 = 0x01,
|
Mode1 = 0x01,
|
||||||
|
|
||||||
// Same as MODE_1 but RAM content is not kept
|
// Same as MODE_1 but RAM content is not kept
|
||||||
MODE_2 = 0x11,
|
Mode2 = 0x11,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct GateDrivingVoltage(pub u8);
|
pub(crate) struct GateDrivingVoltage(pub u8);
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ where
|
||||||
self.set_lut(spi, Some(self.refresh))?;
|
self.set_lut(spi, Some(self.refresh))?;
|
||||||
|
|
||||||
// Python code does this, not sure why
|
// Python code does this, not sure why
|
||||||
// self.cmd_with_data(spi, Command::WRITE_OTP_SELECTION, &[0, 0, 0, 0, 0x40, 0, 0])?;
|
// self.cmd_with_data(spi, Command::WriteOtpSelection, &[0, 0, 0, 0, 0x40, 0, 0])?;
|
||||||
|
|
||||||
// During partial update, clock/analog are not disabled between 2
|
// During partial update, clock/analog are not disabled between 2
|
||||||
// updates.
|
// updates.
|
||||||
|
|
@ -88,7 +88,7 @@ where
|
||||||
spi,
|
spi,
|
||||||
DisplayUpdateControl2::new().enable_analog().enable_clock(),
|
DisplayUpdateControl2::new().enable_analog().enable_clock(),
|
||||||
)?;
|
)?;
|
||||||
self.command(spi, Command::MASTER_ACTIVATION)?;
|
self.command(spi, Command::MasterActivation)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
self.set_border_waveform(
|
self.set_border_waveform(
|
||||||
|
|
@ -101,7 +101,7 @@ where
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::SW_RESET)?;
|
self.command(spi, Command::SwReset)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
self.set_driver_output(
|
self.set_driver_output(
|
||||||
|
|
@ -118,11 +118,7 @@ where
|
||||||
self.set_dummy_line_period(spi, 0x30)?;
|
self.set_dummy_line_period(spi, 0x30)?;
|
||||||
self.set_gate_scan_start_position(spi, 0)?;
|
self.set_gate_scan_start_position(spi, 0)?;
|
||||||
|
|
||||||
self.set_data_entry_mode(
|
self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir)?;
|
||||||
spi,
|
|
||||||
DataEntryModeIncr::X_INCR_Y_INCR,
|
|
||||||
DataEntryModeDir::X_DIR,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// Use simple X/Y auto increase
|
// Use simple X/Y auto increase
|
||||||
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
||||||
|
|
@ -177,7 +173,7 @@ where
|
||||||
) -> Result<Self, SPI::Error> {
|
) -> Result<Self, SPI::Error> {
|
||||||
let mut epd = EPD2in13 {
|
let mut epd = EPD2in13 {
|
||||||
interface: DisplayInterface::new(cs, busy, dc, rst),
|
interface: DisplayInterface::new(cs, busy, dc, rst),
|
||||||
sleep_mode: DeepSleepMode::MODE_1,
|
sleep_mode: DeepSleepMode::Mode1,
|
||||||
background_color: DEFAULT_BACKGROUND_COLOR,
|
background_color: DEFAULT_BACKGROUND_COLOR,
|
||||||
refresh: RefreshLUT::FULL,
|
refresh: RefreshLUT::FULL,
|
||||||
};
|
};
|
||||||
|
|
@ -206,7 +202,7 @@ where
|
||||||
.disable_analog()
|
.disable_analog()
|
||||||
.disable_clock(),
|
.disable_clock(),
|
||||||
)?;
|
)?;
|
||||||
self.command(spi, Command::MASTER_ACTIVATION)?;
|
self.command(spi, Command::MasterActivation)?;
|
||||||
|
|
||||||
self.set_sleep_mode(spi, self.sleep_mode)?;
|
self.set_sleep_mode(spi, self.sleep_mode)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -217,14 +213,14 @@ where
|
||||||
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
||||||
self.set_ram_address_counters(spi, 0, 0)?;
|
self.set_ram_address_counters(spi, 0, 0)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;
|
self.cmd_with_data(spi, Command::WriteRam, buffer)?;
|
||||||
|
|
||||||
if self.refresh == RefreshLUT::FULL {
|
if self.refresh == RefreshLUT::FULL {
|
||||||
// Always keep the base buffer equal to current if not doing partial refresh.
|
// Always keep the base buffer equal to current if not doing partial refresh.
|
||||||
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
||||||
self.set_ram_address_counters(spi, 0, 0)?;
|
self.set_ram_address_counters(spi, 0, 0)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?;
|
self.cmd_with_data(spi, Command::WriteRamRed, buffer)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -254,14 +250,14 @@ where
|
||||||
self.set_ram_area(spi, x, y, x + width, y + height)?;
|
self.set_ram_area(spi, x, y, x + width, y + height)?;
|
||||||
self.set_ram_address_counters(spi, x, y)?;
|
self.set_ram_address_counters(spi, x, y)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;
|
self.cmd_with_data(spi, Command::WriteRam, buffer)?;
|
||||||
|
|
||||||
if self.refresh == RefreshLUT::FULL {
|
if self.refresh == RefreshLUT::FULL {
|
||||||
// Always keep the base buffer equals to current if not doing partial refresh.
|
// Always keep the base buffer equals to current if not doing partial refresh.
|
||||||
self.set_ram_area(spi, x, y, x + width, y + height)?;
|
self.set_ram_area(spi, x, y, x + width, y + height)?;
|
||||||
self.set_ram_address_counters(spi, x, y)?;
|
self.set_ram_address_counters(spi, x, y)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?;
|
self.cmd_with_data(spi, Command::WriteRamRed, buffer)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -283,7 +279,7 @@ where
|
||||||
} else {
|
} else {
|
||||||
self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display())?;
|
self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display())?;
|
||||||
}
|
}
|
||||||
self.command(spi, Command::MASTER_ACTIVATION)?;
|
self.command(spi, Command::MasterActivation)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -305,7 +301,7 @@ where
|
||||||
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
||||||
self.set_ram_address_counters(spi, 0, 0)?;
|
self.set_ram_address_counters(spi, 0, 0)?;
|
||||||
|
|
||||||
self.command(spi, Command::WRITE_RAM)?;
|
self.command(spi, Command::WriteRam)?;
|
||||||
self.interface.data_x_times(
|
self.interface.data_x_times(
|
||||||
spi,
|
spi,
|
||||||
color,
|
color,
|
||||||
|
|
@ -317,7 +313,7 @@ where
|
||||||
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
||||||
self.set_ram_address_counters(spi, 0, 0)?;
|
self.set_ram_address_counters(spi, 0, 0)?;
|
||||||
|
|
||||||
self.command(spi, Command::WRITE_RAM_RED)?;
|
self.command(spi, Command::WriteRamRed)?;
|
||||||
self.interface.data_x_times(
|
self.interface.data_x_times(
|
||||||
spi,
|
spi,
|
||||||
color,
|
color,
|
||||||
|
|
@ -353,7 +349,7 @@ where
|
||||||
Some(RefreshLUT::QUICK) => &LUT_PARTIAL_UPDATE,
|
Some(RefreshLUT::QUICK) => &LUT_PARTIAL_UPDATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)
|
self.cmd_with_data(spi, Command::WriteLutRegister, buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_busy(&self) -> bool {
|
fn is_busy(&self) -> bool {
|
||||||
|
|
@ -380,7 +376,7 @@ where
|
||||||
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
|
||||||
self.set_ram_address_counters(spi, 0, 0)?;
|
self.set_ram_address_counters(spi, 0, 0)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?;
|
self.cmd_with_data(spi, Command::WriteRamRed, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -412,7 +408,7 @@ where
|
||||||
assert!(start <= 295);
|
assert!(start <= 295);
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::GATE_SCAN_START_POSITION,
|
Command::GateScanStartPosition,
|
||||||
&[(start & 0xFF) as u8, ((start >> 8) & 0x1) as u8],
|
&[(start & 0xFF) as u8, ((start >> 8) & 0x1) as u8],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -424,13 +420,13 @@ where
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::BORDER_WAVEFORM_CONTROL,
|
Command::BorderWaveformControl,
|
||||||
&[borderwaveform.to_u8()],
|
&[borderwaveform.to_u8()],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_vcom_register(&mut self, spi: &mut SPI, vcom: VCOM) -> Result<(), SPI::Error> {
|
fn set_vcom_register(&mut self, spi: &mut SPI, vcom: VCOM) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[vcom.0])
|
self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_gate_driving_voltage(
|
fn set_gate_driving_voltage(
|
||||||
|
|
@ -438,7 +434,7 @@ where
|
||||||
spi: &mut SPI,
|
spi: &mut SPI,
|
||||||
voltage: GateDrivingVoltage,
|
voltage: GateDrivingVoltage,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::GATE_DRIVING_VOLTAGE_CTRL, &[voltage.0])
|
self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[voltage.0])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_dummy_line_period(
|
fn set_dummy_line_period(
|
||||||
|
|
@ -447,11 +443,11 @@ where
|
||||||
number_of_lines: u8,
|
number_of_lines: u8,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
assert!(number_of_lines <= 127);
|
assert!(number_of_lines <= 127);
|
||||||
self.cmd_with_data(spi, Command::SET_DUMMY_LINE_PERIOD, &[number_of_lines])
|
self.cmd_with_data(spi, Command::SetDummyLinePeriod, &[number_of_lines])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> {
|
fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::SET_GATE_LINE_WIDTH, &[width & 0x0F])
|
self.cmd_with_data(spi, Command::SetGateLineWidth, &[width & 0x0F])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the source driving voltage value
|
/// Sets the source driving voltage value
|
||||||
|
|
@ -464,7 +460,7 @@ where
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SOURCE_DRIVING_VOLTAGE_CTRL,
|
Command::SourceDrivingVoltageCtrl,
|
||||||
&[vsh1.0, vsh2.0, vsl.0],
|
&[vsh1.0, vsh2.0, vsl.0],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -476,16 +472,16 @@ where
|
||||||
spi: &mut SPI,
|
spi: &mut SPI,
|
||||||
value: DisplayUpdateControl2,
|
value: DisplayUpdateControl2,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[value.0])
|
self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[value.0])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Triggers the deep sleep mode
|
/// Triggers the deep sleep mode
|
||||||
fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> {
|
fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[mode as u8])
|
self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> {
|
fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::DRIVER_OUTPUT_CONTROL, &output.to_bytes())
|
self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the data entry mode (ie. how X and Y positions changes when writing
|
/// Sets the data entry mode (ie. how X and Y positions changes when writing
|
||||||
|
|
@ -497,7 +493,7 @@ where
|
||||||
counter_direction: DataEntryModeDir,
|
counter_direction: DataEntryModeDir,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
let mode = counter_incr_mode as u8 | counter_direction as u8;
|
let mode = counter_incr_mode as u8 | counter_direction as u8;
|
||||||
self.cmd_with_data(spi, Command::DATA_ENTRY_MODE_SETTING, &[mode])
|
self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets both X and Y pixels ranges
|
/// Sets both X and Y pixels ranges
|
||||||
|
|
@ -511,13 +507,13 @@ where
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_X_ADDRESS_START_END_POSITION,
|
Command::SetRamXAddressStartEndPosition,
|
||||||
&[(start_x >> 3) as u8, (end_x >> 3) as u8],
|
&[(start_x >> 3) as u8, (end_x >> 3) as u8],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_Y_ADDRESS_START_END_POSITION,
|
Command::SetRamYAddressStartEndPosition,
|
||||||
&[
|
&[
|
||||||
start_y as u8,
|
start_y as u8,
|
||||||
(start_y >> 8) as u8,
|
(start_y >> 8) as u8,
|
||||||
|
|
@ -535,11 +531,11 @@ where
|
||||||
y: u32,
|
y: u32,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?;
|
self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?;
|
||||||
|
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_Y_ADDRESS_COUNTER,
|
Command::SetRamYAddressCounter,
|
||||||
&[y as u8, (y >> 8) as u8],
|
&[y as u8, (y >> 8) as u8],
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -5,117 +5,116 @@ use crate::traits;
|
||||||
///
|
///
|
||||||
/// More information can be found in the [specification](https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf)
|
/// More information can be found in the [specification](https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf)
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset
|
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
/// Selecting internal and external power
|
/// Selecting internal and external power
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
/// Setting Power OFF sequence
|
/// Setting Power OFF sequence
|
||||||
POWER_OFF_SEQUENCE_SETTING = 0x03,
|
PowerOffSequenceSetting = 0x03,
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
/// This command enables the internal bandgap, which will be cleared by the next POF.
|
/// This command enables the internal bandgap, which will be cleared by the next POF.
|
||||||
POWER_ON_MEASURE = 0x05,
|
PowerOnMeasure = 0x05,
|
||||||
/// Starting data transmission
|
/// Starting data transmission
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// self.send_data(&[0x07, 0x07, 0x17])?;
|
/// self.send_data(&[0x07, 0x07, 0x17])?;
|
||||||
/// ```
|
/// ```
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
/// After this command is transmitted, the chip would enter the deep-sleep mode to save power.
|
/// After this command is transmitted, the chip would enter the deep-sleep mode to save power.
|
||||||
///
|
///
|
||||||
/// The deep sleep mode would return to standby by hardware reset.
|
/// The deep sleep mode would return to standby by hardware reset.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
||||||
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
||||||
///
|
///
|
||||||
/// - In B/W mode, this command writes “OLD” data to SRAM.
|
/// - In B/W mode, this command writes “OLD” data to SRAM.
|
||||||
/// - In B/W/Red mode, this command writes “B/W” data to SRAM.
|
/// - In B/W/Red mode, this command writes “B/W” data to SRAM.
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
/// Stopping data transmission
|
/// Stopping data transmission
|
||||||
DATA_STOP = 0x11,
|
DataStop = 0x11,
|
||||||
/// After this command is issued, driver will refresh display (data/VCOM) according to SRAM data and LUT.
|
/// After this command is issued, driver will refresh display (data/VCOM) according to SRAM data and LUT.
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
||||||
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
||||||
/// - In B/W mode, this command writes “NEW” data to SRAM.
|
/// - In B/W mode, this command writes “NEW” data to SRAM.
|
||||||
/// - In B/W/Red mode, this command writes “RED” data to SRAM.
|
/// - In B/W/Red mode, this command writes “RED” data to SRAM.
|
||||||
DATA_START_TRANSMISSION_2 = 0x13,
|
DataStartTransmission2 = 0x13,
|
||||||
/// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission
|
/// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission
|
||||||
/// complete, user must send command DSP (Data transmission Stop). Then chip will start to send data/VCOM for panel.
|
/// complete, user must send command DSP (Data transmission Stop). Then chip will start to send data/VCOM for panel.
|
||||||
///
|
///
|
||||||
/// - In B/W mode, this command writes “OLD” data to SRAM.
|
/// - In B/W mode, this command writes “OLD” data to SRAM.
|
||||||
/// - In B/W/Red mode, this command writes “B/W” data to SRAM.
|
/// - In B/W/Red mode, this command writes “B/W” data to SRAM.
|
||||||
PARTIAL_DATA_START_TRANSMISSION_1 = 0x14,
|
PartialDataStartTransmission1 = 0x14,
|
||||||
/// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission
|
/// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission
|
||||||
/// complete, user must send command DSP (Data transmission Stop). Then chip will start to send data/VCOM for panel.
|
/// complete, user must send command DSP (Data transmission Stop). Then chip will start to send data/VCOM for panel.
|
||||||
///
|
///
|
||||||
/// - In B/W mode, this command writes “NEW” data to SRAM.
|
/// - In B/W mode, this command writes “NEW” data to SRAM.
|
||||||
/// - In B/W/Red mode, this command writes “RED” data to SRAM.
|
/// - In B/W/Red mode, this command writes “RED” data to SRAM.
|
||||||
PARTIAL_DATA_START_TRANSMISSION_2 = 0x15,
|
PartialDataStartTransmission2 = 0x15,
|
||||||
/// While user sent this command, driver will refresh display (data/VCOM) base on SRAM data and LUT.
|
/// While user sent this command, driver will refresh display (data/VCOM) base on SRAM data and LUT.
|
||||||
///
|
///
|
||||||
/// Only the area (X,Y, W, L) would update, the others pixel output would follow VCOM LUT
|
/// Only the area (X,Y, W, L) would update, the others pixel output would follow VCOM LUT
|
||||||
PARTIAL_DISPLAY_REFRESH = 0x16,
|
PartialDisplayRefresh = 0x16,
|
||||||
/// This command builds the Look-up table for VCOM
|
/// This command builds the Look-up table for VCOM
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
LUT_WHITE_TO_WHITE = 0x21,
|
LutWhiteToWhite = 0x21,
|
||||||
LUT_BLACK_TO_WHITE = 0x22,
|
LutBlackToWhite = 0x22,
|
||||||
LUT_WHITE_TO_BLACK = 0x23,
|
LutWhiteToBlack = 0x23,
|
||||||
LUT_BLACK_TO_BLACK = 0x24,
|
LutBlackToBlack = 0x24,
|
||||||
/// The command controls the PLL clock frequency.
|
/// The command controls the PLL clock frequency.
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
/// This command reads the temperature sensed by the temperature sensor.
|
/// This command reads the temperature sensed by the temperature sensor.
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
/// This command selects Internal or External temperature sensor.
|
/// This command selects Internal or External temperature sensor.
|
||||||
TEMPERATURE_SENSOR_CALIBRATION = 0x41,
|
TemperatureSensorCalibration = 0x41,
|
||||||
/// Write External Temperature Sensor
|
/// Write External Temperature Sensor
|
||||||
TEMPERATURE_SENSOR_WRITE = 0x42,
|
TemperatureSensorWrite = 0x42,
|
||||||
/// Read External Temperature Sensor
|
/// Read External Temperature Sensor
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
TEMPERATURE_SENSOR_READ = 0x43,
|
TemperatureSensorRead = 0x43,
|
||||||
/// This command indicates the interval of Vcom and data output. When setting the vertical back porch, the total blanking will be kept (20 Hsync)
|
/// This command indicates the interval of Vcom and data output. When setting the vertical back porch, the total blanking will be kept (20 Hsync)
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
/// This command indicates the input power condition. Host can read this flag to learn the battery condition.
|
/// This command indicates the input power condition. Host can read this flag to learn the battery condition.
|
||||||
LOW_POWER_DETECTION = 0x51,
|
LowPowerDetection = 0x51,
|
||||||
/// This command defines non-overlap period of Gate and Source.
|
/// This command defines non-overlap period of Gate and Source.
|
||||||
TCON_SETTING = 0x60,
|
TconSetting = 0x60,
|
||||||
/// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR).
|
/// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR).
|
||||||
RESOLUTION_SETTING = 0x61,
|
ResolutionSetting = 0x61,
|
||||||
SOURCE_AND_GATE_SETTING = 0x62,
|
SourceAndGateSetting = 0x62,
|
||||||
/// This command reads the IC status.
|
/// This command reads the IC status.
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
GET_STATUS = 0x71,
|
GetStatus = 0x71,
|
||||||
/// Automatically measure VCOM. This command reads the IC status
|
/// Automatically measure VCOM. This command reads the IC status
|
||||||
AUTO_MEASUREMENT_VCOM = 0x80,
|
AutoMeasurementVcom = 0x80,
|
||||||
/// This command gets the VCOM value
|
/// This command gets the VCOM value
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
READ_VCOM_VALUE = 0x81,
|
ReadVcomValue = 0x81,
|
||||||
/// This command sets VCOM_DC value.
|
/// This command sets VCOM_DC value.
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
/// After this command is issued, the chip would enter the program mode.
|
/// After this command is issued, the chip would enter the program mode.
|
||||||
///
|
///
|
||||||
/// After the programming procedure completed, a hardware reset is necessary for leaving program mode.
|
/// After the programming procedure completed, a hardware reset is necessary for leaving program mode.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
PROGRAM_MODE = 0xA0,
|
ProgramMode = 0xA0,
|
||||||
/// After this command is issued, the chip would enter the program mode.
|
/// After this command is issued, the chip would enter the program mode.
|
||||||
ACTIVE_PROGRAMMING = 0xA1,
|
ActiveProgramming = 0xA1,
|
||||||
/// The command is used for reading the content of OTP for checking the data of programming.
|
/// The command is used for reading the content of OTP for checking the data of programming.
|
||||||
///
|
///
|
||||||
/// The value of (n) is depending on the amount of programmed data, tha max address = 0xFFF.
|
/// The value of (n) is depending on the amount of programmed data, tha max address = 0xFFF.
|
||||||
READ_OTP = 0xA2,
|
ReadOtp = 0xA2,
|
||||||
/// Not shown in commands table, but used in init sequence
|
/// Not shown in commands table, but used in init sequence
|
||||||
POWER_OPTIMIZATION = 0xf8,
|
PowerOptimization = 0xf8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
@ -132,7 +131,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
assert_eq!(Command::PANEL_SETTING.address(), 0x00);
|
assert_eq!(Command::PanelSetting.address(), 0x00);
|
||||||
assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12);
|
assert_eq!(Command::DisplayRefresh.address(), 0x12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,51 +60,51 @@ where
|
||||||
self.interface.reset(delay, 2);
|
self.interface.reset(delay, 2);
|
||||||
|
|
||||||
// power on
|
// power on
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
delay.delay_ms(5);
|
delay.delay_ms(5);
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
// set panel settings, 0xbf is bw, 0xaf is multi-color
|
// set panel settings, 0xbf is bw, 0xaf is multi-color
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::PANEL_SETTING, &[0xaf])?;
|
.cmd_with_data(spi, Command::PanelSetting, &[0xaf])?;
|
||||||
|
|
||||||
// pll control
|
// pll control
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3a])?;
|
.cmd_with_data(spi, Command::PllControl, &[0x3a])?;
|
||||||
|
|
||||||
// set the power settings
|
// set the power settings
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::POWER_SETTING,
|
Command::PowerSetting,
|
||||||
&[0x03, 0x00, 0x2b, 0x2b, 0x09],
|
&[0x03, 0x00, 0x2b, 0x2b, 0x09],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// start the booster
|
// start the booster
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x07, 0x07, 0x17])?;
|
.cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17])?;
|
||||||
|
|
||||||
// power optimization
|
// power optimization
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x60, 0xa5])?;
|
.cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5])?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x89, 0xa5])?;
|
.cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5])?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x90, 0x00])?;
|
.cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00])?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x93, 0x2a])?;
|
.cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a])?;
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x73, 0x41])?;
|
.cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41])?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?;
|
.cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x87])?;
|
.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87])?;
|
||||||
|
|
||||||
self.set_lut(spi, None)?;
|
self.set_lut(spi, None)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::PARTIAL_DISPLAY_REFRESH, &[0x00])?;
|
.cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00])?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -150,27 +150,27 @@ where
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0xf7])?;
|
.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?;
|
||||||
|
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?;
|
.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
self.send_buffer_helper(spi, buffer)?;
|
self.send_buffer_helper(spi, buffer)?;
|
||||||
|
|
||||||
// Clear chromatic layer since we won't be using it here
|
// Clear chromatic layer since we won't be using it here
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?;
|
.data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::DATA_STOP)?;
|
self.interface.cmd(spi, Command::DataStop)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +184,7 @@ where
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::PartialDataStartTransmission1)?;
|
||||||
|
|
||||||
self.send_data(spi, &[(x >> 8) as u8])?;
|
self.send_data(spi, &[(x >> 8) as u8])?;
|
||||||
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
||||||
|
|
@ -198,18 +198,18 @@ where
|
||||||
|
|
||||||
self.send_buffer_helper(spi, buffer)?;
|
self.send_buffer_helper(spi, buffer)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::DATA_STOP)
|
self.interface.cmd(spi, Command::DataStop)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.update_frame(spi, buffer)?;
|
self.update_frame(spi, buffer)?;
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,17 +218,17 @@ where
|
||||||
|
|
||||||
let color_value = self.color.get_byte_value();
|
let color_value = self.color.get_byte_value();
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?;
|
.data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::DATA_STOP)?;
|
self.interface.cmd(spi, Command::DataStop)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?;
|
.data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?;
|
||||||
self.interface.cmd(spi, Command::DATA_STOP)?;
|
self.interface.cmd(spi, Command::DataStop)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -254,11 +254,11 @@ where
|
||||||
_refresh_rate: Option<RefreshLUT>,
|
_refresh_rate: Option<RefreshLUT>,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::LUT_FOR_VCOM, &LUT_VCOM_DC)?;
|
self.cmd_with_data(spi, Command::LutForVcom, &LUT_VCOM_DC)?;
|
||||||
self.cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, &LUT_WW)?;
|
self.cmd_with_data(spi, Command::LutWhiteToWhite, &LUT_WW)?;
|
||||||
self.cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, &LUT_BW)?;
|
self.cmd_with_data(spi, Command::LutBlackToWhite, &LUT_BW)?;
|
||||||
self.cmd_with_data(spi, Command::LUT_WHITE_TO_BLACK, &LUT_WB)?;
|
self.cmd_with_data(spi, Command::LutWhiteToBlack, &LUT_WB)?;
|
||||||
self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, &LUT_BB)?;
|
self.cmd_with_data(spi, Command::LutBlackToBlack, &LUT_BB)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,11 +295,11 @@ where
|
||||||
achromatic: &[u8],
|
achromatic: &[u8],
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
self.send_buffer_helper(spi, achromatic)?;
|
self.send_buffer_helper(spi, achromatic)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::DATA_STOP)
|
self.interface.cmd(spi, Command::DataStop)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update only chromatic data of the display.
|
/// Update only chromatic data of the display.
|
||||||
|
|
@ -311,11 +311,11 @@ where
|
||||||
chromatic: &[u8],
|
chromatic: &[u8],
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
|
|
||||||
self.send_buffer_helper(spi, chromatic)?;
|
self.send_buffer_helper(spi, chromatic)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::DATA_STOP)?;
|
self.interface.cmd(spi, Command::DataStop)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -369,7 +369,7 @@ where
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.command(spi, Command::PARTIAL_DISPLAY_REFRESH)?;
|
self.command(spi, Command::PartialDisplayRefresh)?;
|
||||||
self.send_data(spi, &[(x >> 8) as u8])?;
|
self.send_data(spi, &[(x >> 8) as u8])?;
|
||||||
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
||||||
self.send_data(spi, &[(y >> 8) as u8])?;
|
self.send_data(spi, &[(y >> 8) as u8])?;
|
||||||
|
|
@ -393,7 +393,7 @@ where
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::PartialDataStartTransmission1)?;
|
||||||
self.send_data(spi, &[(x >> 8) as u8])?;
|
self.send_data(spi, &[(x >> 8) as u8])?;
|
||||||
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
||||||
self.send_data(spi, &[(y >> 8) as u8])?;
|
self.send_data(spi, &[(y >> 8) as u8])?;
|
||||||
|
|
@ -423,7 +423,7 @@ where
|
||||||
height: u32,
|
height: u32,
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::PartialDataStartTransmission2)?;
|
||||||
self.send_data(spi, &[(x >> 8) as u8])?;
|
self.send_data(spi, &[(x >> 8) as u8])?;
|
||||||
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
self.send_data(spi, &[(x & 0xf8) as u8])?;
|
||||||
self.send_data(spi, &[(y >> 8) as u8])?;
|
self.send_data(spi, &[(y >> 8) as u8])?;
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ where
|
||||||
// 0.. B[2:0]
|
// 0.. B[2:0]
|
||||||
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
|
// Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?)
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DRIVER_OUTPUT_CONTROL, &[0x27, 0x01, 0x00])?;
|
.cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?;
|
||||||
|
|
||||||
// 3 Databytes: (and default values from datasheet and arduino)
|
// 3 Databytes: (and default values from datasheet and arduino)
|
||||||
// 1 .. A[6:0] = 0xCF | 0xD7
|
// 1 .. A[6:0] = 0xCF | 0xD7
|
||||||
|
|
@ -113,26 +113,26 @@ where
|
||||||
//TODO: test
|
//TODO: test
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::BOOSTER_SOFT_START_CONTROL,
|
Command::BoosterSoftStartControl,
|
||||||
&[0xD7, 0xD6, 0x9D],
|
&[0xD7, 0xD6, 0x9D],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// One Databyte with value 0xA8 for 7V VCOM
|
// One Databyte with value 0xA8 for 7V VCOM
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[0xA8])?;
|
.cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8])?;
|
||||||
|
|
||||||
// One Databyte with default value 0x1A for 4 dummy lines per gate
|
// One Databyte with default value 0x1A for 4 dummy lines per gate
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::SET_DUMMY_LINE_PERIOD, &[0x1A])?;
|
.cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A])?;
|
||||||
|
|
||||||
// One Databyte with default value 0x08 for 2us per line
|
// One Databyte with default value 0x08 for 2us per line
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::SET_GATE_LINE_WIDTH, &[0x08])?;
|
.cmd_with_data(spi, Command::SetGateLineWidth, &[0x08])?;
|
||||||
|
|
||||||
// One Databyte with default value 0x03
|
// One Databyte with default value 0x03
|
||||||
// -> address: x increment, y increment, address counter is updated in x direction
|
// -> address: x increment, y increment, address counter is updated in x direction
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DATA_ENTRY_MODE_SETTING, &[0x03])?;
|
.cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?;
|
||||||
|
|
||||||
self.set_lut(spi, None)
|
self.set_lut(spi, None)
|
||||||
}
|
}
|
||||||
|
|
@ -182,7 +182,7 @@ where
|
||||||
// 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode
|
// 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode
|
||||||
//TODO: is 0x00 needed here? (see also epd1in54)
|
//TODO: is 0x00 needed here? (see also epd1in54)
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x00])?;
|
.cmd_with_data(spi, Command::DeepSleepMode, &[0x00])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,7 +201,7 @@ where
|
||||||
self.use_full_frame(spi)?;
|
self.use_full_frame(spi)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;
|
.cmd_with_data(spi, Command::WriteRam, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ where
|
||||||
self.set_ram_counter(spi, x, y)?;
|
self.set_ram_counter(spi, x, y)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_RAM, buffer)?;
|
.cmd_with_data(spi, Command::WriteRam, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,9 +229,9 @@ where
|
||||||
// enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version)
|
// enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version)
|
||||||
//TODO: test control_1 or control_2 with default value 0xFF (from the datasheet)
|
//TODO: test control_1 or control_2 with default value 0xFF (from the datasheet)
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xC4])?;
|
.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::MASTER_ACTIVATION)?;
|
self.interface.cmd(spi, Command::MasterActivation)?;
|
||||||
// MASTER Activation should not be interupted to avoid currption of panel images
|
// MASTER Activation should not be interupted to avoid currption of panel images
|
||||||
// therefore a terminate command is send
|
// therefore a terminate command is send
|
||||||
self.interface.cmd(spi, Command::NOP)?;
|
self.interface.cmd(spi, Command::NOP)?;
|
||||||
|
|
@ -251,7 +251,7 @@ where
|
||||||
// clear the ram with the background color
|
// clear the ram with the background color
|
||||||
let color = self.background_color.get_byte_value();
|
let color = self.background_color.get_byte_value();
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::WRITE_RAM)?;
|
self.interface.cmd(spi, Command::WriteRam)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color, WIDTH / 8 * HEIGHT)?;
|
.data_x_times(spi, color, WIDTH / 8 * HEIGHT)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -319,14 +319,14 @@ where
|
||||||
// aren't relevant
|
// aren't relevant
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_X_ADDRESS_START_END_POSITION,
|
Command::SetRamXAddressStartEndPosition,
|
||||||
&[(start_x >> 3) as u8, (end_x >> 3) as u8],
|
&[(start_x >> 3) as u8, (end_x >> 3) as u8],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// 2 Databytes: A[7:0] & 0..A[8] for each - start and end
|
// 2 Databytes: A[7:0] & 0..A[8] for each - start and end
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_Y_ADDRESS_START_END_POSITION,
|
Command::SetRamYAddressStartEndPosition,
|
||||||
&[
|
&[
|
||||||
start_y as u8,
|
start_y as u8,
|
||||||
(start_y >> 8) as u8,
|
(start_y >> 8) as u8,
|
||||||
|
|
@ -341,12 +341,12 @@ where
|
||||||
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
|
// x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram
|
||||||
// aren't relevant
|
// aren't relevant
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?;
|
.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?;
|
||||||
|
|
||||||
// 2 Databytes: A[7:0] & 0..A[8]
|
// 2 Databytes: A[7:0] & 0..A[8]
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::SET_RAM_Y_ADDRESS_COUNTER,
|
Command::SetRamYAddressCounter,
|
||||||
&[y as u8, (y >> 8) as u8],
|
&[y as u8, (y >> 8) as u8],
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -357,7 +357,7 @@ where
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
assert!(buffer.len() == 30);
|
assert!(buffer.len() == 30);
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)?;
|
.cmd_with_data(spi, Command::WriteLutRegister, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,33 +2,32 @@
|
||||||
use crate::traits;
|
use crate::traits;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
|
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
DATA_START_TRANSMISSION_2 = 0x13,
|
DataStartTransmission2 = 0x13,
|
||||||
|
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
LUT_WHITE_TO_WHITE = 0x21,
|
LutWhiteToWhite = 0x21,
|
||||||
LUT_BLACK_TO_WHITE = 0x22,
|
LutBlackToWhite = 0x22,
|
||||||
LUT_WHITE_TO_BLACK = 0x23,
|
LutWhiteToBlack = 0x23,
|
||||||
LUT_BLACK_TO_BLACK = 0x24,
|
LutBlackToBlack = 0x24,
|
||||||
|
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
TEMPERATURE_SENSOR_SELECTION = 0x41,
|
TemperatureSensorSelection = 0x41,
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
RESOLUTION_SETTING = 0x61,
|
ResolutionSetting = 0x61,
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
POWER_SAVING = 0xE3,
|
PowerSaving = 0xE3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
|
||||||
|
|
@ -115,26 +115,26 @@ where
|
||||||
|
|
||||||
// start the booster
|
// start the booster
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?;
|
.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?;
|
||||||
|
|
||||||
// power on
|
// power on
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
delay.delay_ms(5);
|
delay.delay_ms(5);
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
// set the panel settings
|
// set the panel settings
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x8F])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0x8F])?;
|
||||||
|
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::VCOM_AND_DATA_INTERVAL_SETTING,
|
Command::VcomAndDataIntervalSetting,
|
||||||
&[WHITE_BORDER | VCOM_DATA_INTERVAL],
|
&[WHITE_BORDER | VCOM_DATA_INTERVAL],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// set resolution
|
// set resolution
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x0A])?;
|
self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A])?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
|
|
@ -166,7 +166,7 @@ where
|
||||||
/// Finish by calling `update_chromatic_frame`.
|
/// Finish by calling `update_chromatic_frame`.
|
||||||
fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> {
|
fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface.data(spi, black)?;
|
self.interface.data(spi, black)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +180,7 @@ where
|
||||||
chromatic: &[u8],
|
chromatic: &[u8],
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data(spi, chromatic)?;
|
self.interface.data(spi, chromatic)?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
@ -220,15 +220,15 @@ where
|
||||||
// Section 8.2 from datasheet
|
// Section 8.2 from datasheet
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::VCOM_AND_DATA_INTERVAL_SETTING,
|
Command::VcomAndDataIntervalSetting,
|
||||||
&[FLOATING_BORDER | VCOM_DATA_INTERVAL],
|
&[FLOATING_BORDER | VCOM_DATA_INTERVAL],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
// The example STM code from Github has a wait after POWER_OFF
|
// The example STM code from Github has a wait after PowerOff
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?;
|
self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -259,7 +259,7 @@ where
|
||||||
|
|
||||||
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
self.interface.data(spi, &buffer)?;
|
self.interface.data(spi, &buffer)?;
|
||||||
|
|
||||||
|
|
@ -267,7 +267,7 @@ where
|
||||||
let color = self.color.get_byte_value();
|
let color = self.color.get_byte_value();
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
@ -288,7 +288,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -307,13 +307,13 @@ where
|
||||||
|
|
||||||
// Clear the black
|
// Clear the black
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
||||||
|
|
||||||
// Clear the chromatic
|
// Clear the chromatic
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
@ -366,7 +366,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::RESOLUTION_SETTING)?;
|
self.command(spi, Command::ResolutionSetting)?;
|
||||||
|
|
||||||
self.send_data(spi, &[w as u8])?;
|
self.send_data(spi, &[w as u8])?;
|
||||||
self.send_data(spi, &[(h >> 8) as u8])?;
|
self.send_data(spi, &[(h >> 8) as u8])?;
|
||||||
|
|
@ -382,7 +382,7 @@ where
|
||||||
};
|
};
|
||||||
self.cmd_with_data(
|
self.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::VCOM_AND_DATA_INTERVAL_SETTING,
|
Command::VcomAndDataIntervalSetting,
|
||||||
&[border | VCOM_DATA_INTERVAL],
|
&[border | VCOM_DATA_INTERVAL],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ use crate::traits;
|
||||||
///
|
///
|
||||||
/// The description of the single commands is mostly taken from IL0398.pdf
|
/// The description of the single commands is mostly taken from IL0398.pdf
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset
|
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset
|
||||||
|
|
@ -17,101 +16,101 @@ pub(crate) enum Command {
|
||||||
/// 0x1F B/W Mode, LUT from OTP
|
/// 0x1F B/W Mode, LUT from OTP
|
||||||
/// 0x2F Red Mode, LUT set by registers
|
/// 0x2F Red Mode, LUT set by registers
|
||||||
/// 0x3F B/W Mode, LUT set by registers
|
/// 0x3F B/W Mode, LUT set by registers
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
/// selecting internal and external power
|
/// selecting internal and external power
|
||||||
/// self.send_data(0x03)?; //VDS_EN, VDG_EN
|
/// self.send_data(0x03)?; //VDS_EN, VDG_EN
|
||||||
/// self.send_data(0x00)?; //VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
/// self.send_data(0x00)?; //VCOM_HV, VGHL_LV[1], VGHL_LV[0]
|
||||||
/// self.send_data(0x2b)?; //VDH
|
/// self.send_data(0x2b)?; //VDH
|
||||||
/// self.send_data(0x2b)?; //VDL
|
/// self.send_data(0x2b)?; //VDL
|
||||||
/// self.send_data(0xff)?; //VDHR
|
/// self.send_data(0xff)?; //VDHR
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
/// After the Power Off command, the driver will power off following the Power Off Sequence. This command will turn off charge
|
/// After the Power Off command, the driver will power off following the Power Off Sequence. This command will turn off charge
|
||||||
/// pump, T-con, source driver, gate driver, VCOM, and temperature sensor, but register data will be kept until VDD becomes OFF.
|
/// pump, T-con, source driver, gate driver, VCOM, and temperature sensor, but register data will be kept until VDD becomes OFF.
|
||||||
/// Source Driver output and Vcom will remain as previous condition, which may have 2 conditions: floating.
|
/// Source Driver output and Vcom will remain as previous condition, which may have 2 conditions: floating.
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
/// Setting Power OFF sequence
|
/// Setting Power OFF sequence
|
||||||
POWER_OFF_SEQUENCE_SETTING = 0x03,
|
PowerOffSequenceSetting = 0x03,
|
||||||
/// Turning On the Power
|
/// Turning On the Power
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
/// This command enables the internal bandgap, which will be cleared by the next POF.
|
/// This command enables the internal bandgap, which will be cleared by the next POF.
|
||||||
POWER_ON_MEASURE = 0x05,
|
PowerOnMeasure = 0x05,
|
||||||
/// Starting data transmission
|
/// Starting data transmission
|
||||||
/// 3-times: self.send_data(0x17)?; //07 0f 17 1f 27 2F 37 2f
|
/// 3-times: self.send_data(0x17)?; //07 0f 17 1f 27 2F 37 2f
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
/// After this command is transmitted, the chip would enter the deep-sleep mode to save power.
|
/// After this command is transmitted, the chip would enter the deep-sleep mode to save power.
|
||||||
///
|
///
|
||||||
/// The deep sleep mode would return to standby by hardware reset.
|
/// The deep sleep mode would return to standby by hardware reset.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
||||||
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
||||||
///
|
///
|
||||||
/// - In B/W mode, this command writes “OLD” data to SRAM.
|
/// - In B/W mode, this command writes “OLD” data to SRAM.
|
||||||
/// - In B/W/Red mode, this command writes “B/W” data to SRAM.
|
/// - In B/W/Red mode, this command writes “B/W” data to SRAM.
|
||||||
/// - In Program mode, this command writes “OTP” data to SRAM for programming.
|
/// - In Program mode, this command writes “OTP” data to SRAM for programming.
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
/// Stopping data transmission
|
/// Stopping data transmission
|
||||||
DATA_STOP = 0x11,
|
DataStop = 0x11,
|
||||||
/// While user sent this command, driver will refresh display (data/VCOM) according to SRAM data and LUT.
|
/// While user sent this command, driver will refresh display (data/VCOM) according to SRAM data and LUT.
|
||||||
///
|
///
|
||||||
/// After Display Refresh command, BUSY_N signal will become “0” and the refreshing of panel starts.
|
/// After Display Refresh command, BUSY_N signal will become “0” and the refreshing of panel starts.
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
/// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data
|
||||||
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
/// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel.
|
||||||
/// - In B/W mode, this command writes “NEW” data to SRAM.
|
/// - In B/W mode, this command writes “NEW” data to SRAM.
|
||||||
/// - In B/W/Red mode, this command writes “RED” data to SRAM.
|
/// - In B/W/Red mode, this command writes “RED” data to SRAM.
|
||||||
DATA_START_TRANSMISSION_2 = 0x13,
|
DataStartTransmission2 = 0x13,
|
||||||
|
|
||||||
/// This command stores VCOM Look-Up Table with 7 groups of data. Each group contains information for one state and is stored
|
/// This command stores VCOM Look-Up Table with 7 groups of data. Each group contains information for one state and is stored
|
||||||
/// with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
/// with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
||||||
///
|
///
|
||||||
/// from IL0373
|
/// from IL0373
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
/// This command stores White-to-White Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
/// This command stores White-to-White Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
||||||
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
||||||
///
|
///
|
||||||
/// from IL0373
|
/// from IL0373
|
||||||
LUT_WHITE_TO_WHITE = 0x21,
|
LutWhiteToWhite = 0x21,
|
||||||
/// This command stores Black-to-White Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
/// This command stores Black-to-White Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
||||||
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
||||||
///
|
///
|
||||||
/// from IL0373
|
/// from IL0373
|
||||||
LUT_BLACK_TO_WHITE = 0x22,
|
LutBlackToWhite = 0x22,
|
||||||
/// This command stores White-to-Black Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
/// This command stores White-to-Black Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
||||||
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
||||||
///
|
///
|
||||||
/// from IL0373
|
/// from IL0373
|
||||||
LUT_WHITE_TO_BLACK = 0x23,
|
LutWhiteToBlack = 0x23,
|
||||||
/// This command stores Black-to-Black Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
/// This command stores Black-to-Black Look-Up Table with 7 groups of data. Each group contains information for one state and is
|
||||||
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
/// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat.
|
||||||
///
|
///
|
||||||
/// from IL0373
|
/// from IL0373
|
||||||
LUT_BLACK_TO_BLACK = 0x24,
|
LutBlackToBlack = 0x24,
|
||||||
/// The command controls the PLL clock frequency.
|
/// The command controls the PLL clock frequency.
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
/// This command reads the temperature sensed by the temperature sensor.
|
/// This command reads the temperature sensed by the temperature sensor.
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
/// Selects the Internal or External temperature sensor and offset
|
/// Selects the Internal or External temperature sensor and offset
|
||||||
TEMPERATURE_SENSOR_SELECTION = 0x41,
|
TemperatureSensorSelection = 0x41,
|
||||||
/// Write External Temperature Sensor
|
/// Write External Temperature Sensor
|
||||||
TEMPERATURE_SENSOR_WRITE = 0x42,
|
TemperatureSensorWrite = 0x42,
|
||||||
/// Read External Temperature Sensor
|
/// Read External Temperature Sensor
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
TEMPERATURE_SENSOR_READ = 0x43,
|
TemperatureSensorRead = 0x43,
|
||||||
/// This command indicates the interval of Vcom and data output. When setting the vertical back porch, the total blanking will be kept (20 Hsync)
|
/// This command indicates the interval of Vcom and data output. When setting the vertical back porch, the total blanking will be kept (20 Hsync)
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
/// This command indicates the input power condition. Host can read this flag to learn the battery condition.
|
/// This command indicates the input power condition. Host can read this flag to learn the battery condition.
|
||||||
LOW_POWER_DETECTION = 0x51,
|
LowPowerDetection = 0x51,
|
||||||
/// This command defines non-overlap period of Gate and Source.
|
/// This command defines non-overlap period of Gate and Source.
|
||||||
TCON_SETTING = 0x60,
|
TconSetting = 0x60,
|
||||||
/// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR).
|
/// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR).
|
||||||
RESOLUTION_SETTING = 0x61,
|
ResolutionSetting = 0x61,
|
||||||
/// This command defines the Fist Active Gate and First Active Source of active channels.
|
/// This command defines the Fist Active Gate and First Active Source of active channels.
|
||||||
GSST_SETTING = 0x65,
|
GsstSetting = 0x65,
|
||||||
/// The LUT_REV / Chip Revision is read from OTP address = 0x001.
|
/// The LUT_REV / Chip Revision is read from OTP address = 0x001.
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
|
|
@ -120,39 +119,39 @@ pub(crate) enum Command {
|
||||||
/// PTL, I2C_ERR, I2C_BUSY, DATA, PON, POF, BUSY
|
/// PTL, I2C_ERR, I2C_BUSY, DATA, PON, POF, BUSY
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
GET_STATUS = 0x71,
|
GetStatus = 0x71,
|
||||||
/// Automatically measure VCOM. This command reads the IC status
|
/// Automatically measure VCOM. This command reads the IC status
|
||||||
AUTO_MEASUREMENT_VCOM = 0x80,
|
AutoMeasurementVcom = 0x80,
|
||||||
/// This command gets the VCOM value
|
/// This command gets the VCOM value
|
||||||
///
|
///
|
||||||
/// Doesn't work! Waveshare doesn't connect the read pin
|
/// Doesn't work! Waveshare doesn't connect the read pin
|
||||||
READ_VCOM_VALUE = 0x81,
|
ReadVcomValue = 0x81,
|
||||||
/// Set VCM_DC
|
/// Set VCM_DC
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
/// This command sets partial window
|
/// This command sets partial window
|
||||||
PARTIAL_WINDOW = 0x90,
|
PartialWindow = 0x90,
|
||||||
/// This command makes the display enter partial mode
|
/// This command makes the display enter partial mode
|
||||||
PARTIAL_IN = 0x91,
|
PartialIn = 0x91,
|
||||||
/// This command makes the display exit partial mode and enter normal mode
|
/// This command makes the display exit partial mode and enter normal mode
|
||||||
PARTIAL_OUT = 0x92,
|
PartialOut = 0x92,
|
||||||
/// After this command is issued, the chip would enter the program mode.
|
/// After this command is issued, the chip would enter the program mode.
|
||||||
///
|
///
|
||||||
/// After the programming procedure completed, a hardware reset is necessary for leaving program mode.
|
/// After the programming procedure completed, a hardware reset is necessary for leaving program mode.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
PROGRAM_MODE = 0xA0,
|
ProgramMode = 0xA0,
|
||||||
/// After this command is transmitted, the programming state machine would be activated.
|
/// After this command is transmitted, the programming state machine would be activated.
|
||||||
///
|
///
|
||||||
/// The BUSY flag would fall to 0 until the programming is completed.
|
/// The BUSY flag would fall to 0 until the programming is completed.
|
||||||
ACTIVE_PROGRAMMING = 0xA1,
|
ActiveProgramming = 0xA1,
|
||||||
/// The command is used for reading the content of OTP for checking the data of programming.
|
/// The command is used for reading the content of OTP for checking the data of programming.
|
||||||
///
|
///
|
||||||
/// The value of (n) is depending on the amount of programmed data, tha max address = 0xFFF.
|
/// The value of (n) is depending on the amount of programmed data, tha max address = 0xFFF.
|
||||||
READ_OTP = 0xA2,
|
ReadOtp = 0xA2,
|
||||||
/// This command is set for saving power during fresh period. If the output voltage of VCOM / Source is from negative to positive or
|
/// This command is set for saving power during fresh period. If the output voltage of VCOM / Source is from negative to positive or
|
||||||
/// from positive to negative, the power saving mechanism will be activated. The active period width is defined by the following two
|
/// from positive to negative, the power saving mechanism will be activated. The active period width is defined by the following two
|
||||||
/// parameters.
|
/// parameters.
|
||||||
POWER_SAVING = 0xE3,
|
PowerSaving = 0xE3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
@ -169,10 +168,10 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
assert_eq!(Command::POWER_SAVING.address(), 0xE3);
|
assert_eq!(Command::PowerSaving.address(), 0xE3);
|
||||||
|
|
||||||
assert_eq!(Command::PANEL_SETTING.address(), 0x00);
|
assert_eq!(Command::PanelSetting.address(), 0x00);
|
||||||
|
|
||||||
assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12);
|
assert_eq!(Command::DisplayRefresh.address(), 0x12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,36 +110,36 @@ where
|
||||||
// set the power settings
|
// set the power settings
|
||||||
self.interface.cmd_with_data(
|
self.interface.cmd_with_data(
|
||||||
spi,
|
spi,
|
||||||
Command::POWER_SETTING,
|
Command::PowerSetting,
|
||||||
&[0x03, 0x00, 0x2b, 0x2b, 0xff],
|
&[0x03, 0x00, 0x2b, 0x2b, 0xff],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// start the booster
|
// start the booster
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?;
|
.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?;
|
||||||
|
|
||||||
// power on
|
// power on
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
delay.delay_ms(5);
|
delay.delay_ms(5);
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
// set the panel settings
|
// set the panel settings
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x3F])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0x3F])?;
|
||||||
|
|
||||||
// Set Frequency, 200 Hz didn't work on my board
|
// Set Frequency, 200 Hz didn't work on my board
|
||||||
// 150Hz and 171Hz wasn't tested yet
|
// 150Hz and 171Hz wasn't tested yet
|
||||||
// TODO: Test these other frequencies
|
// TODO: Test these other frequencies
|
||||||
// 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz
|
// 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz
|
||||||
self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3A])?;
|
self.cmd_with_data(spi, Command::PllControl, &[0x3A])?;
|
||||||
|
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?;
|
.cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?;
|
||||||
|
|
||||||
//VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
//VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?;
|
.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?;
|
||||||
|
|
||||||
self.set_lut(spi, None)?;
|
self.set_lut(spi, None)?;
|
||||||
|
|
||||||
|
|
@ -191,19 +191,19 @@ where
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating
|
.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating
|
||||||
self.command(spi, Command::VCM_DC_SETTING)?; // VCOM to 0V
|
self.command(spi, Command::VcmDcSetting)?; // VCOM to 0V
|
||||||
self.command(spi, Command::PANEL_SETTING)?;
|
self.command(spi, Command::PanelSetting)?;
|
||||||
|
|
||||||
self.command(spi, Command::POWER_SETTING)?; //VG&VS to 0V fast
|
self.command(spi, Command::PowerSetting)?; //VG&VS to 0V fast
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
self.send_data(spi, &[0x00])?;
|
self.send_data(spi, &[0x00])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?;
|
.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,12 +212,12 @@ where
|
||||||
let color_value = self.color.get_byte_value();
|
let color_value = self.color.get_byte_value();
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?;
|
.data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, buffer)?;
|
.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,8 +236,8 @@ where
|
||||||
//return Err("Wrong buffersize");
|
//return Err("Wrong buffersize");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.command(spi, Command::PARTIAL_IN)?;
|
self.command(spi, Command::PartialIn)?;
|
||||||
self.command(spi, Command::PARTIAL_WINDOW)?;
|
self.command(spi, Command::PartialWindow)?;
|
||||||
self.send_data(spi, &[(x >> 8) as u8])?;
|
self.send_data(spi, &[(x >> 8) as u8])?;
|
||||||
let tmp = x & 0xf8;
|
let tmp = x & 0xf8;
|
||||||
self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored
|
self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored
|
||||||
|
|
@ -256,26 +256,26 @@ where
|
||||||
//TODO: handle dtm somehow
|
//TODO: handle dtm somehow
|
||||||
let is_dtm1 = false;
|
let is_dtm1 = false;
|
||||||
if is_dtm1 {
|
if is_dtm1 {
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_1)? //TODO: check if data_start transmission 1 also needs "old"/background data here
|
self.command(spi, Command::DataStartTransmission1)? //TODO: check if data_start transmission 1 also needs "old"/background data here
|
||||||
} else {
|
} else {
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_2)?
|
self.command(spi, Command::DataStartTransmission2)?
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send_data(spi, buffer)?;
|
self.send_data(spi, buffer)?;
|
||||||
|
|
||||||
self.command(spi, Command::PARTIAL_OUT)?;
|
self.command(spi, Command::PartialOut)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.update_frame(spi, buffer)?;
|
self.update_frame(spi, buffer)?;
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,12 +286,12 @@ where
|
||||||
let color_value = self.color.get_byte_value();
|
let color_value = self.color.get_byte_value();
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?;
|
.data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?;
|
.data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -374,7 +374,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::RESOLUTION_SETTING)?;
|
self.command(spi, Command::ResolutionSetting)?;
|
||||||
self.send_data(spi, &[(w >> 8) as u8])?;
|
self.send_data(spi, &[(w >> 8) as u8])?;
|
||||||
self.send_data(spi, &[w as u8])?;
|
self.send_data(spi, &[w as u8])?;
|
||||||
self.send_data(spi, &[(h >> 8) as u8])?;
|
self.send_data(spi, &[(h >> 8) as u8])?;
|
||||||
|
|
@ -392,19 +392,19 @@ where
|
||||||
) -> Result<(), SPI::Error> {
|
) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
// LUT VCOM
|
// LUT VCOM
|
||||||
self.cmd_with_data(spi, Command::LUT_FOR_VCOM, lut_vcom)?;
|
self.cmd_with_data(spi, Command::LutForVcom, lut_vcom)?;
|
||||||
|
|
||||||
// LUT WHITE to WHITE
|
// LUT WHITE to WHITE
|
||||||
self.cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, lut_ww)?;
|
self.cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww)?;
|
||||||
|
|
||||||
// LUT BLACK to WHITE
|
// LUT BLACK to WHITE
|
||||||
self.cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, lut_bw)?;
|
self.cmd_with_data(spi, Command::LutBlackToWhite, lut_bw)?;
|
||||||
|
|
||||||
// LUT WHITE to BLACK
|
// LUT WHITE to BLACK
|
||||||
self.cmd_with_data(spi, Command::LUT_WHITE_TO_BLACK, lut_wb)?;
|
self.cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb)?;
|
||||||
|
|
||||||
// LUT BLACK to BLACK
|
// LUT BLACK to BLACK
|
||||||
self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, lut_bb)?;
|
self.cmd_with_data(spi, Command::LutBlackToBlack, lut_bb)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -451,7 +451,7 @@ where
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
self.interface.data(spi, buffer)?;
|
self.interface.data(spi, buffer)?;
|
||||||
|
|
||||||
|
|
@ -464,7 +464,7 @@ where
|
||||||
// self.send_resolution(spi)?;
|
// self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
|
|
||||||
self.interface.data(spi, buffer)?;
|
self.interface.data(spi, buffer)?;
|
||||||
|
|
||||||
|
|
@ -487,13 +487,13 @@ where
|
||||||
//return Err("Wrong buffersize");
|
//return Err("Wrong buffersize");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::PARTIAL_IN)?;
|
self.interface.cmd(spi, Command::PartialIn)?;
|
||||||
self.interface.cmd(spi, Command::PARTIAL_WINDOW)?;
|
self.interface.cmd(spi, Command::PartialWindow)?;
|
||||||
|
|
||||||
self.shift_display(spi, x, y, width, height)?;
|
self.shift_display(spi, x, y, width, height)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
|
|
||||||
self.interface.data(spi, buffer)?;
|
self.interface.data(spi, buffer)?;
|
||||||
|
|
||||||
|
|
@ -520,11 +520,11 @@ where
|
||||||
self.shift_display(spi, x, y, width, height)?;
|
self.shift_display(spi, x, y, width, height)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
|
|
||||||
self.interface.data(spi, buffer)?;
|
self.interface.data(spi, buffer)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::PARTIAL_OUT)?;
|
self.interface.cmd(spi, Command::PartialOut)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -541,22 +541,22 @@ where
|
||||||
|
|
||||||
let color_value = self.color.get_byte_value();
|
let color_value = self.color.get_byte_value();
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::PARTIAL_IN)?;
|
self.interface.cmd(spi, Command::PartialIn)?;
|
||||||
self.interface.cmd(spi, Command::PARTIAL_WINDOW)?;
|
self.interface.cmd(spi, Command::PartialWindow)?;
|
||||||
|
|
||||||
self.shift_display(spi, x, y, width, height)?;
|
self.shift_display(spi, x, y, width, height)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_1)?;
|
.cmd(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, width / 8 * height)?;
|
.data_x_times(spi, color_value, width / 8 * height)?;
|
||||||
|
|
||||||
self.interface
|
self.interface
|
||||||
.cmd(spi, Command::DATA_START_TRANSMISSION_2)?;
|
.cmd(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, color_value, width / 8 * height)?;
|
.data_x_times(spi, color_value, width / 8 * height)?;
|
||||||
|
|
||||||
self.interface.cmd(spi, Command::PARTIAL_OUT)?;
|
self.interface.cmd(spi, Command::PartialOut)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,127 +8,126 @@ use crate::traits;
|
||||||
///
|
///
|
||||||
/// For more infos about the addresses and what they are doing look into the PDFs.
|
/// For more infos about the addresses and what they are doing look into the PDFs.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift
|
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift
|
||||||
/// direction, booster switch, soft reset.
|
/// direction, booster switch, soft reset.
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
|
|
||||||
/// Selecting internal and external power
|
/// Selecting internal and external power
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
|
|
||||||
/// After the Power Off command, the driver will power off following the Power Off
|
/// After the Power Off command, the driver will power off following the Power Off
|
||||||
/// Sequence; BUSY signal will become "0". This command will turn off charge pump,
|
/// Sequence; BUSY signal will become "0". This command will turn off charge pump,
|
||||||
/// T-con, source driver, gate driver, VCOM, and temperature sensor, but register
|
/// T-con, source driver, gate driver, VCOM, and temperature sensor, but register
|
||||||
/// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain
|
/// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain
|
||||||
/// as previous condition, which may have 2 conditions: 0V or floating.
|
/// as previous condition, which may have 2 conditions: 0V or floating.
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
|
|
||||||
/// Setting Power OFF sequence
|
/// Setting Power OFF sequence
|
||||||
POWER_OFF_SEQUENCE_SETTING = 0x03,
|
PowerOffSequenceSetting = 0x03,
|
||||||
|
|
||||||
/// Turning On the Power
|
/// Turning On the Power
|
||||||
///
|
///
|
||||||
/// After the Power ON command, the driver will power on following the Power ON
|
/// After the Power ON command, the driver will power on following the Power ON
|
||||||
/// sequence. Once complete, the BUSY signal will become "1".
|
/// sequence. Once complete, the BUSY signal will become "1".
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
|
|
||||||
/// Starting data transmission
|
/// Starting data transmission
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
|
|
||||||
/// This command makes the chip enter the deep-sleep mode to save power.
|
/// This command makes the chip enter the deep-sleep mode to save power.
|
||||||
///
|
///
|
||||||
/// The deep sleep mode would return to stand-by by hardware reset.
|
/// The deep sleep mode would return to stand-by by hardware reset.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
|
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data
|
/// This command starts transmitting data and write them into SRAM. To complete data
|
||||||
/// transmission, command DSP (Data Stop) must be issued. Then the chip will start to
|
/// transmission, command DSP (Data Stop) must be issued. Then the chip will start to
|
||||||
/// send data/VCOM for panel.
|
/// send data/VCOM for panel.
|
||||||
///
|
///
|
||||||
/// BLACK/WHITE or OLD_DATA
|
/// BLACK/WHITE or OLD_DATA
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
|
|
||||||
/// To stop data transmission, this command must be issued to check the `data_flag`.
|
/// To stop data transmission, this command must be issued to check the `data_flag`.
|
||||||
///
|
///
|
||||||
/// After this command, BUSY signal will become "0" until the display update is
|
/// After this command, BUSY signal will become "0" until the display update is
|
||||||
/// finished.
|
/// finished.
|
||||||
DATA_STOP = 0x11,
|
DataStop = 0x11,
|
||||||
|
|
||||||
/// After this command is issued, driver will refresh display (data/VCOM) according to
|
/// After this command is issued, driver will refresh display (data/VCOM) according to
|
||||||
/// SRAM data and LUT.
|
/// SRAM data and LUT.
|
||||||
///
|
///
|
||||||
/// After Display Refresh command, BUSY signal will become "0" until the display
|
/// After Display Refresh command, BUSY signal will become "0" until the display
|
||||||
/// update is finished.
|
/// update is finished.
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
|
|
||||||
/// Image Process Command
|
/// Image Process Command
|
||||||
IMAGE_PROCESS_COMMAND = 0x13,
|
ImageProcessCommand = 0x13,
|
||||||
|
|
||||||
/// This command builds the VCOM Look-Up Table (LUTC).
|
/// This command builds the VCOM Look-Up Table (LUTC).
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
/// This command builds the Black Look-Up Table (LUTB).
|
/// This command builds the Black Look-Up Table (LUTB).
|
||||||
LUT_BLACK = 0x21,
|
LutBlack = 0x21,
|
||||||
/// This command builds the White Look-Up Table (LUTW).
|
/// This command builds the White Look-Up Table (LUTW).
|
||||||
LUT_WHITE = 0x22,
|
LutWhite = 0x22,
|
||||||
/// This command builds the Gray1 Look-Up Table (LUTG1).
|
/// This command builds the Gray1 Look-Up Table (LUTG1).
|
||||||
LUT_GRAY_1 = 0x23,
|
LutGray1 = 0x23,
|
||||||
/// This command builds the Gray2 Look-Up Table (LUTG2).
|
/// This command builds the Gray2 Look-Up Table (LUTG2).
|
||||||
LUT_GRAY_2 = 0x24,
|
LutGray2 = 0x24,
|
||||||
/// This command builds the Red0 Look-Up Table (LUTR0).
|
/// This command builds the Red0 Look-Up Table (LUTR0).
|
||||||
LUT_RED_0 = 0x25,
|
LutRed0 = 0x25,
|
||||||
/// This command builds the Red1 Look-Up Table (LUTR1).
|
/// This command builds the Red1 Look-Up Table (LUTR1).
|
||||||
LUT_RED_1 = 0x26,
|
LutRed1 = 0x26,
|
||||||
/// This command builds the Red2 Look-Up Table (LUTR2).
|
/// This command builds the Red2 Look-Up Table (LUTR2).
|
||||||
LUT_RED_2 = 0x27,
|
LutRed2 = 0x27,
|
||||||
/// This command builds the Red3 Look-Up Table (LUTR3).
|
/// This command builds the Red3 Look-Up Table (LUTR3).
|
||||||
LUT_RED_3 = 0x28,
|
LutRed3 = 0x28,
|
||||||
/// This command builds the XON Look-Up Table (LUTXON).
|
/// This command builds the XON Look-Up Table (LUTXON).
|
||||||
LUT_XON = 0x29,
|
LutXon = 0x29,
|
||||||
|
|
||||||
/// The command controls the PLL clock frequency.
|
/// The command controls the PLL clock frequency.
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
|
|
||||||
/// This command reads the temperature sensed by the temperature sensor.
|
/// This command reads the temperature sensed by the temperature sensor.
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
/// This command selects the Internal or External temperature sensor.
|
/// This command selects the Internal or External temperature sensor.
|
||||||
TEMPERATURE_CALIBRATION = 0x41,
|
TemperatureCalibration = 0x41,
|
||||||
/// This command could write data to the external temperature sensor.
|
/// This command could write data to the external temperature sensor.
|
||||||
TEMPERATURE_SENSOR_WRITE = 0x42,
|
TemperatureSensorWrite = 0x42,
|
||||||
/// This command could read data from the external temperature sensor.
|
/// This command could read data from the external temperature sensor.
|
||||||
TEMPERATURE_SENSOR_READ = 0x43,
|
TemperatureSensorRead = 0x43,
|
||||||
|
|
||||||
/// This command indicates the interval of Vcom and data output. When setting the
|
/// This command indicates the interval of Vcom and data output. When setting the
|
||||||
/// vertical back porch, the total blanking will be kept (20 Hsync).
|
/// vertical back porch, the total blanking will be kept (20 Hsync).
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
/// This command indicates the input power condition. Host can read this flag to learn
|
/// This command indicates the input power condition. Host can read this flag to learn
|
||||||
/// the battery condition.
|
/// the battery condition.
|
||||||
LOW_POWER_DETECTION = 0x51,
|
LowPowerDetection = 0x51,
|
||||||
|
|
||||||
/// This command defines non-overlap period of Gate and Source.
|
/// This command defines non-overlap period of Gate and Source.
|
||||||
TCON_SETTING = 0x60,
|
TconSetting = 0x60,
|
||||||
/// This command defines alternative resolution and this setting is of higher priority
|
/// This command defines alternative resolution and this setting is of higher priority
|
||||||
/// than the RES\[1:0\] in R00H (PSR).
|
/// than the RES\[1:0\] in R00H (PSR).
|
||||||
TCON_RESOLUTION = 0x61,
|
TconResolution = 0x61,
|
||||||
/// This command defines MCU host direct access external memory mode.
|
/// This command defines MCU host direct access external memory mode.
|
||||||
//SPI_FLASH_CONTROL = 0x65,
|
//SpiFlashControl = 0x65,
|
||||||
|
|
||||||
/// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000.
|
/// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000.
|
||||||
//REVISION = 0x70,
|
//REVISION = 0x70,
|
||||||
/// This command reads the IC status.
|
/// This command reads the IC status.
|
||||||
GET_STATUS = 0x71,
|
GetStatus = 0x71,
|
||||||
|
|
||||||
/// This command implements related VCOM sensing setting.
|
/// This command implements related VCOM sensing setting.
|
||||||
//AUTO_MEASUREMENT_VCOM = 0x80,
|
//AutoMeasurementVcom = 0x80,
|
||||||
/// This command gets the VCOM value.
|
/// This command gets the VCOM value.
|
||||||
READ_VCOM_VALUE = 0x81,
|
ReadVcomValue = 0x81,
|
||||||
/// This command sets `VCOM_DC` value.
|
/// This command sets `VCOM_DC` value.
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
// /// This is in all the Waveshare controllers for EPD6in65f, but it's not documented
|
// /// This is in all the Waveshare controllers for EPD6in65f, but it's not documented
|
||||||
// /// anywhere in the datasheet `¯\_(ツ)_/¯`
|
// /// anywhere in the datasheet `¯\_(ツ)_/¯`
|
||||||
FLASH_MODE = 0xE3,
|
FlashMode = 0xE3,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
@ -145,7 +144,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
assert_eq!(Command::PANEL_SETTING.address(), 0x00);
|
assert_eq!(Command::PanelSetting.address(), 0x00);
|
||||||
assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12);
|
assert_eq!(Command::DisplayRefresh.address(), 0x12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,21 +57,21 @@ where
|
||||||
// Reset the device
|
// Reset the device
|
||||||
self.interface.reset(delay, 2);
|
self.interface.reset(delay, 2);
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xEF, 0x08])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08])?;
|
||||||
self.cmd_with_data(spi, Command::POWER_SETTING, &[0x37, 0x00, 0x23, 0x23])?;
|
self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00, 0x23, 0x23])?;
|
||||||
self.cmd_with_data(spi, Command::POWER_OFF_SEQUENCE_SETTING, &[0x00])?;
|
self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00])?;
|
||||||
self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0xC7, 0xC7, 0x1D])?;
|
self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D])?;
|
||||||
self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3C])?;
|
self.cmd_with_data(spi, Command::PllControl, &[0x3C])?;
|
||||||
self.cmd_with_data(spi, Command::TEMPERATURE_SENSOR_COMMAND, &[0x00])?;
|
self.cmd_with_data(spi, Command::TemperatureSensorCommand, &[0x00])?;
|
||||||
self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?;
|
self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?;
|
||||||
self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?;
|
self.cmd_with_data(spi, Command::TconSetting, &[0x22])?;
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::FLASH_MODE, &[0xAA])?;
|
self.cmd_with_data(spi, Command::FlashMode, &[0xAA])?;
|
||||||
|
|
||||||
delay.delay_ms(100);
|
delay.delay_ms(100);
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?;
|
self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -113,14 +113,14 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?;
|
self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.wait_busy_high();
|
self.wait_busy_high();
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, buffer)?;
|
self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,11 +138,11 @@ where
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_busy_high();
|
self.wait_busy_high();
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
self.wait_busy_high();
|
self.wait_busy_high();
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
self.wait_busy_high();
|
self.wait_busy_high();
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
self.wait_busy_low();
|
self.wait_busy_low();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +157,7 @@ where
|
||||||
let bg = OctColor::colors_byte(self.color, self.color);
|
let bg = OctColor::colors_byte(self.color, self.color);
|
||||||
self.wait_busy_high();
|
self.wait_busy_high();
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_1)?;
|
self.command(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?;
|
self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?;
|
||||||
self.display_frame(spi)?;
|
self.display_frame(spi)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -227,7 +227,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::TCON_RESOLUTION)?;
|
self.command(spi, Command::TconResolution)?;
|
||||||
self.send_data(spi, &[(w >> 8) as u8])?;
|
self.send_data(spi, &[(w >> 8) as u8])?;
|
||||||
self.send_data(spi, &[w as u8])?;
|
self.send_data(spi, &[w as u8])?;
|
||||||
self.send_data(spi, &[(h >> 8) as u8])?;
|
self.send_data(spi, &[(h >> 8) as u8])?;
|
||||||
|
|
|
||||||
|
|
@ -8,130 +8,129 @@ use crate::traits;
|
||||||
///
|
///
|
||||||
/// For more infos about the addresses and what they are doing look into the PDFs.
|
/// For more infos about the addresses and what they are doing look into the PDFs.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift
|
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift
|
||||||
/// direction, booster switch, soft reset.
|
/// direction, booster switch, soft reset.
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
|
|
||||||
/// Selecting internal and external power
|
/// Selecting internal and external power
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
|
|
||||||
/// After the Power Off command, the driver will power off following the Power Off
|
/// After the Power Off command, the driver will power off following the Power Off
|
||||||
/// Sequence; BUSY signal will become "0". This command will turn off charge pump,
|
/// Sequence; BUSY signal will become "0". This command will turn off charge pump,
|
||||||
/// T-con, source driver, gate driver, VCOM, and temperature sensor, but register
|
/// T-con, source driver, gate driver, VCOM, and temperature sensor, but register
|
||||||
/// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain
|
/// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain
|
||||||
/// as previous condition, which may have 2 conditions: 0V or floating.
|
/// as previous condition, which may have 2 conditions: 0V or floating.
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
|
|
||||||
/// Setting Power OFF sequence
|
/// Setting Power OFF sequence
|
||||||
POWER_OFF_SEQUENCE_SETTING = 0x03,
|
PowerOffSequenceSetting = 0x03,
|
||||||
|
|
||||||
/// Turning On the Power
|
/// Turning On the Power
|
||||||
///
|
///
|
||||||
/// After the Power ON command, the driver will power on following the Power ON
|
/// After the Power ON command, the driver will power on following the Power ON
|
||||||
/// sequence. Once complete, the BUSY signal will become "1".
|
/// sequence. Once complete, the BUSY signal will become "1".
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
|
|
||||||
/// Starting data transmission
|
/// Starting data transmission
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
|
|
||||||
/// This command makes the chip enter the deep-sleep mode to save power.
|
/// This command makes the chip enter the deep-sleep mode to save power.
|
||||||
///
|
///
|
||||||
/// The deep sleep mode would return to stand-by by hardware reset.
|
/// The deep sleep mode would return to stand-by by hardware reset.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
|
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data
|
/// This command starts transmitting data and write them into SRAM. To complete data
|
||||||
/// transmission, command DSP (Data Stop) must be issued. Then the chip will start to
|
/// transmission, command DSP (Data Stop) must be issued. Then the chip will start to
|
||||||
/// send data/VCOM for panel.
|
/// send data/VCOM for panel.
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
|
|
||||||
/// To stop data transmission, this command must be issued to check the `data_flag`.
|
/// To stop data transmission, this command must be issued to check the `data_flag`.
|
||||||
///
|
///
|
||||||
/// After this command, BUSY signal will become "0" until the display update is
|
/// After this command, BUSY signal will become "0" until the display update is
|
||||||
/// finished.
|
/// finished.
|
||||||
DATA_STOP = 0x11,
|
DataStop = 0x11,
|
||||||
|
|
||||||
/// After this command is issued, driver will refresh display (data/VCOM) according to
|
/// After this command is issued, driver will refresh display (data/VCOM) according to
|
||||||
/// SRAM data and LUT.
|
/// SRAM data and LUT.
|
||||||
///
|
///
|
||||||
/// After Display Refresh command, BUSY signal will become "0" until the display
|
/// After Display Refresh command, BUSY signal will become "0" until the display
|
||||||
/// update is finished.
|
/// update is finished.
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
|
|
||||||
/// After this command is issued, image process engine will find thin lines/pixels
|
/// After this command is issued, image process engine will find thin lines/pixels
|
||||||
/// from frame SRAM and update the frame SRAM for applying new gray level waveform.
|
/// from frame SRAM and update the frame SRAM for applying new gray level waveform.
|
||||||
///
|
///
|
||||||
/// After "Image Process Command", BUSY_N signal will become "0" until image process
|
/// After "Image Process Command", BUSY_N signal will become "0" until image process
|
||||||
/// is finished.
|
/// is finished.
|
||||||
IMAGE_PROCESS = 0x13,
|
ImageProcess = 0x13,
|
||||||
|
|
||||||
/// This command builds the VCOM Look-Up Table (LUTC).
|
/// This command builds the VCOM Look-Up Table (LUTC).
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
/// This command builds the Black Look-Up Table (LUTB).
|
/// This command builds the Black Look-Up Table (LUTB).
|
||||||
LUT_BLACK = 0x21,
|
LutBlack = 0x21,
|
||||||
/// This command builds the White Look-Up Table (LUTW).
|
/// This command builds the White Look-Up Table (LUTW).
|
||||||
LUT_WHITE = 0x22,
|
LutWhite = 0x22,
|
||||||
/// This command builds the Gray1 Look-Up Table (LUTG1).
|
/// This command builds the Gray1 Look-Up Table (LUTG1).
|
||||||
LUT_GRAY_1 = 0x23,
|
LutGray1 = 0x23,
|
||||||
/// This command builds the Gray2 Look-Up Table (LUTG2).
|
/// This command builds the Gray2 Look-Up Table (LUTG2).
|
||||||
LUT_GRAY_2 = 0x24,
|
LutGray2 = 0x24,
|
||||||
/// This command builds the Red0 Look-Up Table (LUTR0).
|
/// This command builds the Red0 Look-Up Table (LUTR0).
|
||||||
LUT_RED_0 = 0x25,
|
LutRed0 = 0x25,
|
||||||
/// This command builds the Red1 Look-Up Table (LUTR1).
|
/// This command builds the Red1 Look-Up Table (LUTR1).
|
||||||
LUT_RED_1 = 0x26,
|
LutRed1 = 0x26,
|
||||||
/// This command builds the Red2 Look-Up Table (LUTR2).
|
/// This command builds the Red2 Look-Up Table (LUTR2).
|
||||||
LUT_RED_2 = 0x27,
|
LutRed2 = 0x27,
|
||||||
/// This command builds the Red3 Look-Up Table (LUTR3).
|
/// This command builds the Red3 Look-Up Table (LUTR3).
|
||||||
LUT_RED_3 = 0x28,
|
LutRed3 = 0x28,
|
||||||
/// This command builds the XON Look-Up Table (LUTXON).
|
/// This command builds the XON Look-Up Table (LUTXON).
|
||||||
LUT_XON = 0x29,
|
LutXon = 0x29,
|
||||||
|
|
||||||
/// The command controls the PLL clock frequency.
|
/// The command controls the PLL clock frequency.
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
|
|
||||||
/// This command reads the temperature sensed by the temperature sensor.
|
/// This command reads the temperature sensed by the temperature sensor.
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
/// This command selects the Internal or External temperature sensor.
|
/// This command selects the Internal or External temperature sensor.
|
||||||
TEMPERATURE_CALIBRATION = 0x41,
|
TemperatureCalibration = 0x41,
|
||||||
/// This command could write data to the external temperature sensor.
|
/// This command could write data to the external temperature sensor.
|
||||||
TEMPERATURE_SENSOR_WRITE = 0x42,
|
TemperatureSensorWrite = 0x42,
|
||||||
/// This command could read data from the external temperature sensor.
|
/// This command could read data from the external temperature sensor.
|
||||||
TEMPERATURE_SENSOR_READ = 0x43,
|
TemperatureSensorRead = 0x43,
|
||||||
|
|
||||||
/// This command indicates the interval of Vcom and data output. When setting the
|
/// This command indicates the interval of Vcom and data output. When setting the
|
||||||
/// vertical back porch, the total blanking will be kept (20 Hsync).
|
/// vertical back porch, the total blanking will be kept (20 Hsync).
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
/// This command indicates the input power condition. Host can read this flag to learn
|
/// This command indicates the input power condition. Host can read this flag to learn
|
||||||
/// the battery condition.
|
/// the battery condition.
|
||||||
LOW_POWER_DETECTION = 0x51,
|
LowPowerDetection = 0x51,
|
||||||
|
|
||||||
/// This command defines non-overlap period of Gate and Source.
|
/// This command defines non-overlap period of Gate and Source.
|
||||||
TCON_SETTING = 0x60,
|
TconSetting = 0x60,
|
||||||
/// This command defines alternative resolution and this setting is of higher priority
|
/// This command defines alternative resolution and this setting is of higher priority
|
||||||
/// than the RES\[1:0\] in R00H (PSR).
|
/// than the RES\[1:0\] in R00H (PSR).
|
||||||
TCON_RESOLUTION = 0x61,
|
TconResolution = 0x61,
|
||||||
/// This command defines MCU host direct access external memory mode.
|
/// This command defines MCU host direct access external memory mode.
|
||||||
SPI_FLASH_CONTROL = 0x65,
|
SpiFlashControl = 0x65,
|
||||||
|
|
||||||
/// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000.
|
/// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000.
|
||||||
REVISION = 0x70,
|
REVISION = 0x70,
|
||||||
/// This command reads the IC status.
|
/// This command reads the IC status.
|
||||||
GET_STATUS = 0x71,
|
GetStatus = 0x71,
|
||||||
|
|
||||||
/// This command implements related VCOM sensing setting.
|
/// This command implements related VCOM sensing setting.
|
||||||
AUTO_MEASUREMENT_VCOM = 0x80,
|
AutoMeasurementVcom = 0x80,
|
||||||
/// This command gets the VCOM value.
|
/// This command gets the VCOM value.
|
||||||
READ_VCOM_VALUE = 0x81,
|
ReadVcomValue = 0x81,
|
||||||
/// This command sets `VCOM_DC` value.
|
/// This command sets `VCOM_DC` value.
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
|
|
||||||
/// This is in all the Waveshare controllers for EPD7in5, but it's not documented
|
/// This is in all the Waveshare controllers for EPD7in5, but it's not documented
|
||||||
/// anywhere in the datasheet `¯\_(ツ)_/¯`
|
/// anywhere in the datasheet `¯\_(ツ)_/¯`
|
||||||
FLASH_MODE = 0xE5,
|
FlashMode = 0xE5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
@ -148,7 +147,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
assert_eq!(Command::PANEL_SETTING.address(), 0x00);
|
assert_eq!(Command::PanelSetting.address(), 0x00);
|
||||||
assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12);
|
assert_eq!(Command::DisplayRefresh.address(), 0x12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,41 +58,41 @@ where
|
||||||
self.interface.reset(delay, 10);
|
self.interface.reset(delay, 10);
|
||||||
|
|
||||||
// Set the power settings
|
// Set the power settings
|
||||||
self.cmd_with_data(spi, Command::POWER_SETTING, &[0x37, 0x00])?;
|
self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00])?;
|
||||||
|
|
||||||
// Set the panel settings:
|
// Set the panel settings:
|
||||||
// - 600 x 448
|
// - 600 x 448
|
||||||
// - Using LUT from external flash
|
// - Using LUT from external flash
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xCF, 0x08])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0xCF, 0x08])?;
|
||||||
|
|
||||||
// Start the booster
|
// Start the booster
|
||||||
self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0xC7, 0xCC, 0x28])?;
|
self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xCC, 0x28])?;
|
||||||
|
|
||||||
// Power on
|
// Power on
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
delay.delay_ms(5);
|
delay.delay_ms(5);
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
|
|
||||||
// Set the clock frequency to 50Hz (default)
|
// Set the clock frequency to 50Hz (default)
|
||||||
self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3C])?;
|
self.cmd_with_data(spi, Command::PllControl, &[0x3C])?;
|
||||||
|
|
||||||
// Select internal temperature sensor (default)
|
// Select internal temperature sensor (default)
|
||||||
self.cmd_with_data(spi, Command::TEMPERATURE_CALIBRATION, &[0x00])?;
|
self.cmd_with_data(spi, Command::TemperatureCalibration, &[0x00])?;
|
||||||
|
|
||||||
// Set Vcom and data interval to 10 (default), border output to white
|
// Set Vcom and data interval to 10 (default), border output to white
|
||||||
self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x77])?;
|
self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77])?;
|
||||||
|
|
||||||
// Set S2G and G2S non-overlap periods to 12 (default)
|
// Set S2G and G2S non-overlap periods to 12 (default)
|
||||||
self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?;
|
self.cmd_with_data(spi, Command::TconSetting, &[0x22])?;
|
||||||
|
|
||||||
// Set the real resolution
|
// Set the real resolution
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
// Set VCOM_DC to -1.5V
|
// Set VCOM_DC to -1.5V
|
||||||
self.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x1E])?;
|
self.cmd_with_data(spi, Command::VcmDcSetting, &[0x1E])?;
|
||||||
|
|
||||||
// This is in all the Waveshare controllers for EPD7in5
|
// This is in all the Waveshare controllers for EPD7in5
|
||||||
self.cmd_with_data(spi, Command::FLASH_MODE, &[0x03])?;
|
self.cmd_with_data(spi, Command::FlashMode, &[0x03])?;
|
||||||
|
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -137,15 +137,15 @@ where
|
||||||
|
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?;
|
self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_1)?;
|
self.command(spi, Command::DataStartTransmission1)?;
|
||||||
for byte in buffer {
|
for byte in buffer {
|
||||||
let mut temp = *byte;
|
let mut temp = *byte;
|
||||||
for _ in 0..4 {
|
for _ in 0..4 {
|
||||||
|
|
@ -174,13 +174,13 @@ where
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.update_frame(spi, buffer)?;
|
self.update_frame(spi, buffer)?;
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -189,7 +189,7 @@ where
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
// The Waveshare controllers all implement clear using 0x33
|
// The Waveshare controllers all implement clear using 0x33
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_1)?;
|
self.command(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface
|
self.interface
|
||||||
.data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4)?;
|
.data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -257,7 +257,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::TCON_RESOLUTION)?;
|
self.command(spi, Command::TconResolution)?;
|
||||||
self.send_data(spi, &[(w >> 8) as u8])?;
|
self.send_data(spi, &[(w >> 8) as u8])?;
|
||||||
self.send_data(spi, &[w as u8])?;
|
self.send_data(spi, &[w as u8])?;
|
||||||
self.send_data(spi, &[(h >> 8) as u8])?;
|
self.send_data(spi, &[(h >> 8) as u8])?;
|
||||||
|
|
|
||||||
|
|
@ -8,130 +8,129 @@ use crate::traits;
|
||||||
///
|
///
|
||||||
/// For more infos about the addresses and what they are doing look into the PDFs.
|
/// For more infos about the addresses and what they are doing look into the PDFs.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift
|
/// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift
|
||||||
/// direction, booster switch, soft reset.
|
/// direction, booster switch, soft reset.
|
||||||
PANEL_SETTING = 0x00,
|
PanelSetting = 0x00,
|
||||||
|
|
||||||
/// Selecting internal and external power
|
/// Selecting internal and external power
|
||||||
POWER_SETTING = 0x01,
|
PowerSetting = 0x01,
|
||||||
|
|
||||||
/// After the Power Off command, the driver will power off following the Power Off
|
/// After the Power Off command, the driver will power off following the Power Off
|
||||||
/// Sequence; BUSY signal will become "0". This command will turn off charge pump,
|
/// Sequence; BUSY signal will become "0". This command will turn off charge pump,
|
||||||
/// T-con, source driver, gate driver, VCOM, and temperature sensor, but register
|
/// T-con, source driver, gate driver, VCOM, and temperature sensor, but register
|
||||||
/// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain
|
/// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain
|
||||||
/// as previous condition, which may have 2 conditions: 0V or floating.
|
/// as previous condition, which may have 2 conditions: 0V or floating.
|
||||||
POWER_OFF = 0x02,
|
PowerOff = 0x02,
|
||||||
|
|
||||||
/// Setting Power OFF sequence
|
/// Setting Power OFF sequence
|
||||||
POWER_OFF_SEQUENCE_SETTING = 0x03,
|
PowerOffSequenceSetting = 0x03,
|
||||||
|
|
||||||
/// Turning On the Power
|
/// Turning On the Power
|
||||||
///
|
///
|
||||||
/// After the Power ON command, the driver will power on following the Power ON
|
/// After the Power ON command, the driver will power on following the Power ON
|
||||||
/// sequence. Once complete, the BUSY signal will become "1".
|
/// sequence. Once complete, the BUSY signal will become "1".
|
||||||
POWER_ON = 0x04,
|
PowerOn = 0x04,
|
||||||
|
|
||||||
/// Starting data transmission
|
/// Starting data transmission
|
||||||
BOOSTER_SOFT_START = 0x06,
|
BoosterSoftStart = 0x06,
|
||||||
|
|
||||||
/// This command makes the chip enter the deep-sleep mode to save power.
|
/// This command makes the chip enter the deep-sleep mode to save power.
|
||||||
///
|
///
|
||||||
/// The deep sleep mode would return to stand-by by hardware reset.
|
/// The deep sleep mode would return to stand-by by hardware reset.
|
||||||
///
|
///
|
||||||
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
/// The only one parameter is a check code, the command would be excuted if check code = 0xA5.
|
||||||
DEEP_SLEEP = 0x07,
|
DeepSleep = 0x07,
|
||||||
|
|
||||||
/// This command starts transmitting data and write them into SRAM. To complete data
|
/// This command starts transmitting data and write them into SRAM. To complete data
|
||||||
/// transmission, command DSP (Data Stop) must be issued. Then the chip will start to
|
/// transmission, command DSP (Data Stop) must be issued. Then the chip will start to
|
||||||
/// send data/VCOM for panel.
|
/// send data/VCOM for panel.
|
||||||
///
|
///
|
||||||
/// BLACK/WHITE or OLD_DATA
|
/// BLACK/WHITE or OLD_DATA
|
||||||
DATA_START_TRANSMISSION_1 = 0x10,
|
DataStartTransmission1 = 0x10,
|
||||||
|
|
||||||
/// To stop data transmission, this command must be issued to check the `data_flag`.
|
/// To stop data transmission, this command must be issued to check the `data_flag`.
|
||||||
///
|
///
|
||||||
/// After this command, BUSY signal will become "0" until the display update is
|
/// After this command, BUSY signal will become "0" until the display update is
|
||||||
/// finished.
|
/// finished.
|
||||||
DATA_STOP = 0x11,
|
DataStop = 0x11,
|
||||||
|
|
||||||
/// After this command is issued, driver will refresh display (data/VCOM) according to
|
/// After this command is issued, driver will refresh display (data/VCOM) according to
|
||||||
/// SRAM data and LUT.
|
/// SRAM data and LUT.
|
||||||
///
|
///
|
||||||
/// After Display Refresh command, BUSY signal will become "0" until the display
|
/// After Display Refresh command, BUSY signal will become "0" until the display
|
||||||
/// update is finished.
|
/// update is finished.
|
||||||
DISPLAY_REFRESH = 0x12,
|
DisplayRefresh = 0x12,
|
||||||
|
|
||||||
/// RED or NEW_DATA
|
/// RED or NEW_DATA
|
||||||
DATA_START_TRANSMISSION_2 = 0x13,
|
DataStartTransmission2 = 0x13,
|
||||||
|
|
||||||
/// Dual SPI - what for?
|
/// Dual SPI - what for?
|
||||||
DUAL_SPI = 0x15,
|
DualSpi = 0x15,
|
||||||
|
|
||||||
/// This command builds the VCOM Look-Up Table (LUTC).
|
/// This command builds the VCOM Look-Up Table (LUTC).
|
||||||
LUT_FOR_VCOM = 0x20,
|
LutForVcom = 0x20,
|
||||||
/// This command builds the Black Look-Up Table (LUTB).
|
/// This command builds the Black Look-Up Table (LUTB).
|
||||||
LUT_BLACK = 0x21,
|
LutBlack = 0x21,
|
||||||
/// This command builds the White Look-Up Table (LUTW).
|
/// This command builds the White Look-Up Table (LUTW).
|
||||||
LUT_WHITE = 0x22,
|
LutWhite = 0x22,
|
||||||
/// This command builds the Gray1 Look-Up Table (LUTG1).
|
/// This command builds the Gray1 Look-Up Table (LUTG1).
|
||||||
LUT_GRAY_1 = 0x23,
|
LutGray1 = 0x23,
|
||||||
/// This command builds the Gray2 Look-Up Table (LUTG2).
|
/// This command builds the Gray2 Look-Up Table (LUTG2).
|
||||||
LUT_GRAY_2 = 0x24,
|
LutGray2 = 0x24,
|
||||||
/// This command builds the Red0 Look-Up Table (LUTR0).
|
/// This command builds the Red0 Look-Up Table (LUTR0).
|
||||||
LUT_RED_0 = 0x25,
|
LutRed0 = 0x25,
|
||||||
/// This command builds the Red1 Look-Up Table (LUTR1).
|
/// This command builds the Red1 Look-Up Table (LUTR1).
|
||||||
LUT_RED_1 = 0x26,
|
LutRed1 = 0x26,
|
||||||
/// This command builds the Red2 Look-Up Table (LUTR2).
|
/// This command builds the Red2 Look-Up Table (LUTR2).
|
||||||
LUT_RED_2 = 0x27,
|
LutRed2 = 0x27,
|
||||||
/// This command builds the Red3 Look-Up Table (LUTR3).
|
/// This command builds the Red3 Look-Up Table (LUTR3).
|
||||||
LUT_RED_3 = 0x28,
|
LutRed3 = 0x28,
|
||||||
/// This command builds the XON Look-Up Table (LUTXON).
|
/// This command builds the XON Look-Up Table (LUTXON).
|
||||||
LUT_XON = 0x29,
|
LutXon = 0x29,
|
||||||
|
|
||||||
/// The command controls the PLL clock frequency.
|
/// The command controls the PLL clock frequency.
|
||||||
PLL_CONTROL = 0x30,
|
PllControl = 0x30,
|
||||||
|
|
||||||
/// This command reads the temperature sensed by the temperature sensor.
|
/// This command reads the temperature sensed by the temperature sensor.
|
||||||
TEMPERATURE_SENSOR_COMMAND = 0x40,
|
TemperatureSensorCommand = 0x40,
|
||||||
/// This command selects the Internal or External temperature sensor.
|
/// This command selects the Internal or External temperature sensor.
|
||||||
TEMPERATURE_CALIBRATION = 0x41,
|
TemperatureCalibration = 0x41,
|
||||||
/// This command could write data to the external temperature sensor.
|
/// This command could write data to the external temperature sensor.
|
||||||
TEMPERATURE_SENSOR_WRITE = 0x42,
|
TemperatureSensorWrite = 0x42,
|
||||||
/// This command could read data from the external temperature sensor.
|
/// This command could read data from the external temperature sensor.
|
||||||
TEMPERATURE_SENSOR_READ = 0x43,
|
TemperatureSensorRead = 0x43,
|
||||||
|
|
||||||
/// This command indicates the interval of Vcom and data output. When setting the
|
/// This command indicates the interval of Vcom and data output. When setting the
|
||||||
/// vertical back porch, the total blanking will be kept (20 Hsync).
|
/// vertical back porch, the total blanking will be kept (20 Hsync).
|
||||||
VCOM_AND_DATA_INTERVAL_SETTING = 0x50,
|
VcomAndDataIntervalSetting = 0x50,
|
||||||
/// This command indicates the input power condition. Host can read this flag to learn
|
/// This command indicates the input power condition. Host can read this flag to learn
|
||||||
/// the battery condition.
|
/// the battery condition.
|
||||||
LOW_POWER_DETECTION = 0x51,
|
LowPowerDetection = 0x51,
|
||||||
|
|
||||||
/// This command defines non-overlap period of Gate and Source.
|
/// This command defines non-overlap period of Gate and Source.
|
||||||
TCON_SETTING = 0x60,
|
TconSetting = 0x60,
|
||||||
/// This command defines alternative resolution and this setting is of higher priority
|
/// This command defines alternative resolution and this setting is of higher priority
|
||||||
/// than the RES\[1:0\] in R00H (PSR).
|
/// than the RES\[1:0\] in R00H (PSR).
|
||||||
TCON_RESOLUTION = 0x61,
|
TconResolution = 0x61,
|
||||||
/// This command defines MCU host direct access external memory mode.
|
/// This command defines MCU host direct access external memory mode.
|
||||||
SPI_FLASH_CONTROL = 0x65,
|
SpiFlashControl = 0x65,
|
||||||
|
|
||||||
/// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000.
|
/// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000.
|
||||||
REVISION = 0x70,
|
REVISION = 0x70,
|
||||||
/// This command reads the IC status.
|
/// This command reads the IC status.
|
||||||
GET_STATUS = 0x71,
|
GetStatus = 0x71,
|
||||||
|
|
||||||
/// This command implements related VCOM sensing setting.
|
/// This command implements related VCOM sensing setting.
|
||||||
AUTO_MEASUREMENT_VCOM = 0x80,
|
AutoMeasurementVcom = 0x80,
|
||||||
/// This command gets the VCOM value.
|
/// This command gets the VCOM value.
|
||||||
READ_VCOM_VALUE = 0x81,
|
ReadVcomValue = 0x81,
|
||||||
/// This command sets `VCOM_DC` value.
|
/// This command sets `VCOM_DC` value.
|
||||||
VCM_DC_SETTING = 0x82,
|
VcmDcSetting = 0x82,
|
||||||
// /// This is in all the Waveshare controllers for EPD7in5, but it's not documented
|
// /// This is in all the Waveshare controllers for EPD7in5, but it's not documented
|
||||||
// /// anywhere in the datasheet `¯\_(ツ)_/¯`
|
// /// anywhere in the datasheet `¯\_(ツ)_/¯`
|
||||||
// FLASH_MODE = 0xE5,
|
// FlashMode = 0xE5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl traits::Command for Command {
|
impl traits::Command for Command {
|
||||||
|
|
@ -148,7 +147,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
assert_eq!(Command::PANEL_SETTING.address(), 0x00);
|
assert_eq!(Command::PanelSetting.address(), 0x00);
|
||||||
assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12);
|
assert_eq!(Command::DisplayRefresh.address(), 0x12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,16 +66,16 @@ where
|
||||||
// and as per specs:
|
// and as per specs:
|
||||||
// https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf
|
// https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf
|
||||||
|
|
||||||
self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x27, 0x17])?;
|
self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?;
|
||||||
self.cmd_with_data(spi, Command::POWER_SETTING, &[0x07, 0x17, 0x3F, 0x3F])?;
|
self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x17, 0x3F, 0x3F])?;
|
||||||
self.command(spi, Command::POWER_ON)?;
|
self.command(spi, Command::PowerOn)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x1F])?;
|
self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?;
|
||||||
self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x06])?;
|
self.cmd_with_data(spi, Command::PllControl, &[0x06])?;
|
||||||
self.cmd_with_data(spi, Command::TCON_RESOLUTION, &[0x03, 0x20, 0x01, 0xE0])?;
|
self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?;
|
||||||
self.cmd_with_data(spi, Command::DUAL_SPI, &[0x00])?;
|
self.cmd_with_data(spi, Command::DualSpi, &[0x00])?;
|
||||||
self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?;
|
self.cmd_with_data(spi, Command::TconSetting, &[0x22])?;
|
||||||
self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x10, 0x07])?;
|
self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07])?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -119,15 +119,15 @@ where
|
||||||
|
|
||||||
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::POWER_OFF)?;
|
self.command(spi, Command::PowerOff)?;
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?;
|
self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, buffer)?;
|
self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,13 +145,13 @@ where
|
||||||
|
|
||||||
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> {
|
||||||
self.update_frame(spi, buffer)?;
|
self.update_frame(spi, buffer)?;
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,13 +159,13 @@ where
|
||||||
self.wait_until_idle();
|
self.wait_until_idle();
|
||||||
self.send_resolution(spi)?;
|
self.send_resolution(spi)?;
|
||||||
|
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_1)?;
|
self.command(spi, Command::DataStartTransmission1)?;
|
||||||
self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?;
|
self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?;
|
||||||
|
|
||||||
self.command(spi, Command::DATA_START_TRANSMISSION_2)?;
|
self.command(spi, Command::DataStartTransmission2)?;
|
||||||
self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?;
|
self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?;
|
||||||
|
|
||||||
self.command(spi, Command::DISPLAY_REFRESH)?;
|
self.command(spi, Command::DisplayRefresh)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -231,7 +231,7 @@ where
|
||||||
let w = self.width();
|
let w = self.width();
|
||||||
let h = self.height();
|
let h = self.height();
|
||||||
|
|
||||||
self.command(spi, Command::TCON_RESOLUTION)?;
|
self.command(spi, Command::TconResolution)?;
|
||||||
self.send_data(spi, &[(w >> 8) as u8])?;
|
self.send_data(spi, &[(w >> 8) as u8])?;
|
||||||
self.send_data(spi, &[w as u8])?;
|
self.send_data(spi, &[w as u8])?;
|
||||||
self.send_data(spi, &[(h >> 8) as u8])?;
|
self.send_data(spi, &[(h >> 8) as u8])?;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ use crate::traits;
|
||||||
///
|
///
|
||||||
/// For more infos about the addresses and what they are doing look into the pdfs
|
/// For more infos about the addresses and what they are doing look into the pdfs
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub(crate) enum Command {
|
pub(crate) enum Command {
|
||||||
/// Driver Output control
|
/// Driver Output control
|
||||||
|
|
@ -17,56 +16,56 @@ pub(crate) enum Command {
|
||||||
/// 0.. A[8]
|
/// 0.. A[8]
|
||||||
/// 0.. B[2:0]
|
/// 0.. B[2:0]
|
||||||
/// Default: Set A[8:0] = 0x127 and B[2:0] = 0x0
|
/// Default: Set A[8:0] = 0x127 and B[2:0] = 0x0
|
||||||
DRIVER_OUTPUT_CONTROL = 0x01,
|
DriverOutputControl = 0x01,
|
||||||
/// Booster Soft start control
|
/// Booster Soft start control
|
||||||
/// 3 Databytes:
|
/// 3 Databytes:
|
||||||
/// 1.. A[6:0]
|
/// 1.. A[6:0]
|
||||||
/// 1.. B[6:0]
|
/// 1.. B[6:0]
|
||||||
/// 1.. C[6:0]
|
/// 1.. C[6:0]
|
||||||
/// Default: A[7:0] = 0xCF, B[7:0] = 0xCE, C[7:0] = 0x8D
|
/// Default: A[7:0] = 0xCF, B[7:0] = 0xCE, C[7:0] = 0x8D
|
||||||
BOOSTER_SOFT_START_CONTROL = 0x0C,
|
BoosterSoftStartControl = 0x0C,
|
||||||
GATE_SCAN_START_POSITION = 0x0F,
|
GateScanStartPosition = 0x0F,
|
||||||
//TODO: useful?
|
//TODO: useful?
|
||||||
// GATE_SCAN_START_POSITION = 0x0F,
|
// GateScanStartPosition = 0x0F,
|
||||||
/// Deep Sleep Mode Control
|
/// Deep Sleep Mode Control
|
||||||
/// 1 Databyte:
|
/// 1 Databyte:
|
||||||
/// 0.. A[0]
|
/// 0.. A[0]
|
||||||
/// Values:
|
/// Values:
|
||||||
/// A[0] = 0: Normal Mode (POR)
|
/// A[0] = 0: Normal Mode (POR)
|
||||||
/// A[0] = 1: Enter Deep Sleep Mode
|
/// A[0] = 1: Enter Deep Sleep Mode
|
||||||
DEEP_SLEEP_MODE = 0x10,
|
DeepSleepMode = 0x10,
|
||||||
// /// Data Entry mode setting
|
// /// Data Entry mode setting
|
||||||
DATA_ENTRY_MODE_SETTING = 0x11,
|
DataEntryModeSetting = 0x11,
|
||||||
|
|
||||||
SW_RESET = 0x12,
|
SwReset = 0x12,
|
||||||
|
|
||||||
TEMPERATURE_SENSOR_CONTROL = 0x1A,
|
TemperatureSensorControl = 0x1A,
|
||||||
|
|
||||||
MASTER_ACTIVATION = 0x20,
|
MasterActivation = 0x20,
|
||||||
|
|
||||||
DISPLAY_UPDATE_CONTROL_1 = 0x21,
|
DisplayUpdateControl1 = 0x21,
|
||||||
|
|
||||||
DISPLAY_UPDATE_CONTROL_2 = 0x22,
|
DisplayUpdateControl2 = 0x22,
|
||||||
|
|
||||||
WRITE_RAM = 0x24,
|
WriteRam = 0x24,
|
||||||
|
|
||||||
WRITE_VCOM_REGISTER = 0x2C,
|
WriteVcomRegister = 0x2C,
|
||||||
|
|
||||||
WRITE_LUT_REGISTER = 0x32,
|
WriteLutRegister = 0x32,
|
||||||
|
|
||||||
SET_DUMMY_LINE_PERIOD = 0x3A,
|
SetDummyLinePeriod = 0x3A,
|
||||||
|
|
||||||
SET_GATE_LINE_WIDTH = 0x3B,
|
SetGateLineWidth = 0x3B,
|
||||||
|
|
||||||
BORDER_WAVEFORM_CONTROL = 0x3C,
|
BorderWaveformControl = 0x3C,
|
||||||
|
|
||||||
SET_RAM_X_ADDRESS_START_END_POSITION = 0x44,
|
SetRamXAddressStartEndPosition = 0x44,
|
||||||
|
|
||||||
SET_RAM_Y_ADDRESS_START_END_POSITION = 0x45,
|
SetRamYAddressStartEndPosition = 0x45,
|
||||||
|
|
||||||
SET_RAM_X_ADDRESS_COUNTER = 0x4E,
|
SetRamXAddressCounter = 0x4E,
|
||||||
|
|
||||||
SET_RAM_Y_ADDRESS_COUNTER = 0x4F,
|
SetRamYAddressCounter = 0x4F,
|
||||||
|
|
||||||
NOP = 0xFF,
|
NOP = 0xFF,
|
||||||
}
|
}
|
||||||
|
|
@ -85,9 +84,9 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn command_addr() {
|
fn command_addr() {
|
||||||
assert_eq!(Command::DRIVER_OUTPUT_CONTROL.address(), 0x01);
|
assert_eq!(Command::DriverOutputControl.address(), 0x01);
|
||||||
|
|
||||||
assert_eq!(Command::SET_RAM_X_ADDRESS_COUNTER.address(), 0x4E);
|
assert_eq!(Command::SetRamXAddressCounter.address(), 0x4E);
|
||||||
|
|
||||||
assert_eq!(Command::NOP.address(), 0xFF);
|
assert_eq!(Command::NOP.address(), 0xFF);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue