Compare commits
No commits in common. "8bc7a4c288dc2dcaebf199ed4cef05a7d1242314" and "911bc97b69704e90697848e097753339c436aa82" have entirely different histories.
8bc7a4c288
...
911bc97b69
File diff suppressed because it is too large
Load Diff
|
@ -32,7 +32,5 @@ members = [
|
||||||
"sgf",
|
"sgf",
|
||||||
"timezone-testing",
|
"timezone-testing",
|
||||||
"tree",
|
"tree",
|
||||||
"visions/server",
|
"visions/server", "gm-dash/server", "halloween-leds"
|
||||||
"gm-dash/server",
|
|
||||||
"pico-st7789"
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
[build]
|
|
||||||
target = "thumbv6m-none-eabi"
|
|
||||||
|
|
||||||
[target.thumbv6m-none-eabi]
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=--nmagic",
|
|
||||||
"-C", "link-arg=-Tlink.x",
|
|
||||||
"-C", "no-vectorize-loops",
|
|
||||||
]
|
|
||||||
|
|
||||||
runner = "elf2uf2-rs -d"
|
|
|
@ -1,11 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "pico-st7789"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
cortex-m-rt = "0.7.3"
|
|
||||||
embedded-hal = "1.0.0"
|
|
||||||
fugit = "0.3.7"
|
|
||||||
panic-halt = "1.0.0"
|
|
||||||
rp-pico = "0.9.0"
|
|
|
@ -1,237 +0,0 @@
|
||||||
#![no_main]
|
|
||||||
#![no_std]
|
|
||||||
|
|
||||||
use embedded_hal::{delay::DelayNs, digital::OutputPin, spi::SpiBus};
|
|
||||||
use fugit::RateExtU32;
|
|
||||||
use panic_halt as _;
|
|
||||||
use rp_pico::{
|
|
||||||
entry,
|
|
||||||
hal::{
|
|
||||||
clocks::init_clocks_and_plls,
|
|
||||||
gpio::{FunctionSio, Pin, PinId, PullDown, SioOutput},
|
|
||||||
spi::{Enabled, Spi, SpiDevice, ValidSpiPinout},
|
|
||||||
Clock, Sio, Timer, Watchdog,
|
|
||||||
},
|
|
||||||
pac, Pins,
|
|
||||||
};
|
|
||||||
|
|
||||||
const XOSC_CRYSTAL_FREQ: u32 = 12_000_000; // MHz, https://forums.raspberrypi.com/viewtopic.php?t=356764
|
|
||||||
|
|
||||||
const ROWS: usize = 320;
|
|
||||||
const COLUMNS: usize = 240;
|
|
||||||
const FRAMEBUF: usize = ROWS * COLUMNS * 3;
|
|
||||||
|
|
||||||
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: [0x08, 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; 9] = [
|
|
||||||
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, 0, 0, 240],
|
|
||||||
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.
|
|
||||||
let mut peripherals = pac::Peripherals::take().unwrap();
|
|
||||||
|
|
||||||
// SIO inidcates "Single Cycle IO". I don't know what this means, but it could mean that this
|
|
||||||
// is a class of IO operations that can be run in a single clock cycle, such as switching a
|
|
||||||
// GPIO pin on or off.
|
|
||||||
let sio = Sio::new(peripherals.SIO);
|
|
||||||
|
|
||||||
// Many of the following systems require a watchdog. I do not know what this does, either, but
|
|
||||||
// it may be some failsafe software that will reset operations if the watchdog detects a lack
|
|
||||||
// of activity.
|
|
||||||
let mut watchdog = Watchdog::new(peripherals.WATCHDOG);
|
|
||||||
|
|
||||||
// Here we grab the GPIO pins in bank 0.
|
|
||||||
let pins = Pins::new(
|
|
||||||
peripherals.IO_BANK0,
|
|
||||||
peripherals.PADS_BANK0,
|
|
||||||
sio.gpio_bank0,
|
|
||||||
&mut peripherals.RESETS,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Initialize an abstraction of the clock system with a batch of standard hardware clocks.
|
|
||||||
let clocks = init_clocks_and_plls(
|
|
||||||
XOSC_CRYSTAL_FREQ,
|
|
||||||
peripherals.XOSC,
|
|
||||||
peripherals.CLOCKS,
|
|
||||||
peripherals.PLL_SYS,
|
|
||||||
peripherals.PLL_USB,
|
|
||||||
&mut peripherals.RESETS,
|
|
||||||
&mut watchdog,
|
|
||||||
)
|
|
||||||
.ok()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// An abstraction for a timer which we can use to delay the code.
|
|
||||||
let mut timer = Timer::new(peripherals.TIMER, &mut peripherals.RESETS, &clocks);
|
|
||||||
|
|
||||||
// Grab the clock and data pins for SPI1. For Clock pins and for Data pins, there are only two
|
|
||||||
// pins each on the Pico which can function for SPI1.
|
|
||||||
let spi_clk = pins.gpio2.into_function();
|
|
||||||
let spi_sdo = pins.gpio3.into_function();
|
|
||||||
// let spi_sdi = pins.gpio4.into_function();
|
|
||||||
// Chip select 1 means the chip is not enabled
|
|
||||||
let mut board_select = pins.gpio13.into_function();
|
|
||||||
let mut data_command = pins.gpio15.into_function();
|
|
||||||
let mut reset = pins.gpio14.into_function();
|
|
||||||
|
|
||||||
let _ = reset.set_low();
|
|
||||||
let _ = board_select.set_high();
|
|
||||||
let _ = data_command.set_high();
|
|
||||||
|
|
||||||
// Now, create the SPI function abstraction for SPI1 with spi_clk and spi_sdo.
|
|
||||||
let mut spi = Spi::<_, _, _, 8>::new(peripherals.SPI0, (spi_sdo, spi_clk)).init(
|
|
||||||
&mut peripherals.RESETS,
|
|
||||||
// The SPI system uses the peripheral clock
|
|
||||||
clocks.peripheral_clock.freq(),
|
|
||||||
// Transmit data at a rate of 1Mbit.
|
|
||||||
32_u32.MHz(),
|
|
||||||
// Run with SPI Mode 1. This means that the clock line should start high and that data will
|
|
||||||
// be sampled starting at the first falling edge.
|
|
||||||
embedded_hal::spi::MODE_3,
|
|
||||||
);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
timer.delay_ms(1000);
|
|
||||||
|
|
||||||
let mut bitmap: [u8; FRAMEBUF] = [0; FRAMEBUF];
|
|
||||||
|
|
||||||
let mut i = 0;
|
|
||||||
loop {
|
|
||||||
let _ = board_select.set_low();
|
|
||||||
let _ = data_command.set_low();
|
|
||||||
let _ = spi.write(&[RAMWR]);
|
|
||||||
let _ = data_command.set_high();
|
|
||||||
let _ = spi.write(&bitmap);
|
|
||||||
let _ = board_select.set_high();
|
|
||||||
|
|
||||||
let color = i << 2;
|
|
||||||
bitmap = [color; FRAMEBUF];
|
|
||||||
|
|
||||||
i = if i >= 64 { 0 } else { i + 1 };
|
|
||||||
|
|
||||||
timer.delay_ms(10);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue