Use init sequence from TDO
This commit is contained in:
parent
f3eaf0bc91
commit
ae7e727ad6
165
src/main.rs
165
src/main.rs
@ -1,14 +1,15 @@
|
|||||||
extern crate enum_primitive;
|
extern crate enum_primitive;
|
||||||
extern crate num;
|
extern crate num;
|
||||||
extern crate spidev;
|
extern crate spidev;
|
||||||
use std::{thread, time};
|
|
||||||
|
|
||||||
mod instructions;
|
mod instructions;
|
||||||
mod panel;
|
mod panel;
|
||||||
|
mod sequence_linux_kernel;
|
||||||
|
mod sequence_tdo;
|
||||||
mod spi;
|
mod spi;
|
||||||
|
|
||||||
use instructions::{BK0Command2, BK1Command2, Command, Command2Selection, CommandsGeneral};
|
|
||||||
use panel::TDOMode;
|
use panel::TDOMode;
|
||||||
|
use sequence_tdo::init;
|
||||||
use spi::ST7701S;
|
use spi::ST7701S;
|
||||||
|
|
||||||
/// ST7701S supports two kinds of RGB interface, DE mode (mode 1) and HV mode
|
/// ST7701S supports two kinds of RGB interface, DE mode (mode 1) and HV mode
|
||||||
@ -19,166 +20,8 @@ use spi::ST7701S;
|
|||||||
fn main() {
|
fn main() {
|
||||||
println!("Initializing SPI driver for ST7701S panel");
|
println!("Initializing SPI driver for ST7701S panel");
|
||||||
|
|
||||||
let mut CMD2: Command2Selection = Command2Selection::Disabled;
|
|
||||||
let mut display = ST7701S::new(String::from("/dev/spidev1.0"));
|
let mut display = ST7701S::new(String::from("/dev/spidev1.0"));
|
||||||
let mode = TDOMode;
|
let mode = TDOMode;
|
||||||
|
|
||||||
// SOFTWARE RESET
|
init(&mut display, mode);
|
||||||
// 5ms delay
|
|
||||||
display.write_command(CommandsGeneral::software_reset());
|
|
||||||
thread::sleep(time::Duration::from_millis(10));
|
|
||||||
|
|
||||||
// EXIT SLEEP MODE
|
|
||||||
// Variable delay (200ms is "safe")
|
|
||||||
display.write_command(CommandsGeneral::sleep_mode_off());
|
|
||||||
thread::sleep(time::Duration::from_millis(300));
|
|
||||||
|
|
||||||
// ENTER BK0 COMMAND2 MODE
|
|
||||||
display.write_command(CommandsGeneral::set_command_2(Command2Selection::BK0));
|
|
||||||
CMD2 = Command2Selection::BK0;
|
|
||||||
|
|
||||||
display.write_command(BK0Command2::positive_gamma_control(
|
|
||||||
&CMD2,
|
|
||||||
&[
|
|
||||||
0x00, 0x0E, 0x15, 0x0F, 0x11, 0x08, 0x08, 0x08, 0x08, 0x23, 0x04, 0x13, 0x12, 0x2B,
|
|
||||||
0x34, 0x1F,
|
|
||||||
],
|
|
||||||
));
|
|
||||||
display.write_command(BK0Command2::negative_gamma_control(
|
|
||||||
&CMD2,
|
|
||||||
&[
|
|
||||||
0x00, 0x0E, 0x95, 0x0F, 0x13, 0x07, 0x09, 0x08, 0x08, 0x22, 0x04, 0x10, 0x0E, 0x2C,
|
|
||||||
0x34, 0x1F,
|
|
||||||
],
|
|
||||||
));
|
|
||||||
display.write_command(BK0Command2::display_line_setting(&CMD2, 0x80, 0x69, 0x02));
|
|
||||||
display.write_command(BK0Command2::porch_control(&CMD2, &mode));
|
|
||||||
display.write_command(BK0Command2::inversion_select(
|
|
||||||
&CMD2,
|
|
||||||
instructions::Inversion::Column,
|
|
||||||
0xFF,
|
|
||||||
));
|
|
||||||
display.write_command(BK0Command2::rgb_control(
|
|
||||||
&CMD2,
|
|
||||||
instructions::DataEnable::DE,
|
|
||||||
instructions::VsyncActive::Low,
|
|
||||||
instructions::HsyncActive::Low,
|
|
||||||
instructions::DataPolarity::Rising,
|
|
||||||
instructions::EnablePolarity::Low,
|
|
||||||
&mode,
|
|
||||||
));
|
|
||||||
|
|
||||||
// ENTER BK1 COMMAND2 MODE
|
|
||||||
display.write_command(CommandsGeneral::set_command_2(Command2Selection::BK1));
|
|
||||||
CMD2 = Command2Selection::BK1;
|
|
||||||
|
|
||||||
display.write_command(BK1Command2::set_vop_amplitude(&CMD2, 0x45));
|
|
||||||
display.write_command(BK1Command2::set_vcom_amplitude(&CMD2, 0x13));
|
|
||||||
display.write_command(BK1Command2::set_vgh_voltage(&CMD2, 0x07));
|
|
||||||
display.write_command(BK1Command2::test_command_setting(&CMD2));
|
|
||||||
display.write_command(BK1Command2::set_vgl_voltage(&CMD2, 0x07));
|
|
||||||
display.write_command(BK1Command2::power_control_one(
|
|
||||||
&CMD2,
|
|
||||||
instructions::GammaOPBias::Middle,
|
|
||||||
instructions::SourceOPInput::Min,
|
|
||||||
instructions::SourceOPOutput::Off,
|
|
||||||
));
|
|
||||||
|
|
||||||
display.write_command(BK1Command2::power_control_two(
|
|
||||||
&CMD2,
|
|
||||||
instructions::VoltageAVDD::Pos6_6,
|
|
||||||
instructions::VoltageAVCL::Neg4_4,
|
|
||||||
));
|
|
||||||
display.write_command(BK1Command2::set_pre_drive_timing_one(&CMD2, 0x03));
|
|
||||||
display.write_command(BK1Command2::set_pre_drive_timing_two(&CMD2, 0x03));
|
|
||||||
|
|
||||||
// UNKNOWABLE CARGO-CULTED MYSTERY MEAT
|
|
||||||
//
|
|
||||||
// I copied this command sequence from the Linux MIPI driver for the ST7701,
|
|
||||||
// written in C. The author of that driver _also_ had no idea what this
|
|
||||||
// command sequence does or means, and claims to have himself copied it from
|
|
||||||
// a sample provided by a Sitronix engineer. Since this is a Linux SPI
|
|
||||||
// driver for the ST7701S written in Rust, there's ample opportunity for
|
|
||||||
// something to not line up.
|
|
||||||
//
|
|
||||||
// May whatever gods you pray to have mercy on our souls.
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE0,
|
|
||||||
parameters: vec![0x00, 0x00, 0x02],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE1,
|
|
||||||
parameters: vec![
|
|
||||||
0x0B, 0x00, 0x0D, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x00, 0x44, 0x44,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE2,
|
|
||||||
parameters: vec![
|
|
||||||
0x33, 0x33, 0x44, 0x44, 0x64, 0x00, 0x66, 0x00, 0x65, 0x00, 0x67, 0x00, 0x00,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE3,
|
|
||||||
parameters: vec![0x00, 0x00, 0x33, 0x33],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE4,
|
|
||||||
parameters: vec![0x44, 0x44],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE5,
|
|
||||||
parameters: vec![
|
|
||||||
0x0C, 0x78, 0x3C, 0xA0, 0x0E, 0x78, 0x3C, 0xA0, 0x10, 0x78, 0x3C, 0xA0, 0x12, 0x78,
|
|
||||||
0x3C, 0xA0,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE6,
|
|
||||||
parameters: vec![0x00, 0x00, 0x33, 0x33],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE7,
|
|
||||||
parameters: vec![0x44, 0x44],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xE8,
|
|
||||||
parameters: vec![
|
|
||||||
0x0D, 0x78, 0x3C, 0xA0, 0x0F, 0x78, 0x3C, 0xA0, 0x11, 0x78, 0x3C, 0xA0, 0x13, 0x78,
|
|
||||||
0x3C, 0xA0,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xEB,
|
|
||||||
parameters: vec![0x02, 0x02, 0x39, 0x39, 0xEE, 0x44, 0x00],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xEC,
|
|
||||||
parameters: vec![0x00, 0x00],
|
|
||||||
}));
|
|
||||||
display.write_command(Ok(Command {
|
|
||||||
address: 0xED,
|
|
||||||
parameters: vec![
|
|
||||||
0xFF, 0xF1, 0x04, 0x56, 0x72, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0x27, 0x65, 0x40,
|
|
||||||
0x1F, 0xFF,
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
|
|
||||||
// BK1 COMMAND2 DISABLE
|
|
||||||
display.write_command(CommandsGeneral::set_command_2(Command2Selection::Disabled));
|
|
||||||
CMD2 = Command2Selection::Disabled;
|
|
||||||
|
|
||||||
display.write_command(CommandsGeneral::set_color_mode(
|
|
||||||
instructions::BitsPerPixel::Rgb666,
|
|
||||||
));
|
|
||||||
display.write_command(CommandsGeneral::display_data_control(
|
|
||||||
instructions::ScanDirection::Normal,
|
|
||||||
instructions::ColorOrder::Rgb,
|
|
||||||
));
|
|
||||||
display.write_command(CommandsGeneral::tearing_effect_on(
|
|
||||||
instructions::TearingEffect::VHBlank,
|
|
||||||
));
|
|
||||||
|
|
||||||
display.write_command(CommandsGeneral::display_on());
|
|
||||||
thread::sleep(time::Duration::from_millis(200));
|
|
||||||
}
|
}
|
||||||
|
164
src/sequence_tdo.rs
Normal file
164
src/sequence_tdo.rs
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
use std::{thread, time};
|
||||||
|
|
||||||
|
use crate::instructions;
|
||||||
|
use crate::instructions::{BK0Command2, BK1Command2, Command, Command2Selection, CommandsGeneral};
|
||||||
|
use crate::panel::Mode;
|
||||||
|
use crate::spi::ST7701S;
|
||||||
|
|
||||||
|
pub fn init(display: &mut ST7701S, mode: Mode) {
|
||||||
|
let mut CMD2: Command2Selection = Command2Selection::Disabled;
|
||||||
|
|
||||||
|
// Set Command2 for BK0
|
||||||
|
display.write_command(CommandsGeneral::set_command_2(Command2Selection::BK0));
|
||||||
|
CMD2 = Command2Selection::BK0;
|
||||||
|
|
||||||
|
display.write_command(BK0Command2::display_line_setting(&CMD2, 0x3B, 0x00, 0x00));
|
||||||
|
// Note: This will be off by one from the TDO spec:
|
||||||
|
// SPI_WriteComm(0xC1); // PORCTRL
|
||||||
|
// 0x0B); // V,
|
||||||
|
// 0x02); // V,
|
||||||
|
display.write_command(BK0Command2::porch_control(&CMD2, &mode));
|
||||||
|
display.write_command(BK0Command2::inversion_select(
|
||||||
|
&CMD2,
|
||||||
|
instructions::Inversion::OneDot,
|
||||||
|
0x02,
|
||||||
|
));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xCC,
|
||||||
|
parameters: vec![0x10],
|
||||||
|
}));
|
||||||
|
display.write_command(BK0Command2::color_control(
|
||||||
|
&CMD2,
|
||||||
|
instructions::PWMPolarity::Low,
|
||||||
|
instructions::LEDPolarity::Low,
|
||||||
|
instructions::PixelPinout::Condensed,
|
||||||
|
instructions::EndPixelFormat::SelfMSB,
|
||||||
|
));
|
||||||
|
display.write_command(BK0Command2::positive_gamma_control(
|
||||||
|
&CMD2,
|
||||||
|
&[
|
||||||
|
0x02, 0x13, 0x1B, 0x0D, 0x10, 0x05, 0x08, 0x07, 0x07, 0x24, 0x04, 0x11, 0x0E, 0x2C, 0x33,
|
||||||
|
0x1D,
|
||||||
|
],
|
||||||
|
));
|
||||||
|
display.write_command(BK0Command2::negative_gamma_control(
|
||||||
|
&CMD2,
|
||||||
|
&[
|
||||||
|
0xB1, 0x05, 0x13, 0x1B, 0x0D, 0x11, 0x05, 0x08, 0x07, 0x07, 0x24, 0x04, 0x11, 0x0E, 0x2C,
|
||||||
|
0x33, 0x1D,
|
||||||
|
],
|
||||||
|
));
|
||||||
|
|
||||||
|
// Set Command2 for BK1
|
||||||
|
display.write_command(CommandsGeneral::set_command_2(Command2Selection::BK1));
|
||||||
|
CMD2 = Command2Selection::BK1;
|
||||||
|
|
||||||
|
display.write_command(BK1Command2::set_vop_amplitude(&CMD2, 0x5d));
|
||||||
|
display.write_command(BK1Command2::set_vcom_amplitude(&CMD2, 0x43));
|
||||||
|
display.write_command(BK1Command2::set_vgh_voltage(&CMD2, 0x81));
|
||||||
|
display.write_command(BK1Command2::test_command_setting(&CMD2));
|
||||||
|
display.write_command(BK1Command2::set_vgl_voltage(&CMD2, 0x43));
|
||||||
|
display.write_command(BK1Command2::power_control_one(
|
||||||
|
&CMD2,
|
||||||
|
instructions::GammaOPBias::Middle,
|
||||||
|
instructions::SourceOPInput::Min,
|
||||||
|
instructions::SourceOPOutput::Min,
|
||||||
|
));
|
||||||
|
|
||||||
|
display.write_command(BK1Command2::power_control_two(
|
||||||
|
&CMD2,
|
||||||
|
instructions::VoltageAVDD::Pos6_6,
|
||||||
|
instructions::VoltageAVCL::Neg4_4,
|
||||||
|
));
|
||||||
|
display.write_command(BK1Command2::set_pre_drive_timing_one(&CMD2, 0x08));
|
||||||
|
display.write_command(BK1Command2::set_pre_drive_timing_two(&CMD2, 0x08));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xD0,
|
||||||
|
parameters: vec![0x88],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE0,
|
||||||
|
parameters: vec![0x00, 0x00, 0x02],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE1,
|
||||||
|
parameters: vec![
|
||||||
|
0x03, 0xA0, 0x00, 0x00, 0x04, 0xA0, 0x00, 0x00, 0x00, 0x20, 0x20,
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE2,
|
||||||
|
parameters: vec![
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE3,
|
||||||
|
parameters: vec![0x00, 0x00, 0x11, 0x00],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE4,
|
||||||
|
parameters: vec![0x22, 0x00],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE5,
|
||||||
|
parameters: vec![
|
||||||
|
0x05, 0xEC, 0xA0, 0xA0, 0x07, 0xEE, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00,
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE6,
|
||||||
|
parameters: vec![0x00, 0x00, 0x11, 0x00],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE7,
|
||||||
|
parameters: vec![0x22, 0x00],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xE8,
|
||||||
|
parameters: vec![
|
||||||
|
0x06, 0xED, 0xA0, 0xA0, 0x08, 0xEF, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00,
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xEB,
|
||||||
|
parameters: vec![0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xED,
|
||||||
|
parameters: vec![
|
||||||
|
0xFF, 0xFF, 0xFF, 0xBA, 0x0A, 0xBF, 0x45, 0xFF, 0xFF, 0x54, 0xFB, 0xA0, 0xAB, 0xFF, 0xFF,
|
||||||
|
0xFF,
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xEF,
|
||||||
|
parameters: vec![0x10, 0x0D, 0x04, 0x08, 0x3F, 0x1F],
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Set Command2 for BK3
|
||||||
|
display.write_command(CommandsGeneral::set_command_2(Command2Selection::BK1));
|
||||||
|
CMD2 = Command2Selection::BK1;
|
||||||
|
display.write_command(Ok(Command {
|
||||||
|
address: 0xEF,
|
||||||
|
parameters: vec![0x08],
|
||||||
|
}));
|
||||||
|
|
||||||
|
// COMMAND2 DISABLE
|
||||||
|
display.write_command(CommandsGeneral::set_command_2(Command2Selection::Disabled));
|
||||||
|
CMD2 = Command2Selection::Disabled;
|
||||||
|
|
||||||
|
display.write_command(CommandsGeneral::sleep_mode_off());
|
||||||
|
thread::sleep(time::Duration::from_millis(120));
|
||||||
|
|
||||||
|
display.write_command(CommandsGeneral::display_on());
|
||||||
|
display.write_command(CommandsGeneral::display_data_control(
|
||||||
|
instructions::ScanDirection::Normal,
|
||||||
|
instructions::ColorOrder::Rgb,
|
||||||
|
));
|
||||||
|
display.write_command(CommandsGeneral::set_color_mode(
|
||||||
|
instructions::BitsPerPixel::Rgb666,
|
||||||
|
));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user