Move board control into a self-contained object
This commit is contained in:
parent
a69a864dca
commit
45dc19c329
@ -15,6 +15,10 @@ use rp_pico::{
|
||||
pac, Pins,
|
||||
};
|
||||
|
||||
mod st7789;
|
||||
use st7789::{ST7789Display, SETUP_PROGRAM};
|
||||
pub use st7789::Step;
|
||||
|
||||
const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // MHz, https://forums.raspberrypi.com/viewtopic.php?t=356764
|
||||
|
||||
const ROWS: usize = 320;
|
||||
@ -28,125 +32,6 @@ struct Frame {
|
||||
}
|
||||
*/
|
||||
|
||||
struct Step {
|
||||
param_cnt: usize,
|
||||
command: u8,
|
||||
params: [u8; 4],
|
||||
delay: Option<u32>,
|
||||
}
|
||||
|
||||
impl Step {
|
||||
fn send_command<D, Pinout, P>(
|
||||
&self,
|
||||
spi: &mut Spi<Enabled, D, Pinout, 8>,
|
||||
data_command: &mut Pin<P, FunctionSio<SioOutput>, PullDown>,
|
||||
) where
|
||||
D: SpiDevice,
|
||||
Pinout: ValidSpiPinout<D>,
|
||||
P: PinId,
|
||||
{
|
||||
let _ = data_command.set_low();
|
||||
let _ = spi.write(&[self.command]);
|
||||
if self.param_cnt > 0 {
|
||||
let _ = data_command.set_high();
|
||||
let _ = spi.write(&self.params[0..self.param_cnt]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const NOP: u8 = 0x00;
|
||||
|
||||
const SWRESET: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x01,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(150),
|
||||
};
|
||||
const SLPOUT: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x11,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const COLMOD: u8 = 0x3a;
|
||||
const MADCTL: Step = Step {
|
||||
param_cnt: 1,
|
||||
command: 0x36,
|
||||
params: [0x00, 0, 0, 0],
|
||||
delay: None,
|
||||
};
|
||||
const CASET: u8 = 0x2a;
|
||||
const RASET: u8 = 0x2b;
|
||||
const INVON: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x21,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const NORON: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x13,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const DISPON: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x29,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const RAMWR: u8 = 0x2c;
|
||||
|
||||
// Adafruit setup instructions
|
||||
// SWRESET (0x01), 150ms delay
|
||||
// SLPOUT (0x11), 10ms delay
|
||||
// COLMOD (0x3a) 0x55 (65K RGB, 16bit/pixel), 10ms delay
|
||||
// MADCTL (0x36) 0x00,
|
||||
// memory data access control, RGB
|
||||
// CASET 0x00, 0, 0, 170,
|
||||
// column address set, 4 parameters
|
||||
// 0x00, 0x00 indicates xstart is 0
|
||||
// 0x00, 170 indicates xend is 170
|
||||
// RASET 0x00, 0, 320 >> 8, 320 & 0xFF,
|
||||
// row address set, 4 parameters
|
||||
// 0x00, 0x00 indicates ystart is 0
|
||||
// 3230 >> 8, 320 & 0xff indicates that 320 is the last y address
|
||||
// INVON, 10ms delay
|
||||
// invert the display
|
||||
// NORON, 10ms delay
|
||||
// normal display mode
|
||||
// DISPON, 10ms delay
|
||||
// turn the display on
|
||||
|
||||
const SETUP_PROGRAM: [Step; 8] = [
|
||||
SWRESET,
|
||||
SLPOUT,
|
||||
Step {
|
||||
param_cnt: 1,
|
||||
command: COLMOD,
|
||||
params: [0x66, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
},
|
||||
MADCTL,
|
||||
Step {
|
||||
param_cnt: 4,
|
||||
command: CASET,
|
||||
params: [0, 35, 0, 204],
|
||||
delay: None,
|
||||
},
|
||||
/*
|
||||
Step {
|
||||
param_cnt: 4,
|
||||
command: RASET,
|
||||
params: [0, 0, (320 >> 8) as u8, (320 & 0xff) as u8],
|
||||
delay: None,
|
||||
},
|
||||
*/
|
||||
INVON,
|
||||
NORON,
|
||||
DISPON,
|
||||
];
|
||||
|
||||
#[entry]
|
||||
unsafe fn main() -> ! {
|
||||
// rp_pico::pac::Peripherals is a reference to physical hardware defined on the Pico.
|
||||
@ -214,36 +99,34 @@ unsafe fn main() -> ! {
|
||||
embedded_hal::spi::MODE_3,
|
||||
);
|
||||
|
||||
let mut display = ST7789Display::new(board_select, data_command, spi);
|
||||
|
||||
let _ = reset.set_high();
|
||||
timer.delay_ms(10);
|
||||
let _ = board_select.set_low();
|
||||
timer.delay_ms(10);
|
||||
for step in SETUP_PROGRAM {
|
||||
step.send_command(&mut spi, &mut data_command);
|
||||
if let Some(delay) = step.delay {
|
||||
timer.delay_ms(delay);
|
||||
}
|
||||
let mut display = display.acquire();
|
||||
display.send_command(&step, &mut timer);
|
||||
}
|
||||
|
||||
timer.delay_ms(1000);
|
||||
|
||||
let mut frame: [u8; FRAMEBUF] = [0; FRAMEBUF];
|
||||
/*
|
||||
let mut frame = Frame {
|
||||
columns: COLUMNS,
|
||||
buf: [0; FRAMEBUF],
|
||||
};
|
||||
*/
|
||||
|
||||
let mut strength = 0;
|
||||
loop {
|
||||
led.set_high();
|
||||
/*
|
||||
let _ = board_select.set_low();
|
||||
let _ = data_command.set_low();
|
||||
let _ = spi.write(&[RAMWR]);
|
||||
let _ = data_command.set_high();
|
||||
let _ = spi.write(&frame);
|
||||
let _ = board_select.set_high();
|
||||
*/
|
||||
{
|
||||
let display = display.acquire();
|
||||
display.send_buf(&frame);
|
||||
}
|
||||
|
||||
for x in 80..90 {
|
||||
for y in 155..165 {
|
||||
|
196
pico-st7789/src/st7789.rs
Normal file
196
pico-st7789/src/st7789.rs
Normal file
@ -0,0 +1,196 @@
|
||||
use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiBus};
|
||||
use rp_pico::hal::{
|
||||
gpio::{FunctionSio, Pin, PinId, PullDown, SioOutput},
|
||||
spi::{Enabled, SpiDevice, ValidSpiPinout},
|
||||
Spi, Timer,
|
||||
};
|
||||
|
||||
pub struct Step {
|
||||
param_cnt: usize,
|
||||
command: u8,
|
||||
params: [u8; 4],
|
||||
delay: Option<u32>,
|
||||
}
|
||||
|
||||
impl Step {
|
||||
pub fn send_command<D, Pinout, P>(
|
||||
&self,
|
||||
spi: &mut Spi<Enabled, D, Pinout, 8>,
|
||||
data_command: &mut Pin<P, FunctionSio<SioOutput>, PullDown>,
|
||||
) where
|
||||
D: SpiDevice,
|
||||
Pinout: ValidSpiPinout<D>,
|
||||
P: PinId,
|
||||
{
|
||||
let _ = data_command.set_low();
|
||||
let _ = spi.write(&[self.command]);
|
||||
if self.param_cnt > 0 {
|
||||
let _ = data_command.set_high();
|
||||
let _ = spi.write(&self.params[0..self.param_cnt]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const NOP: u8 = 0x00;
|
||||
|
||||
const SWRESET: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x01,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(150),
|
||||
};
|
||||
const SLPOUT: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x11,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const COLMOD: u8 = 0x3a;
|
||||
const MADCTL: Step = Step {
|
||||
param_cnt: 1,
|
||||
command: 0x36,
|
||||
params: [0x00, 0, 0, 0],
|
||||
delay: None,
|
||||
};
|
||||
const CASET: u8 = 0x2a;
|
||||
const RASET: u8 = 0x2b;
|
||||
const INVON: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x21,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const NORON: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x13,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const DISPON: Step = Step {
|
||||
param_cnt: 0,
|
||||
command: 0x29,
|
||||
params: [0, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
};
|
||||
const RAMWR: u8 = 0x2c;
|
||||
|
||||
// Adafruit setup instructions
|
||||
// SWRESET (0x01), 150ms delay
|
||||
// SLPOUT (0x11), 10ms delay
|
||||
// COLMOD (0x3a) 0x55 (65K RGB, 16bit/pixel), 10ms delay
|
||||
// MADCTL (0x36) 0x00,
|
||||
// memory data access control, RGB
|
||||
// CASET 0x00, 0, 0, 170,
|
||||
// column address set, 4 parameters
|
||||
// 0x00, 0x00 indicates xstart is 0
|
||||
// 0x00, 170 indicates xend is 170
|
||||
// RASET 0x00, 0, 320 >> 8, 320 & 0xFF,
|
||||
// row address set, 4 parameters
|
||||
// 0x00, 0x00 indicates ystart is 0
|
||||
// 3230 >> 8, 320 & 0xff indicates that 320 is the last y address
|
||||
// INVON, 10ms delay
|
||||
// invert the display
|
||||
// NORON, 10ms delay
|
||||
// normal display mode
|
||||
// DISPON, 10ms delay
|
||||
// turn the display on
|
||||
|
||||
pub const SETUP_PROGRAM: [Step; 8] = [
|
||||
SWRESET,
|
||||
SLPOUT,
|
||||
Step {
|
||||
param_cnt: 1,
|
||||
command: COLMOD,
|
||||
params: [0x66, 0, 0, 0],
|
||||
delay: Some(10),
|
||||
},
|
||||
MADCTL,
|
||||
Step {
|
||||
param_cnt: 4,
|
||||
command: CASET,
|
||||
params: [0, 35, 0, 204],
|
||||
delay: None,
|
||||
},
|
||||
/*
|
||||
Step {
|
||||
param_cnt: 4,
|
||||
command: RASET,
|
||||
params: [0, 0, (320 >> 8) as u8, (320 & 0xff) as u8],
|
||||
delay: None,
|
||||
},
|
||||
*/
|
||||
INVON,
|
||||
NORON,
|
||||
DISPON,
|
||||
];
|
||||
|
||||
pub struct ST7789Display<
|
||||
BoardSelectId: PinId,
|
||||
DataCommandId: PinId,
|
||||
D: SpiDevice,
|
||||
Pinout: ValidSpiPinout<D>,
|
||||
> {
|
||||
inner: ST7789DisplayEnabled<BoardSelectId, DataCommandId, D, Pinout>,
|
||||
}
|
||||
|
||||
impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiPinout<D>>
|
||||
ST7789Display<BoardSelectId, DataCommandId, D, Pinout>
|
||||
{
|
||||
pub fn new(
|
||||
board_select: Pin<BoardSelectId, FunctionSio<SioOutput>, PullDown>,
|
||||
data_command: Pin<DataCommandId, FunctionSio<SioOutput>, PullDown>,
|
||||
spi: Spi<Enabled, D, Pinout, 8>,
|
||||
) -> Self {
|
||||
Self {
|
||||
inner: ST7789DisplayEnabled {
|
||||
board_select,
|
||||
data_command,
|
||||
spi,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn acquire(
|
||||
&mut self,
|
||||
) -> &mut ST7789DisplayEnabled<BoardSelectId, DataCommandId, D, Pinout> {
|
||||
self.inner.board_select.set_low();
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ST7789DisplayEnabled<
|
||||
BoardSelectId: PinId,
|
||||
DataCommandId: PinId,
|
||||
D: SpiDevice,
|
||||
Pinout: ValidSpiPinout<D>,
|
||||
> {
|
||||
board_select: Pin<BoardSelectId, FunctionSio<SioOutput>, PullDown>,
|
||||
data_command: Pin<DataCommandId, FunctionSio<SioOutput>, PullDown>,
|
||||
spi: Spi<Enabled, D, Pinout, 8>,
|
||||
}
|
||||
|
||||
impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiPinout<D>>
|
||||
ST7789DisplayEnabled<BoardSelectId, DataCommandId, D, Pinout>
|
||||
{
|
||||
pub fn send_command(&mut self, step: &Step, timer: &mut Timer) {
|
||||
step.send_command(&mut self.spi, &mut self.data_command);
|
||||
if let Some(delay) = step.delay {
|
||||
timer.delay_ms(delay);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_buf(&mut self, frame: &[u8]) {
|
||||
let _ = self.data_command.set_low();
|
||||
let _ = self.spi.write(&[RAMWR]);
|
||||
let _ = self.data_command.set_high();
|
||||
let _ = self.spi.write(&frame);
|
||||
}
|
||||
}
|
||||
|
||||
impl<BoardSelectId: PinId, DataCommandId: PinId, D: SpiDevice, Pinout: ValidSpiPinout<D>> Drop
|
||||
for ST7789DisplayEnabled<BoardSelectId, DataCommandId, D, Pinout>
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.board_select.set_high();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user