1use crate::TM1637;
4
5mod direction;
6mod style;
7
8use super::{windows::windows, DisplayOptions};
9pub use direction::ScrollDirection;
10pub use style::ScrollStyle;
11
12#[derive(Debug)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub struct ScrollDisplayOptions<'d, const N: usize, T, CLK, DIO, DELAY, I, D> {
16 options: DisplayOptions<'d, N, T, CLK, DIO, DELAY, I, D>,
17 delay_ms: u32,
18 direction: ScrollDirection,
19 style: ScrollStyle,
20}
21
22impl<'d, const N: usize, T, CLK, DIO, DELAY, I, M>
23 ScrollDisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M>
24{
25 pub const fn new(
27 options: DisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M>,
28 delay_ms: u32,
29 direction: ScrollDirection,
30 style: ScrollStyle,
31 ) -> Self {
32 Self {
33 options,
34 delay_ms,
35 direction,
36 style,
37 }
38 }
39
40 pub const fn new_with_defaults(
42 options: DisplayOptions<'d, N, T, CLK, DIO, DELAY, I, M>,
43 ) -> Self {
44 Self::new(
45 options,
46 500,
47 ScrollDirection::RightToLeft,
48 ScrollStyle::Circular,
49 )
50 }
51
52 pub const fn delay_ms(mut self, delay_ms: u32) -> Self {
54 self.delay_ms = delay_ms;
55 self
56 }
57
58 pub const fn direction(mut self, direction: ScrollDirection) -> Self {
60 self.direction = direction;
61 self
62 }
63
64 pub const fn left_to_right(mut self) -> Self {
66 self.direction = ScrollDirection::LeftToRight;
67 self
68 }
69
70 pub const fn right_to_left(mut self) -> Self {
72 self.direction = ScrollDirection::RightToLeft;
73 self
74 }
75
76 pub const fn style(mut self, style: ScrollStyle) -> Self {
78 self.style = style;
79 self
80 }
81
82 pub const fn circular(mut self) -> Self {
84 self.style = ScrollStyle::Circular;
85 self
86 }
87
88 pub const fn linear(mut self) -> Self {
90 self.style = ScrollStyle::Linear;
91 self
92 }
93
94 pub fn finish(
96 self,
97 ) -> Scroller<
98 'd,
99 N,
100 T,
101 CLK,
102 DIO,
103 DELAY,
104 impl Iterator<Item = impl DoubleEndedIterator<Item = u8> + ExactSizeIterator>,
105 M,
106 >
107 where
108 I: DoubleEndedIterator<Item = u8> + ExactSizeIterator,
109 {
110 let iter =
111 windows::<N>(self.options.iter, self.direction, self.style).map(|i| i.into_iter());
112
113 Scroller {
114 device: self.options.device,
115 inner_iter_len: N,
116 position: self.options.position,
117 delay_ms: self.delay_ms,
118 iter,
119 _flip: self.options._flip,
120 }
121 }
122}
123
124#[derive(Debug)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub struct Scroller<'d, const N: usize, T, CLK, DIO, DELAY, I, M> {
130 device: &'d mut TM1637<N, T, CLK, DIO, DELAY>,
131 inner_iter_len: usize,
132 position: usize,
133 delay_ms: u32,
134 iter: I,
135 _flip: M,
136}
137
138impl<'d, const N: usize, T, CLK, DIO, DELAY, I, M> Scroller<'d, N, T, CLK, DIO, DELAY, I, M> {
139 pub const fn new(
141 device: &'d mut TM1637<N, T, CLK, DIO, DELAY>,
142 inner_iter_len: usize,
143 position: usize,
144 delay_ms: u32,
145 iter: I,
146 _flip: M,
147 ) -> Self {
148 Self {
149 device,
150 inner_iter_len,
151 position,
152 delay_ms,
153 iter,
154 _flip,
155 }
156 }
157}
158
159#[::duplicate::duplicate_item(
160 module async await Token DelayTrait ScrollIter;
161 [asynch] [async] [await.identity()] [crate::tokens::Async] [::embedded_hal_async::delay::DelayNs] [::futures::Stream];
162 [blocking] [] [identity()] [crate::tokens::Blocking] [::embedded_hal::delay::DelayNs] [Iterator];
163)]
164mod module {
165 use ::embedded_hal::digital::OutputPin;
166 #[allow(unused_imports)]
167 use ::futures::StreamExt as _;
168
169 use crate::{
170 align::{Align, Aligned},
171 maybe_flipped::MaybeFlipped,
172 ConditionalInputPin, Error, Identity,
173 };
174
175 use super::Scroller;
176
177 #[::duplicate::duplicate_item(
178 NUM_POS ;
179 [4] ;
180 [6] ;
181 )]
182 impl<'d, CLK, DIO, DELAY, ERR, I, M, InI> Scroller<'d, NUM_POS, Token, CLK, DIO, DELAY, I, M>
183 where
184 ERR: 'd,
185 CLK: OutputPin<Error = ERR>,
186 DIO: OutputPin<Error = ERR> + ConditionalInputPin<ERR>,
187 DELAY: DelayTrait,
188 I: Iterator<Item = InI> + 'd,
189 InI: DoubleEndedIterator<Item = u8> + ExactSizeIterator + 'd,
190 M: MaybeFlipped<NUM_POS> + 'd,
191 {
192 fn _calculate(
193 position: usize,
194 iter: I,
195 inner_iter_len: usize,
196 ) -> (usize, impl Iterator<Item = impl Iterator<Item = u8>>) {
197 let original_position = position;
198
199 let iter = iter.map(move |item| {
200 let (position, bytes) = M::calculate(original_position, item.into_iter());
201 let (_, bytes) = Align::<NUM_POS>::align(position, bytes);
202
203 bytes
204 });
205
206 let position = M::position(original_position, inner_iter_len);
207 let position = Align::<NUM_POS>::position(position);
208
209 (position, iter)
210 }
211
212 pub fn calculate(self) -> (usize, impl Iterator<Item = impl Iterator<Item = u8>>) {
214 Self::_calculate(self.position, self.iter, self.inner_iter_len)
215 }
216
217 pub fn steps(self) -> impl ScrollIter<Item = Result<(), Error<ERR>>> + 'd {
219 let (position, iter) = Self::_calculate(self.position, self.iter, self.inner_iter_len);
220
221 self.device.scroll(position, self.delay_ms, iter)
222 }
223
224 pub async fn run(self) -> usize {
226 self.steps().count().await
227 }
228 }
229}