1#![no_std]
2#![no_main]
3
4use hal::{
5 blocking::delay::DelayUs,
6 digital::v2::{InputPin, OutputPin},
7};
8
9use log::debug;
10
11pub const BRIGHTNESS_MAX: u8 = 0x7;
12
13const DISPLAY_MASK: u8 = 0x88;
14const DISPLAY_OFF: u8 = 0x80;
15const DISPLAY_ON: u8 = DISPLAY_MASK | BRIGHTNESS_MAX;
16const AUTO_INC: u8 = 0x40;
17const C0H: u8 = 0xC0;
18const ENCODINGS: &[u8] = &[
19 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111,
20 0b01111111, 0b01101111,
21];
22
23pub struct TM1637<DIO, CLK, DL, E>
24where
25 DIO: InputPin<Error = E> + OutputPin<Error = E>,
26 CLK: OutputPin<Error = E>,
27 DL: DelayUs<u32>,
28{
29 lock_time: u32,
31
32 dio_pin: DIO,
34
35 clk_pin: CLK,
37
38 delay: DL,
40}
41
42impl<DIO, CLK, DL, E> TM1637<DIO, CLK, DL, E>
43where
44 DIO: InputPin<Error = E> + OutputPin<Error = E>,
45 CLK: OutputPin<Error = E>,
46 DL: DelayUs<u32>,
47{
48 pub fn new(dio_pin: DIO, clk_pin: CLK, delay: DL) -> Result<TM1637<DIO, CLK, DL, E>, E> {
49 let mut ret = TM1637 {
50 lock_time: 3,
51 dio_pin,
52 clk_pin,
53 delay,
54 };
55 ret.init()?;
56 Ok(ret)
57 }
58
59 pub fn send_bytes(&mut self, data: &[u8], brightness: u8) -> Result<(), E> {
60 self.send_iter(data.iter().map(|x| *x), brightness)
61 }
62
63 pub fn send_digits(&mut self, data: &[u8], clock_mode: bool, brightness: u8) -> Result<(), E> {
64 self.send_iter(
65 data.iter()
66 .map(|x| ENCODINGS[*x as usize])
67 .map(|x| x | (clock_mode as u8) << 7),
68 brightness,
69 )
70 }
71
72 pub fn send_number(&mut self, mut data: u32, brightness: u8) -> Result<(), E> {
73 let mut base = 1;
74 while base <= data {
75 base *= 10;
76 }
77 base /= 10;
78 self.send_iter(
79 core::iter::from_fn(move || {
80 if base > 0 {
81 let res = data / base;
82 data = data % base;
83 base /= 10;
84 Some(ENCODINGS[res as usize])
85 } else {
86 None
87 }
88 }),
89 brightness,
90 )
91 }
92
93 fn send_iter<Iter: Iterator<Item = u8>>(
94 &mut self,
95 data: Iter,
96 brightness: u8,
97 ) -> Result<(), E> {
98 self.start_send()?;
99 self.send_byte(AUTO_INC)?;
100 self.stop_send()?;
101
102 self.start_send()?;
103 self.send_byte(C0H)?;
104 for b in data {
105 self.send_byte(b)?;
106 }
107 self.stop_send()?;
108
109 self.start_send()?;
110 assert!(brightness <= BRIGHTNESS_MAX);
111 let display_byte = DISPLAY_MASK | brightness;
112 self.send_byte(display_byte)?;
113 self.stop_send()
114 }
115
116 fn init(&mut self) -> Result<(), E> {
117 self.dio_pin.set_high()?;
118 self.clk_pin.set_high()?;
119
120 self.delay.delay_us(self.lock_time);
121 Ok(())
122 }
123
124 fn send_byte(&mut self, mut data: u8) -> Result<(), E> {
125 debug!("Send byte {:#x}", data);
126 for _ in 0..8 {
127 let data_bit = data & 1;
128 if data_bit == 1 {
129 self.dio_pin.set_high()?;
130 } else if data_bit == 0 {
131 self.dio_pin.set_low()?;
132 } else {
133 unreachable!()
134 }
135 self.delay.delay_us(self.lock_time / 2);
136 self.clk_pin.set_high()?;
137 self.delay.delay_us(self.lock_time);
138 self.clk_pin.set_low()?;
139 self.delay.delay_us(self.lock_time / 2);
140 data >>= 1;
141 }
142
143 self.dio_pin.set_high()?;
144 self.wait_for_ack()?;
145
146 self.delay.delay_us(self.lock_time / 2);
147
148 Ok(())
149 }
150
151 fn wait_for_ack(&mut self) -> Result<(), E> {
152 for i in 0..255 {
153 if self.dio_pin.is_high()? {
154 self.delay.delay_us(self.lock_time);
155 } else {
156 debug!("Found on {} tact", i);
157 self.delay.delay_us(self.lock_time);
158 self.clk_pin.set_high()?;
159 self.delay.delay_us(self.lock_time);
160 self.clk_pin.set_low()?;
161 return Ok(());
162 }
163 }
164 panic!("Timed out wait for ack!");
165 }
166
167 fn start_send(&mut self) -> Result<(), E> {
168 self.clk_pin.set_high()?;
169 self.dio_pin.set_high()?;
170 self.delay.delay_us(self.lock_time);
171
172 self.dio_pin.set_low()?;
173 self.delay.delay_us(self.lock_time);
174 self.clk_pin.set_low()?;
175 self.delay.delay_us(self.lock_time / 2);
176
177 Ok(())
178 }
179
180 fn stop_send(&mut self) -> Result<(), E> {
181 self.clk_pin.set_low()?;
182 self.delay.delay_us(self.lock_time);
183 self.dio_pin.set_low()?;
184 self.delay.delay_us(self.lock_time);
185
186 self.clk_pin.set_high()?;
187 self.delay.delay_us(self.lock_time);
188 self.dio_pin.set_high()?;
189 self.delay.delay_us(self.lock_time);
190
191 Ok(())
192 }
193
194 pub fn enable(&mut self) -> Result<(), E> {
195 self.start_send()?;
196 self.send_byte(DISPLAY_ON)?;
197 self.stop_send()
198 }
199
200 fn disable(&mut self) -> Result<(), E> {
201 self.start_send()?;
202 self.send_byte(DISPLAY_OFF)?;
203 self.stop_send()
204 }
205}
206
207impl<DIO, CLK, DL, E> Drop for TM1637<DIO, CLK, DL, E>
208where
209 DIO: InputPin<Error = E> + OutputPin<Error = E>,
210 CLK: OutputPin<Error = E>,
211 DL: DelayUs<u32>,
212{
213 fn drop(&mut self) {
214 let _ = self.disable();
215 }
216}