1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/* mod.rs
 *
 * Developed by Tim Walls <tim.walls@snowgoons.com>
 * Copyright (c) All Rights Reserved, Tim Walls
 */
//! Higher-level device abstractions for things like LEDs, system clocks,
//! buttons.
use avr_oxide::alloc::boxed::Box;
use avr_oxide::devices::button::Button;
use avr_oxide::devices::led::Led;
use avr_oxide::devices::masterclock::MasterClock;
use avr_oxide::devices::serialbus::SerialBus;
use avr_oxide::devices::serialport::SerialPort;
use avr_oxide::devices::wallclock::WallClock;
use avr_oxide::hal::generic::port::Pin;
use avr_oxide::oxide::OxideSupervisor;
use avr_oxide::util::OwnOrBorrow;

pub mod masterclock;
pub mod wallclock;
pub mod led;
pub mod button;
pub mod serialport;
pub mod debouncer;
pub mod inverter;
pub mod nc;
pub mod serialbus;

/// A simple button attached to a hardware pin that generates events with the
/// standard AVRoxide Supervisor implementation.
pub type OxideButton<'a,'b> = Button<'a,OxideSupervisor<'b>>;
/// A simple LED attached to a hardware pin.
pub type OxideLed = Led;
/// A high-frequency, low-accuracy clock event source that works with the
/// standard AVRoxide Supervisor implementation.
pub type OxideMasterClock<'a,'b,T> = MasterClock<'a,T,OxideSupervisor<'b>>;
/// A simple serial port device that works with the standard AVRoxide
/// Supervisor implementation.
pub type OxideSerialPort<'a,'s> = SerialPort<'a,OxideSupervisor<'s>>;
/// A low-frequency, high-accuracy clock event source that works with the
/// standard AVRoxide Supervisor implementation.
pub type OxideWallClock<'a,'b,T> = WallClock<'a,T,OxideSupervisor<'b>>;
/// A serial data bus device (i.e. I2C) that works with the standard
/// AVRoxide Supervisor implementation.
pub type OxideSerialBus<'s> = SerialBus<OxideSupervisor<'s>>;

/// Convenience trait implemented by any devices that use (and are constructed
/// with) an I/O pin.
pub trait UsesPin {
  /// Create an instance of this device that uses the given instance of
  /// a pin (by ownership or reference.)
  fn using<OP: Into<OwnOrBorrow<'static, dyn Pin>>>(pin: OP) -> Self;

  /// Convenience method to create an instance of this device with a
  /// given static reference to a pin (avoids a certain amount of type
  /// hinting boilerplate for the caller.)
  fn with_pin(pin: &'static dyn Pin) -> Self
  where
    Self: Sized
  {
    Self::using(pin)
  }

  /// Create an instance of this device that uses the given instance of a pin,
  /// and return a static reference good for the lifetime of the program.
  ///
  /// # Note
  /// This method leaks memory, deliberately - the create instance will never
  /// be freed.  In our intended embedded environment, this is entirely
  /// deliberate.
  fn static_using<OP: Into<OwnOrBorrow<'static, dyn Pin>>>(pin: OP) -> &'static mut Self where Self:Sized { 
    Box::leak(Box::new(Self::using(pin)))
  }

  /// Create an instance of this device that uses the given reference to a pin,
  /// and return a static reference good for the lifetime of the program.
  ///
  /// # Note
  /// This method leaks memory, deliberately - the create instance will never
  /// be freed.  In our intended embedded environment, this is entirely
  /// deliberate.
  fn static_with_pin(pin: &'static dyn Pin) -> &'static mut Self where Self:Sized {
    Box::leak(Box::new(Self::with_pin(pin)))
  }
}