77) ]
88
99use desk_control_panel:: meeting_instruction:: {
10- self , MeetingSignInstruction , UART_COMMUNICATION_TIMEOUT ,
10+ self , MeetingSignInstruction , ProgressRatio , UART_COMMUNICATION_TIMEOUT ,
1111} ;
1212use embassy_executor:: Spawner ;
1313use embassy_futures:: select:: { select, Either } ;
@@ -23,7 +23,6 @@ use esp_hal::{
2323 Async ,
2424} ;
2525use log:: { debug, error, info, trace, warn, LevelFilter } ;
26- use micromath:: F32Ext ;
2726use static_cell:: StaticCell ;
2827
2928const NUM_LEDS : usize = 9 ;
@@ -42,15 +41,15 @@ static mut PANIC_PIN: Option<Output<'static>> = None;
4241#[ derive( Clone ) ]
4342enum MeetingSignState {
4443 NoUart ,
45- Uart ,
44+ Uart ( MeetingSignInstruction ) ,
4645}
4746
4847type LEDsMutex = Mutex < CriticalSectionRawMutex , LEDs < ' static > > ;
4948static LEDS : StaticCell < LEDsMutex > = StaticCell :: new ( ) ;
5049
5150const STATE_PUB_SUB_CAPACITY : usize = 1 ;
5251const STATE_NUM_PUBLISHERS : usize = 0 ;
53- const STATE_NUM_SUBSCRIBERS : usize = 3 ;
52+ const STATE_NUM_SUBSCRIBERS : usize = 2 ;
5453type MeetingSignStatePubSubChannel = PubSubChannel <
5554 CriticalSectionRawMutex ,
5655 MeetingSignState ,
@@ -122,12 +121,9 @@ async fn main(spawner: Spawner) {
122121 let state_subscriber_1 = meeting_sign_state
123122 . subscriber ( )
124123 . expect ( "Failed to create state subscriber 1" ) ;
125- let state_subscriber_2 = meeting_sign_state
124+ let mut state_subscriber_2 = meeting_sign_state
126125 . subscriber ( )
127126 . expect ( "Failed to create state subscriber 2" ) ;
128- let mut state_subscriber_3 = meeting_sign_state
129- . subscriber ( )
130- . expect ( "Failed to create state subscriber 3" ) ;
131127
132128 let rx_pin = peripherals. GPIO1 ;
133129 let uart_config = Config :: default ( ) . with_rx (
@@ -138,63 +134,46 @@ async fn main(spawner: Spawner) {
138134 . with_rx ( rx_pin)
139135 . into_async ( ) ;
140136
137+ spawner. spawn ( uart_reader ( uart, state_publisher_1) ) . ok ( ) ;
141138 spawner
142- . spawn ( uart_reader ( uart, state_publisher_1, state_subscriber_1) )
143- . ok ( ) ;
144- spawner
145- . spawn ( uart_timeout_monitor ( state_publisher_2, state_subscriber_2) )
139+ . spawn ( uart_timeout_monitor ( state_publisher_2, state_subscriber_1) )
146140 . ok ( ) ;
147141
148- // Initialize hardcoded timer if no UART within threshold
149- match select (
150- state_subscriber_3. next_message_pure ( ) ,
151- Timer :: after ( UART_COMMUNICATION_TIMEOUT ) ,
152- )
153- . await
154- {
155- Either :: First ( state) => {
156- match state {
157- MeetingSignState :: NoUart => {
158- info ! ( "State changed to NoUart." ) ;
159- // Turn off all LEDs
160- leds. lock ( ) . await . set_portion_high ( 1.0 , 2.0 ) ;
161- }
162- MeetingSignState :: Uart => {
163- info ! ( "State changed to Uart." ) ;
164- // Set LEDs to indicate UART communication
165- leds. lock ( ) . await . set_portion_high ( 1.0 , 1.0 ) ;
166- }
167- }
168- }
169- Either :: Second ( _) => {
170- info ! ( "No initial state change detected within {}s, initializing LEDs according to hardcoded timer..." ,
171- UART_COMMUNICATION_TIMEOUT . as_secs( ) ) ;
172- }
173- }
174-
142+ // Main loop
175143 loop {
176144 match select (
177- state_subscriber_3 . next_message_pure ( ) ,
178- Timer :: after_secs ( 60 ) ,
145+ state_subscriber_2 . next_message_pure ( ) ,
146+ Timer :: after ( UART_COMMUNICATION_TIMEOUT ) ,
179147 )
180148 . await
181149 {
182- Either :: First ( state) => {
183- match state {
184- MeetingSignState :: NoUart => {
185- info ! ( "State changed to NoUart." ) ;
186- // Turn off all LEDs
187- leds. lock ( ) . await . set_portion_high ( 1.0 , 2.0 ) ;
188- }
189- MeetingSignState :: Uart => {
190- info ! ( "State changed to Uart." ) ;
191- // Set LEDs to indicate UART communication
192- leds. lock ( ) . await . set_portion_high ( 1.0 , 1.0 ) ;
150+ Either :: First ( state) => match state {
151+ MeetingSignState :: NoUart => {
152+ info ! ( "Initial state changed to NoUart." ) ;
153+ leds. lock ( ) . await . set_ratio_low ( ProgressRatio ( u8:: MAX / 2 ) ) ;
154+ }
155+ MeetingSignState :: Uart ( instruction) => {
156+ info ! ( "Initial state changed to Uart." ) ;
157+ match instruction {
158+ MeetingSignInstruction :: On ( progress_ratio) => {
159+ leds. lock ( ) . await . set_ratio_low ( progress_ratio)
160+ }
161+ MeetingSignInstruction :: Off => {
162+ leds. lock ( ) . await . set_ratio_low ( ProgressRatio ( 0 ) )
163+ }
164+ MeetingSignInstruction :: Diagnostic => todo ! ( ) ,
193165 }
166+ leds. lock ( ) . await . set_ratio_low ( ProgressRatio ( u8:: MAX ) ) ;
194167 }
195- }
168+ } ,
196169 Either :: Second ( _) => {
197- info ! ( "No state change detected within 60 seconds, updating LEDs according to internal timer..." ) ;
170+ info ! ( "No initial state change detected within {}s, initializing LEDs according to builtin timer..." ,
171+ UART_COMMUNICATION_TIMEOUT . as_secs( ) ) ;
172+
173+ // leds.lock().await.display_builtin_timer();
174+ leds. lock ( ) . await . set_pattern_array ( & [
175+ false , true , true , false , false , false , true , true , false ,
176+ ] ) ;
198177 }
199178 }
200179 }
@@ -211,38 +190,30 @@ impl<'a> LEDs<'a> {
211190 Self { led_outs }
212191 }
213192
214- /// Set the portion of LEDs to high based on the given numerator and denominator.
215- pub fn set_portion_high ( & mut self , numerator : f32 , denominator : f32 ) {
216- let num_on_leds = if numerator <= 0.0 || denominator <= 0.0 {
217- warn ! (
218- "Invalid portion values: numerator {}, denominator {}" ,
219- numerator, denominator
220- ) ;
221- 0 // This will turn off all LEDs
222- } else {
223- ( NUM_LEDS as f32 * numerator / denominator) . round ( ) as usize
224- } ;
193+ /// Set the portion of LEDs to low based on the given numerator and denominator.
194+ pub fn set_ratio_low ( & mut self , ratio : ProgressRatio ) {
195+ let num_on_leds = ratio. apply_to ( NUM_LEDS ) ;
225196
226197 for ( led_idx, led) in self . led_outs . iter_mut ( ) . enumerate ( ) {
227198 if led_idx < num_on_leds {
228- led. set_high ( ) ;
229- } else {
230199 led. set_low ( ) ;
200+ } else {
201+ led. set_high ( ) ;
231202 }
232203 }
233204 }
234205
235- pub fn set_pattern ( & mut self , pattern : u16 ) {
236- for ( i , led ) in self . led_outs . iter_mut ( ) . enumerate ( ) {
237- if pattern & ( 1 << i ) != 0 {
206+ pub fn set_pattern_array ( & mut self , pattern : & [ bool ; NUM_LEDS ] ) {
207+ for ( led , & should_be_on ) in self . led_outs . iter_mut ( ) . zip ( pattern . iter ( ) ) {
208+ if should_be_on {
238209 led. set_high ( ) ;
239210 } else {
240211 led. set_low ( ) ;
241212 }
242213 }
243214 }
244215
245- pub fn display_current_timer ( & mut self ) {
216+ pub fn display_builtin_timer ( & mut self ) {
246217 let on_duration = Instant :: now ( ) . elapsed ( ) ;
247218 if on_duration >= DEFAULT_MAX_DURATION {
248219 // If the timer has expired, turn off all LEDs
@@ -251,50 +222,18 @@ impl<'a> LEDs<'a> {
251222 }
252223 } else {
253224 // Calculate the portion of time elapsed
254- let portion = on_duration. as_secs ( ) as f32 / DEFAULT_MAX_DURATION . as_secs ( ) as f32 ;
255- assert ! (
256- portion >= 0.0 ,
257- "Portion is zero or negative: {on_duration} / {DEFAULT_MAX_DURATION} = {}" ,
258- portion
259- ) ;
225+ let ratio = ProgressRatio :: from_durations ( & on_duration, & DEFAULT_MAX_DURATION )
226+ . expect ( "Failed to calculate ratio from durations" ) ;
260227 // Set LEDs based on the portion
261- self . set_portion_high (
262- on_duration. as_secs ( ) as f32 ,
263- DEFAULT_MAX_DURATION . as_secs ( ) as f32 ,
264- ) ;
265- }
266- }
267- }
268-
269- #[ derive( Clone , Copy ) ]
270- struct Progress {
271- elapsed : u32 ,
272- total : u32 ,
273- }
274-
275- impl Progress {
276- fn new ( current : u32 , total : u32 ) -> Self {
277- Self { current, total }
278- }
279-
280- fn as_ratio ( & self ) -> f32 {
281- if self . total == 0 {
282- 0.0
283- } else {
284- self . current as f32 / self . total as f32
228+ self . set_ratio_low ( ratio) ;
285229 }
286230 }
287231}
288232
289- fn set_progress ( & mut self , progress : Progress ) {
290- self . set_portion_high ( progress. as_ratio ( ) ) ;
291- }
292-
293233#[ embassy_executor:: task]
294234async fn uart_reader (
295235 mut uart : Uart < ' static , Async > ,
296236 state_publisher : MeetingSignStatePublisher < ' static > ,
297- mut state_subscriber : MeetingSignStateSubscriber < ' static > ,
298237) {
299238 debug ! ( "Starting UART reader task" ) ;
300239
@@ -322,18 +261,8 @@ async fn uart_reader(
322261 match postcard:: from_bytes :: < MeetingSignInstruction > ( decoded_data) {
323262 Ok ( instruction) => {
324263 debug ! ( "Received: {:?}" , instruction) ;
325- match state_subscriber. try_next_message_pure ( ) {
326- None | Some ( MeetingSignState :: NoUart ) => {
327- // If we were not in UART state, switch to UART
328- debug ! ( "Switching state to UART" ) ;
329- state_publisher
330- . publish_immediate ( MeetingSignState :: Uart ) ;
331- }
332- Some ( MeetingSignState :: Uart ) => {
333- // Already in UART state, just log
334- debug ! ( "Already in UART state, processing instruction" ) ;
335- }
336- }
264+ state_publisher
265+ . publish_immediate ( MeetingSignState :: Uart ( instruction) ) ;
337266 }
338267 Err ( e) => warn ! ( "Deserialization error: {:?}" , e) ,
339268 }
@@ -367,7 +296,7 @@ async fn uart_timeout_monitor(
367296 // Wait for UART state
368297 loop {
369298 match state_subscriber. next_message_pure ( ) . await {
370- MeetingSignState :: Uart => break , // Start monitoring
299+ MeetingSignState :: Uart ( _ ) => break , // Start monitoring
371300 MeetingSignState :: NoUart => continue , // Keep waiting
372301 }
373302 }
@@ -379,7 +308,7 @@ async fn uart_timeout_monitor(
379308 match select ( state_subscriber. next_message_pure ( ) , & mut timeout_timer) . await {
380309 Either :: First ( state) => {
381310 match state {
382- MeetingSignState :: Uart => {
311+ MeetingSignState :: Uart ( _ ) => {
383312 // New UART message received, reset the timer
384313 debug ! ( "UART activity detected, resetting timeout" ) ;
385314 timeout_timer = Timer :: after ( UART_COMMUNICATION_TIMEOUT ) ;
0 commit comments