Skip to content

Commit dfa97f5

Browse files
committed
wip: init scroll implementation: xpos/ypos and buffer as fields
1 parent d869d7a commit dfa97f5

File tree

4 files changed

+109
-46
lines changed

4 files changed

+109
-46
lines changed

examples/arduino-uno-pcd8544/src/main.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#![no_main]
33

44
use panic_halt as _;
5-
use pcd8544_hal::Pcd8544;
5+
// use pcd8544_hal::Pcd8544;
66

77
static RUST_LOGO: &[u8; 504] = include_bytes!("logo.bin");
88

@@ -11,15 +11,22 @@ fn main() -> ! {
1111
let dp = arduino_hal::Peripherals::take().unwrap();
1212
let pins = arduino_hal::pins!(dp);
1313

14-
let mut pcd8544 = pcd8544_hal::Pcd8544Gpio::new(
14+
let gpio_backend = pcd8544_hal::Pcd8544Gpio::new(
1515
/* sck/clk */ pins.d7.into_output(),
1616
/* miso/din */ pins.d6.into_output(),
1717
/* mosi/dc */ pins.d5.into_output(),
1818
/* cs/ce */ pins.d4.into_output(),
1919
/* rst */ Some(&mut pins.d3.into_output()),
2020
&mut arduino_hal::Delay::new(),
2121
);
22-
pcd8544.draw_buffer(RUST_LOGO);
22+
// 2. Wrap it in the driver with shared logic
23+
let mut display = pcd8544_hal::Pcd8544Driver::new(gpio_backend);
24+
25+
// 3. Use the unified display logic
26+
display.init();
27+
display.print("Hello,\nworld!");
28+
// pcd8544.print("Hello, worldy");
29+
// pcd8544.draw_buffer(RUST_LOGO);
2330

2431
#[allow(clippy::empty_loop)]
2532
loop {}

src/lib.rs

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#![deny(unsafe_code)]
2-
#![deny(warnings)]
2+
// #![deny(warnings)]
33
#![no_std]
44

55
mod font;
@@ -9,58 +9,112 @@ mod pcd8544_spi;
99
pub use pcd8544_gpio::Pcd8544Gpio;
1010
pub use pcd8544_spi::Pcd8544Spi;
1111

12-
pub trait Pcd8544 {
12+
const DISPLAY_WIDTH: usize = 84;
13+
const DISPLAY_HEIGHT: usize = 6;
14+
const BUFFER_SIZE: usize = DISPLAY_WIDTH * DISPLAY_HEIGHT;
15+
16+
// #[repr(usize)]
17+
// enum Command {
18+
// SetXAddress = 0x80,
19+
// SetYAddress = 0x40,
20+
// FunctionSet = 0x20, // Basic instruction set, only supported mode currently
21+
// }
22+
23+
pub trait Pcd8544Backend {
1324
fn command(&mut self, command: u8);
1425
fn data(&mut self, data: &[u8]);
26+
}
27+
28+
pub struct Pcd8544Driver<B: Pcd8544Backend> {
29+
backend: B,
30+
xpos: u8,
31+
ypos: u8,
32+
buffer: [0u8; BUFFER_SIZE],
33+
}
34+
35+
impl<B: Pcd8544Backend> Pcd8544Driver<B> {
36+
pub fn new(backend: B) -> Self {
37+
Self {
38+
backend,
39+
xpos: 0,
40+
ypos: 0,
41+
}
42+
}
1543

16-
fn init(&mut self) {
17-
self.command(0x21); // chip active; horizontal addressing mode (V = 0); use extended instruction set (H = 1)
18-
// set LCD Vop (contrast), which may require some tweaking:
19-
self.command(0xB8); // try 0xB1 (for 3.3V red SparkFun), 0xB8 (for 3.3V blue SparkFun), 0xBF if your display is too dark, or 0x80 to 0xFF if experimenting
20-
self.command(0x04); // set temp coefficient
21-
self.command(0x14); // LCD bias mode 1:48: try 0x13 or 0x14
44+
pub fn init(&mut self) {
45+
self.backend.command(0x21); // chip active; horizontal addressing mode (V = 0); use extended instruction set (H = 1)
46+
// set LCD Vop (contrast), which may require some tweaking:
47+
self.backend.command(0xB8); // try 0xB1 (for 3.3V red SparkFun), 0xB8 (for 3.3V blue SparkFun), 0xBF if your display is too dark, or 0x80 to 0xFF if experimenting
48+
self.backend.command(0x04); // set temp coefficient
49+
self.backend.command(0x14); // LCD bias mode 1:48: try 0x13 or 0x14
2250

23-
self.command(0x20); // we must send 0x20 before modifying the display control mode
24-
self.command(0x0C); // set display control to normal mode: 0x0D for inverse
51+
self.backend.command(0x20); // we must send 0x20 before modifying the display control mode
52+
self.backend.command(0x0C); // set display control to normal mode: 0x0D for inverse
2553

2654
self.clear();
2755
}
2856

29-
fn print_char(&mut self, c: u8) {
30-
let i = (c as usize) - 0x20;
57+
fn new_line(&mut self) {
3158

32-
self.data(&font::ASCII[i]);
33-
self.data(&[0x00]);
59+
// move to the next line
60+
// TODO
61+
// let ypos = *YPOS.lock();
62+
if ypos < DISPLAY_HEIGHT - 1 {
63+
self.set_position(xpos, ypos + 1);
64+
} else {
65+
// scroll the display up
66+
// TODO
67+
// let buffer = *BUFFER.lock();
68+
// buffer.copy_within(0..BUFFER_SIZE - DISPLAY_WIDTH, DISPLAY_WIDTH);
69+
// self.draw_buffer(&buffer);
70+
self.set_position(0, 0);
71+
}
3472
}
3573

36-
fn print(&mut self, s: &str) {
37-
for c in s.bytes() {
38-
self.print_char(c);
74+
fn print_char(&mut self, c: u8) {
75+
self.backend.data(&font::ASCII[c as usize - 0x20]);
76+
self.backend.data(&[0x00]);
77+
}
78+
79+
pub fn print(&mut self, s: &str) {
80+
for byte in s.bytes() {
81+
match byte {
82+
// printable ASCII byte or newline
83+
0x20..=0x7e => self.print_char(byte),
84+
b'\n' => self.new_line(),
85+
// not part of printable ASCII range
86+
_ => self.print_char(b'?'),
87+
}
3988
}
4089
}
4190

4291
fn set_position(&mut self, x: u8, y: u8) {
43-
assert!(x <= 84);
44-
assert!(y < 6);
92+
assert!(usize::from(x) < DISPLAY_WIDTH);
93+
assert!(usize::from(y) < DISPLAY_HEIGHT);
94+
95+
// self.backend.command(Command::SetYAddress.into() + y);
96+
// self.backend.command(Command::SetXAddress | x);
97+
self.backend.command(0x40 + y);
98+
self.backend.command(0x80 + y);
4599

46-
self.command(0x40 + y);
47-
self.command(0x80 + x);
100+
self.xpos = x;
101+
self.ypos = y;
48102
}
49103

50104
// note: data direction is vertical: [1 2 3 4 5 6]
51105
// 1 3 5
52106
// 2 4 6
53-
fn draw_buffer(&mut self, buffer: &[u8; 6 * 84]) {
54-
self.command(0x22); // vertical addressing
107+
fn draw_buffer(&mut self, buffer: &[u8; BUFFER_SIZE]) {
108+
self.backend.command(0x22); // vertical addressing
55109
self.set_position(0, 0);
56-
self.data(buffer);
57-
self.command(0x20); // horizontal addressing
110+
self.backend.data(buffer);
111+
self.backend.command(0x20); // horizontal addressing
58112
self.set_position(0, 0);
59113
}
60114

61115
fn clear(&mut self) {
62116
self.set_position(0, 0);
63-
self.data(&[0u8; 6 * 84]);
117+
self.backend.data(&[0u8; BUFFER_SIZE]);
64118
self.set_position(0, 0);
65119
}
66120
}

src/pcd8544_gpio.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use embedded_hal::delay::DelayNs;
22
use embedded_hal::digital::OutputPin;
33

4-
use crate::Pcd8544;
4+
use crate::Pcd8544Backend;
55

66
pub struct Pcd8544Gpio<CLK, DIN, DC, CS> {
77
clk: CLK,
@@ -24,16 +24,14 @@ where
2424
cs: CS,
2525
rst: Option<&mut T>,
2626
delay: &mut R,
27-
) -> Pcd8544Gpio<CLK, DIN, DC, CS> {
27+
) -> Self {
2828
if let Some(r) = rst {
2929
let _ = r.set_low();
3030
delay.delay_ns(1);
3131
let _ = r.set_high();
3232
}
3333

34-
let mut pcd = Pcd8544Gpio { clk, din, dc, cs };
35-
pcd.init();
36-
pcd
34+
Self { clk, din, dc, cs }
3735
}
3836

3937
fn send(&mut self, byte: u8) {
@@ -50,18 +48,24 @@ where
5048
}
5149
}
5250

53-
impl<CLK, DIN, DC, CS> Pcd8544 for Pcd8544Gpio<CLK, DIN, DC, CS>
51+
impl<CLK, DIN, DC, CS> Pcd8544Backend for Pcd8544Gpio<CLK, DIN, DC, CS>
5452
where
5553
CLK: OutputPin,
5654
DIN: OutputPin,
5755
DC: OutputPin,
5856
CS: OutputPin,
5957
{
60-
fn command(&mut self, cmd: u8) {
61-
let _ = self.dc.set_low();
62-
let _ = self.cs.set_low();
63-
self.send(cmd);
64-
let _ = self.cs.set_high();
58+
fn command(&mut self, byte: u8) {
59+
for bit in (0..8).rev() {
60+
if (byte & (1 << bit)) != 0 {
61+
let _ = self.din.set_high();
62+
} else {
63+
let _ = self.din.set_low();
64+
}
65+
66+
let _ = self.clk.set_high();
67+
let _ = self.clk.set_low();
68+
}
6569
}
6670

6771
fn data(&mut self, data: &[u8]) {

src/pcd8544_spi.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use embedded_hal::delay::DelayNs;
22
use embedded_hal::digital::OutputPin;
33
use embedded_hal::spi::SpiBus;
44

5-
use crate::Pcd8544;
5+
use crate::Pcd8544Backend;
66

77
pub struct Pcd8544Spi<SPI, DC, CS> {
88
spi: SPI,
@@ -22,20 +22,18 @@ where
2222
cs: CS,
2323
rst: Option<&mut T>,
2424
delay: &mut R,
25-
) -> Pcd8544Spi<SPI, DC, CS> {
25+
) -> Self {
2626
if let Some(r) = rst {
2727
let _ = r.set_low();
2828
delay.delay_ns(1);
2929
let _ = r.set_high();
3030
}
3131

32-
let mut pcd = Pcd8544Spi { spi, dc, cs };
33-
pcd.init();
34-
pcd
32+
Self { spi, dc, cs }
3533
}
3634
}
3735

38-
impl<SPI, DC, CS> Pcd8544 for Pcd8544Spi<SPI, DC, CS>
36+
impl<SPI, DC, CS> Pcd8544Backend for Pcd8544Spi<SPI, DC, CS>
3937
where
4038
SPI: SpiBus,
4139
DC: OutputPin,

0 commit comments

Comments
 (0)