1#![no_implicit_prelude]
21
22extern crate core;
23extern crate rpsp;
24
25use core::clone::Clone;
26use core::convert::{Into, TryInto};
27use core::option::Option::{self, None, Some};
28use core::result::Result::{self, Ok};
29
30use rpsp::Board;
31use rpsp::clock::Timer;
32use rpsp::pin::gpio::{Input, Output};
33use rpsp::pin::{Pin, PinID};
34use rpsp::spi::{Spi, SpiBus, SpiConfig, SpiError, SpiFormat, SpiIO, SpiPhase, SpiPolarity};
35
36use crate::frame::ShiftRegister;
37
38const SR_BUSY: u8 = 7u8;
39const BAUDRATE: u32 = 3_000_000u32;
40
41pub enum BusySignal {
42 Pin(Pin<Input>),
43 SR(ShiftRegister),
44}
45
46pub struct Display<'a, const W: u16, const H: u16> {
47 bs: BusySignal,
48 cs: Pin<Output>,
49 rst: Pin<Output>,
50 spi: SpiBus<'a>,
51 data: Pin<Output>,
52 timer: Timer,
53}
54
55impl BusySignal {
56 #[inline]
57 fn is_ready(&self) -> bool {
58 match self {
59 BusySignal::Pin(v) => v.is_high(),
60 BusySignal::SR(v) => v.is_set(SR_BUSY),
61 }
62 }
63}
64impl<const W: u16, const H: u16> Display<'_, W, H> {
65 #[inline]
66 pub fn new<'a>(p: &Board, spi: SpiBus<'a>, cs: PinID, rst: PinID, data: PinID, bs: BusySignal) -> Display<'a, W, H> {
67 Display {
68 bs,
69 spi,
70 cs: p.pin(cs).output_high(),
71 rst: p.pin(rst).output_high(),
72 data: p.pin(data),
73 timer: p.timer().clone(),
74 }
75 }
76 pub fn create(p: &Board, tx: PinID, sck: PinID, cs: PinID, rst: PinID, data: PinID, bs: BusySignal) -> Result<Display<W, H>, SpiError> {
77 Ok(Display {
78 bs,
79 cs: p.pin(cs).output_high(),
80 rst: p.pin(rst).output_high(),
81 spi: Spi::new(
82 p,
83 BAUDRATE,
84 SpiConfig::new()
85 .bits(8)
86 .format(SpiFormat::Motorola)
87 .phase(SpiPhase::First)
88 .polarity(SpiPolarity::Low)
89 .primary(true),
90 (tx, sck).try_into()?,
91 )?
92 .into(),
93 data: p.pin(data),
94 timer: p.timer().clone(),
95 })
96 }
97
98 #[inline]
99 pub fn off(&mut self) {
100 self.wait();
101 self.cmd(0x2) }
103 #[inline]
104 pub fn sleep(&mut self) {
105 self.wait();
106 self.cmd(0xA5) }
108 #[inline]
109 pub fn refresh(&mut self) {
110 self.setup();
111 self.cmd(0x4);
112 self.wait();
113 self.cmd(0x12);
114 self.wait();
115 }
116 #[inline(always)]
117 pub fn width(&self) -> u16 {
118 W
119 }
120 #[inline(always)]
121 pub fn height(&self) -> u16 {
122 H
123 }
124 #[inline(always)]
125 pub fn is_busy(&self) -> bool {
126 !self.bs.is_ready()
127 }
128 #[inline(always)]
129 pub fn is_ready(&self) -> bool {
130 self.bs.is_ready()
131 }
132 pub fn update(&mut self, b: &[u8]) {
133 self.setup();
134 self.cmd_data(0x10, b); self.wait();
136 self.cmd(0x4); self.wait();
138 self.cmd(0x12); self.wait();
140 self.cmd(0x2); }
142 #[inline(always)]
143 pub fn spi_bus(&mut self) -> &mut Spi {
144 &mut self.spi
145 }
146 #[inline(always)]
147 pub fn shift_register(&self) -> Option<&ShiftRegister> {
148 match &self.bs {
149 BusySignal::Pin(_) => None,
150 BusySignal::SR(v) => Some(v),
151 }
152 }
153
154 pub unsafe fn update_async(&mut self, b: &[u8]) {
158 self.setup();
159 self.cmd_data(0x10, b); self.wait();
161 self.cmd(0x4); self.wait();
163 self.cmd(0x12); }
165
166 #[inline]
167 fn wait(&self) {
168 while !self.bs.is_ready() {
169 self.timer.sleep_ms(10);
170 }
171 }
172 fn setup(&mut self) {
173 self.reset();
174 self.cmd_data(0x0, &[0xAF | if W == 600 { 0x40 } else { 0 }, 0x8]); self.cmd_data(0x1, &[0x37, 0, 0x23, 0x23]); self.cmd_data(0x3, &[0]); self.cmd_data(0x6, &[0xC7, 0xC7, 0x1D]); self.cmd_data(0x30, &[0x3C]); self.cmd_data(0x40, &[0]); self.cmd_data(0x50, &[0x37]); self.cmd_data(0x60, &[0x22]); self.cmd_data(0x61, &[(W >> 8) as u8, W as u8, (H >> 8) as u8, H as u8]); self.cmd_data(0xE3, &[0xAA]); self.timer.sleep_ms(100);
185 self.cmd_data(0x50, &[0x37]) }
187 fn reset(&self) {
188 self.rst.low();
189 self.timer.sleep_ms(10);
190 self.rst.high();
191 self.timer.sleep_ms(10);
192 self.wait();
193 }
194 fn cmd(&mut self, v: u8) {
195 self.cs.low();
196 self.data.low();
197 self.spi.write_single(v);
198 self.cs.high();
199 }
200 fn cmd_data(&mut self, v: u8, b: &[u8]) {
201 self.cs.low();
202 self.data.low();
203 self.spi.write_single(v);
204 self.data.high();
205 self.spi.write(b);
206 self.cs.high();
207 }
208}