|
|
|
|
@ -80,7 +80,7 @@ where
|
|
|
|
|
self.set_lut(spi, Some(self.refresh))?; |
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
// updates.
|
|
|
|
|
@ -88,7 +88,7 @@ where
|
|
|
|
|
spi, |
|
|
|
|
DisplayUpdateControl2::new().enable_analog().enable_clock(), |
|
|
|
|
)?; |
|
|
|
|
self.command(spi, Command::MASTER_ACTIVATION)?; |
|
|
|
|
self.command(spi, Command::MasterActivation)?; |
|
|
|
|
self.wait_until_idle(); |
|
|
|
|
|
|
|
|
|
self.set_border_waveform( |
|
|
|
|
@ -101,7 +101,7 @@ where
|
|
|
|
|
)?; |
|
|
|
|
} else { |
|
|
|
|
self.wait_until_idle(); |
|
|
|
|
self.command(spi, Command::SW_RESET)?; |
|
|
|
|
self.command(spi, Command::SwReset)?; |
|
|
|
|
self.wait_until_idle(); |
|
|
|
|
|
|
|
|
|
self.set_driver_output( |
|
|
|
|
@ -118,11 +118,7 @@ where
|
|
|
|
|
self.set_dummy_line_period(spi, 0x30)?; |
|
|
|
|
self.set_gate_scan_start_position(spi, 0)?; |
|
|
|
|
|
|
|
|
|
self.set_data_entry_mode( |
|
|
|
|
spi, |
|
|
|
|
DataEntryModeIncr::X_INCR_Y_INCR, |
|
|
|
|
DataEntryModeDir::X_DIR, |
|
|
|
|
)?; |
|
|
|
|
self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir)?; |
|
|
|
|
|
|
|
|
|
// Use simple X/Y auto increase
|
|
|
|
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; |
|
|
|
|
@ -177,7 +173,7 @@ where
|
|
|
|
|
) -> Result<Self, SPI::Error> { |
|
|
|
|
let mut epd = EPD2in13 { |
|
|
|
|
interface: DisplayInterface::new(cs, busy, dc, rst), |
|
|
|
|
sleep_mode: DeepSleepMode::MODE_1, |
|
|
|
|
sleep_mode: DeepSleepMode::Mode1, |
|
|
|
|
background_color: DEFAULT_BACKGROUND_COLOR, |
|
|
|
|
refresh: RefreshLUT::FULL, |
|
|
|
|
}; |
|
|
|
|
@ -206,7 +202,7 @@ where
|
|
|
|
|
.disable_analog() |
|
|
|
|
.disable_clock(), |
|
|
|
|
)?; |
|
|
|
|
self.command(spi, Command::MASTER_ACTIVATION)?; |
|
|
|
|
self.command(spi, Command::MasterActivation)?; |
|
|
|
|
|
|
|
|
|
self.set_sleep_mode(spi, self.sleep_mode)?; |
|
|
|
|
Ok(()) |
|
|
|
|
@ -217,14 +213,14 @@ where
|
|
|
|
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; |
|
|
|
|
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 { |
|
|
|
|
// 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_address_counters(spi, 0, 0)?; |
|
|
|
|
|
|
|
|
|
self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?; |
|
|
|
|
self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
@ -254,14 +250,14 @@ where
|
|
|
|
|
self.set_ram_area(spi, x, y, x + width, y + height)?; |
|
|
|
|
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 { |
|
|
|
|
// 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_address_counters(spi, x, y)?; |
|
|
|
|
|
|
|
|
|
self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?; |
|
|
|
|
self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
@ -283,7 +279,7 @@ where
|
|
|
|
|
} else { |
|
|
|
|
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(); |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
@ -305,7 +301,7 @@ where
|
|
|
|
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; |
|
|
|
|
self.set_ram_address_counters(spi, 0, 0)?; |
|
|
|
|
|
|
|
|
|
self.command(spi, Command::WRITE_RAM)?; |
|
|
|
|
self.command(spi, Command::WriteRam)?; |
|
|
|
|
self.interface.data_x_times( |
|
|
|
|
spi, |
|
|
|
|
color, |
|
|
|
|
@ -317,7 +313,7 @@ where
|
|
|
|
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; |
|
|
|
|
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( |
|
|
|
|
spi, |
|
|
|
|
color, |
|
|
|
|
@ -353,7 +349,7 @@ where
|
|
|
|
|
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 { |
|
|
|
|
@ -380,7 +376,7 @@ where
|
|
|
|
|
self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; |
|
|
|
|
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(()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -412,7 +408,7 @@ where
|
|
|
|
|
assert!(start <= 295); |
|
|
|
|
self.cmd_with_data( |
|
|
|
|
spi, |
|
|
|
|
Command::GATE_SCAN_START_POSITION, |
|
|
|
|
Command::GateScanStartPosition, |
|
|
|
|
&[(start & 0xFF) as u8, ((start >> 8) & 0x1) as u8], |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
@ -424,13 +420,13 @@ where
|
|
|
|
|
) -> Result<(), SPI::Error> { |
|
|
|
|
self.cmd_with_data( |
|
|
|
|
spi, |
|
|
|
|
Command::BORDER_WAVEFORM_CONTROL, |
|
|
|
|
Command::BorderWaveformControl, |
|
|
|
|
&[borderwaveform.to_u8()], |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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( |
|
|
|
|
@ -438,7 +434,7 @@ where
|
|
|
|
|
spi: &mut SPI, |
|
|
|
|
voltage: GateDrivingVoltage, |
|
|
|
|
) -> 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( |
|
|
|
|
@ -447,11 +443,11 @@ where
|
|
|
|
|
number_of_lines: u8, |
|
|
|
|
) -> Result<(), SPI::Error> { |
|
|
|
|
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> { |
|
|
|
|
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
|
|
|
|
|
@ -464,7 +460,7 @@ where
|
|
|
|
|
) -> Result<(), SPI::Error> { |
|
|
|
|
self.cmd_with_data( |
|
|
|
|
spi, |
|
|
|
|
Command::SOURCE_DRIVING_VOLTAGE_CTRL, |
|
|
|
|
Command::SourceDrivingVoltageCtrl, |
|
|
|
|
&[vsh1.0, vsh2.0, vsl.0], |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
@ -476,16 +472,16 @@ where
|
|
|
|
|
spi: &mut SPI, |
|
|
|
|
value: DisplayUpdateControl2, |
|
|
|
|
) -> 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
|
|
|
|
|
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> { |
|
|
|
|
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
|
|
|
|
|
@ -497,7 +493,7 @@ where
|
|
|
|
|
counter_direction: DataEntryModeDir, |
|
|
|
|
) -> Result<(), SPI::Error> { |
|
|
|
|
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
|
|
|
|
|
@ -511,13 +507,13 @@ where
|
|
|
|
|
) -> Result<(), SPI::Error> { |
|
|
|
|
self.cmd_with_data( |
|
|
|
|
spi, |
|
|
|
|
Command::SET_RAM_X_ADDRESS_START_END_POSITION, |
|
|
|
|
Command::SetRamXAddressStartEndPosition, |
|
|
|
|
&[(start_x >> 3) as u8, (end_x >> 3) as u8], |
|
|
|
|
)?; |
|
|
|
|
|
|
|
|
|
self.cmd_with_data( |
|
|
|
|
spi, |
|
|
|
|
Command::SET_RAM_Y_ADDRESS_START_END_POSITION, |
|
|
|
|
Command::SetRamYAddressStartEndPosition, |
|
|
|
|
&[ |
|
|
|
|
start_y as u8, |
|
|
|
|
(start_y >> 8) as u8, |
|
|
|
|
@ -535,11 +531,11 @@ where
|
|
|
|
|
y: u32, |
|
|
|
|
) -> Result<(), SPI::Error> { |
|
|
|
|
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( |
|
|
|
|
spi, |
|
|
|
|
Command::SET_RAM_Y_ADDRESS_COUNTER, |
|
|
|
|
Command::SetRamYAddressCounter, |
|
|
|
|
&[y as u8, (y >> 8) as u8], |
|
|
|
|
)?; |
|
|
|
|
Ok(()) |
|
|
|
|
|