1#![no_std]
39
40extern crate embedded_hal as hal;
41
42use core::fmt;
43use hal::blocking::delay::DelayMs;
44use hal::blocking::i2c::{Read, Write, WriteRead};
45
46pub const I2C_ADRESS: u8 = 0x3e;
47
48#[derive(Debug, PartialEq)]
50enum InstructionSet {
51 Normal,
52 Extented,
53}
54
55#[derive(Debug, PartialEq, Clone, Copy)]
57pub enum Direction {
58 LeftToRigh,
59 RightToLeft,
60}
61
62#[derive(Debug)]
64pub struct ST7032i<I2C, D> {
65 i2c: I2C,
66 delay: D,
67 entry: Direction,
68 lines: u8,
69 scroll: bool,
70 display: bool,
71 cursor: bool,
72 blink: bool,
73}
74
75impl<I2C, E, D> ST7032i<I2C, D>
76where
77 I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
78 D: DelayMs<u8>,
79{
80 pub fn new(i2c: I2C, delay: D, lines: u8) -> Self {
82 ST7032i {
83 i2c,
84 delay,
85 lines,
86 entry: Direction::RightToLeft,
87 scroll: false,
88 display: false,
89 cursor: false,
90 blink: false,
91 }
92 }
93
94 pub fn init(&mut self) -> Result<(), E> {
96 match self.send_function(InstructionSet::Normal, 1, false) {
97 Ok(_) => self.delay.delay_ms(1),
98 Err(_) => self.delay.delay_ms(20),
99 };
100
101 self.send_function(InstructionSet::Extented, 1, false)?;
102 self.delay.delay_ms(5);
103
104 self.send_function(InstructionSet::Extented, 1, false)?;
105 self.delay.delay_ms(5);
106
107 self.send_function(InstructionSet::Extented, self.lines, false)?;
108 self.delay.delay_ms(5);
109
110 self.off()?;
111
112 self.send_osc_config(true, 0)?;
113 self.send_contrast(0)?;
114 self.send_booster_config(true, false, 0)?;
115 self.send_follower_config(true, 0)?;
116
117 self.send_entry_mode()?;
118 self.delay.delay_ms(20);
119
120 self.on()?;
121
122 self.clear()
123 }
124
125 pub fn on(&mut self) -> Result<(), E> {
127 self.display = true;
128 self.send_display_mode()
129 }
130
131 pub fn off(&mut self) -> Result<(), E> {
133 self.display = false;
134 self.send_display_mode()
135 }
136
137 pub fn clear(&mut self) -> Result<(), E> {
140 const CLEAR_DISPLAY: u8 = 0b_00000001;
141 self.send_command(CLEAR_DISPLAY)?;
142 self.delay.delay_ms(2);
143 Ok(())
144 }
145
146 pub fn home(&mut self) -> Result<(), E> {
149 const RETURN_HOME: u8 = 0b_00000010;
150 self.send_command(RETURN_HOME)?;
151 self.delay.delay_ms(2);
152 Ok(())
153 }
154
155 pub fn move_cursor(&mut self, row: u8, col: u8) -> Result<(), E> {
157 let command = match row {
158 0 => col | 0b_10000000,
159 _ => col | 0b_11000000,
160 };
161 self.send_command(command)
162 }
163
164 pub fn show_cursor(&mut self, blink: bool) -> Result<(), E> {
166 self.cursor = true;
167 self.blink = blink;
168 self.send_display_mode()
169 }
170
171 pub fn hide_cursor(&mut self) -> Result<(), E> {
173 self.cursor = false;
174 self.blink = false;
175 self.send_display_mode()
176 }
177
178 pub fn enable_scroll(&mut self, entry: Direction) -> Result<(), E> {
180 self.scroll = true;
181 self.entry = entry;
182 self.send_entry_mode()
183 }
184
185 pub fn disable_scroll(&mut self) -> Result<(), E> {
187 self.scroll = false;
188 self.send_entry_mode()
189 }
190
191 pub fn shift_display(&mut self, dir: Direction) -> Result<(), E> {
193 let mut command = 0b_00011000;
194 if dir == Direction::LeftToRigh {
195 command |= 0b_00000100;
196 }
197 self.send_command(command)
198 }
199
200 pub fn shift_cursor(&mut self, dir: Direction) -> Result<(), E> {
202 let mut command = 0b_00010000;
203 if dir == Direction::LeftToRigh {
204 command |= 0b_00000100;
205 }
206 self.send_command(command)
207 }
208
209 pub fn create_char(&mut self, offset: u8, bitmap: [u8; 8]) -> Result<(), E> {
211 self.send_command(0x40 | ((offset & 0x7) << 3))?;
212
213 let mut command = [0x40, 0];
214 for byte in bitmap.iter() {
215 command[1] = *byte;
216 self.i2c.write(I2C_ADRESS, &command).ok();
217 }
218
219 self.delay.delay_ms(1);
220 Ok(())
221 }
222
223 fn send_entry_mode(&mut self) -> Result<(), E> {
224 let mut command = 0b_00000100;
225 if self.scroll {
226 command |= 0b_00000001;
227 }
228 if self.entry == Direction::LeftToRigh {
229 command |= 0b_00000010;
230 }
231 self.send_command(command)
232 }
233
234 fn send_display_mode(&mut self) -> Result<(), E> {
235 let mut command = 0b_00001000;
236 if self.blink {
237 command |= 0b_00000001;
238 }
239 if self.cursor {
240 command |= 0b_00000010;
241 }
242 if self.display {
243 command |= 0b_00000100;
244 }
245 self.send_command(command)
246 }
247
248 fn send_function(&mut self, is: InstructionSet, lines: u8, dbl: bool) -> Result<(), E> {
249 let mut command = 0b_00110000;
250 if lines > 1 {
251 command |= 0b_00001000;
252 } else if dbl {
253 command |= 0b_00000100;
254 }
255 if is == InstructionSet::Extented {
256 command |= 0b_00000001;
257 }
258 self.send_command(command)
259 }
260
261 fn send_osc_config(&mut self, bias: bool, freq: u8) -> Result<(), E> {
262 assert!(freq < 8);
263 let mut command = 0b_00010000 | freq;
264 if bias {
265 command |= 0b_00001000;
266 }
267 self.send_command(command)
268 }
269
270 fn send_contrast(&mut self, contrast: u8) -> Result<(), E> {
271 assert!(contrast < 16);
272 self.send_command(0b_01110000 | contrast)
273 }
274
275 fn send_booster_config(&mut self, on: bool, icon: bool, contrast_low: u8) -> Result<(), E> {
276 assert!(contrast_low < 4);
277 let mut command = 0b_01010000 | contrast_low;
278 if on {
279 command |= 0b_00000100;
280 }
281 if icon {
282 command |= 0b_00001000;
283 }
284 self.send_command(command)
285 }
286
287 fn send_follower_config(&mut self, on: bool, ratio: u8) -> Result<(), E> {
288 assert!(ratio < 8);
289 let mut command = 0b_01100000 | ratio;
290 if on {
291 command |= 0b_00001000;
292 }
293 self.send_command(command)
294 }
295
296 fn send_command(&mut self, command: u8) -> Result<(), E> {
297 self.i2c.write(I2C_ADRESS, &[0x80, command])?;
298 self.delay.delay_ms(1);
299 Ok(())
300 }
301}
302
303impl<I2C, E, D> fmt::Write for ST7032i<I2C, D>
304where
305 I2C: Read<Error = E> + Write<Error = E> + WriteRead<Error = E>,
306 D: DelayMs<u8>,
307{
308 fn write_str(&mut self, s: &str) -> fmt::Result {
309 for c in s.chars() {
310 self.write_char(c)?;
311 }
312 self.delay.delay_ms(1);
313 Ok(())
314 }
315
316 fn write_char(&mut self, c: char) -> fmt::Result {
317 let mut command = [0x40, 0, 0, 0];
318 c.encode_utf8(&mut command[1..]);
319 self.i2c.write(I2C_ADRESS, &command[..2]).ok();
320 Ok(())
321 }
322}