Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce RGB/DPI driver #2415

Merged
merged 8 commits into from
Nov 19, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use official devkit
  • Loading branch information
Dominic Fischer committed Nov 16, 2024
commit 2afc12e4e7d0775258961b152317a9465da324c5
291 changes: 187 additions & 104 deletions examples/src/bin/lcd_dpi.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
//! Drives the 16-bit parallel RGB display on Makerfabs ESP32-S3-Parallel-TFT-with-Touch-4.3inch
//! Drives the 16-bit parallel RGB display on ESP32-S3-LCD-EV-Board v1.5
//!
//! This example fills the screen with every color.
//!
//! The following wiring is assumed:
//! - LCD_VYSNC => GPIO41
//! - LCD_HSYNC => GPIO39
//! - LCD_DE => GPIO40
//! - LCD_PCLK => GPIO42
//! - LCD_DATA0 => GPIO8
//! - LCD_DATA1 => GPIO3
//! - LCD_DATA2 => GPIO46
//! - LCD_DATA3 => GPIO9
//! - LCD_DATA4 => GPIO1
//! - LCD_DATA5 => GPIO5
//! - LCD_DATA6 => GPIO6
//! - LCD_DATA7 => GPIO7
//! - LCD_DATA8 => GPIO15
//! - LCD_DATA9 => GPIO16
//! - LCD_DATA10 => GPIO4
//! - LCD_DATA11 => GPIO45
//! - LCD_DATA12 => GPIO48
//! - LCD_DATA13 => GPIO47
//! - LCD_DATA14 => GPIO21
//! - LCD_DATA15 => GPIO14
//! - LCD_VYSNC => GPIO3
//! - LCD_HSYNC => GPIO46
//! - LCD_DE => GPIO17
//! - LCD_PCLK => GPIO9
//! - LCD_DATA0 => GPIO10
//! - LCD_DATA1 => GPIO11
//! - LCD_DATA2 => GPIO12
//! - LCD_DATA3 => GPIO13
//! - LCD_DATA4 => GPIO14
//! - LCD_DATA5 => GPIO21
//! - LCD_DATA6 => GPIO8
//! - LCD_DATA7 => GPIO18
//! - LCD_DATA8 => GPIO45
//! - LCD_DATA9 => GPIO38
//! - LCD_DATA10 => GPIO39
//! - LCD_DATA11 => GPIO40
//! - LCD_DATA12 => GPIO41
//! - LCD_DATA13 => GPIO42
//! - LCD_DATA14 => GPIO2
//! - LCD_DATA15 => GPIO1

//% CHIPS: esp32s3

Expand All @@ -32,17 +32,25 @@
use core::iter::{empty, once};

use esp_backtrace as _;
use esp_hal::{dma::{Dma, DmaPriority}, dma_loop_buffer, gpio::{Io, Level}, i2c, lcd_cam::{
lcd::{
dpi::{Config, Dpi, Format, FrameTiming},
ClockMode,
Phase,
Polarity,
use esp_hal::{
delay::Delay,
dma::{Dma, DmaPriority},
dma_loop_buffer,
gpio::{Io, Level, Output},
i2c,
i2c::I2c,
lcd_cam::{
lcd::{
dpi::{Config, Dpi, Format, FrameTiming},
ClockMode,
Phase,
Polarity,
},
LcdCam,
},
LcdCam,
}, prelude::*, Blocking};
use esp_hal::delay::Delay;
use esp_hal::i2c::I2c;
prelude::*,
Blocking,
};
use esp_println::println;

#[entry]
Expand All @@ -53,7 +61,7 @@ fn main() -> ! {

let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);

let i2c = I2c::new(peripherals.I2C0, io.pins.gpio47, io.pins.gpio48, 100.kHz());
let i2c = I2c::new(peripherals.I2C0, io.pins.gpio47, io.pins.gpio48, 400.kHz());
let dma = Dma::new(peripherals.DMA);
let channel = dma.channel2.configure(true, DmaPriority::Priority0);
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
Expand All @@ -64,36 +72,47 @@ fn main() -> ! {

let delay = Delay::new();

println!("Ughh....");
println!("Initialising");

let mut write_byte = |b: u8, is_cmd: bool| {
// const fn compose(cs: bool, scl: bool, sda: bool) -> u8 {
// let mut base = 0b1111_0001;
// if cs {
// base |= 0b0000_0010;
// }
// if scl {
// base |= 0b0000_0100;
// }
// if sda {
// base |= 0b0000_1000;
// }
// base
// }

expander.write_output_reg(0b1111_0101).unwrap();
const SCS_BIT: u8 = 0b0000_0010;
const SCL_BIT: u8 = 0b0000_0100;
const SDA_BIT: u8 = 0b0000_1000;

let mut output = 0b1111_0001 & !SCS_BIT;
expander.write_output_reg(output).unwrap();

for bit in once(!is_cmd).chain((0..8).map(|i| (b >> i) & 0b1 != 0).rev()) {
let sda = if bit { 0b0000_1000 } else { 0b0000_0000 };
// Set SDA
expander.write_output_reg(0b1111_0101 | sda).unwrap();
let prev = output;
if bit {
output |= SDA_BIT;
} else {
output &= !SDA_BIT;
}
if prev != output {
expander.write_output_reg(output).unwrap();
}

// Toggle SCL
expander.write_output_reg(0b1111_0001 | sda).unwrap();
expander.write_output_reg(0b1111_0101 | sda).unwrap();
output &= !SCL_BIT;
expander.write_output_reg(output).unwrap();

output |= SCL_BIT;
expander.write_output_reg(output).unwrap();
}
expander.write_output_reg(0b1111_0111).unwrap();

output &= !SCL_BIT;
expander.write_output_reg(output).unwrap();

output &= !SDA_BIT;
expander.write_output_reg(output).unwrap();

output |= SCS_BIT;
expander.write_output_reg(output).unwrap();
};

let mut vsync_pin = io.pins.gpio3;

let vsync_must_be_high_during_setup = Output::new(&mut vsync_pin, Level::High);
for &init in INIT_CMDS.iter() {
match init {
InitCmd::Cmd(cmd, args) => {
Expand All @@ -107,48 +126,44 @@ fn main() -> ! {
}
}
}
drop(vsync_must_be_high_during_setup);

let mut dma_buf = dma_loop_buffer!(2 * 16);

let config = Config {
clock_mode: ClockMode {
polarity: Polarity::IdleLow,
phase: Phase::ShiftHigh,
phase: Phase::ShiftLow,
},
format: Format {
enable_2byte_mode: true,
..Default::default()
},
// https://www.makerfabs.com/desfile/files/QT4300H40R10-V03-Spec.pdf
timing: FrameTiming {
horizontal_active_width: 480,
horizontal_total_width: 608,
horizontal_blank_front_porch: 40,
horizontal_total_width: 520,
horizontal_blank_front_porch: 10,

vertical_active_height: 480,
vertical_total_height: 525,
vertical_blank_front_porch: 13,
vertical_total_height: 510,
vertical_blank_front_porch: 10,

hsync_width: 48, // 1..255
vsync_width: 3, // 3..255
hsync_width: 10,
vsync_width: 10,

hsync_position: 0,
},
vsync_idle_level: Level::Low,
hsync_idle_level: Level::Low,
de_idle_level: Level::High,
vsync_idle_level: Level::High,
hsync_idle_level: Level::High,
de_idle_level: Level::Low,
disable_black_region: false,
..Default::default()
};

let mut dpi = Dpi::new(lcd_cam.lcd, channel.tx, 30.MHz(), config)
.with_ctrl_pins(
io.pins.gpio3,
io.pins.gpio46,
io.pins.gpio17,
io.pins.gpio9,
)
let mut dpi = Dpi::new(lcd_cam.lcd, channel.tx, 16.MHz(), config)
.with_ctrl_pins(vsync_pin, io.pins.gpio46, io.pins.gpio17, io.pins.gpio9)
.with_data_pins(
// Blue
io.pins.gpio10,
io.pins.gpio11,
io.pins.gpio12,
Expand Down Expand Up @@ -228,7 +243,7 @@ impl Tca9554 {
#[derive(Copy, Clone)]
enum InitCmd {
Cmd(u8, &'static [u8]),
Delay(u8)
Delay(u8),
}

const INIT_CMDS: &[InitCmd] = &[
Expand All @@ -255,42 +270,110 @@ const INIT_CMDS: &[InitCmd] = &[
InitCmd::Cmd(0x9a, &[0x72]),
InitCmd::Cmd(0x9b, &[0x5a]),
InitCmd::Cmd(0x82, &[0x2c, 0x2c]),
InitCmd::Cmd(0x6d, &[0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00]),
InitCmd::Cmd(0x64, &[0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a]),
InitCmd::Cmd(0x65, &[0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a]),
InitCmd::Cmd(0x66, &[0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a]),
InitCmd::Cmd(0x67, &[0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a]),
InitCmd::Cmd(0x68, &[0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a]),
InitCmd::Cmd(0xB1, &[0x10]),
InitCmd::Cmd(
0x6d,
&[
0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f,
0x1a, 0x19, 0x1f, 0x00,
],
),
InitCmd::Cmd(
0x64,
&[
0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a,
0x7a, 0x7a,
],
),
InitCmd::Cmd(
0x65,
&[
0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a,
0x7a, 0x7a,
],
),
InitCmd::Cmd(
0x66,
&[
0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a,
0x7a, 0x7a,
],
),
InitCmd::Cmd(
0x67,
&[
0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a,
0x7a, 0x7a,
],
),
InitCmd::Cmd(
0x68,
&[
0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a,
],
),
InitCmd::Cmd(0x60, &[0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a]),
InitCmd::Cmd(0x63, &[0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a]),
InitCmd::Cmd(0x69, &[0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08]),
InitCmd::Cmd(0x6b, &[0x07]),
InitCmd::Cmd(0x7a, &[0x08, 0x13]),
InitCmd::Cmd(0x7b, &[0x08, 0x13]),
InitCmd::Cmd(0xd1, &[0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
0xff]),
InitCmd::Cmd(0xd2, &[0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
0xff]),
InitCmd::Cmd(0xd3, &[0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
0xff]),
InitCmd::Cmd(0xd4, &[0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
0xff]),
InitCmd::Cmd(0xd5, &[0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
0xff]),
InitCmd::Cmd(0xd6, &[0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00,
0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee,
0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03,
0xff]),
InitCmd::Cmd(
0xd1,
&[
0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35,
0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7,
0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5,
0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
],
),
InitCmd::Cmd(
0xd2,
&[
0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35,
0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7,
0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5,
0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
],
),
InitCmd::Cmd(
0xd3,
&[
0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35,
0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7,
0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5,
0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
],
),
InitCmd::Cmd(
0xd4,
&[
0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35,
0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7,
0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5,
0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
],
),
InitCmd::Cmd(
0xd5,
&[
0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35,
0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7,
0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5,
0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
],
),
InitCmd::Cmd(
0xd6,
&[
0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35,
0x00, 0x47, 0x00, 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7,
0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5,
0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, 0xff,
],
),
InitCmd::Cmd(0x3A, &[0x66]),
InitCmd::Cmd(0x11, &[]),
InitCmd::Delay(120),
InitCmd::Cmd(0x29, &[]),
Expand Down