//! This example shows powerful PIO module in the RP2040 chip to communicate with a HD44780 display. //! See (https://www.sparkfun.com/datasheets/LCD/HD44780.pdf) #![no_std] #![no_main] use core::fmt::Write; use embassy_executor::Spawner; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{InterruptHandler, Pio}; use embassy_rp::pio_programs::hd44780::{PioHD44780, PioHD44780CommandSequenceProgram, PioHD44780CommandWordProgram}; use embassy_rp::pwm::{self, Pwm}; use embassy_time::{Instant, Timer}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(pub struct Irqs { PIO0_IRQ_0 => InterruptHandler; }); #[embassy_executor::main] async fn main(_spawner: Spawner) { // this test assumes a 2x16 HD44780 display attached as follow: // rs = PIN0 // rw = PIN1 // e = PIN2 // db4 = PIN3 // db5 = PIN4 // db6 = PIN5 // db7 = PIN6 // additionally a pwm signal for a bias voltage charge pump is provided on pin 15, // allowing direct connection of the display to the RP2040 without level shifters. let p = embassy_rp::init(Default::default()); let _pwm = Pwm::new_output_b(p.PWM_SLICE7, p.PIN_15, { let mut c = pwm::Config::default(); c.divider = 125.into(); c.top = 100; c.compare_b = 50; c }); let Pio { mut common, sm0, irq0, .. } = Pio::new(p.PIO0, Irqs); let word_prg = PioHD44780CommandWordProgram::new(&mut common); let seq_prg = PioHD44780CommandSequenceProgram::new(&mut common); let mut hd = PioHD44780::new( &mut common, sm0, irq0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, &word_prg, &seq_prg, ) .await; loop { struct Buf([u8; N], usize); impl Write for Buf { fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { for b in s.as_bytes() { if self.1 >= N { return Err(core::fmt::Error); } self.0[self.1] = *b; self.1 += 1; } Ok(()) } } let mut buf = Buf([0; 16], 0); write!(buf, "up {}s", Instant::now().as_micros() as f32 / 1e6).unwrap(); hd.add_line(&buf.0[0..buf.1]).await; Timer::after_secs(1).await; } }