First working version of lcd driver
This commit is contained in:
parent
169aa5963f
commit
265864a2e8
|
@ -0,0 +1,136 @@
|
||||||
|
#![no_std]
|
||||||
|
#![feature(asm, used, const_fn, naked_functions, alloc, box_syntax)]
|
||||||
|
#![no_main]
|
||||||
|
#![feature(extern_prelude)]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate hcl;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
|
use core::mem;
|
||||||
|
use hcl::platform::gpio;
|
||||||
|
use hcl::platform::irq;
|
||||||
|
use hcl::platform::rcc;
|
||||||
|
use hcl::platform::scs;
|
||||||
|
use hcl::platform::timer;
|
||||||
|
use hcl::platform::usart;
|
||||||
|
use hcl::platform::dma;
|
||||||
|
use hcl::dma::*;
|
||||||
|
|
||||||
|
mod printer;
|
||||||
|
|
||||||
|
use printer::UsartPrinter;
|
||||||
|
|
||||||
|
fn configure_clocks(rcc: &mut rcc::RCC) {
|
||||||
|
rcc.clock_control.set_hse_on(true);
|
||||||
|
while !rcc.clock_control.hse_ready() {
|
||||||
|
}
|
||||||
|
|
||||||
|
rcc.clock_config.configure(|c| c
|
||||||
|
.set_pll_multiplier(10)
|
||||||
|
.set_pll_source(rcc::PllSource::HsiDiv2));
|
||||||
|
|
||||||
|
rcc.clock_control.set_pll_on(true);
|
||||||
|
while !rcc.clock_control.pll_ready() {
|
||||||
|
}
|
||||||
|
|
||||||
|
rcc.clock_config.switch_clock_source(rcc::SystemClockSource::Pll);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn configure_peripherals(rcc: &mut hcl::platform::rcc::RCC,
|
||||||
|
gpio: &mut gpio::GPIO,
|
||||||
|
usart: &mut usart::USART) {
|
||||||
|
rcc.apb2_enable.configure(|a| a
|
||||||
|
.set_gpio_a(true)
|
||||||
|
.set_spi1(true));
|
||||||
|
rcc.apb1_enable.configure(|a| a
|
||||||
|
.set_usart2(true));
|
||||||
|
|
||||||
|
gpio.configure(|g| g
|
||||||
|
.set_mode(2, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(2, gpio::OutputConfig::AfPushPull)
|
||||||
|
.set_mode(3, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(3, gpio::OutputConfig::AfPushPull)
|
||||||
|
// SCK1
|
||||||
|
.set_mode(5, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(5, gpio::OutputConfig::AfPushPull)
|
||||||
|
// MOSI1
|
||||||
|
.set_mode(7, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(7, gpio::OutputConfig::AfPushPull)
|
||||||
|
// MISO1
|
||||||
|
.set_mode(6, gpio::PinMode::Input)
|
||||||
|
.set_input_config(6, gpio::InputConfig::PullUpDown)
|
||||||
|
// NSS1
|
||||||
|
.set_mode(4, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(4, gpio::OutputConfig::PushPull));
|
||||||
|
|
||||||
|
usart.configure(|u| u
|
||||||
|
.set_enabled(true)
|
||||||
|
.set_tx_enabled(true)
|
||||||
|
.set_baudgen((21, 11))); // 115.2 kbaud
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// allowing inlining into main() breaks the stack, since main() must be naked to set up a process stack.
|
||||||
|
#[inline(never)]
|
||||||
|
fn run(mut scs: scs::Instance, mut p: hcl::platform::Instance) {
|
||||||
|
configure_clocks(&mut p.rcc);
|
||||||
|
configure_peripherals(&mut p.rcc, &mut p.gpio_a, &mut p.usart2);
|
||||||
|
|
||||||
|
let mut printer = UsartPrinter::init(p.usart2);
|
||||||
|
|
||||||
|
let mut spi = p.spi1;
|
||||||
|
spi.configure(|s| s
|
||||||
|
.set_enabled(true)
|
||||||
|
.set_master_mode(true)
|
||||||
|
.set_slave_select_output_enabled(true)
|
||||||
|
.set_bidi_tx(false)
|
||||||
|
.set_clock_divider(128)
|
||||||
|
.set_data_16bit(true)
|
||||||
|
.set_clock_idles_high(false)
|
||||||
|
.set_lsb_first(false)
|
||||||
|
.set_clock_skip_first(true));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
|
||||||
|
p.gpio_a.reset_bit(4);
|
||||||
|
spi.set_data(0xFFFF);
|
||||||
|
|
||||||
|
while !spi.rx_buffer_not_empty() {
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = spi.data() >> 3;
|
||||||
|
let temp = (i as f32) * 0.25;
|
||||||
|
|
||||||
|
while spi.busy() {
|
||||||
|
}
|
||||||
|
p.gpio_a.set_bit(4);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let x = format!("> {}\r\n", temp).into_bytes();
|
||||||
|
|
||||||
|
printer.print(x);
|
||||||
|
|
||||||
|
for y in 0u32..0xFFFFFF {
|
||||||
|
unsafe { asm!("nop" :::: "volatile") };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
entry_point!(main);
|
||||||
|
fn main(scs: scs::Instance, p: hcl::platform::Instance) {
|
||||||
|
declare_thread_stack!(stack, 4096);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
hcl::set_process_stack(&stack);
|
||||||
|
hcl::use_process_stack(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
run(scs, p);
|
||||||
|
}
|
2
hcl
2
hcl
|
@ -1 +1 @@
|
||||||
Subproject commit 9dc33a9abadbde8e0c2ffc853a35feaf6990c143
|
Subproject commit 001d44d6b9693a9ad3fd6fc8bc44e8dc22ad7149
|
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/bash
|
||||||
|
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/bash
|
||||||
|
cargo build --target=thumbv7m-none-eabi || exit -1
|
||||||
|
arm-none-eabi-gdb target/thumbv7m-none-eabi/debug/reflow-firmware
|
35
src/main.rs
35
src/main.rs
|
@ -50,9 +50,6 @@ hcl_ivt!{
|
||||||
systick => systick::isr;
|
systick => systick::isr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn configure_peripherals(rcc: &mut hcl::platform::rcc::RCC,
|
fn configure_peripherals(rcc: &mut hcl::platform::rcc::RCC,
|
||||||
gpio_a: &mut gpio::GPIO,
|
gpio_a: &mut gpio::GPIO,
|
||||||
gpio_c: &mut gpio::GPIO,
|
gpio_c: &mut gpio::GPIO,
|
||||||
|
@ -75,12 +72,21 @@ fn configure_peripherals(rcc: &mut hcl::platform::rcc::RCC,
|
||||||
// MISO1
|
// MISO1
|
||||||
.set_mode(6, gpio::PinMode::Input)
|
.set_mode(6, gpio::PinMode::Input)
|
||||||
.set_input_config(6, gpio::InputConfig::PullUpDown)
|
.set_input_config(6, gpio::InputConfig::PullUpDown)
|
||||||
// ???
|
|
||||||
.set_mode(4, gpio::PinMode::Output50MHz)
|
|
||||||
.set_output_config(4, gpio::OutputConfig::PushPull)
|
|
||||||
// SS MAX6675
|
// SS MAX6675
|
||||||
.set_mode(9, gpio::PinMode::Output50MHz)
|
.set_mode(9, gpio::PinMode::Output50MHz)
|
||||||
.set_output_config(9, gpio::OutputConfig::PushPull)
|
.set_output_config(9, gpio::OutputConfig::PushPull)
|
||||||
|
// ST7735 cs pin
|
||||||
|
.set_mode(0, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(0, gpio::OutputConfig::PushPull)
|
||||||
|
// ST7735 rst pin
|
||||||
|
.set_mode(1, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(1, gpio::OutputConfig::PushPull)
|
||||||
|
// ST7735 rs pin
|
||||||
|
.set_mode(4, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(4, gpio::OutputConfig::PushPull)
|
||||||
|
// ST7735 led pin
|
||||||
|
.set_mode(8, gpio::PinMode::Output50MHz)
|
||||||
|
.set_output_config(8, gpio::OutputConfig::PushPull)
|
||||||
});
|
});
|
||||||
|
|
||||||
gpio_c.configure(|g| {
|
gpio_c.configure(|g| {
|
||||||
|
@ -104,7 +110,7 @@ fn run(mut scs: scs::Instance, mut p: hcl::platform::Instance) {
|
||||||
systick::configure(&mut scs.systick);
|
systick::configure(&mut scs.systick);
|
||||||
configure_peripherals(&mut p.rcc, &mut p.gpio_a, &mut p.gpio_c, &mut p.usart2);
|
configure_peripherals(&mut p.rcc, &mut p.gpio_a, &mut p.gpio_c, &mut p.usart2);
|
||||||
|
|
||||||
let mut printer = UsartPrinter::init(p.usart2);
|
//let mut printer = UsartPrinter::init(p.usart2);
|
||||||
|
|
||||||
|
|
||||||
let mut spi = p.spi1;
|
let mut spi = p.spi1;
|
||||||
|
@ -113,12 +119,22 @@ fn run(mut scs: scs::Instance, mut p: hcl::platform::Instance) {
|
||||||
let mut st7735 = st7735::St7735::new(st7735::DisplayType::RED_18_BLACKTAB, 0, 1, 4, 8);
|
let mut st7735 = st7735::St7735::new(st7735::DisplayType::RED_18_BLACKTAB, 0, 1, 4, 8);
|
||||||
|
|
||||||
let mut st7735io = st7735.start(spi, gpio);
|
let mut st7735io = st7735.start(spi, gpio);
|
||||||
st7735io.init();
|
loop {
|
||||||
|
st7735io.init();
|
||||||
|
st7735io.fill_rect(0, 0, 128, 160, 0x00, 0x00);
|
||||||
|
st7735io.fill_rect(4, 4, 60, 76, 0x00, 0x1F);
|
||||||
|
st7735io.fill_rect(4, 80, 60, 76, 0xF8, 0x00);
|
||||||
|
st7735io.fill_rect(64, 4, 60, 76, 0x07, 0xE0);
|
||||||
|
st7735io.fill_rect(64, 80, 60, 76, 0xFF, 0xE0);
|
||||||
|
systick::delay_ms(2000);
|
||||||
|
}
|
||||||
let (st7735, mut spi, mut gpio) = st7735io.done();
|
let (st7735, mut spi, mut gpio) = st7735io.done();
|
||||||
|
|
||||||
|
/*
|
||||||
loop {
|
loop {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let res = max6675::read(&mut spi, &mut gpio, 9);
|
let res = max6675::read(&mut spi, &mut gpio, 9);
|
||||||
|
|
||||||
let msg = match res {
|
let msg = match res {
|
||||||
|
@ -133,6 +149,7 @@ fn run(mut scs: scs::Instance, mut p: hcl::platform::Instance) {
|
||||||
|
|
||||||
systick::delay_ms(1000);
|
systick::delay_ms(1000);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
150
src/st7735.rs
150
src/st7735.rs
|
@ -68,7 +68,7 @@ enum Command {
|
||||||
GMCTRN1([u8; 16]),
|
GMCTRN1([u8; 16]),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_to_byte(cmd : Command) -> u8 {
|
fn command_to_byte(cmd : &Command) -> u8 {
|
||||||
match cmd {
|
match cmd {
|
||||||
Command::NOP => 0x00,
|
Command::NOP => 0x00,
|
||||||
Command::SWRESET => 0x01,
|
Command::SWRESET => 0x01,
|
||||||
|
@ -169,7 +169,7 @@ const ST7735_BLUE_INIT : [(Command, u32); 18] = [
|
||||||
|
|
||||||
|
|
||||||
// Init for 7735R, part 1 (red or green tab)
|
// Init for 7735R, part 1 (red or green tab)
|
||||||
const ST7735_RED_INIT : [(Command, u32); 15] = [
|
const ST7735_RED_INIT1 : [(Command, u32); 15] = [
|
||||||
(Command::SWRESET, 150), // 1: Software reset, 150ms delay
|
(Command::SWRESET, 150), // 1: Software reset, 150ms delay
|
||||||
(Command::SLPOUT, 500), // 2: Out of sleep mode
|
(Command::SLPOUT, 500), // 2: Out of sleep mode
|
||||||
(Command::FRMCTR1([0x01, 0x2C, 0x2D]), 0), // 3: Frame rate ctrl - normal mode
|
(Command::FRMCTR1([0x01, 0x2C, 0x2D]), 0), // 3: Frame rate ctrl - normal mode
|
||||||
|
@ -347,10 +347,9 @@ impl<SPIAddr, GPIOAddr> St7735IO<SPIAddr, GPIOAddr>
|
||||||
GPIOAddr: Location {
|
GPIOAddr: Location {
|
||||||
|
|
||||||
spi.configure(|s| {
|
spi.configure(|s| {
|
||||||
s.set_enabled(true)
|
s.set_master_mode(true)
|
||||||
.set_master_mode(true)
|
|
||||||
.set_software_slave_select(true)
|
.set_software_slave_select(true)
|
||||||
.set_clock_divider(128)
|
.set_clock_divider(8)
|
||||||
// required for master mode, even if ss is done manually
|
// required for master mode, even if ss is done manually
|
||||||
.set_slave_select_output_enabled(true)
|
.set_slave_select_output_enabled(true)
|
||||||
});
|
});
|
||||||
|
@ -409,11 +408,14 @@ impl<SPIAddr, GPIOAddr> St7735IO<SPIAddr, GPIOAddr>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_byte(&mut self, byte : u8) {
|
fn write_byte(&mut self, byte : u8) {
|
||||||
|
self.spi.set_enabled(true);
|
||||||
self.spi.set_data(byte as u32);
|
self.spi.set_data(byte as u32);
|
||||||
|
while !self.spi.rx_buffer_not_empty() {}
|
||||||
while self.spi.busy() {}
|
while self.spi.busy() {}
|
||||||
|
self.spi.set_enabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_data_byte(&mut self, data : u8) {
|
pub fn write_data_byte(&mut self, data : u8) {
|
||||||
self.set_rs();
|
self.set_rs();
|
||||||
|
|
||||||
self.reset_cs();
|
self.reset_cs();
|
||||||
|
@ -421,28 +423,156 @@ impl<SPIAddr, GPIOAddr> St7735IO<SPIAddr, GPIOAddr>
|
||||||
self.set_cs();
|
self.set_cs();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_command_byte(&mut self, cmd : u8) {
|
pub fn write_color_bytes(&mut self, data0 : u8, data1 : u8) {
|
||||||
self.set_rs();
|
self.set_rs();
|
||||||
|
|
||||||
|
self.reset_cs();
|
||||||
|
self.write_byte(data0);
|
||||||
|
self.write_byte(data1);
|
||||||
|
self.set_cs();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_command_byte(&mut self, cmd : u8) {
|
||||||
|
self.reset_rs();
|
||||||
|
|
||||||
self.reset_cs();
|
self.reset_cs();
|
||||||
self.write_byte(cmd);
|
self.write_byte(cmd);
|
||||||
self.set_cs();
|
self.set_cs();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_command(&mut self, cmd : Command) {
|
pub fn write_command(&mut self, cmd : &Command) {
|
||||||
let cmd_byte = command_to_byte(cmd);
|
let cmd_byte = command_to_byte(cmd);
|
||||||
self.write_command_byte(cmd_byte);
|
self.write_command_byte(cmd_byte);
|
||||||
|
|
||||||
|
match cmd {
|
||||||
|
Command::COLMOD(arg) |
|
||||||
|
Command::MADCTL(arg) |
|
||||||
|
Command::INVCTR(arg) |
|
||||||
|
Command::PWCTR2(arg) => self.write_data_byte(*arg),
|
||||||
|
|
||||||
|
Command::DISSET5(args) |
|
||||||
|
Command::PWCTR3(args) |
|
||||||
|
Command::PWCTR4(args) |
|
||||||
|
Command::PWCTR5(args) |
|
||||||
|
Command::PWCTR6(args) |
|
||||||
|
Command::VMCTR1(args) |
|
||||||
|
Command::PWCTR1(args) => {
|
||||||
|
for &arg in args.iter() {
|
||||||
|
self.write_data_byte(arg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Command::CASET(args) |
|
||||||
|
Command::RASET(args) => {
|
||||||
|
for &arg in args.iter() {
|
||||||
|
self.write_data_byte(arg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Command::FRMCTR1(args) |
|
||||||
|
Command::FRMCTR2(args) => {
|
||||||
|
for &arg in args.iter() {
|
||||||
|
self.write_data_byte(arg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Command::FRMCTR3(args) => {
|
||||||
|
for &arg in args.iter() {
|
||||||
|
self.write_data_byte(arg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Command::GMCTRP1(args) |
|
||||||
|
Command::GMCTRN1(args) => {
|
||||||
|
for &arg in args.iter() {
|
||||||
|
self.write_data_byte(arg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run_commands(&mut self, cmds: &[(Command, u32)]) {
|
||||||
|
for &(ref cmd, ref delay) in cmds.iter() {
|
||||||
|
self.write_command(cmd);
|
||||||
|
delay_ms(*delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn init(&mut self) {
|
pub fn init(&mut self) {
|
||||||
|
|
||||||
|
self.enable_led();
|
||||||
|
self.reset();
|
||||||
|
|
||||||
|
match self.st7735.display_type {
|
||||||
|
DisplayType::BLUE => {
|
||||||
|
self.run_commands(&ST7735_BLUE_INIT);
|
||||||
|
},
|
||||||
|
DisplayType::RED_18_GREENTAB => {
|
||||||
|
self.run_commands(&ST7735_RED_INIT1);
|
||||||
|
self.run_commands(&ST7735_RED_INIT_GREEN2);
|
||||||
|
self.run_commands(&ST7735_RED_INIT3);
|
||||||
|
},
|
||||||
|
DisplayType::RED_18_REDTAB => {
|
||||||
|
self.run_commands(&ST7735_RED_INIT1);
|
||||||
|
self.run_commands(&ST7735_RED_INIT_RED2);
|
||||||
|
self.run_commands(&ST7735_RED_INIT3);
|
||||||
|
},
|
||||||
|
DisplayType::RED_18_BLACKTAB => {
|
||||||
|
self.run_commands(&ST7735_RED_INIT1);
|
||||||
|
self.run_commands(&ST7735_RED_INIT_RED2);
|
||||||
|
self.run_commands(&ST7735_RED_INIT3);
|
||||||
|
// Change MADCTL color filter for black
|
||||||
|
self.write_command(&Command::MADCTL(0xC0));
|
||||||
|
},
|
||||||
|
DisplayType::RED144_GREENTAB => {
|
||||||
|
self.run_commands(&ST7735_RED_INIT1);
|
||||||
|
self.run_commands(&ST7735_RED_INIT_GREEN1442);
|
||||||
|
self.run_commands(&ST7735_RED_INIT3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_addr_win(&mut self, x0 : u8, y0 : u8, x1 : u8, y1 : u8) {
|
||||||
|
let xstart = x0 + self.st7735.column_start;
|
||||||
|
let xend = x1 + self.st7735.column_start;
|
||||||
|
self.write_command(&Command::CASET([0x00,
|
||||||
|
xstart,
|
||||||
|
0x00,
|
||||||
|
xend])); // Column addr set
|
||||||
|
|
||||||
|
let ystart = y0 + self.st7735.row_start;
|
||||||
|
let yend = y1 + self.st7735.row_start;
|
||||||
|
self.write_command(&Command::RASET([0x00,
|
||||||
|
ystart,
|
||||||
|
0x00,
|
||||||
|
yend])); // Column addr set
|
||||||
|
|
||||||
|
self.write_command(&Command::RAMWR); // write to RAM
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_rect(&mut self, x : u8, y : u8, w : u8, h : u8, c1 : u8, c2 : u8) {
|
||||||
|
|
||||||
|
self.set_addr_win(x, y, x + w - 1, y + h - 1);
|
||||||
|
|
||||||
|
self.set_rs();
|
||||||
|
self.reset_cs();
|
||||||
|
|
||||||
|
for i in 0..h {
|
||||||
|
for j in 0..w {
|
||||||
|
self.write_byte(c1);
|
||||||
|
self.write_byte(c2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set_cs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn done(mut self) -> (St7735, PeripheralRef<spi::SPI, SPIAddr>, PeripheralRef<gpio::GPIO, GPIOAddr>) {
|
pub fn done(mut self) -> (St7735, PeripheralRef<spi::SPI, SPIAddr>, PeripheralRef<gpio::GPIO, GPIOAddr>) {
|
||||||
self.set_cs();
|
self.set_cs();
|
||||||
self.spi.set_enabled(false);
|
|
||||||
(self.st7735, self.spi, self.gpio)
|
(self.st7735, self.spi, self.gpio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue