Attempting to communicate with the TFT

This commit is contained in:
Savanni D'Gerinel 2024-08-08 22:04:12 -04:00
parent 506a13e802
commit 93b84ee72d
5 changed files with 266 additions and 0 deletions

6
tft/.cargo/config.toml Normal file
View File

@ -0,0 +1,6 @@
[build]
target = "thumbv6m-none-eabi"
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
runner = "elf2uf2-rs -d -s"

19
tft/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "e-ink"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
embassy-embedded-hal = { version = "0.1.0", features = ["defmt"] }
embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.5.0", features = ["task-arena-size-98304", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.1", features = ["defmt", "defmt-timestamp-uptime"] }
embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] }
defmt = "0.3"
defmt-rtt = "0.4"
cortex-m-rt = "0.7.0"
panic-probe = { version = "0.3", features = ["print-defmt"] }
embedded-hal = "1.0.0"

26
tft/build.rs Normal file
View File

@ -0,0 +1,26 @@
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
fn main() {
// Put `memory.x` in our output directory and ensure it's
// on the linker search path.
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
// By default, Cargo will re-run a build script whenever
// any file in the project changes. By specifying `memory.x`
// here, we ensure the build script is only re-run when
// `memory.x` is changed.
println!("cargo:rerun-if-changed=memory.x");
println!("cargo:rustc-link-arg-bins=--nmagic");
println!("cargo:rustc-link-arg-bins=-Tlink.x");
println!("cargo:rustc-link-arg-bins=-Tlink-rp.x");
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}

36
tft/memory.x Normal file
View File

@ -0,0 +1,36 @@
MEMORY {
BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
/*
* RAM consists of 4 banks, SRAM0-SRAM3, with a striped mapping.
* This is usually good for performance, as it distributes load on
* those banks evenly.
*/
RAM : ORIGIN = 0x20000000, LENGTH = 256K
/*
* RAM banks 4 and 5 use a direct mapping. They can be used to have
* memory areas dedicated for some specific job, improving predictability
* of access times.
* Example: Separate stacks for core0 and core1.
*/
SRAM4 : ORIGIN = 0x20040000, LENGTH = 4k
SRAM5 : ORIGIN = 0x20041000, LENGTH = 4k
/* SRAM banks 0-3 can also be accessed directly. However, those ranges
alias with the RAM mapping, above. So don't use them at the same time!
SRAM0 : ORIGIN = 0x21000000, LENGTH = 64k
SRAM1 : ORIGIN = 0x21010000, LENGTH = 64k
SRAM2 : ORIGIN = 0x21020000, LENGTH = 64k
SRAM3 : ORIGIN = 0x21030000, LENGTH = 64k
*/
}
EXTERN(BOOT2_FIRMWARE)
SECTIONS {
/* ### Boot loader */
.boot2 ORIGIN(BOOT2) :
{
KEEP(*(.boot2));
} > BOOT2
} INSERT BEFORE .text;

179
tft/src/main.rs Normal file
View File

@ -0,0 +1,179 @@
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_rp::{spi, spi::Spi, gpio};
use embedded_hal::delay::DelayNs;
use embassy_time::Delay;
use gpio::{Level, Output};
use defmt::*;
use defmt_rtt as _;
use panic_probe as _;
/*
* width: 320
* height: 170
*/
fn software_reset<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
let _ = spi.blocking_write(&[0x01]);
timer.delay_ms(150);
}
fn sleep_out<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
let _ = spi.blocking_write(&[0x11]);
timer.delay_ms(10);
}
fn color_mode<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
let _ = spi.blocking_write(&[0x11]);
dcx.set_high();
let _ = spi.blocking_write(&[0x63]);
timer.delay_ms(10);
}
fn normal_display<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
let _ = spi.blocking_write(&[0x13]);
timer.delay_ms(10);
}
fn display_on<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
let _ = spi.blocking_write(&[0x29]);
timer.delay_ms(10);
}
fn memory_address_set<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
spi.blocking_write(&[0x36]);
dcx.set_high();
spi.blocking_write(&[0x08]);
timer.delay_ms(10);
}
fn column_set<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
let width: u16 = 320;
dcx.set_low();
let _ = spi.blocking_write(&[0x2a]);
dcx.set_high();
let _ = spi.blocking_write(&[0x0, 0x0, (width >> 8) as u8, (width & 0xff) as u8]);
timer.delay_ms(10);
}
fn row_set<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
let height: u16 = 170;
dcx.set_low();
let _ = spi.blocking_write(&[0x2b]);
dcx.set_high();
let _ = spi.blocking_write(&[0x0, 0x0, (height >> 8) as u8, (170 & 0xff) as u8]);
timer.delay_ms(10);
}
fn write_image<T, M, R>(spi: &mut Spi<T, M>, timer: &mut Delay, dcx: &mut Output<R>)
where
T: embassy_rp::spi::Instance,
M: embassy_rp::spi::Mode,
R: embassy_rp::gpio::Pin,
{
dcx.set_low();
let _ = spi.blocking_write(&[0x2c]);
dcx.set_high();
let mut buf: [u8; 320 * 170 * 3] = [0; 320 * 170 * 3];
buf[0] = 0xff;
buf[2] = 0xff;
buf[3] = 0xff;
let _ = spi.blocking_write(&buf);
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let mut timer = Delay;
let mut tft_select = Output::new(p.PIN_10, Level::High); /* Pull low to activate the chip */
let mut tft_reset = Output::new(p.PIN_11, Level::Low);
timer.delay_ms(10);
tft_reset.set_high();
let mut dcx = Output::new(p.PIN_15, Level::Low); /* Low == Command, High == Data */
let mut spi_config = spi::Config::default();
spi_config.frequency = 2_000_000;
let mut spi = embassy_rp::spi::Spi::new_blocking(
p.SPI0,
p.PIN_2,
p.PIN_3,
p.PIN_4,
spi_config
);
tft_select.set_low();
/* Software reset, 150ms delay */
software_reset(&mut spi, &mut timer, &mut dcx);
/* 10 ms delay after each additonal command */
/* Sleep out */
sleep_out(&mut spi, &mut timer, &mut dcx);
/* Color mode */
color_mode(&mut spi, &mut timer, &mut dcx);
/* Memory access ctrl */
memory_address_set(&mut spi, &mut timer, &mut dcx);
/* Column addr set */
column_set(&mut spi, &mut timer, &mut dcx);
/* Row addr set */
row_set(&mut spi, &mut timer, &mut dcx);
/* Normal Display on */
normal_display(&mut spi, &mut timer, &mut dcx);
/* Main screen on */
display_on(&mut spi, &mut timer, &mut dcx);
write_image(&mut spi, &mut timer, &mut dcx);
tft_select.set_high();
}