AskSin++
Led.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __STATUSLED_H__
7 #define __STATUSLED_H__
8 
9 #include "Alarm.h"
10 #include "Debug.h"
11 
12 namespace as {
13 
14 class LedStates {
15 public:
16  enum Mode { nothing=0, pairing=1,send=2, ack=3,
17  nack=4, bat_low=5, welcome=6, key_long=7, failure=8 };
18 
19  struct BlinkPattern {
20  uint8_t length;
21  uint8_t duration;
22  uint8_t pattern[6];
23  };
24 
25  static const BlinkPattern single[9] PROGMEM;
26  static const BlinkPattern dual1[9] PROGMEM;
27  static const BlinkPattern dual2[9] PROGMEM;
28 };
29 
30 template <class PINTYPE=ArduinoPins>
31 class Led : public Alarm, public LedStates {
32 private:
33  BlinkPattern current;
34  uint8_t step; // current step in pattern
35  uint8_t repeat; // current repeat of the pattern
36  uint8_t pin;
37  uint8_t inv;
38 
39  void copyPattern (Mode stat,const BlinkPattern* patt) {
40  memcpy_P(&current,patt+stat,sizeof(BlinkPattern));
41  }
42 
43  void next (AlarmClock& clock) {
44  tick = decis2ticks(current.pattern[step++]);
45  ((step & 0x01) == 0x01) ? ledOn() : ledOff();
46  clock.add(*this);
47  }
48 
49 public:
50  Led () : Alarm(0), step(0), repeat(0), pin(0), inv(false) {
51  async(true);
52  }
53  virtual ~Led() {}
54 
55  void init (uint8_t p) {
56  pin = p;
57  PINTYPE::setOutput(pin);
58  ledOff();
59  }
60 
61  void invert (bool value) {
62  inv = value;
63  }
64 
65  bool invert () const {
66  return inv;
67  }
68 
69  void set(Mode stat,const BlinkPattern* patt) {
70  sysclock.cancel(*this);
71  ledOff();
72  copyPattern(stat,patt);
73  if( current.length > 0 ) {
74  step = 0;
75  repeat = 0;
76  next(sysclock);
77  }
78  }
79 
80  void ledOff () {
81  if( invert() == true ) {
82  PINTYPE::setHigh(pin);
83  }
84  else {
85  PINTYPE::setLow(pin);
86  }
87  }
88 
89  void ledOn () {
90  if( invert() == true ) {
91  PINTYPE::setLow(pin);
92  }
93  else {
94  PINTYPE::setHigh(pin);
95  }
96  }
97 
98  void ledOn (uint32_t ticks) {
99  if( active() == false && ticks > 0 ) {
100  current.length = 2;
101  current.duration = 1;
102  current.pattern[0] = ticks2decis(ticks);
103  current.pattern[1] = 0;
104  // start the pattern
105  step = repeat = 0;
106  next(sysclock);
107  }
108  }
109 
110  bool active () const { return current.length != 0; }
111 
112  virtual void trigger (AlarmClock& clock) {
113  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
114  if( step < current.length ) {
115  next(clock);
116  }
117  else {
118  step = 0;
119  if( current.duration == 0 || ++repeat < current.duration ) {
120  next(clock);
121  }
122  else {
123  ledOff();
124  copyPattern(nothing,single);
125  }
126  }
127  }
128  }
129 };
130 
131 template<uint8_t LEDPIN1, class PINTYPE=ArduinoPins>
132 class StatusLed : public LedStates {
133 
134  Led<PINTYPE> led1;
135 
136 public:
137  StatusLed () {}
138 
139  void init () { led1.init(LEDPIN1); }
140  bool active () const { return led1.active(); }
141  void ledOn (uint32_t ticks) { led1.ledOn(ticks); }
142  void ledOn (uint32_t ticks,__attribute__((unused)) uint32_t tacks) { led1.ledOn(ticks); }
143  void set(Mode stat) { led1.set(stat,single); }
144  void ledOn () { led1.ledOn(); }
145  void ledOff () { led1.ledOff(); }
146  void invert (bool value) { led1.invert(value); }
147 };
148 
149 template <uint8_t LEDPIN1,uint8_t LEDPIN2, class PINTYPE1=ArduinoPins, class PINTYPE2=ArduinoPins>
150 class DualStatusLed : public LedStates {
151 private:
152  Led<PINTYPE1> led1;
153  Led<PINTYPE1> led2;
154 public:
155  DualStatusLed () {}
156  void init () { led1.init(LEDPIN1); led2.init(LEDPIN2); }
157  bool active () const { return led1.active() || led2.active(); }
158  void ledOn (uint32_t ticks) { led1.ledOn(ticks); led2.ledOn(ticks); }
159  void ledOn (uint32_t ticks,uint32_t tacks) { led1.ledOn(ticks); led2.ledOn(tacks); }
160  void set(Mode stat) { led1.set(stat,dual1); led2.set(stat,dual2); }
161  void ledOn () { led1.ledOn(); led2.ledOn(); }
162  void ledOff () { led1.ledOff(); led2.ledOff(); }
163  void invert (bool value) { led1.invert(value); led2.invert(value); }
164 };
165 
166 class NoLed {
167 public:
168  NoLed () {}
169  void init () {}
170  bool active () const { return false; }
171  void ledOn (__attribute__((unused)) uint32_t ticks) {}
172  void ledOn (__attribute__((unused)) uint32_t ticks,__attribute__((unused)) uint32_t tacks) {}
173  void set(__attribute__((unused)) LedStates::Mode stat) {}
174  void ledOn () {}
175  void ledOff () {}
176  void invert (__attribute__((unused)) bool value) {}
177 };
178 
179 }
180 
181 #endif
as::LedStates
Definition: Led.h:14
as::Alarm
Definition: Alarm.h:15
as::NoLed
Definition: Led.h:166
as::AlarmClock
Definition: AlarmClock.h:32
as::StatusLed
Definition: Led.h:132
as::Led
Definition: Led.h:31
as::DualStatusLed
Definition: Led.h:150