1use ::core::marker::PhantomData;
2
3use ::embedded_hal::digital::OutputPin;
4use ::futures::Stream;
5
6use crate::{
7 tokens::{Async, Blocking},
8 Brightness, ConditionalInputPin, Error, TM1637Builder,
9};
10
11#[derive(Debug, Clone)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct TM1637<const N: usize, T, CLK, DIO, DELAY> {
23 clk: CLK,
25 dio: DIO,
27 delay: DELAY,
29 brightness: Brightness,
31 delay_us: u32,
35 _token: PhantomData<T>,
36}
37
38impl<const N: usize, T, CLK, DIO, DELAY> TM1637<N, T, CLK, DIO, DELAY> {
39 pub const fn new(
41 clk: CLK,
42 dio: DIO,
43 delay: DELAY,
44 brightness: Brightness,
45 delay_us: u32,
46 ) -> Self {
47 Self {
48 clk,
49 dio,
50 delay,
51 brightness,
52 delay_us,
53 _token: PhantomData,
54 }
55 }
56
57 pub const fn builder(clk: CLK, dio: DIO, delay: DELAY) -> TM1637Builder<CLK, DIO, DELAY> {
61 TM1637Builder::new(clk, dio, delay)
62 }
63
64 pub const fn num_positions(&self) -> usize {
66 N
67 }
68
69 pub const fn brightness(&self) -> Brightness {
71 self.brightness
72 }
73
74 pub const fn delay_us(&self) -> u32 {
76 self.delay_us
77 }
78
79 pub const fn clk(&self) -> &CLK {
81 &self.clk
82 }
83
84 pub const fn clk_mut(&mut self) -> &mut CLK {
86 &mut self.clk
87 }
88
89 pub const fn dio(&self) -> &DIO {
91 &self.dio
92 }
93
94 pub const fn dio_mut(&mut self) -> &mut DIO {
96 &mut self.dio
97 }
98
99 pub const fn delay(&self) -> &DELAY {
101 &self.delay
102 }
103
104 pub const fn delay_mut(&mut self) -> &mut DELAY {
106 &mut self.delay
107 }
108
109 pub fn into_parts(self) -> (CLK, DIO, DELAY) {
111 (self.clk, self.dio, self.delay)
112 }
113}
114
115impl<const N: usize, CLK, DIO, DELAY, ERR> TM1637<N, Async, CLK, DIO, DELAY>
116where
117 CLK: OutputPin<Error = ERR>,
118 DIO: OutputPin<Error = ERR> + ConditionalInputPin<ERR>,
119 DELAY: ::embedded_hal_async::delay::DelayNs,
120{
121 pub(crate) fn scroll<'a>(
127 &'a mut self,
128 position: usize,
129 delay_ms: u32,
130 iter: impl Iterator<Item = impl Iterator<Item = u8>> + 'a,
131 ) -> impl Stream<Item = Result<(), Error<ERR>>> + 'a {
132 futures::stream::unfold((self, iter), move |(this, mut bytes)| async move {
133 match bytes.next() {
134 Some(window) => match this.display(position, window).await {
135 Ok(_) => {
136 this.delay.delay_ms(delay_ms).await;
137
138 Some((Ok(()), (this, bytes)))
139 }
140 Err(e) => Some((Err(e), (this, bytes))),
141 },
142 None => None,
143 }
144 })
145 }
146}
147
148impl<const N: usize, CLK, DIO, DELAY, ERR> TM1637<N, Blocking, CLK, DIO, DELAY>
149where
150 CLK: OutputPin<Error = ERR>,
151 DIO: OutputPin<Error = ERR> + ConditionalInputPin<ERR>,
152 DELAY: ::embedded_hal::delay::DelayNs,
153{
154 pub(crate) fn scroll<'a>(
160 &'a mut self,
161 position: usize,
162 delay_ms: u32,
163 iter: impl Iterator<Item = impl Iterator<Item = u8>> + 'a,
164 ) -> impl Iterator<Item = Result<(), Error<ERR>>> + 'a {
165 iter.map(move |bytes| match self.display(position, bytes) {
166 Ok(_) => {
167 self.delay.delay_ms(delay_ms);
168
169 Ok(())
170 }
171 Err(e) => Err(e),
172 })
173 }
174}
175
176#[::duplicate::duplicate_item(
177 module async await Token DelayTrait;
178 [asynch] [async] [await.identity()] [crate::tokens::Async] [::embedded_hal_async::delay::DelayNs];
179 [blocking] [] [identity()] [crate::tokens::Blocking] [::embedded_hal::delay::DelayNs];
180)]
181pub mod module {
182 use crate::{
183 options::{circles::CirclesDisplayOptions, DisplayOptions},
184 tokens::NotFlipped,
185 Brightness, ConditionalInputPin, Error, Identity, TM1637,
186 };
187 use ::embedded_hal::digital::OutputPin;
188
189 impl<const N: usize, CLK, DIO, DELAY, ERR> TM1637<N, Token, CLK, DIO, DELAY>
190 where
191 CLK: OutputPin<Error = ERR>,
192 DIO: OutputPin<Error = ERR> + ConditionalInputPin<ERR>,
193 DELAY: DelayTrait,
194 {
195 async fn write_byte(&mut self, byte: u8) -> Result<(), Error<ERR>> {
197 let mut rest = byte;
198
199 for _ in 0..8 {
200 self.clk.set_low()?;
201
202 match rest & 0x01 {
203 1 => self.dio.set_high()?,
204 _ => self.dio.set_low()?,
205 }
206
207 self.bit_delay().await;
208
209 self.clk.set_high()?;
210 self.bit_delay().await;
211
212 rest >>= 1;
213 }
214
215 self.clk.set_low()?;
216 self.dio.set_low()?;
217 self.bit_delay().await;
218
219 self.clk.set_high()?;
220 self.bit_delay().await;
221
222 #[cfg(feature = "ack")]
224 let ack = self.wait_for_ack().await?;
225
226 self.clk.set_low()?;
227 self.dio.set_low()?;
228 self.bit_delay().await;
229
230 #[cfg(feature = "ack")]
231 ack.then_some(()).ok_or(Error::Ack)?;
232
233 Ok(())
234 }
235
236 #[cfg(feature = "ack")]
238 async fn wait_for_ack(&mut self) -> Result<bool, Error<ERR>> {
239 for _ in 0..255 {
240 if self.dio.is_low()? {
241 return Ok(true);
242 }
243
244 self.bit_delay().await;
245 }
246
247 Ok(false)
248 }
249
250 async fn start(&mut self) -> Result<(), Error<ERR>> {
252 self.dio.set_high()?;
253 self.clk.set_high()?;
254 self.bit_delay().await;
255 self.dio.set_low()?;
256 self.bit_delay().await;
257
258 Ok(())
259 }
260
261 async fn stop(&mut self) -> Result<(), Error<ERR>> {
263 self.dio.set_low()?;
264 self.clk.set_high()?;
265 self.bit_delay().await;
266 self.dio.set_high()?;
267 self.bit_delay().await;
268
269 Ok(())
270 }
271
272 async fn write_cmd(&mut self, cmd: u8) -> Result<(), Error<ERR>> {
274 self.start().await?;
275 self.write_byte(cmd).await?;
276 self.stop().await?;
277
278 Ok(())
279 }
280
281 async fn write_start_display_cmd(&mut self) -> Result<(), Error<ERR>> {
283 self.write_cmd(0x40).await?;
284
285 Ok(())
286 }
287
288 async fn write_display_cmd(
290 &mut self,
291 position: usize,
292 bytes: impl Iterator<Item = u8>,
293 ) -> Result<(), Error<ERR>> {
294 self.start().await?;
295
296 self.write_byte(0xc0 | (position as u8 & 0x03)).await?;
297
298 for byte in bytes {
299 self.write_byte(byte).await?;
300 }
301
302 self.stop().await?;
303
304 Ok(())
305 }
306
307 async fn write_brightness_cmd(&mut self, brightness: Brightness) -> Result<(), Error<ERR>> {
309 self.write_cmd(brightness as u8).await
310 }
311
312 async fn bit_delay(&mut self) {
314 self.delay.delay_us(self.delay_us).await;
315 }
316
317 pub async fn init(&mut self) -> Result<(), Error<ERR>> {
321 self.clear().await?;
322 self.write_cmd(self.brightness as u8).await
323 }
324
325 pub async fn on(&mut self) -> Result<(), Error<ERR>> {
327 self.write_cmd(self.brightness as u8).await
328 }
329
330 pub async fn off(&mut self) -> Result<(), Error<ERR>> {
332 self.write_cmd(Brightness::Off as u8).await
333 }
334
335 pub async fn clear(&mut self) -> Result<(), Error<ERR>> {
337 self.display(0, ::core::iter::repeat_n(0, self.num_positions()))
338 .await
339 }
340
341 pub async fn set_brightness(&mut self, brightness: Brightness) -> Result<(), Error<ERR>> {
343 self.brightness = brightness;
344
345 self.write_brightness_cmd(brightness).await
346 }
347
348 pub async fn display(
352 &mut self,
353 position: usize,
354 bytes: impl Iterator<Item = u8>,
355 ) -> Result<(), Error<ERR>> {
356 self.write_start_display_cmd().await?;
358
359 self.write_display_cmd(position, bytes).await?;
361
362 Ok(())
363 }
364
365 pub async fn display_slice(
369 &mut self,
370 position: usize,
371 bytes: &[u8],
372 ) -> Result<(), Error<ERR>> {
373 self.display(position, bytes.iter().copied()).await
374 }
375
376 pub const fn options(
398 &mut self,
399 ) -> DisplayOptions<'_, N, Token, CLK, DIO, DELAY, ::core::iter::Empty<u8>, NotFlipped>
400 {
401 DisplayOptions::empty(self)
402 }
403
404 pub const fn circles(&mut self) -> CirclesDisplayOptions<'_, N, Token, CLK, DIO, DELAY> {
406 CirclesDisplayOptions::new(self)
407 }
408 }
409}