1use crate::utils::BitOps;
4
5#[derive(Clone, Copy, PartialEq)]
7#[allow(missing_docs)]
8pub enum CommandSet {
9 ClearDisplay,
10 ReturnHome,
11 EntryModeSet(MoveDirection, ShiftType),
12 DisplayOnOff {
13 display: State,
14 cursor: State,
15 cursor_blink: State,
16 },
17 CursorOrDisplayShift(ShiftType, MoveDirection),
18 HalfFunctionSet,
22 FunctionSet(DataWidth, LineMode, Font),
23 SetCGRAM(u8),
24 SetDDRAM(u8),
25 ReadBusyFlagAndAddress,
26 WriteDataToRAM(u8),
27 ReadDataFromRAM,
28}
29
30#[derive(Clone, Copy, PartialEq, Default)]
32pub enum MoveDirection {
33 #[allow(missing_docs)]
34 RightToLeft,
35 #[allow(missing_docs)]
36 #[default]
37 LeftToRight,
38}
39
40#[derive(Clone, Copy, Default, PartialEq)]
42pub enum ShiftType {
43 #[allow(missing_docs)]
44 #[default]
45 CursorOnly,
46 #[allow(missing_docs)]
47 CursorAndDisplay,
48}
49
50#[derive(Clone, Copy, PartialEq, Default)]
52pub enum State {
53 #[allow(missing_docs)]
54 Off,
55 #[allow(missing_docs)]
56 #[default]
57 On,
58}
59
60#[derive(Clone, Copy, Default, PartialEq)]
63pub enum DataWidth {
64 #[allow(missing_docs)]
65 #[default]
66 Bit4,
67 #[allow(missing_docs)]
68 Bit8,
69}
70
71#[derive(Clone, Copy, Default, PartialEq)]
73pub enum LineMode {
74 #[allow(missing_docs)]
75 OneLine,
76 #[allow(missing_docs)]
77 #[default]
78 TwoLine,
79}
80
81#[derive(Clone, Copy, Default, PartialEq)]
83pub enum Font {
84 #[allow(missing_docs)]
85 #[default]
86 Font5x8,
87 #[allow(missing_docs)]
88 Font5x11,
89}
90
91#[derive(Clone, Copy, Default, PartialEq)]
93pub enum RAMType {
94 #[default]
96 DDRam,
97 CGRam,
99}
100
101pub struct Command {
103 rs: RegisterSelection,
104 rw: ReadWriteOp,
105 data: Option<Bits>, }
107
108#[derive(Clone, Copy, PartialEq)]
111pub enum RegisterSelection {
112 Command,
114 Data,
116}
117
118#[derive(Clone, Copy, PartialEq)]
121pub enum ReadWriteOp {
122 Write,
124 Read,
126}
127
128#[derive(Clone, Copy, PartialEq)]
131pub enum Bits {
132 Bit4(u8),
134 Bit8(u8),
136}
137
138#[allow(dead_code)]
139impl Command {
140 pub(crate) fn new(rs: RegisterSelection, rw: ReadWriteOp, data: Option<Bits>) -> Self {
141 if (rw == ReadWriteOp::Write) && (data.is_none()) {
142 panic!("Write Operation Should have Data");
143 }
144
145 Self { rs, rw, data }
146 }
147
148 pub(crate) fn get_register_selection(&self) -> RegisterSelection {
149 self.rs
150 }
151
152 pub(crate) fn set_register_selection(&mut self, rs: RegisterSelection) {
153 self.rs = rs
154 }
155
156 pub(crate) fn get_read_write_op(&self) -> ReadWriteOp {
157 self.rw
158 }
159
160 pub(crate) fn set_read_write_op(&mut self, rw: ReadWriteOp) {
161 self.rw = rw
162 }
163
164 pub(crate) fn get_data(&self) -> Option<Bits> {
165 self.data
166 }
167
168 pub(crate) fn set_data(&mut self, data: Option<Bits>) {
169 self.data = data
170 }
171}
172
173impl From<CommandSet> for Command {
174 fn from(command: CommandSet) -> Self {
175 match command {
176 CommandSet::ClearDisplay => {
177 let raw_bits: u8 = 0b0000_0001;
178 Self::new(
179 RegisterSelection::Command,
180 ReadWriteOp::Write,
181 Some(Bits::Bit8(raw_bits)),
182 )
183 }
184
185 CommandSet::ReturnHome => {
186 let raw_bits: u8 = 0b0000_0010;
187 Self::new(
188 RegisterSelection::Command,
189 ReadWriteOp::Write,
190 Some(Bits::Bit8(raw_bits)),
191 )
192 }
193
194 CommandSet::EntryModeSet(dir, st) => {
195 let mut raw_bits: u8 = 0b0000_0100;
196
197 match dir {
198 MoveDirection::RightToLeft => raw_bits.clear_bit(1),
199 MoveDirection::LeftToRight => raw_bits.set_bit(1),
200 };
201
202 match st {
203 ShiftType::CursorOnly => raw_bits.clear_bit(0),
204 ShiftType::CursorAndDisplay => raw_bits.set_bit(0),
205 };
206
207 Self::new(
208 RegisterSelection::Command,
209 ReadWriteOp::Write,
210 Some(Bits::Bit8(raw_bits)),
211 )
212 }
213
214 CommandSet::DisplayOnOff {
215 display,
216 cursor,
217 cursor_blink,
218 } => {
219 let mut raw_bits = 0b0000_1000;
220
221 match display {
222 State::Off => raw_bits.clear_bit(2),
223 State::On => raw_bits.set_bit(2),
224 };
225 match cursor {
226 State::Off => raw_bits.clear_bit(1),
227 State::On => raw_bits.set_bit(1),
228 };
229 match cursor_blink {
230 State::Off => raw_bits.clear_bit(0),
231 State::On => raw_bits.set_bit(0),
232 };
233
234 Self::new(
235 RegisterSelection::Command,
236 ReadWriteOp::Write,
237 Some(Bits::Bit8(raw_bits)),
238 )
239 }
240
241 CommandSet::CursorOrDisplayShift(st, dir) => {
242 let mut raw_bits = 0b0001_0000;
243
244 match st {
245 ShiftType::CursorOnly => raw_bits.clear_bit(3),
246 ShiftType::CursorAndDisplay => raw_bits.set_bit(3),
247 };
248
249 match dir {
250 MoveDirection::RightToLeft => raw_bits.clear_bit(2),
251 MoveDirection::LeftToRight => raw_bits.set_bit(2),
252 };
253
254 Self::new(
255 RegisterSelection::Command,
256 ReadWriteOp::Write,
257 Some(Bits::Bit8(raw_bits)),
258 )
259 }
260
261 CommandSet::HalfFunctionSet => Self::new(
262 RegisterSelection::Command,
263 ReadWriteOp::Write,
264 Some(Bits::Bit4(0b0010)),
265 ),
266
267 CommandSet::FunctionSet(width, line, font) => {
268 let mut raw_bits = 0b0010_0000;
269
270 match width {
271 DataWidth::Bit4 => raw_bits.clear_bit(4),
272 DataWidth::Bit8 => raw_bits.set_bit(4),
273 };
274
275 match line {
276 LineMode::OneLine => raw_bits.clear_bit(3),
277 LineMode::TwoLine => raw_bits.set_bit(3),
278 };
279
280 match font {
281 Font::Font5x8 => raw_bits.clear_bit(2),
282 Font::Font5x11 => raw_bits.set_bit(2),
283 };
284
285 Self::new(
286 RegisterSelection::Command,
287 ReadWriteOp::Write,
288 Some(Bits::Bit8(raw_bits)),
289 )
290 }
291
292 CommandSet::SetCGRAM(addr) => {
293 let mut raw_bits = 0b0100_0000;
294
295 assert!(addr < 2u8.pow(6), "CGRAM address out of range");
296
297 raw_bits += addr;
298
299 Self::new(
300 RegisterSelection::Command,
301 ReadWriteOp::Write,
302 Some(Bits::Bit8(raw_bits)),
303 )
304 }
305
306 CommandSet::SetDDRAM(addr) => {
307 let mut raw_bits = 0b1000_0000;
308
309 assert!(addr < 2u8.pow(7), "DDRAM address out of range");
310
311 raw_bits += addr;
312
313 Self::new(
314 RegisterSelection::Command,
315 ReadWriteOp::Write,
316 Some(Bits::Bit8(raw_bits)),
317 )
318 }
319
320 CommandSet::ReadBusyFlagAndAddress => {
321 Self::new(RegisterSelection::Command, ReadWriteOp::Read, None)
322 }
323
324 CommandSet::WriteDataToRAM(data) => Self::new(
325 RegisterSelection::Data,
326 ReadWriteOp::Write,
327 Some(Bits::Bit8(data)),
328 ),
329
330 CommandSet::ReadDataFromRAM => {
331 Self::new(RegisterSelection::Data, ReadWriteOp::Read, None)
332 }
333 }
334 }
335}