-
Notifications
You must be signed in to change notification settings - Fork 30
/
Led.cpp
137 lines (104 loc) · 2.97 KB
/
Led.cpp
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#ifndef Led_h
#define Led_h
#include "Arduino.h"
class Led {
public:
/**
* Setup the LED, specifying and optional minimum "on" duration for user visibility
*/
void init(byte pin, unsigned int minDurationMs = 0) {
this->pin = pin;
this->minDurationMs = minDurationMs;
this->state = false;
this->stateHardware = false;
this->blinkMs = 0;
this->lastOnMs = 0;
pinMode(this->pin, OUTPUT);
digitalWrite(this->pin, LOW);
}
/**
* Turn the LED on or off.
* If a minimum duration was set, it could not turn off if it was
* on for too little, you need to call loop() to update the state.
*/
void set(bool state) {
this->blinkMs = 0; // Stop blinking
this->state = state;
if (state) {
// Remember last time it was requested to be on
this->lastOnMs = millis();
// Turn on the LED if necessary
if (!this->stateHardware) {
this->stateHardware = true;
digitalWrite(this->pin, HIGH);
}
} else {
// Turn the LED off if necessary
this->loop();
}
}
/**
* Starts blinking with given period, until any other method is called.
* Use duty to specify how long the LED will be on, and invert to flip the blinking phase.
* This method can also be used make it fade, using a short period and duty to adjust brightness.
* Make sure to call loop() to keep the LED blinking.
*/
void blink(unsigned int periodMs, float duty = 0.5, bool invert = false) {
this->blinkMs = periodMs;
this->blinkDuty = max(0, min(periodMs, duty * periodMs));
this->blinkStartedMs = millis() - (invert ? this->blinkDuty : 0);
}
/**
* Turn the LED off if necessary, or keep it blinking.
* Call this in the main loop.
*/
void loop() {
if (this->blinkMs > 0) {
unsigned long t = ((millis() - this->blinkStartedMs) % this->blinkMs);
this->stateHardware = t < this->blinkDuty;
digitalWrite(this->pin, this->stateHardware);
} else {
// Turn the LED off if necessary
if (!this->state && this->stateHardware) {
if (millis() - this->lastOnMs >= this->minDurationMs) {
this->stateHardware = false;
digitalWrite(this->pin, LOW);
}
}
}
}
void on() {
this->set(true);
}
void off() {
this->set(false);
}
void toggle() {
this->set(!state);
}
/**
* Turn on the LED, then turn it off immediately.
* A single impulse of light will be visible if LED's minDurationMs is long enough.
*/
void flash() {
this->set(true);
this->set(false);
}
/**
* Set the optional minimum "on" duration for user visibility
*/
void setMinDurationMs(unsigned int minDurationMs = 0) {
this->minDurationMs = minDurationMs;
this->loop();
}
private:
byte pin;
unsigned int minDurationMs;
bool state;
bool stateHardware;
unsigned int blinkMs;
unsigned long blinkStartedMs;
unsigned int blinkDuty;
unsigned long lastOnMs;
};
#endif