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