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,
|
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 XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // MHz, https://forums.raspberrypi.com/viewtopic.php?t=356764
|
||||||
|
|
||||||
const ROWS: usize = 320;
|
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]
|
#[entry]
|
||||||
unsafe fn main() -> ! {
|
unsafe fn main() -> ! {
|
||||||
// rp_pico::pac::Peripherals is a reference to physical hardware defined on the Pico.
|
// 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,
|
embedded_hal::spi::MODE_3,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut display = ST7789Display::new(board_select, data_command, spi);
|
||||||
|
|
||||||
let _ = reset.set_high();
|
let _ = reset.set_high();
|
||||||
timer.delay_ms(10);
|
timer.delay_ms(10);
|
||||||
let _ = board_select.set_low();
|
|
||||||
timer.delay_ms(10);
|
|
||||||
for step in SETUP_PROGRAM {
|
for step in SETUP_PROGRAM {
|
||||||
step.send_command(&mut spi, &mut data_command);
|
let mut display = display.acquire();
|
||||||
if let Some(delay) = step.delay {
|
display.send_command(&step, &mut timer);
|
||||||
timer.delay_ms(delay);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timer.delay_ms(1000);
|
timer.delay_ms(1000);
|
||||||
|
|
||||||
let mut frame: [u8; FRAMEBUF] = [0; FRAMEBUF];
|
let mut frame: [u8; FRAMEBUF] = [0; FRAMEBUF];
|
||||||
/*
|
|
||||||
let mut frame = Frame {
|
|
||||||
columns: COLUMNS,
|
|
||||||
buf: [0; FRAMEBUF],
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
let mut strength = 0;
|
let mut strength = 0;
|
||||||
loop {
|
loop {
|
||||||
led.set_high();
|
led.set_high();
|
||||||
|
/*
|
||||||
let _ = board_select.set_low();
|
let _ = board_select.set_low();
|
||||||
let _ = data_command.set_low();
|
let _ = data_command.set_low();
|
||||||
let _ = spi.write(&[RAMWR]);
|
let _ = spi.write(&[RAMWR]);
|
||||||
let _ = data_command.set_high();
|
let _ = data_command.set_high();
|
||||||
let _ = spi.write(&frame);
|
let _ = spi.write(&frame);
|
||||||
let _ = board_select.set_high();
|
let _ = board_select.set_high();
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
let display = display.acquire();
|
||||||
|
display.send_buf(&frame);
|
||||||
|
}
|
||||||
|
|
||||||
for x in 80..90 {
|
for x in 80..90 {
|
||||||
for y in 155..165 {
|
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