@@ -6,6 +6,7 @@ use std::sync::Mutex;
6
6
use std:: thread;
7
7
use std:: thread:: JoinHandle ;
8
8
use std:: time:: Duration ;
9
+ use palette:: rgb:: Rgb ;
9
10
10
11
/// Represents a generic GPIO output device.
11
12
#[ derive( Debug ) ]
@@ -257,19 +258,223 @@ impl DigitalOutputDevice {
257
258
}
258
259
259
260
pub struct RGBLED {
260
- pub red : LED ,
261
- pub green : LED ,
262
- pub blue : LED ,
261
+ devices : [ Arc < Mutex < OutputDevice > > ; 3 ] ,
262
+ on_color : Rgb ,
263
+ off_color : Rgb ,
264
+ blinking : Arc < AtomicBool > ,
265
+ handle : Option < JoinHandle < ( ) > > ,
266
+ blink_count : Option < i32 > ,
263
267
}
264
268
265
269
impl RGBLED {
266
270
pub fn new ( pin_red : u8 , pin_green : u8 , pin_blue : u8 ) -> RGBLED {
267
271
RGBLED {
268
- red : LED :: new ( pin_red) ,
269
- green : LED :: new ( pin_green) ,
270
- blue : LED :: new ( pin_blue) ,
272
+ devices : [
273
+ Arc :: new ( Mutex :: new ( OutputDevice :: new ( pin_red) ) ) ,
274
+ Arc :: new ( Mutex :: new ( OutputDevice :: new ( pin_green) ) ) ,
275
+ Arc :: new ( Mutex :: new ( OutputDevice :: new ( pin_blue) ) ) ,
276
+ ] ,
277
+ on_color : Rgb :: new ( 1.0 , 1.0 , 1.0 ) ,
278
+ off_color : Rgb :: new ( 0.0 , 0.0 , 0.0 ) ,
279
+ blinking : Arc :: new ( AtomicBool :: new ( false ) ) ,
280
+ handle : None ,
281
+ blink_count : None ,
282
+ }
283
+ }
284
+
285
+ pub fn set_color ( & mut self , color : Rgb ) {
286
+ Self :: write_color ( & self . devices , color) ;
287
+ }
288
+
289
+ fn write_color ( devices : & [ Arc < Mutex < OutputDevice > > ; 3 ] , color : Rgb ) {
290
+ Self :: write_state ( & devices[ 0 ] , color. red > 0.5 ) ;
291
+ Self :: write_state ( & devices[ 1 ] , color. green > 0.5 ) ;
292
+ Self :: write_state ( & devices[ 2 ] , color. blue > 0.5 ) ;
293
+ }
294
+
295
+ fn write_state ( device : & Arc < Mutex < OutputDevice > > , value : bool ) {
296
+ if device. lock ( ) . unwrap ( ) . value_to_state ( value) {
297
+ device. lock ( ) . unwrap ( ) . pin . set_high ( )
298
+ } else {
299
+ device. lock ( ) . unwrap ( ) . pin . set_low ( )
271
300
}
272
301
}
302
+
303
+ fn blinker ( & mut self , on_time : f32 , off_time : f32 , on_color : Rgb , off_color : Rgb , n : Option < i32 > ) {
304
+ self . stop ( ) ;
305
+
306
+ let devices = [
307
+ Arc :: clone ( & self . devices [ 0 ] ) ,
308
+ Arc :: clone ( & self . devices [ 1 ] ) ,
309
+ Arc :: clone ( & self . devices [ 2 ] ) ,
310
+ ] ;
311
+ let blinking = Arc :: clone ( & self . blinking ) ;
312
+
313
+ self . handle = Some ( thread:: spawn ( move || {
314
+ blinking. store ( true , Ordering :: SeqCst ) ;
315
+ match n {
316
+ Some ( end) => {
317
+ for _ in 0 ..end {
318
+ if !blinking. load ( Ordering :: SeqCst ) {
319
+ devices[ 0 ] . lock ( ) . unwrap ( ) . off ( ) ;
320
+ devices[ 1 ] . lock ( ) . unwrap ( ) . off ( ) ;
321
+ devices[ 2 ] . lock ( ) . unwrap ( ) . off ( ) ;
322
+ break ;
323
+ }
324
+ Self :: write_color ( & devices, on_color) ;
325
+ thread:: sleep ( Duration :: from_millis ( ( on_time * 1000.0 ) as u64 ) ) ;
326
+ Self :: write_color ( & devices, off_color) ;
327
+ thread:: sleep ( Duration :: from_millis ( ( off_time * 1000.0 ) as u64 ) ) ;
328
+ }
329
+ }
330
+ None => loop {
331
+ if !blinking. load ( Ordering :: SeqCst ) {
332
+ devices[ 0 ] . lock ( ) . unwrap ( ) . off ( ) ;
333
+ devices[ 1 ] . lock ( ) . unwrap ( ) . off ( ) ;
334
+ devices[ 2 ] . lock ( ) . unwrap ( ) . off ( ) ;
335
+ break ;
336
+ }
337
+ Self :: write_color ( & devices, on_color) ;
338
+ thread:: sleep ( Duration :: from_millis ( ( on_time * 1000.0 ) as u64 ) ) ;
339
+ Self :: write_color ( & devices, off_color) ;
340
+ thread:: sleep ( Duration :: from_millis ( ( off_time * 1000.0 ) as u64 ) ) ;
341
+ } ,
342
+ }
343
+ } ) ) ;
344
+ }
345
+ /// Returns ``True`` if the device is currently active and ``False`` otherwise.
346
+ pub fn is_active ( & self ) -> bool {
347
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . is_active ( )
348
+ || self . devices [ 1 ] . lock ( ) . unwrap ( ) . is_active ( )
349
+ || self . devices [ 2 ] . lock ( ) . unwrap ( ) . is_active ( )
350
+ }
351
+ /// Turns the device on.
352
+ pub fn on ( & self ) {
353
+ self . stop ( ) ;
354
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . on ( ) ;
355
+ self . devices [ 1 ] . lock ( ) . unwrap ( ) . on ( ) ;
356
+ self . devices [ 2 ] . lock ( ) . unwrap ( ) . on ( ) ;
357
+ }
358
+ /// Turns the device off.
359
+ pub fn off ( & self ) {
360
+ self . stop ( ) ;
361
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . off ( ) ;
362
+ self . devices [ 1 ] . lock ( ) . unwrap ( ) . off ( ) ;
363
+ self . devices [ 2 ] . lock ( ) . unwrap ( ) . off ( ) ;
364
+ }
365
+ /// Reverse the state of the device. If it's on, turn it off; if it's off, turn it on.
366
+ pub fn toggle ( & mut self ) {
367
+ if self . is_active ( ) {
368
+ self . on ( )
369
+ } else {
370
+ self . off ( )
371
+ }
372
+ }
373
+
374
+ /// Returns ``True`` if the device is currently active and ``False`` otherwise.
375
+ pub fn value_red ( & self ) -> bool {
376
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . value ( )
377
+ }
378
+
379
+ /// Returns ``True`` if the device is currently active and ``False`` otherwise.
380
+ pub fn value_green ( & self ) -> bool {
381
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . value ( )
382
+ }
383
+
384
+ /// Returns ``True`` if the device is currently active and ``False`` otherwise.
385
+ pub fn value_blue ( & self ) -> bool {
386
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . value ( )
387
+ }
388
+
389
+ fn stop ( & self ) {
390
+ self . blinking . clone ( ) . store ( false , Ordering :: SeqCst ) ;
391
+ self . devices [ 0 ] . lock ( ) . unwrap ( ) . pin . set_low ( ) ;
392
+ self . devices [ 1 ] . lock ( ) . unwrap ( ) . pin . set_low ( ) ;
393
+ self . devices [ 2 ] . lock ( ) . unwrap ( ) . pin . set_low ( ) ;
394
+ }
395
+
396
+ // /// When ``True``, the `value` property is ``True`` when the device's
397
+ // /// `pin` is high. When ``False`` the `value` property is
398
+ // /// ``True`` when the device's pin is low (i.e. the value is inverted).
399
+ // /// Be warned that changing it will invert `value` (i.e. changing this property doesn't change
400
+ // /// the device's pin state - it just changes how that state is interpreted).
401
+ pub fn active_high ( & self ) -> bool {
402
+ self . device_red . lock ( ) . unwrap ( ) . active_high ( )
403
+ self . device_green . lock ( ) . unwrap ( ) . active_high ( )
404
+ self . device_blue . lock ( ) . unwrap ( ) . active_high ( )
405
+ }
406
+
407
+ // /// Set the state for active_high
408
+ // pub fn set_active_high(&mut self, value: bool) {
409
+ // self.device_red.lock().unwrap().set_active_high(value)
410
+ // self.device_green.lock().unwrap().set_active_high(value)
411
+ // self.device_blue.lock().unwrap().set_active_high(value)
412
+ // }
413
+
414
+ // /// The `Pin` that the device is connected to.
415
+ // pub fn pin_red(&self) -> u8 {
416
+ // self.device_red.lock().unwrap().pin.pin()
417
+ // }
418
+
419
+ // /// The `Pin` that the device is connected to.
420
+ // pub fn pin_green(&self) -> u8 {
421
+ // self.device_green.lock().unwrap().pin.pin()
422
+ // }
423
+
424
+ // /// The `Pin` that the device is connected to.
425
+ // pub fn pin_blue(&self) -> u8 {
426
+ // self.device_blue.lock().unwrap().pin.pin()
427
+ // }
428
+
429
+ // /// Shut down the device and release all associated resources.
430
+ // pub fn close(self) {
431
+ // drop(self)
432
+ // }
433
+
434
+ /// Block until background process is done
435
+ pub fn wait ( & mut self ) {
436
+ self . handle
437
+ . take ( )
438
+ . expect ( "Called stop on non-running thread" )
439
+ . join ( )
440
+ . expect ( "Could not join spawned thread" ) ;
441
+ }
442
+
443
+ /// Make the device turn on and off repeatedly in the background.
444
+ /// Use `set_blink_count` to set the number of times to blink the device
445
+ /// * `on_time` - Number of seconds on
446
+ /// * `off_time` - Number of seconds off
447
+ ///
448
+ pub fn blink ( & mut self , on_time : f32 , off_time : f32 , on_color : Rgb , off_color : Rgb ) {
449
+ match self . blink_count {
450
+ None => self . blinker ( on_time, off_time, on_color, off_color, None ) ,
451
+ Some ( n) => self . blinker ( on_time, off_time, on_color, off_color, Some ( n) ) ,
452
+ }
453
+ }
454
+ /// Set the number of times to blink the device
455
+ /// * `n` - Number of times to blink
456
+ pub fn set_blink_count ( & mut self , n : i32 ) {
457
+ self . blink_count = Some ( n)
458
+ }
459
+
460
+ //
461
+ // pub fn is_active(&self) -> bool {
462
+ // self.red.is_active() || self.blue.is_active() || self.green.is_active()
463
+ // }
464
+ //
465
+ // pub fn is_lit(&self) -> bool {
466
+ // self.is_active()
467
+ // }
468
+ //
469
+ // fn set_blink_count(&mut self, n: i32) {
470
+ // self.red.set_blink_count(n);
471
+ // self.green.set_blink_count(n);
472
+ // self.blue.set_blink_count(n);
473
+ // }
474
+ //
475
+ // fn set_blink_colors(&mut self, on_color: Rgb, off_color: Rgb) {
476
+ // }
477
+ //
273
478
}
274
479
275
480
/// Represents a light emitting diode (LED)
0 commit comments