1use crate::{
4 exact_size::ExactSizeChainExt, mappings::SegmentBits, maybe_flipped::MaybeFlipped, numbers,
5 str::StrParser, tokens::NotFlipped, TM1637,
6};
7
8pub mod circles;
9mod windows;
10
11mod clock;
12mod repeat;
13mod scroll;
14
15pub use clock::*;
16pub use repeat::*;
17pub use scroll::*;
18
19#[derive(Debug)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct DisplayOptions<'d, const N: usize, T, CLK, DIO, DELAY, I, M> {
23 device: &'d mut TM1637<N, T, CLK, DIO, DELAY>,
24 position: usize,
25 iter: I,
26 _flip: M,
27}
28
29impl<'d, const N: usize, T, CLK, DIO, DELAY>
30 DisplayOptions<'d, N, T, CLK, DIO, DELAY, ::core::iter::Empty<u8>, NotFlipped>
31{
32 pub const fn empty(device: &'d mut TM1637<N, T, CLK, DIO, DELAY>) -> Self {
34 DisplayOptions {
35 device,
36 position: 0,
37 iter: ::core::iter::empty(),
38 _flip: NotFlipped,
39 }
40 }
41}
42
43impl<'d, 'b, const N: usize, T, CLK, DIO, DELAY, I, M>
44 DisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M>
45{
46 pub fn map_iter<U, F: FnMut(I) -> U>(
48 self,
49 mut f: F,
50 ) -> DisplayOptions<'d, N, T, CLK, DIO, DELAY, U, M> {
51 DisplayOptions {
52 device: self.device,
53 position: self.position,
54 iter: f(self.iter),
55 _flip: self._flip,
56 }
57 }
58
59 pub const fn position(mut self, position: usize) -> Self {
61 self.position = position;
62 self
63 }
64
65 pub fn slice(
67 self,
68 bytes: &'b [u8],
69 ) -> DisplayOptions<
70 'd,
71 N,
72 T,
73 CLK,
74 DIO,
75 DELAY,
76 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator + 'b,
77 M,
78 >
79 where
80 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator + 'b,
81 {
82 DisplayOptions {
83 device: self.device,
84 position: self.position,
85 iter: self.iter.exact_size_chain(bytes.iter().copied()),
86 _flip: self._flip,
87 }
88 }
89
90 pub fn str(
92 self,
93 str: &'b str,
94 ) -> DisplayOptions<
95 'd,
96 N,
97 T,
98 CLK,
99 DIO,
100 DELAY,
101 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator + 'b,
102 M,
103 >
104 where
105 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator + 'b,
106 {
107 DisplayOptions {
108 device: self.device,
109 position: self.position,
110 iter: self.iter.exact_size_chain(StrParser::new(str)),
111 _flip: self._flip,
112 }
113 }
114
115 pub fn iter<It>(
146 self,
147 iter: It,
148 ) -> DisplayOptions<
149 'd,
150 N,
151 T,
152 CLK,
153 DIO,
154 DELAY,
155 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
156 M,
157 >
158 where
159 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
160 It: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
161 {
162 DisplayOptions {
163 device: self.device,
164 position: self.position,
165 iter: self.iter.exact_size_chain(iter),
166 _flip: self._flip,
167 }
168 }
169
170 pub const fn clock(self) -> ClockDisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M> {
174 ClockDisplayOptions::new(self)
175 }
176
177 pub const fn scroll(self) -> ScrollDisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M> {
179 ScrollDisplayOptions::new_with_defaults(self)
180 }
181
182 pub const fn repeat(self) -> RepeatDisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M> {
188 RepeatDisplayOptions::new_with_defaults(self)
189 }
190
191 pub fn dot(
197 self,
198 position: usize,
199 ) -> DisplayOptions<
200 'd,
201 N,
202 T,
203 CLK,
204 DIO,
205 DELAY,
206 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
207 M,
208 >
209 where
210 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
211 {
212 DisplayOptions {
213 device: self.device,
214 position: self.position,
215 iter: self.iter.enumerate().map(move |(i, b)| {
216 if i == position {
217 b | SegmentBits::Dot as u8
218 } else {
219 b
220 }
221 }),
222 _flip: self._flip,
223 }
224 }
225
226 pub fn remove_dot(
228 self,
229 position: usize,
230 ) -> DisplayOptions<
231 'd,
232 N,
233 T,
234 CLK,
235 DIO,
236 DELAY,
237 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
238 M,
239 >
240 where
241 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
242 {
243 DisplayOptions {
244 device: self.device,
245 position: self.position,
246 iter: self.iter.enumerate().map(move |(i, b)| {
247 if i == position {
248 b & !(SegmentBits::Dot as u8)
249 } else {
250 b
251 }
252 }),
253 _flip: self._flip,
254 }
255 }
256
257 pub fn set_dot(
259 self,
260 position: usize,
261 dot: bool,
262 ) -> DisplayOptions<
263 'd,
264 N,
265 T,
266 CLK,
267 DIO,
268 DELAY,
269 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
270 M,
271 >
272 where
273 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
274 {
275 DisplayOptions {
276 device: self.device,
277 position: self.position,
278 iter: self.iter.enumerate().map(move |(i, b)| {
279 if i == position {
280 if dot {
281 b | SegmentBits::Dot as u8
282 } else {
283 b & !(SegmentBits::Dot as u8)
284 }
285 } else {
286 b
287 }
288 }),
289 _flip: self._flip,
290 }
291 }
292
293 pub fn dots(
295 self,
296 ) -> DisplayOptions<
297 'd,
298 N,
299 T,
300 CLK,
301 DIO,
302 DELAY,
303 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
304 M,
305 >
306 where
307 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
308 {
309 DisplayOptions {
310 device: self.device,
311 position: self.position,
312 iter: self.iter.map(|b| b | SegmentBits::Dot as u8),
313 _flip: self._flip,
314 }
315 }
316
317 pub fn remove_dots(
319 self,
320 ) -> DisplayOptions<
321 'd,
322 N,
323 T,
324 CLK,
325 DIO,
326 DELAY,
327 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
328 M,
329 >
330 where
331 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
332 {
333 DisplayOptions {
334 device: self.device,
335 position: self.position,
336 iter: self.iter.map(|b| b & !(SegmentBits::Dot as u8)),
337 _flip: self._flip,
338 }
339 }
340
341 pub fn map<F: FnMut(u8) -> u8>(
367 self,
368 f: F,
369 ) -> DisplayOptions<
370 'd,
371 N,
372 T,
373 CLK,
374 DIO,
375 DELAY,
376 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
377 M,
378 >
379 where
380 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
381 {
382 DisplayOptions {
383 device: self.device,
384 position: self.position,
385 iter: self.iter.map(f),
386 _flip: self._flip,
387 }
388 }
389
390 pub fn flip(
392 self,
393 ) -> DisplayOptions<
394 'd,
395 N,
396 T,
397 CLK,
398 DIO,
399 DELAY,
400 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
401 impl MaybeFlipped<N>,
402 >
403 where
404 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
405 M: MaybeFlipped<N>,
406 {
407 DisplayOptions {
408 device: self.device,
409 position: self.position,
410 iter: self.iter,
411 _flip: M::flip(),
412 }
413 }
414}
415
416#[::duplicate::duplicate_item(
417 module async await Token DelayTrait ScrollIter;
418 [asynch] [async] [await.identity()] [crate::tokens::Async] [::embedded_hal_async::delay::DelayNs] [::futures::Stream];
419 [blocking] [] [identity()] [crate::tokens::Blocking] [::embedded_hal::delay::DelayNs] [Iterator];
420)]
421mod module {
422 use ::embedded_hal::digital::OutputPin;
423 #[allow(unused_imports)]
424 use ::futures::StreamExt as _;
425
426 use crate::{
427 align::{Align, Aligned},
428 maybe_flipped::MaybeFlipped,
429 options::DisplayOptions,
430 ConditionalInputPin, Error, Identity,
431 };
432
433 #[::duplicate::duplicate_item(
434 NUM_POS ;
435 [4] ;
436 [6] ;
437 )]
438 impl<CLK, DIO, DELAY, ERR, I, M> DisplayOptions<'_, NUM_POS, Token, CLK, DIO, DELAY, I, M>
439 where
440 CLK: OutputPin<Error = ERR>,
441 DIO: OutputPin<Error = ERR> + ConditionalInputPin<ERR>,
442 DELAY: DelayTrait,
443 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
444 M: MaybeFlipped<NUM_POS>,
445 {
446 pub fn calculate(self) -> (usize, impl Iterator<Item = u8>) {
448 let (position, bytes) = M::calculate(self.position, self.iter);
449
450 Align::<NUM_POS>::align(position, bytes)
451 }
452
453 pub async fn display(self) -> Result<(), Error<ERR>> {
455 let (position, bytes) = M::calculate(self.position, self.iter);
456
457 let (position, bytes) = Align::<NUM_POS>::align(position, bytes);
458
459 self.device.display(position, bytes).await
460 }
461 }
462}
463
464#[::duplicate::duplicate_item(
465 function type_ link;
466 [u8] [u8] ["[`u8`](crate::numbers::u8)"];
467 [u8_2] [u8] ["[`u8_2`](crate::numbers::u8_2)"];
468 [r_u8_2] [u8] ["[`r_u8_2`](crate::numbers::r_u8_2)"];
469 [u16_3] [u16] ["[`u16_3`](crate::numbers::u16_3)"];
470 [r_u16_3] [u16] ["[`r_u16_3`](crate::numbers::r_u16_3)"];
471 [u16_4] [u16] ["[`u16_4`](crate::numbers::u16_4)"];
472 [r_u16_4] [u16] ["[`r_u16_4`](crate::numbers::r_u16_4)"];
473 [u32_5] [u32] ["[`u32_5`](crate::numbers::u32_5)"];
474 [r_u32_5] [u32] ["[`r_u32_5`](crate::numbers::r_u32_5)"];
475 [u32_6] [u32] ["[`u32_6`](crate::numbers::u32_6)"];
476 [r_u32_6] [u32] ["[`r_u32_6`](crate::numbers::r_u32_6)"];
477 [i8_2] [i8] ["[`i8_2`](crate::numbers::i8_2)"];
478 [i16_3] [i16] ["[`i16_3`](crate::numbers::i16_3)"];
479 [r_i16_3] [i16] ["[`r_i16_3`](crate::numbers::r_i16_3)"];
480 [i16_4] [i16] ["[`i16_4`](crate::numbers::i16_4)"];
481 [r_i16_4] [i16] ["[`r_i16_4`](crate::numbers::r_i16_4)"];
482 [i32_5] [i32] ["[`i32_5`](crate::numbers::i32_5)"];
483 [r_i32_5] [i32] ["[`r_i32_5`](crate::numbers::r_i32_5)"];
484 [i32_6] [i32] ["[`i32_6`](crate::numbers::i32_6)"];
485 [r_i32_6] [i32] ["[`r_i32_6`](crate::numbers::r_i32_6)"];
486)]
487impl<'d, const N: usize, T, CLK, DIO, DELAY, I, M> DisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M>
488where
489 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
490{
491 #[doc = "See "]
492 #[doc = link]
493 pub fn function(
494 self,
495 n: type_,
496 ) -> DisplayOptions<
497 'd,
498 N,
499 T,
500 CLK,
501 DIO,
502 DELAY,
503 impl DoubleEndedIterator<Item = u8> + ExactSizeIterator,
504 M,
505 > {
506 DisplayOptions {
507 device: self.device,
508 position: self.position,
509 iter: self.iter.exact_size_chain(numbers::function(n).into_iter()),
510 _flip: self._flip,
511 }
512 }
513}
514
515#[cfg(test)]
516mod tests {
517 extern crate std;
518 use std::vec;
519 use std::vec::Vec;
520
521 use crate::{mappings::str_from_byte, mock::Noop, TM1637Builder};
522
523 #[test]
524 fn dot_is_dynamically_tied_to_byte() {
525 let mut tm = TM1637Builder::new(Noop, Noop, Noop).build_blocking::<4>();
526
527 let (_, iter) = tm.options().str("HELLO").dot(1).dot(3).calculate();
528 let collected = iter.map(str_from_byte).collect::<Vec<_>>();
529
530 assert_eq!(vec!["H", "E.", "L", "L."], collected);
531
532 let (_, iter) = tm.options().str("HELLO").dot(1).dot(3).flip().calculate();
533 let collected = iter.map(str_from_byte).collect::<Vec<_>>();
534
535 assert_eq!(vec!["7.", "7", "3.", "H"], collected);
536 }
537}