1use embedded_hal::delay::DelayNs;
2
3use crate::{
4 command::{CommandSet, DataWidth, Font, LineMode, MoveDirection, RAMType, ShiftType, State},
5 lcd::Lcd,
6 sender::SendCommand,
7 state::LcdState,
8};
9
10#[derive(Default)]
12pub struct Config {
13 state: LcdState,
14
15 font_set_by_user: Option<Font>,
17 line_mode_set_by_user: Option<LineMode>,
18}
19
20#[allow(missing_docs)]
21impl Config {
22 pub fn get_backlight(&self) -> State {
23 self.state.get_backlight()
24 }
25
26 pub fn set_backlight(mut self, backlight: State) -> Self {
27 self.state.set_backlight(backlight);
28 self
29 }
30
31 pub fn get_data_width(&self) -> DataWidth {
32 self.state.get_data_width()
33 }
34
35 pub fn set_data_width(mut self, data_width: DataWidth) -> Self {
36 self.state.set_data_width(data_width);
37 self
38 }
39
40 pub fn get_line_mode(&self) -> LineMode {
41 self.state.get_line_mode()
42 }
43
44 pub fn set_line_mode(mut self, line_mode: LineMode) -> Self {
45 self.line_mode_set_by_user = Some(line_mode);
46
47 self.state.set_font(match line_mode {
49 LineMode::OneLine => self.font_set_by_user.unwrap_or_default(),
50 LineMode::TwoLine => Font::Font5x8,
51 });
52
53 self.state.set_line_mode(line_mode);
54 self
55 }
56
57 pub fn get_line_capacity(&self) -> u8 {
58 self.state.get_line_capacity()
59 }
60
61 pub fn get_font(&self) -> Font {
62 self.state.get_font()
63 }
64
65 pub fn set_font(mut self, font: Font) -> Self {
66 self.font_set_by_user = Some(font);
67
68 self.state.set_line_mode(match font {
70 Font::Font5x8 => self.line_mode_set_by_user.unwrap_or_default(),
71 Font::Font5x11 => LineMode::OneLine,
72 });
73
74 self.state.set_font(font);
75 self
76 }
77
78 pub fn get_display_state(&self) -> State {
79 self.state.get_display_state()
80 }
81
82 pub fn set_display_state(mut self, display: State) -> Self {
83 self.state.set_display_state(display);
84 self
85 }
86
87 pub fn get_cursor_state(&self) -> State {
88 self.state.get_cursor_state()
89 }
90
91 pub fn set_cursor_state(mut self, cursor: State) -> Self {
92 self.state.set_cursor_state(cursor);
93 self
94 }
95
96 pub fn get_cursor_blink(&self) -> State {
97 self.state.get_cursor_blink()
98 }
99
100 pub fn set_cursor_blink(mut self, blink: State) -> Self {
101 self.state.set_cursor_blink(blink);
102 self
103 }
104
105 pub fn get_direction(&self) -> MoveDirection {
106 self.state.get_direction()
107 }
108
109 pub fn set_direction(mut self, dir: MoveDirection) -> Self {
110 self.state.set_direction(dir);
111 self
112 }
113
114 pub fn get_shift_type(&self) -> ShiftType {
115 self.state.get_shift_type()
116 }
117
118 pub fn set_shift_type(mut self, shift: ShiftType) -> Self {
119 self.state.set_shift_type(shift);
120 self
121 }
122
123 pub fn get_cursor_pos(&self) -> (u8, u8) {
124 self.state.get_cursor_pos()
125 }
126
127 pub fn set_cursor_pos(mut self, pos: (u8, u8)) -> Self {
128 self.state.set_cursor_pos(pos);
129 self
130 }
131
132 pub fn get_display_offset(&self) -> u8 {
133 self.state.get_display_offset()
134 }
135
136 pub fn set_display_offset(mut self, offset: u8) -> Self {
137 self.state.set_display_offset(offset);
138 self
139 }
140
141 pub fn get_ram_type(&self) -> RAMType {
142 self.state.get_ram_type()
143 }
144
145 pub fn set_ram_type(mut self, ram_type: RAMType) -> Self {
146 self.state.set_ram_type(ram_type);
147 self
148 }
149}
150
151impl<'a, 'b, Sender, Delayer, const READABLE: bool> Lcd<'a, 'b, Sender, Delayer, READABLE>
152where
153 Sender: SendCommand<Delayer, READABLE>,
154 Delayer: DelayNs,
155{
156 pub fn new(
161 sender: &'a mut Sender,
162 delayer: &'b mut Delayer,
163 config: Config,
164 poll_interval_us: Option<u32>,
165 ) -> Self {
166 let poll_interval_us = if !READABLE {
167 poll_interval_us.unwrap_or_default().max(40)
168 } else {
169 poll_interval_us.unwrap_or_default().max(10)
170 };
171
172 let state = config.state;
173
174 match state.get_data_width() {
178 DataWidth::Bit4 => {
179 sender.delay_and_send(
180 CommandSet::HalfFunctionSet,
181 delayer,
182 poll_interval_us.max(40_000),
183 );
184
185 sender.delay_and_send(
186 CommandSet::FunctionSet(
187 DataWidth::Bit4,
188 state.get_line_mode(),
189 state.get_font(),
190 ),
191 delayer,
192 poll_interval_us,
193 );
194
195 sender.delay_and_send(
196 CommandSet::FunctionSet(
197 DataWidth::Bit4,
198 state.get_line_mode(),
199 state.get_font(),
200 ),
201 delayer,
202 poll_interval_us,
203 );
204 }
205
206 DataWidth::Bit8 => {
207 sender.delay_and_send(
208 CommandSet::FunctionSet(
209 DataWidth::Bit8,
210 state.get_line_mode(),
211 state.get_font(),
212 ),
213 delayer,
214 poll_interval_us.max(40_000),
215 );
216
217 sender.delay_and_send(
218 CommandSet::FunctionSet(
219 DataWidth::Bit8,
220 state.get_line_mode(),
221 state.get_font(),
222 ),
223 delayer,
224 poll_interval_us,
225 );
226 }
227 }
228
229 sender.wait_and_send(
230 CommandSet::DisplayOnOff {
231 display: state.get_display_state(),
232 cursor: state.get_cursor_state(),
233 cursor_blink: state.get_cursor_blink(),
234 },
235 delayer,
236 poll_interval_us,
237 );
238
239 sender.wait_and_send(CommandSet::ClearDisplay, delayer, poll_interval_us);
240
241 sender.wait_and_send(
242 CommandSet::EntryModeSet(state.get_direction(), state.get_shift_type()),
243 delayer,
244 poll_interval_us,
245 );
246
247 sender.set_actual_backlight(state.get_backlight());
249
250 Lcd {
251 sender,
252 delayer,
253 state,
254 poll_interval_us,
255 }
256 }
257}