esp_tm1637/
lib.rs

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    // Time to wait before switching the lock in us.
30    lock_time: u32,
31
32    // Pin on which data input resides.
33    dio_pin: DIO,
34
35    // Pin on which clock input resides.
36    clk_pin: CLK,
37
38    // Delay timer
39    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}