arduino-audio-tools
Loading...
Searching...
No Matches
AudioActions.h
1#pragma once
2#include "AudioTools/CoreAudio/AudioBasic/Collections/Vector.h"
3#include "AudioTools/CoreAudio/AudioLogger.h"
4
5#ifndef TOUCH_LIMIT
6#define TOUCH_LIMIT 20
7#endif
8
9#ifndef DEBOUNCE_DELAY
10#define DEBOUNCE_DELAY 500
11#endif
12
13#if defined(IS_MIN_DESKTOP)
14extern "C" void pinMode(int, int);
15extern "C" int digitalRead(int);
16#endif
17
18namespace audio_tools {
19
20// global reference to access from static callback methods
21class AudioActions;
22static AudioActions* selfAudioActions = nullptr;
23
30 public:
31 enum ActiveLogic : uint8_t {
32 ActiveLow,
33 ActiveHigh,
34 ActiveChange,
35 ActiveTouch
36 };
37
38 struct Action {
39 Action() = default;
40 virtual ~Action() {}
41 int16_t pin = -1;
42 void (*actionOn)(bool pinStatus, int pin, void* ref) = nullptr;
43 void (*actionOff)(bool pinStatus, int pin, void* ref) = nullptr;
44 void* ref = nullptr;
45 unsigned long debounceTimeout = 0;
46 ActiveLogic activeLogic = ActiveHigh;
47 bool lastState = true;
48 bool enabled = true;
49
51 int debounceDelayValue = DEBOUNCE_DELAY;
52 int touchLimit = TOUCH_LIMIT;
53 std::function<bool(int)> read_cb = nullptr;
54
55 virtual int id() { return pin; }
56
57 virtual bool readValue() {
58#if defined(USE_TOUCH_READ)
59 bool result;
60 if (this->activeLogic == ActiveTouch) {
61 int value = touchRead(this->pin);
62 result = value <= touchLimit;
63 if (result) {
64 // retry to confirm reading
65 value = touchRead(this->pin);
66 result = value <= touchLimit;
67 LOGI("touch pin: %d value %d (limit: %d) -> %s", this->pin, value,
68 touchLimit, result ? "true" : "false");
69 }
70 } else {
71 result = readPin(this->pin);
72 }
73 return result;
74#else
75 return this->readPin(this->pin);
76#endif
77 }
78
79 virtual void process() {
80 if (this->enabled) {
81 bool value = readValue();
82 if (this->actionOn != nullptr && this->actionOff != nullptr) {
83 // we have on and off action defined
84 if (value != this->lastState) {
85 // LOGI("processActions: case with on and off");
86 // execute action -> reports active instead of pin state
87 if ((value && this->activeLogic == ActiveHigh) ||
88 (!value && this->activeLogic == ActiveLow)) {
89 this->actionOn(true, this->pin, this->ref);
90 } else {
91 this->actionOff(false, this->pin, this->ref);
92 }
93 this->lastState = value;
94 }
95 } else if (this->activeLogic == ActiveChange) {
96 bool active = value;
97 // reports pin state
98 if (value != this->lastState && millis() > this->debounceTimeout) {
99 // LOGI("processActions: ActiveChange");
100 // execute action
101 this->actionOn(active, this->pin, this->ref);
102 this->lastState = value;
103 this->debounceTimeout = millis() + debounceDelayValue;
104 }
105 } else {
106 bool active = (this->activeLogic == ActiveLow) ? !value : value;
107 if (active &&
108 (active != this->lastState || millis() > this->debounceTimeout)) {
109 // LOGI("processActions: %d Active %d - %d", this->pin, value,
110 // execute action
111 this->actionOn(active, this->pin, this->ref);
112 this->lastState = active;
113 this->debounceTimeout = millis() + debounceDelayValue;
114 }
115 }
116 }
117 }
118
119 protected:
120 bool readPin(int pin) {
121 if (read_cb) {
122 return read_cb(pin);
123 } else {
124 return (bool)::digitalRead(pin);
125 }
126 }
127 };
128
130 AudioActions(bool useInterrupt = false) {
131 selfAudioActions = this;
132 setUsePinInterrupt(useInterrupt);
133 }
134
136 virtual ~AudioActions() { clear(); }
137
139 void add(Action& action) { insertAction(action); }
140
142 void add(int pin, void (*actionOn)(bool pinStatus, int pin, void* ref),
143 ActiveLogic activeLogic = ActiveLow, void* ref = nullptr) {
144 add(pin, actionOn, nullptr, activeLogic, ref);
145 }
146
148 void add(int pin, void (*actionOn)(bool pinStatus, int pin, void* ref),
149 void (*actionOff)(bool pinStatus, int pin, void* ref),
150 ActiveLogic activeLogicPar = ActiveLow, void* ref = nullptr) {
151 LOGI("ActionLogic::add pin: %d / logic: %d", pin, activeLogicPar);
152 if (pin >= 0) {
153 // setup pin mode
154 setupPin(pin, activeLogicPar);
155
156 // add value
157 Action& action = *new Action();
158 action.pin = pin;
159 action.actionOn = actionOn;
160 action.actionOff = actionOff;
161 action.activeLogic = activeLogicPar;
162 action.ref = ref;
163 action.debounceDelayValue = debounceDelayValue;
164 action.touchLimit = touchLimit;
165 action.read_cb = read_cb;
166
167 insertAction(action);
168 } else {
169 LOGW("pin %d -> Ignored", pin);
170 }
171 }
172
174 void setEnabled(int pin, bool enabled) {
175 Action* p_action = findAction(pin);
176 if (p_action) {
177 p_action->enabled = enabled;
178 }
179 }
180
186 static int pos = 0;
187 if (actions.empty()) return;
188 // execute action
189 actions[pos]->process();
190 pos++;
191 if (pos >= actions.size()) {
192 pos = 0;
193 }
194 }
195
198 for (Action* action : actions) {
199 action->process();
200 }
201 }
202
205 for (Action* action : actions) {
206 if (action->id() == id) {
207 return action;
208 }
209 }
210 return nullptr;
211 }
212
214 int findActionIdx(int id) {
215 int pos = 0;
216 for (Action* action : actions) {
217 if (action->id() == id) {
218 return pos;
219 }
220 pos++;
221 }
222 return -1;
223 }
224
226 void setDebounceDelay(int value) { debounceDelayValue = value; }
228 void setTouchLimit(int value) { touchLimit = value; }
230 void setUsePinInterrupt(bool active) { use_pin_interrupt = active; }
232 void setPinMode(bool active) { use_pin_mode = active; }
233
234 void clear() {
235 for (Action* act : actions) {
236 delete (act);
237 }
238 actions.reset();
239 }
240
242 void setReadCallback(std::function<bool(int)> read_cb_par) { read_cb = read_cb_par; }
243
244 protected:
245 int debounceDelayValue = DEBOUNCE_DELAY;
246 int touchLimit = TOUCH_LIMIT;
247 bool use_pin_interrupt = false;
248 bool use_pin_mode = true;
249 Vector<Action*> actions{0};
250 std::function<bool(int)> read_cb = nullptr;
251
252 void insertAction(Action& action) {
253 int idx = findActionIdx(action.id());
254 if (idx >= 0) {
255 // replace old action
256 delete (actions[idx]);
257 actions[idx] = &action;
258 } else {
259 // add new action
260 actions.push_back(&action);
261 }
262 }
263
264 static void audioActionsISR() { selfAudioActions->processAllActions(); }
265
266 void setupPin(int pin, ActiveLogic logic) {
267 // in the audio-driver library the pins are already set up
268 if (use_pin_mode) {
269 if (logic == ActiveLow) {
270 pinMode(pin, INPUT_PULLUP);
271 LOGI("pin %d -> INPUT_PULLUP", pin);
272 } else {
273 pinMode(pin, INPUT);
274 LOGI("pin %d -> INPUT", pin);
275 }
276 }
277
278#if defined(ARDUINO) && !defined(IS_MIN_DESKTOP)
279 if (use_pin_interrupt) {
280 attachInterrupt(digitalPinToInterrupt(pin), audioActionsISR, CHANGE);
281 }
282#endif
283 }
284};
285
286} // namespace audio_tools
int digitalRead(int pin)
e.g. for AudioActions
Definition NoArduino.h:201
A simple class to assign functions to gpio pins e.g. to implement a simple navigation control or volu...
Definition AudioActions.h:29
int findActionIdx(int id)
Determines the action for the pin/id.
Definition AudioActions.h:214
AudioActions(bool useInterrupt=false)
Default constructor.
Definition AudioActions.h:130
void add(int pin, void(*actionOn)(bool pinStatus, int pin, void *ref), ActiveLogic activeLogic=ActiveLow, void *ref=nullptr)
Adds an action.
Definition AudioActions.h:142
void setReadCallback(std::function< bool(int)> read_cb_par)
Sets a callback function to read the pin state.
Definition AudioActions.h:242
void setTouchLimit(int value)
Defines the touch limit (Default 20)
Definition AudioActions.h:228
virtual ~AudioActions()
deletes all actions
Definition AudioActions.h:136
Action * findAction(int id)
Determines the action for the pin/id.
Definition AudioActions.h:204
void setDebounceDelay(int value)
Defines the debounce delay.
Definition AudioActions.h:226
void processActions()
Execute all actions if the corresponding pin is low To minimize the runtime: With each call we proces...
Definition AudioActions.h:185
void add(Action &action)
Adds an Action.
Definition AudioActions.h:139
void add(int pin, void(*actionOn)(bool pinStatus, int pin, void *ref), void(*actionOff)(bool pinStatus, int pin, void *ref), ActiveLogic activeLogicPar=ActiveLow, void *ref=nullptr)
Adds an action.
Definition AudioActions.h:148
void processAllActions()
Execute all actions.
Definition AudioActions.h:197
void setUsePinInterrupt(bool active)
Use interrupts instead of processActions() call in loop.
Definition AudioActions.h:230
void setEnabled(int pin, bool enabled)
enable/disable pin actions
Definition AudioActions.h:174
void setPinMode(bool active)
setup pin mode when true
Definition AudioActions.h:232
Vector implementation which provides the most important methods as defined by std::vector....
Definition Vector.h:21
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
uint32_t millis()
Returns the milliseconds since the start.
Definition Time.h:12
Definition AudioActions.h:38
int debounceDelayValue
determines the value for the action
Definition AudioActions.h:51