172 lines
4.4 KiB
Rust
Executable file
172 lines
4.4 KiB
Rust
Executable file
#![no_main]
|
|
#![no_std]
|
|
|
|
use defmt::{debug, info};
|
|
use hal::{
|
|
delay::Delay,
|
|
gpio::{
|
|
Output, PushPull,
|
|
gpioa::{PA8, PA10},
|
|
gpiob::{PB3, PB4, PB5, PB10},
|
|
},
|
|
};
|
|
use panic_probe as _;
|
|
|
|
use defmt_rtt as _; // global logger
|
|
|
|
use core::fmt::Write;
|
|
|
|
use cortex_m_rt::entry;
|
|
use hal::{pac, prelude::*, rcc::Config};
|
|
|
|
pub type D2PIN = PA10<Output<PushPull>>;
|
|
pub type D3PIN = PB3<Output<PushPull>>;
|
|
pub type D4PIN = PB5<Output<PushPull>>;
|
|
pub type D5PIN = PB4<Output<PushPull>>;
|
|
pub type D6PIN = PB10<Output<PushPull>>;
|
|
pub type D7PIN = PA8<Output<PushPull>>;
|
|
|
|
struct LCDHardware<'a> {
|
|
d4: &'a mut PB5<Output<PushPull>>,
|
|
d5: &'a mut PB4<Output<PushPull>>,
|
|
d6: &'a mut PB10<Output<PushPull>>,
|
|
d7: &'a mut PA8<Output<PushPull>>,
|
|
rs: &'a mut PA10<Output<PushPull>>,
|
|
en: &'a mut PB3<Output<PushPull>>,
|
|
delay: &'a mut Delay,
|
|
}
|
|
|
|
impl<'a> LCDHardware<'a> {
|
|
fn new(
|
|
d4: &'a mut D4PIN,
|
|
d5: &'a mut D5PIN,
|
|
d6: &'a mut D6PIN,
|
|
d7: &'a mut D7PIN,
|
|
rs: &'a mut D2PIN,
|
|
en: &'a mut D3PIN,
|
|
delay: &'a mut Delay,
|
|
) -> lcd::Display<LCDHardware<'a>> {
|
|
let hw: LCDHardware<'a> = LCDHardware {
|
|
d4,
|
|
d5,
|
|
d6,
|
|
d7,
|
|
rs,
|
|
en,
|
|
delay,
|
|
};
|
|
let mut lcd = lcd::Display::new(hw);
|
|
lcd.init(lcd::FunctionLine::Line2, lcd::FunctionDots::Dots5x8);
|
|
lcd.display(
|
|
lcd::DisplayMode::DisplayOn,
|
|
lcd::DisplayCursor::CursorOn,
|
|
lcd::DisplayBlink::BlinkOn,
|
|
);
|
|
lcd.entry_mode(
|
|
lcd::EntryModeDirection::EntryRight,
|
|
lcd::EntryModeShift::NoShift,
|
|
);
|
|
|
|
lcd
|
|
}
|
|
}
|
|
|
|
impl lcd::Delay for LCDHardware<'_> {
|
|
fn delay_us(&mut self, delay_usec: u32) {
|
|
self.delay.delay_us(delay_usec);
|
|
}
|
|
}
|
|
|
|
impl lcd::Hardware for LCDHardware<'_> {
|
|
fn rs(&mut self, bit: bool) {
|
|
self.rs
|
|
.set_state(PinState::from(bit))
|
|
.expect("could not set LCD RS")
|
|
}
|
|
|
|
fn enable(&mut self, bit: bool) {
|
|
self.en
|
|
.set_state(PinState::from(bit))
|
|
.expect("could not set LCD RS")
|
|
}
|
|
|
|
fn data(&mut self, data: u8) {
|
|
let d4 = data & 0b00000001;
|
|
let d5 = data & 0b00000010;
|
|
let d6 = data & 0b00000100;
|
|
let d7 = data & 0b00001000;
|
|
|
|
debug!("Writing data: d4:{}, d5:{}, d6:{}, d7:{}", d4, d5, d6, d7);
|
|
|
|
self.d4
|
|
.set_state(PinState::from(d4 > 0))
|
|
.expect("could not set LCD D4");
|
|
self.d5
|
|
.set_state(PinState::from(d5 > 0))
|
|
.expect("could not set LCD D5");
|
|
self.d6
|
|
.set_state(PinState::from(d6 > 0))
|
|
.expect("could not set LCD D6");
|
|
self.d7
|
|
.set_state(PinState::from(d7 > 0))
|
|
.expect("could not set LCD D7");
|
|
}
|
|
|
|
fn mode(&self) -> lcd::FunctionMode {
|
|
lcd::FunctionMode::Bit4
|
|
}
|
|
|
|
fn can_read(&self) -> bool {
|
|
false
|
|
}
|
|
}
|
|
|
|
#[defmt::panic_handler]
|
|
fn panic() -> ! {
|
|
cortex_m::asm::udf()
|
|
}
|
|
|
|
#[entry]
|
|
fn main() -> ! {
|
|
let dp = pac::Peripherals::take().unwrap();
|
|
let cp = cortex_m::Peripherals::take().unwrap();
|
|
|
|
let mut rcc = dp.RCC.freeze(Config::hsi16());
|
|
|
|
let gpioa = dp.GPIOA.split(&mut rcc);
|
|
let gpiob = dp.GPIOB.split(&mut rcc);
|
|
let _gpioc = dp.GPIOC.split(&mut rcc);
|
|
|
|
// clock enable on D2
|
|
let mut rs: D2PIN = gpioa.pa10.into_push_pull_output();
|
|
// register select on D3, the lib wants that but I'd just put it on ground otherwise
|
|
let mut en: D3PIN = gpiob.pb3.into_push_pull_output();
|
|
|
|
let mut d4: D4PIN = gpiob.pb5.into_push_pull_output();
|
|
let mut d5: D5PIN = gpiob.pb4.into_push_pull_output();
|
|
let mut d6: D6PIN = gpiob.pb10.into_push_pull_output();
|
|
let mut d7: D7PIN = gpioa.pa8.into_push_pull_output();
|
|
|
|
// See https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller#Interface
|
|
// for the pins of the LCD
|
|
|
|
let mut delay = cp.SYST.delay(rcc.clocks);
|
|
|
|
let mut led = gpioa.pa5.into_push_pull_output();
|
|
|
|
led.set_high().unwrap();
|
|
info!("Writing to LCD...");
|
|
let mut lcd = LCDHardware::new(
|
|
&mut d4, &mut d5, &mut d6, &mut d7, &mut rs, &mut en, &mut delay,
|
|
);
|
|
write!(&mut lcd, "Hello World").expect("could not write to lcd");
|
|
info!("Done!");
|
|
led.set_low().unwrap();
|
|
|
|
let mut i = 0;
|
|
loop {
|
|
delay.delay_ms(500_u16);
|
|
|
|
i += 1;
|
|
}
|
|
}
|