arduino-audio-tools
AudioBoardStream.h
1 #pragma once
2 
3 #include "AudioConfig.h"
4 #include "AudioTools/AudioLibs/I2SCodecStream.h"
5 #include "AudioTools/CoreAudio/AudioActions.h"
6 
7 namespace audio_tools {
8 
20  struct AudioBoardAction : public AudioActions::Action {
21  AudioBoardAction(AudioBoard &board, AudioDriverKey key) {
22  this->key = key;
23  this->p_board = &board;
24  }
25  AudioDriverKey key;
26  AudioBoard *p_board;
27  int id() override { return key | 0x400; }
28  bool readValue() override { return p_board->isKeyPressed(key); }
29  };
30 
31  public:
39  AudioBoardStream(audio_driver::AudioBoard &board) : I2SCodecStream(board) {
40  // pin mode already set up by driver library
41  actions.setPinMode(false);
42  }
43 
44  bool begin() override { return I2SCodecStream::begin(); }
45 
46  bool begin(I2SCodecConfig cfg) override { return I2SCodecStream::begin(cfg); }
47 
52  void processActions() {
53  // TRACED();
54  actions.processActions();
55  yield();
56  }
57 
58 
62  void addAction(AudioDriverKey key, void (*action)(bool, int, void *),
63  void *ref = nullptr) {
64  AudioBoardAction *abo = new AudioBoardAction(board(), key);
65  abo->actionOn = action;
66  abo->ref = (ref == nullptr) ? this : ref;
67  actions.add(*abo);
68  }
69 
73  void addAction(AudioDriverKey key, void (*actionOn)(bool, int, void *),
74  void (*actionOff)(bool, int, void *),
75  void *ref = nullptr) {
76 
77  AudioBoardAction *abo = new AudioBoardAction(board(), key);
78  abo->actionOn = actionOn;
79  abo->actionOn = actionOff;
80  abo->ref = (ref == nullptr) ? this : ref;
81  actions.add(*abo);
82  }
83 
92  void addAction(int pin, void (*action)(bool, int, void *),
93  void *ref = nullptr) {
94  TRACEI();
95  // determine logic from config
96  AudioActions::ActiveLogic activeLogic = getActionLogic(pin);
97  actions.add(pin, action, activeLogic, ref == nullptr ? this : ref);
98  }
99 
109  void addAction(int pin, void (*action)(bool, int, void *),
110  AudioActions::ActiveLogic activeLogic, void *ref = nullptr) {
111  TRACEI();
112  actions.add(pin, action, activeLogic, ref == nullptr ? this : ref);
113  }
114 
116  AudioActions &audioActions() { return actions; }
117 
118  AudioActions &getActions() { return actions; }
119 
125  void incrementVolume(float inc) {
126  float current_volume = getVolume();
127  float new_volume = current_volume + inc;
128  LOGI("incrementVolume: %f -> %f", current_volume, new_volume);
129  setVolume(new_volume);
130  }
131 
136  static void actionVolumeUp(bool, int, void *ref) {
137  TRACEI();
138  AudioBoardStream *self = (AudioBoardStream *)ref;
139  self->incrementVolume(+self->actionVolumeIncrementValue());
140  }
141 
146  static void actionVolumeDown(bool, int, void *ref) {
147  TRACEI();
148  AudioBoardStream *self = (AudioBoardStream *)ref;
149  self->incrementVolume(-self->actionVolumeIncrementValue());
150  }
151 
156  static void actionStartStop(bool, int, void *ref) {
157  TRACEI();
158  AudioBoardStream *self = (AudioBoardStream *)ref;
159  self->active = !self->active;
160  self->setActive(self->active);
161  }
162 
167  static void actionStart(bool, int, void *ref) {
168  TRACEI();
169  AudioBoardStream *self = (AudioBoardStream *)ref;
170  self->active = true;
171  self->setActive(self->active);
172  }
173 
177  static void actionStop(bool, int, void *ref) {
178  TRACEI();
179  AudioBoardStream *self = (AudioBoardStream *)ref;
180  self->active = false;
181  self->setActive(self->active);
182  }
183 
189  static void actionHeadphoneDetection(bool, int, void *ref) {
190  AudioBoardStream *self = (AudioBoardStream *)ref;
191  if (self->pinHeadphoneDetect() >= 0) {
192  // detect changes
193  bool isConnected = self->headphoneStatus();
194  if (self->headphoneIsConnected != isConnected) {
195  self->headphoneIsConnected = isConnected;
196 
197  // update if things have stabilized
198  bool powerActive = !isConnected;
199  LOGW("Headphone jack has been %s",
200  isConnected ? "inserted" : "removed");
201  self->setSpeakerActive(powerActive);
202  }
203  }
204  yield();
205  }
206 
213  GpioPin pinAuxin() { return getPinID(PinFunction::AUXIN_DETECT); }
214 
221  GpioPin pinHeadphoneDetect() {
222  return getPinID(PinFunction::HEADPHONE_DETECT);
223  }
224 
231  GpioPin pinPaEnable() { return getPinID(PinFunction::PA); }
232 
233  // /**
234  // * @brief Get the gpio number for adc detection
235  // *
236  // * @return -1 non-existent
237  // * Others gpio number
238  // */
239  // GpioPin pinAdcDetect() { return getPin(AUXIN_DETECT); }
240 
247  GpioPin pinInputRec() { return getPinID(PinFunction::KEY, 1); }
248 
255  GpioPin pinInputMode() { return getPinID(PinFunction::KEY, 2); }
256 
263  GpioPin pinInputSet() { return getPinID(PinFunction::KEY, 4); }
264 
271  GpioPin pinInputPlay() { return getPinID(PinFunction::KEY, 3); }
272 
279  GpioPin pinVolumeUp() { return getPinID(PinFunction::KEY, 6); }
280 
287  GpioPin pinVolumeDown() { return getPinID(PinFunction::KEY, 5); }
288 
295  GpioPin pinLed(int idx) { return getPinID(PinFunction::LED, idx); }
296 
298  void setSpeakerActive(bool active) { setPAPower(active); }
299 
307  int headphoneGpioPin = pinHeadphoneDetect();
308  return headphoneGpioPin > 0 ? !digitalRead(headphoneGpioPin) : false;
309  }
310 
314  void setActive(bool active) { setMute(!active); }
315 
318  // pin conflicts for pinInputMode() with the SD CS pin for AIThinker and
319  // buttons
320  int sd_cs = getSdCsPin();
321  int input_mode = pinInputMode();
322  if (input_mode != -1 && (input_mode != sd_cs || !cfg.sd_active)) {
323  LOGD("actionInputMode")
324  addAction(input_mode, actionStartStop);
325  }
326  }
327 
330  // pin conflicts with SD Lyrat SD CS GpioPin and buttons / Conflict on
331  // Audiokit V. 2957
332  int sd_cs = getSdCsPin();
333  int vol_up = pinVolumeUp();
334  int vol_down = pinVolumeDown();
335  if ((vol_up != -1 && vol_down != -1) &&
336  (!cfg.sd_active || (vol_down != sd_cs && vol_up != sd_cs))) {
337  LOGD("actionVolumeDown")
338  addAction(vol_down, actionVolumeDown);
339  LOGD("actionVolumeUp")
340  addAction(vol_up, actionVolumeUp);
341  } else {
342  LOGW("Volume Buttons ignored because of conflict: %d ", pinVolumeDown());
343  }
344  }
345 
348  // pin conflicts with AIThinker A101: key6 and headphone detection
349  int head_phone = pinHeadphoneDetect();
350  if (head_phone != -1 && (getPinID(PinFunction::KEY, 6) != head_phone)) {
351  actions.add(head_phone, actionHeadphoneDetection,
352  AudioActions::ActiveChange, this);
353  }
354  }
355 
361  TRACEI();
365  }
366 
368  void setActionVolumeIncrementValue(float value) {
369  action_increment_value = value;
370  }
371 
372  float actionVolumeIncrementValue() { return action_increment_value; }
373 
374  bool isKeyPressed(int key) {
375  if (!board()) return false;
376  return board().isKeyPressed(key);
377  }
378 
379  protected:
380  AudioActions actions;
381  bool headphoneIsConnected = false;
382  bool active = true;
383  float action_increment_value = 0.02;
384 
385  int getSdCsPin() {
386  static GpioPin sd_cs = -2;
387  // execute only once
388  if (sd_cs != -2) return sd_cs;
389 
390  auto sd_opt = getPins().getSPIPins(PinFunction::SD);
391  if (sd_opt) {
392  sd_cs = sd_opt.value().cs;
393  } else {
394  // no spi -> no sd
395  LOGI("No sd defined -> sd_active=false")
396  cfg.sd_active = false;
397  sd_cs = -1;
398  }
399  return sd_cs;
400  }
401 
403  AudioActions::ActiveLogic getActionLogic(int pin) {
404  auto opt = board().getPins().getPin(pin);
405  PinLogic logic = PinLogic::Input;
406  if (opt) logic = opt.value().pin_logic;
407  switch (logic) {
408  case PinLogic::Input:
409  case PinLogic::InputActiveLow:
410  return AudioActions::ActiveLow;
411  case PinLogic::InputActiveHigh:
412  return AudioActions::ActiveHigh;
413  case PinLogic::InputActiveTouch:
414  return AudioActions::ActiveTouch;
415  default:
416  return AudioActions::ActiveLow;
417  }
418  }
419 };
420 
421 } // namespace audio_tools
int digitalRead(int pin)
e.g. for AudioActions
Definition: NoArduino.h:206
A simple class to assign functions to gpio pins e.g. to implement a simple navigation control or volu...
Definition: AudioActions.h:29
void processActions()
Execute all actions if the corresponding pin is low To minimize the runtime: With each call we proces...
Definition: AudioActions.h:178
void add(Action &action)
Adds an Action.
Definition: AudioActions.h:131
void setPinMode(bool active)
setup pin mode when true
Definition: AudioActions.h:226
New functionality which replaces the AudioKitStream that is based on the legacy AudioKit library....
Definition: AudioBoardStream.h:19
void addAction(AudioDriverKey key, void(*actionOn)(bool, int, void *), void(*actionOff)(bool, int, void *), void *ref=nullptr)
Defines a new action that is executed when the Button is pressed and released.
Definition: AudioBoardStream.h:73
GpioPin pinInputRec()
Get the record-button id for adc-button.
Definition: AudioBoardStream.h:247
void addAction(int pin, void(*action)(bool, int, void *), void *ref=nullptr)
Defines a new action that is executed when the indicated pin is active.
Definition: AudioBoardStream.h:92
GpioPin pinVolumeDown()
Get number for volume down function.
Definition: AudioBoardStream.h:287
static void actionVolumeUp(bool, int, void *ref)
Increase the volume.
Definition: AudioBoardStream.h:136
void setSpeakerActive(bool active)
the same as setPAPower()
Definition: AudioBoardStream.h:298
static void actionHeadphoneDetection(bool, int, void *ref)
Switch off the PA if the headphone in plugged in and switch it on again if the headphone is unplugged...
Definition: AudioBoardStream.h:189
static void actionVolumeDown(bool, int, void *ref)
Decrease the volume.
Definition: AudioBoardStream.h:146
void addAction(int pin, void(*action)(bool, int, void *), AudioActions::ActiveLogic activeLogic, void *ref=nullptr)
Defines a new action that is executed when the indicated pin is active.
Definition: AudioBoardStream.h:109
void addAction(AudioDriverKey key, void(*action)(bool, int, void *), void *ref=nullptr)
Defines a new action that is executed when the Button is pressed.
Definition: AudioBoardStream.h:62
GpioPin pinLed(int idx)
Get LED pin.
Definition: AudioBoardStream.h:295
GpioPin pinAuxin()
Get the gpio number for auxin detection.
Definition: AudioBoardStream.h:213
AudioActions::ActiveLogic getActionLogic(int pin)
Determines the action logic (ActiveLow or ActiveTouch) for the pin.
Definition: AudioBoardStream.h:403
AudioActions & audioActions()
Provides access to the AudioActions.
Definition: AudioBoardStream.h:116
static void actionStartStop(bool, int, void *ref)
Toggle start stop.
Definition: AudioBoardStream.h:156
GpioPin pinPaEnable()
Get the gpio number for PA enable.
Definition: AudioBoardStream.h:231
GpioPin pinInputMode()
Get the number for mode-button.
Definition: AudioBoardStream.h:255
GpioPin pinInputPlay()
Get number for play function.
Definition: AudioBoardStream.h:271
GpioPin pinHeadphoneDetect()
Get the gpio number for headphone detection.
Definition: AudioBoardStream.h:221
GpioPin pinInputSet()
Get number for set function.
Definition: AudioBoardStream.h:263
bool begin(I2SCodecConfig cfg) override
Starts the I2S interface.
Definition: AudioBoardStream.h:46
void addHeadphoneDetectionAction()
Adds headphone determination.
Definition: AudioBoardStream.h:347
void processActions()
Process input keys and pins.
Definition: AudioBoardStream.h:52
void setActionVolumeIncrementValue(float value)
Defines the increment value used by actionVolumeDown/actionVolumeUp.
Definition: AudioBoardStream.h:368
void addDefaultActions()
Setup the supported default actions (volume, start/stop, headphone detection)
Definition: AudioBoardStream.h:360
void incrementVolume(float inc)
Relative volume control.
Definition: AudioBoardStream.h:125
AudioBoardStream(audio_driver::AudioBoard &board)
Default constructor: for available AudioBoard values check the audioboard variables in https://pschat...
Definition: AudioBoardStream.h:39
void setActive(bool active)
The oposite of setMute(): setActive(true) calls setMute(false)
Definition: AudioBoardStream.h:314
void addVolumeActions()
add volume up and volume down action
Definition: AudioBoardStream.h:329
void addStartStopAction()
add start/stop on inputMode
Definition: AudioBoardStream.h:317
GpioPin pinVolumeUp()
number for volume up function
Definition: AudioBoardStream.h:279
bool headphoneStatus()
Returns true if the headphone was detected.
Definition: AudioBoardStream.h:306
static void actionStart(bool, int, void *ref)
Start.
Definition: AudioBoardStream.h:167
static void actionStop(bool, int, void *ref)
Stop.
Definition: AudioBoardStream.h:177
I2S Stream which also sets up a codec chip and i2s.
Definition: I2SCodecStream.h:45
AudioBoard & board()
Provides the board.
Definition: I2SCodecStream.h:179
bool setMute(bool mute)
Mute / unmote.
Definition: I2SCodecStream.h:156
float getVolume()
legacy: same as volume()
Definition: I2SCodecStream.h:153
bool setPAPower(bool active)
Sets the output of the PA Power Pin.
Definition: I2SCodecStream.h:167
bool setVolume(float vol) override
sets the volume (range 0.0f - 1.0f)
Definition: I2SCodecStream.h:141
GpioPin getPinID(PinFunction function)
Provides the gpio for the indicated function.
Definition: I2SCodecStream.h:188
DriverPins & getPins()
Provides access to the pin information.
Definition: I2SCodecStream.h:203
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:823
Definition: AudioActions.h:38
Configuration for I2SCodecStream.
Definition: I2SCodecStream.h:24