Attempting to communicate with the TFT
This commit is contained in:
parent
506a13e802
commit
93b84ee72d
|
@ -0,0 +1,6 @@
|
|||
[build]
|
||||
target = "thumbv6m-none-eabi"
|
||||
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
runner = "elf2uf2-rs -d -s"
|
||||
|
|
@ -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"
|
|
@ -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");
|
||||
}
|
|
@ -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;
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue