arduino-audio-tools
All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Modules Pages
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
30public:
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
54 virtual int id() {
55 return pin;
56 }
57
58 virtual bool readValue() {
59#if defined(USE_TOUCH_READ)
60 bool result;
61 if (this->activeLogic == ActiveTouch) {
62 int value = touchRead(this->pin);
63 result = value <= touchLimit;
64 if (result) {
65 // retry to confirm reading
66 value = touchRead(this->pin);
67 result = value <= touchLimit;
68 LOGI("touch pin: %d value %d (limit: %d) -> %s", this->pin, value,
69 touchLimit, result ? "true" : "false");
70 }
71 } else {
72 result = digitalRead(this->pin);
73 }
74 return result;
75#else
76 return digitalRead(this->pin);
77#endif
78 }
79
80 virtual void process() {
81 if (this->enabled) {
82 bool value = readValue();
83 if (this->actionOn != nullptr && this->actionOff != nullptr) {
84 // we have on and off action defined
85 if (value != this->lastState) {
86 //LOGI("processActions: case with on and off");
87 // execute action -> reports active instead of pin state
88 if ((value && this->activeLogic == ActiveHigh) ||
89 (!value && this->activeLogic == ActiveLow)) {
90 this->actionOn(true, this->pin, this->ref);
91 } else {
92 this->actionOff(false, this->pin, this->ref);
93 }
94 this->lastState = value;
95 }
96 } else if (this->activeLogic == ActiveChange) {
97 bool active = value;
98 // reports pin state
99 if (value != this->lastState && millis() > this->debounceTimeout) {
100 //LOGI("processActions: ActiveChange");
101 // execute action
102 this->actionOn(active, this->pin, this->ref);
103 this->lastState = value;
104 this->debounceTimeout = millis() + debounceDelayValue;
105 }
106 } else {
107 bool active = (this->activeLogic == ActiveLow) ? !value : value;
108 if (active &&
109 (active != this->lastState || millis() > this->debounceTimeout)) {
110 // LOGI("processActions: %d Active %d - %d", this->pin, value,
111 // execute action
112 this->actionOn(active, this->pin, this->ref);
113 this->lastState = active;
114 this->debounceTimeout = millis() + debounceDelayValue;
115 }
116 }
117 }
118 }
119 };
120
122 AudioActions(bool useInterrupt = false) {
123 selfAudioActions = this;
124 setUsePinInterrupt(useInterrupt);
125 }
126
128 virtual ~AudioActions() {
129 clear();
130 }
131
133 void add(Action &action){
134 insertAction(action);
135 }
136
138 void add(int pin, void (*actionOn)(bool pinStatus, int pin, void *ref),
139 ActiveLogic activeLogic = ActiveLow, void *ref = nullptr) {
140 add(pin, actionOn, nullptr, activeLogic, ref);
141 }
142
144 void add(int pin, void (*actionOn)(bool pinStatus, int pin, void *ref),
145 void (*actionOff)(bool pinStatus, int pin, void *ref),
146 ActiveLogic activeLogicPar = ActiveLow, void *ref = nullptr) {
147 LOGI("ActionLogic::add pin: %d / logic: %d", pin, activeLogicPar);
148 if (pin >= 0) {
149 // setup pin mode
150 setupPin(pin, activeLogicPar);
151
152 // add value
153 Action& action = *new Action();
154 action.pin = pin;
155 action.actionOn = actionOn;
156 action.actionOff = actionOff;
157 action.activeLogic = activeLogicPar;
158 action.ref = ref;
159 action.debounceDelayValue = debounceDelayValue;
160 action.touchLimit = touchLimit;
161
162 insertAction(action);
163 } else {
164 LOGW("pin %d -> Ignored", pin);
165 }
166 }
167
169 void setEnabled(int pin, bool enabled) {
170 Action *p_action = findAction(pin);
171 if (p_action) {
172 p_action->enabled = enabled;
173 }
174 }
175
181 static int pos = 0;
182 if (actions.empty())
183 return;
184 // execute action
185 actions[pos]->process();
186 pos++;
187 if (pos >= actions.size()) {
188 pos = 0;
189 }
190 }
191
194 for (Action *action : actions) {
195 action->process();
196 }
197 }
198
201 for (Action *action : actions) {
202 if (action->id() == id) {
203 return action;
204 }
205 }
206 return nullptr;
207 }
208
210 int findActionIdx(int id) {
211 int pos = 0;
212 for (Action *action : actions) {
213 if (action->id() == id) {
214 return pos;
215 }
216 pos++;
217 }
218 return -1;
219 }
220
222 void setDebounceDelay(int value) { debounceDelayValue = value; }
224 void setTouchLimit(int value) { touchLimit = value; }
226 void setUsePinInterrupt(bool active) { use_pin_interrupt = active; }
228 void setPinMode(bool active) { use_pin_mode = active; }
229
230 void clear() {
231 for (Action *act : actions){
232 delete(act);
233 }
234 actions.reset();
235 }
236
237protected:
238 int debounceDelayValue = DEBOUNCE_DELAY;
239 int touchLimit = TOUCH_LIMIT;
240 bool use_pin_interrupt = false;
241 bool use_pin_mode = true;
242 Vector<Action*> actions{0};
243
244 void insertAction(Action& action){
245 int idx = findActionIdx(action.id());
246 if (idx >= 0) {
247 // replace old action
248 delete(actions[idx]);
249 actions[idx] = &action;
250 } else {
251 // add new action
252 actions.push_back(&action);
253 }
254 }
255
256 static void audioActionsISR() { selfAudioActions->processAllActions(); }
257
258 void setupPin(int pin, ActiveLogic logic) {
259 // in the audio-driver library the pins are already set up
260 if (use_pin_mode) {
261 if (logic == ActiveLow) {
262 pinMode(pin, INPUT_PULLUP);
263 LOGI("pin %d -> INPUT_PULLUP", pin);
264 } else {
265 pinMode(pin, INPUT);
266 LOGI("pin %d -> INPUT", pin);
267 }
268 }
269
270#if defined(ARDUINO) && !defined(IS_MIN_DESKTOP)
271 if (use_pin_interrupt) {
272 attachInterrupt(digitalPinToInterrupt(pin), audioActionsISR, CHANGE);
273 }
274#endif
275 }
276};
277
278} // namespace audio_tools
int digitalRead(int pin)
e.g. for AudioActions
Definition NoArduino.h:200
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:210
AudioActions(bool useInterrupt=false)
Default constructor.
Definition AudioActions.h:122
void add(int pin, void(*actionOn)(bool pinStatus, int pin, void *ref), ActiveLogic activeLogic=ActiveLow, void *ref=nullptr)
Adds an action.
Definition AudioActions.h:138
void setTouchLimit(int value)
Defines the touch limit (Default 20)
Definition AudioActions.h:224
virtual ~AudioActions()
deletes all actions
Definition AudioActions.h:128
Action * findAction(int id)
Determines the action for the pin/id.
Definition AudioActions.h:200
void setDebounceDelay(int value)
Defines the debounce delay.
Definition AudioActions.h:222
void processActions()
Execute all actions if the corresponding pin is low To minimize the runtime: With each call we proces...
Definition AudioActions.h:180
void add(Action &action)
Adds an Action.
Definition AudioActions.h:133
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:144
void processAllActions()
Execute all actions.
Definition AudioActions.h:193
void setUsePinInterrupt(bool active)
Use interrupts instead of processActions() call in loop.
Definition AudioActions.h:226
void setEnabled(int pin, bool enabled)
enable/disable pin actions
Definition AudioActions.h:169
void setPinMode(bool active)
setup pin mode when true
Definition AudioActions.h:228
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