Air aux mute switch 1,2 works

* update LED+mute status from MIDI
* toggle mute status via keyboard
master
unicod 3 years ago
parent 6073eab934
commit 93a0eb3af6

@ -1,12 +1,9 @@
#include "TimedPin.h" #include "TimedPin.h"
/***************************************************************************//**
* @brief Constructor
*******************************************************************************/
TimedPin::TimedPin(uint8_t pin_id, bool inverted) { TimedPin::TimedPin(uint8_t pin_id, bool inverted) {
PinId = pin_id; PinId = pin_id;
PinInvert = inverted; PinInvert = inverted;
PinMode = TPM_OFF; TPinMode = TPM_OFF;
OnTime = 0; OnTime = 0;
OffTime = 0; OffTime = 0;
} }
@ -19,7 +16,7 @@ void TimedPin::begin() {
void TimedPin::loop() { void TimedPin::loop() {
uint32_t t = millis(); uint32_t t = millis();
int32_t tdif = t - RefTime; int32_t tdif = t - RefTime;
switch (PinMode) { switch (TPinMode) {
case TPM_OFF: case TPM_OFF:
break; break;
case TPM_ON: case TPM_ON:
@ -33,6 +30,12 @@ void TimedPin::loop() {
} }
} else { // pin == off } else { // pin == off
if (tdif >= OffTime) { // off time expired if (tdif >= OffTime) { // off time expired
if (CycleCnt) { // cycle count defined: counting down
if (--CycleCnt == 0) { // last cycle reached:
TPinMode = TPM_OFF; // stop blinking
break;
}
}
RefTime = t; RefTime = t;
PinOn(); // toggle pin PinOn(); // toggle pin
} }
@ -42,55 +45,56 @@ void TimedPin::loop() {
case TPM_TIMED_ON: { case TPM_TIMED_ON: {
if (tdif >= OnTime) { // on time expired if (tdif >= OnTime) { // on time expired
PinOff(); PinOff();
PinMode = TPM_OFF; TPinMode = TPM_OFF;
} }
} break; } break;
case TPM_TIMED_OFF: { case TPM_TIMED_OFF: {
if (tdif >= OffTime) { // off time expired if (tdif >= OffTime) { // off time expired
PinOn(); PinOn();
PinMode = TPM_ON; TPinMode = TPM_ON;
} }
} break; } break;
default: { default: {
PinMode = TPM_OFF; TPinMode = TPM_OFF;
} break; } break;
} }
} }
void TimedPin::OffTimed(uint32_t t) { void TimedPin::OffTimed(uint32_t t) {
PinOff(); PinOff();
PinMode = TPM_TIMED_OFF; TPinMode = TPM_TIMED_OFF;
RefTime = millis(); RefTime = millis();
OffTime = t; OffTime = t;
} }
void TimedPin::OnTimed(uint32_t t) { void TimedPin::OnTimed(uint32_t t) {
PinOn(); PinOn();
PinMode = TPM_TIMED_ON; TPinMode = TPM_TIMED_ON;
RefTime = millis(); RefTime = millis();
OffTime = t; OffTime = t;
} }
void TimedPin::Blink(uint32_t t_on, uint32_t t_off) { void TimedPin::Blink(uint32_t t_on, uint32_t t_off, uint16_t cycles) {
if (PinMode != TPM_BLINK) { if (TPinMode != TPM_BLINK) {
PinMode = TPM_BLINK; TPinMode = TPM_BLINK;
PinOn(); PinOn();
} }
RefTime = millis(); RefTime = millis();
OnTime = t_on; OnTime = t_on;
OffTime = t_off; OffTime = t_off;
CycleCnt = cycles;
} }
void TimedPin::On() { void TimedPin::On() {
PinOn(); PinOn();
PinMode = TPM_ON; TPinMode = TPM_ON;
} }
void TimedPin::Off() { void TimedPin::Off() {
PinOff(); PinOff();
PinMode = TPM_OFF; TPinMode = TPM_OFF;
} }
// ============================================================================= // =============================================================================

@ -4,39 +4,39 @@
#include <Arduino.h> #include <Arduino.h>
enum TPinModes { enum TPinModes {
TPM_OFF, // On TPM_OFF, // permanent on
TPM_ON, // Off TPM_ON, // permanent off
TPM_BLINK, // Blink TPM_BLINK, // blink
TPM_ASYM, // asymmetric blink TPM_TIMED_ON, // timed on, then off permanently
TPM_TIMED_ON, // timed on, then off TPM_TIMED_OFF // timed off, then on permanently
TPM_TIMED_OFF // timed off, then on
}; };
class TimedPin { class TimedPin {
private: private:
uint8_t PinId; uint8_t PinId; /// pin number (assignment on board)
TPinModes PinMode; TPinModes TPinMode; /// current working mode
bool PinState; bool PinState; /// current state of pin
bool PinInvert; bool PinInvert; /// pin configuration (normal:on=HIGH, inverted:on=LOW)
uint32_t RefTime; uint32_t RefTime; /// time of start or state change
uint32_t OnTime; uint32_t OnTime; /// on time duration
uint32_t OffTime; uint32_t OffTime; /// off time duration
uint16_t CycleCnt; uint16_t CycleCnt; /// count of cycles at blink (0=non stop)
void PinOn(); void PinOn(); /// set pin to "on" (internal function)
void PinOff(); void PinOff(); /// set pin to "off" (internal function)
public: public:
TimedPin(uint8_t pin, bool inverted = false); TimedPin(uint8_t pin, bool inverted = false);
void begin(); void begin();
void loop(); void loop();
void Blink(uint32_t t_on, uint32_t t_off); void Blink(uint32_t t_on, uint32_t t_off, uint16_t cycles = 0);
void Blink(uint32_t t) { Blink(t, t); } void Blink(uint32_t t) { Blink(t, t); }
// void BlinkCycles(uint32_t t_on, uint32_t t_off, uint16_t cycles); void BlinkCycles(uint32_t t_on, uint32_t t_off, uint16_t cycles) { Blink(t_on, t_off, cycles); };
void Off(); void Off();
void OffTimed(uint32_t t); void OffTimed(uint32_t t);
void On(); void On();
void OnTimed(uint32_t t); void OnTimed(uint32_t t);
void Set(bool val) { if (val) On(); else Off(); };
}; };
#endif #endif

@ -37,36 +37,30 @@ Tmr Tmr1s = { .Period = 1000 };
/***************************************************************************//** /***************************************************************************//**
* @brief Button - port assignment * @brief Button - port assignment
*******************************************************************************/ *******************************************************************************/
const uint8_t pinBtnChOn1 = 2;
const uint8_t pinBtnChOn2 = 3;
const uint8_t pinBtnInc1 = 8; const uint8_t pinBtnInc1 = 8;
const uint8_t pinBtnDec1 = 9; const uint8_t pinBtnDec1 = 9;
const uint8_t pinBtnInc2 = 10; const uint8_t pinBtnInc2 = 10;
const uint8_t pinBtnDec2 = 11; const uint8_t pinBtnDec2 = 11;
const uint8_t pinBtnChOn1 = 12;
const uint8_t pinBtnChOn2 = 13;
/***************************************************************************//**
* @brief Button codes
*******************************************************************************/
enum _BTN_CODES {
BTN_INC1 = 0,
BTN_DEC1,
BTN_INC2,
BTN_DEC2,
BTN_CH_ON1,
BTN_CH_ON2,
BTN_MAX
};
/***************************************************************************//** /***************************************************************************//**
* @brief LED * @brief LED
*******************************************************************************/ *******************************************************************************/
TimedPin LedBoard(LED_BUILTIN); TimedPin LedBoard(LED_BUILTIN);
TimedPin LedChOn1(2); TimedPin LedChOn1(A0, true);
TimedPin LedChOn2(3); TimedPin LedChOn2(A1, true);
bool MidiCfgTxOnly; /// duplex or only tx configuration (without MIDI rx line)
MixerMuteState AirMutes[2] = {
//MixerMuteState(23, &LedBoard),
MixerMuteState(21, &LedChOn1, BTN_CH_ON1, EV_UI_RX_MUTE_CH1_ON, EV_UI_RX_MUTE_CH1_OFF),
MixerMuteState(22, &LedChOn2, BTN_CH_ON2, EV_UI_RX_MUTE_CH2_ON, EV_UI_RX_MUTE_CH2_OFF)
};
/***************************************************************************//** /***************************************************************************//**
* @brief MIDI instance (serial port) * @brief MIDI instance (serial port)
@ -74,19 +68,21 @@ TimedPin LedChOn2(3);
MIDI_CREATE_DEFAULT_INSTANCE(); MIDI_CREATE_DEFAULT_INSTANCE();
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void MidiCCHandler(byte channel, byte ctrl_no, byte val) {
// This function will be automatically called when a NoteOn is received. if (channel == 2) { // Mutes: ch=2
// It must be a void-returning function with the correct parameters, see documentation here: for (uint_fast8_t i=0; i<ELEMCNT(AirMutes); i++) {
// https://github.com/FortySevenEffects/arduino_midi_library/wiki/Using-Callbacks MixerMuteState& mute = AirMutes[i];
void handleNoteOn(byte channel, byte pitch, byte velocity) { if (ctrl_no == mute.MidiCtrlNr) {
// Do whatever you want when a note is pressed. mute.MuteMixer = (val >= 64);
mute.MuteLocal = mute.MuteMixer;
// Try to keep your callbacks short (no delays ect) otherwise it would slow down the loop() and have a bad impact on real-time performance. mute.Led->Set(!mute.MuteMixer);
UI_EventProc(mute.MuteMixer ? mute.UiEventOff : mute.UiEventOn);
LedBoard.OnTimed(200);
}
}
}
} }
void handleNoteOff(byte channel, byte pitch, byte velocity) {
// Do something when the note is released. Note that NoteOn messages with 0 velocity are interpreted as NoteOffs.
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -102,10 +98,9 @@ void setup() {
LedChOn1.begin(); LedChOn1.begin();
LedChOn2.begin(); LedChOn2.begin();
// Connect the handleNoteOn function to the library, so it is called upon reception of a NoteOn. MIDI.setHandleControlChange(MidiCCHandler);
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
MIDI.setHandleNoteOff(handleNoteOff); // Do the same for NoteOffs
MIDI.begin(MIDI_CHANNEL_OMNI); // Initiate MIDI communications, listen to all channels MIDI.begin(MIDI_CHANNEL_OMNI); // Initiate MIDI communications, listen to all channels
MIDI.turnThruOff();
UI_Init(); // Start user interface (main state machine) UI_Init(); // Start user interface (main state machine)
} }
@ -119,29 +114,31 @@ void loop() {
uint32_t t = millis(); uint32_t t = millis();
// execute every 10ms ******************************************************* // execute every 10ms *******************************************************
if (Tmr10ms.Check(t)) { if (Tmr10ms.Check(t)) {
static uint8_t BtnPrev = 0xFF; static uint8_t BtnPrev = 0x00;
static uint8_t BtnNew = 0; static uint8_t BtnNew = 0;
static uint8_t BtnRel = 0; static uint8_t BtnRel = 0;
uint8_t btn = (digitalRead(pinBtnInc1) ? (1 << BTN_INC1 ) : 0) uint8_t btn = (digitalRead(pinBtnInc1) ? 0: (1 << BTN_INC1 ))
| (digitalRead(pinBtnDec1) ? (1 << BTN_DEC1 ) : 0) | (digitalRead(pinBtnDec1) ? 0: (1 << BTN_DEC1 ))
| (digitalRead(pinBtnInc2) ? (1 << BTN_INC2 ) : 0) | (digitalRead(pinBtnInc2) ? 0: (1 << BTN_INC2 ))
| (digitalRead(pinBtnInc2) ? (1 << BTN_DEC2 ) : 0) | (digitalRead(pinBtnDec2) ? 0: (1 << BTN_DEC2 ))
| (digitalRead(pinBtnChOn1) ? (1 << BTN_CH_ON1) : 0) | (digitalRead(pinBtnChOn1) ? 0: (1 << BTN_CH_ON1))
| (digitalRead(pinBtnChOn1) ? (1 << BTN_CH_ON2) : 0); | (digitalRead(pinBtnChOn2) ? 0: (1 << BTN_CH_ON2));
BtnNew |= (~btn) & BtnPrev; BtnNew |= btn & (~BtnPrev);
BtnRel |= btn & (~BtnPrev); BtnRel |= (~btn) & BtnPrev;
BtnPrev = btn;
uint8_t mask = 1; uint8_t mask = 1;
if (BtnNew) { if (BtnNew) {
for (uint_fast8_t i = 0; i < BTN_MAX; i++) { for (uint_fast8_t i = 0; i < 8; i++) {
if (BtnNew & mask) { if (BtnNew & mask) {
BtnNew &= ~mask; // Bit clr BtnNew &= ~mask; // Bit clr
UI_EventProc(EV_UI_KEY_PRESS + i); UI_EventProc(EV_UI_KEY_PRESS + i);
LedBoard.OnTimed(50);
break; break;
} }
mask <<= 1; mask <<= 1;
} }
}else if (BtnRel) { // released button }else if (BtnRel) { // released button
for (uint_fast8_t i = 0; i < BTN_MAX; i++) { for (uint_fast8_t i = 0; i < 8; i++) {
if (BtnRel & mask) { if (BtnRel & mask) {
BtnRel &= ~mask; // Bit clr BtnRel &= ~mask; // Bit clr
UI_EventProc(EV_UI_KEY_REL + i); UI_EventProc(EV_UI_KEY_REL + i);

@ -20,10 +20,14 @@
// Extern variables ============================================================ // Extern variables ============================================================
extern TimedPin LedBoard; extern TimedPin LedBoard;
extern TimedPin LedChOn1;
extern TimedPin LedChOn2;
extern MIDI_NAMESPACE::SerialMIDI<HardwareSerial> serialMIDI; extern MIDI_NAMESPACE::SerialMIDI<HardwareSerial> serialMIDI;
extern MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial>> MIDI; extern MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial>> MIDI;
extern MixerMuteState AirMutes[2];
// Typedefs ==================================================================== // Typedefs ====================================================================
struct UI_SM { struct UI_SM {
@ -110,21 +114,27 @@ void UiSt_MixerStartup(UI_SM* const me, uint16_t event) {
switch (event) { switch (event) {
case EV_STATE_ENTER: { //u MixerStartup: entry: case EV_STATE_ENTER: { //u MixerStartup: entry:
me->Timer = 0; me->Timer = 0;
LedBoard.Blink(50, 450); LedBoard.Blink(30, 270, 5);
LedChOn1.Blink(500, 500);
LedChOn2.Blink(500, 500);
}break; }break;
case EV_STATE_EXIT: { case EV_STATE_EXIT: {
}break; }break;
case EV_UI_TICK_100MS: { case EV_UI_RX_MUTE_CH1_ON:
case EV_UI_RX_MUTE_CH1_OFF:
case EV_UI_RX_MUTE_CH2_ON:
case EV_UI_RX_MUTE_CH2_OFF: { // mixer alive
SM_SET_STATE(&UiSt_Home);
}break; }break;
case EV_UI_TICK_1S: { case EV_UI_TICK_1S: {
if (++me->Timer == 15) { if (++me->Timer == 15) {
SM_SET_STATE(&UiSt_Home); //u MixerStartup -left-> Home : timeout SM_SET_STATE(&UiSt_Home); //u MixerStartup -left-> Home : timeout
} }
static uint8_t MuteVal = 0; //static uint8_t MuteVal = 0;
MIDI.sendControlChange(21, MuteVal, 2); // Send Mute: CH2, 21-26: Aux1-6 //MIDI.sendControlChange(21, MuteVal, 2); // Send Mute: CH2, 21-26: Aux1-6
MuteVal = MuteVal ? 0 : 127; //MuteVal = MuteVal ? 0 : 127;
}break; }break;
} }
} }
@ -136,13 +146,35 @@ void UiSt_MixerStartup(UI_SM* const me, uint16_t event) {
* @brief Standby (home) state * @brief Standby (home) state
*******************************************************************************/ *******************************************************************************/
void UiSt_Home(UI_SM* const me, uint16_t event) { void UiSt_Home(UI_SM* const me, uint16_t event) {
uint8_t btn = 0;
if (event >= EV_UI_KEY_PRESS && event <= EV_UI_KEY_PRESS_MAX) {
btn = event - EV_UI_KEY_PRESS;
event = EV_UI_KEY_PRESS;
}else if (event >= EV_UI_KEY_REL && event <= EV_UI_KEY_REL_MAX) {
btn = event - EV_UI_KEY_REL;
event = EV_UI_KEY_REL;
}
switch (event) { switch (event) {
case EV_STATE_ENTER: { case EV_STATE_ENTER: {
LedBoard.Blink(1900, 100); LedBoard.Blink(30, 270, 5);
}break; }break;
case EV_STATE_EXIT: { case EV_STATE_EXIT: {
}break; }break;
case EV_UI_KEY_PRESS: {
for (uint_fast8_t i=0; i<ELEMCNT(AirMutes); i++) {
MixerMuteState& mute = AirMutes[i];
if (btn == mute.UiButton) {
mute.MuteLocal = !mute.MuteLocal;
uint16_t t_on = 950;
uint16_t t_off = 50;
if (mute.MuteLocal) { t_on = 50; t_off = 950; }
mute.Led->Blink(t_on, t_off);
MIDI.sendControlChange(mute.MidiCtrlNr, mute.MuteLocal ? 0 : 127, 2);
}
}
}break;
case EV_UI_TICK_10MS: { case EV_UI_TICK_10MS: {
}break; }break;
} }

43
ui.h

@ -8,18 +8,61 @@ extern "C" {
#include "stdint.h" #include "stdint.h"
#include "statemachine.h" #include "statemachine.h"
#ifndef ELEMCNT
#define ELEMCNT(x) (sizeof(x) / sizeof((x)[0]))
#endif
/***************************************************************************//**
* @brief Button codes
*******************************************************************************/
enum BTN_CODES {
BTN_INC1 = 0,
BTN_DEC1,
BTN_INC2,
BTN_DEC2,
BTN_CH_ON1,
BTN_CH_ON2,
BTN_MAX
};
enum UI_EVENTS { enum UI_EVENTS {
EV_UI_TICK_10MS = EV_USER_FIRST, EV_UI_TICK_10MS = EV_USER_FIRST,
EV_UI_TICK_100MS, EV_UI_TICK_100MS,
EV_UI_TICK_1S, EV_UI_TICK_1S,
EV_UI_RX_MUTE_CH1_ON,
EV_UI_RX_MUTE_CH1_OFF,
EV_UI_RX_MUTE_CH2_ON,
EV_UI_RX_MUTE_CH2_OFF,
EV_UI_KEY_PRESS = 0x0100, EV_UI_KEY_PRESS = 0x0100,
EV_UI_KEY_PRESS_MAX = 0x01FF, EV_UI_KEY_PRESS_MAX = 0x01FF,
EV_UI_KEY_REL = 0x0200, EV_UI_KEY_REL = 0x0200,
EV_UI_KEY_REL_MAX = 0x02FF, EV_UI_KEY_REL_MAX = 0x02FF,
EV_NO_EVENT = 0xFFFF
};
/***************************************************************************//**
* @brief Unit for mute switch from Air mixer
*******************************************************************************/
struct MixerMuteState {
bool MuteMixer; /// state received from mixer
bool MuteLocal; /// local state (sent to mixer)
uint8_t MidiCtrlNr; /// assign MIDI CC number to MUTE switch of Air mixer
BTN_CODES UiButton; /// assigned button
uint16_t UiEventOn; /// event to send to UI statemachine
uint16_t UiEventOff; /// event to send to UI statemachine
TimedPin* Led;
MixerMuteState(uint8_t ctrl_nr, TimedPin* led, BTN_CODES button = BTN_MAX, uint16_t uieventon = EV_NO_EVENT, uint16_t uieventoff = EV_NO_EVENT) :
MuteMixer(false), MuteLocal(false), MidiCtrlNr(ctrl_nr), UiButton(button), UiEventOn(uieventon), UiEventOff(uieventoff), Led(led) { }
}; };
extern void UI_Init(); extern void UI_Init();
extern void UI_EventProc(uint16_t event); extern void UI_EventProc(uint16_t event);
extern void UI_EventSend(uint16_t event); extern void UI_EventSend(uint16_t event);

Loading…
Cancel
Save