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"
/***************************************************************************//**
* @brief Constructor
*******************************************************************************/
TimedPin::TimedPin(uint8_t pin_id, bool inverted) {
PinId = pin_id;
PinInvert = inverted;
PinMode = TPM_OFF;
TPinMode = TPM_OFF;
OnTime = 0;
OffTime = 0;
}
@ -19,7 +16,7 @@ void TimedPin::begin() {
void TimedPin::loop() {
uint32_t t = millis();
int32_t tdif = t - RefTime;
switch (PinMode) {
switch (TPinMode) {
case TPM_OFF:
break;
case TPM_ON:
@ -33,6 +30,12 @@ void TimedPin::loop() {
}
} else { // pin == off
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;
PinOn(); // toggle pin
}
@ -42,55 +45,56 @@ void TimedPin::loop() {
case TPM_TIMED_ON: {
if (tdif >= OnTime) { // on time expired
PinOff();
PinMode = TPM_OFF;
TPinMode = TPM_OFF;
}
} break;
case TPM_TIMED_OFF: {
if (tdif >= OffTime) { // off time expired
PinOn();
PinMode = TPM_ON;
TPinMode = TPM_ON;
}
} break;
default: {
PinMode = TPM_OFF;
TPinMode = TPM_OFF;
} break;
}
}
void TimedPin::OffTimed(uint32_t t) {
PinOff();
PinMode = TPM_TIMED_OFF;
TPinMode = TPM_TIMED_OFF;
RefTime = millis();
OffTime = t;
}
void TimedPin::OnTimed(uint32_t t) {
PinOn();
PinMode = TPM_TIMED_ON;
TPinMode = TPM_TIMED_ON;
RefTime = millis();
OffTime = t;
}
void TimedPin::Blink(uint32_t t_on, uint32_t t_off) {
if (PinMode != TPM_BLINK) {
PinMode = TPM_BLINK;
void TimedPin::Blink(uint32_t t_on, uint32_t t_off, uint16_t cycles) {
if (TPinMode != TPM_BLINK) {
TPinMode = TPM_BLINK;
PinOn();
}
RefTime = millis();
OnTime = t_on;
OffTime = t_off;
CycleCnt = cycles;
}
void TimedPin::On() {
PinOn();
PinMode = TPM_ON;
TPinMode = TPM_ON;
}
void TimedPin::Off() {
PinOff();
PinMode = TPM_OFF;
TPinMode = TPM_OFF;
}
// =============================================================================

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

@ -37,36 +37,30 @@ Tmr Tmr1s = { .Period = 1000 };
/***************************************************************************//**
* @brief Button - port assignment
*******************************************************************************/
const uint8_t pinBtnChOn1 = 2;
const uint8_t pinBtnChOn2 = 3;
const uint8_t pinBtnInc1 = 8;
const uint8_t pinBtnDec1 = 9;
const uint8_t pinBtnInc2 = 10;
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
*******************************************************************************/
TimedPin LedBoard(LED_BUILTIN);
TimedPin LedChOn1(2);
TimedPin LedChOn2(3);
TimedPin LedChOn1(A0, true);
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)
@ -74,19 +68,21 @@ TimedPin LedChOn2(3);
MIDI_CREATE_DEFAULT_INSTANCE();
// -----------------------------------------------------------------------------
// This function will be automatically called when a NoteOn is received.
// It must be a void-returning function with the correct parameters, see documentation here:
// https://github.com/FortySevenEffects/arduino_midi_library/wiki/Using-Callbacks
void handleNoteOn(byte channel, byte pitch, byte velocity) {
// Do whatever you want when a note is pressed.
// 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.
void MidiCCHandler(byte channel, byte ctrl_no, byte val) {
if (channel == 2) { // Mutes: ch=2
for (uint_fast8_t i=0; i<ELEMCNT(AirMutes); i++) {
MixerMuteState& mute = AirMutes[i];
if (ctrl_no == mute.MidiCtrlNr) {
mute.MuteMixer = (val >= 64);
mute.MuteLocal = mute.MuteMixer;
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();
LedChOn2.begin();
// Connect the handleNoteOn function to the library, so it is called upon reception of a NoteOn.
MIDI.setHandleNoteOn(handleNoteOn); // Put only the name of the function
MIDI.setHandleNoteOff(handleNoteOff); // Do the same for NoteOffs
MIDI.setHandleControlChange(MidiCCHandler);
MIDI.begin(MIDI_CHANNEL_OMNI); // Initiate MIDI communications, listen to all channels
MIDI.turnThruOff();
UI_Init(); // Start user interface (main state machine)
}
@ -119,29 +114,31 @@ void loop() {
uint32_t t = millis();
// execute every 10ms *******************************************************
if (Tmr10ms.Check(t)) {
static uint8_t BtnPrev = 0xFF;
static uint8_t BtnPrev = 0x00;
static uint8_t BtnNew = 0;
static uint8_t BtnRel = 0;
uint8_t btn = (digitalRead(pinBtnInc1) ? (1 << BTN_INC1 ) : 0)
| (digitalRead(pinBtnDec1) ? (1 << BTN_DEC1 ) : 0)
| (digitalRead(pinBtnInc2) ? (1 << BTN_INC2 ) : 0)
| (digitalRead(pinBtnInc2) ? (1 << BTN_DEC2 ) : 0)
| (digitalRead(pinBtnChOn1) ? (1 << BTN_CH_ON1) : 0)
| (digitalRead(pinBtnChOn1) ? (1 << BTN_CH_ON2) : 0);
BtnNew |= (~btn) & BtnPrev;
BtnRel |= btn & (~BtnPrev);
uint8_t btn = (digitalRead(pinBtnInc1) ? 0: (1 << BTN_INC1 ))
| (digitalRead(pinBtnDec1) ? 0: (1 << BTN_DEC1 ))
| (digitalRead(pinBtnInc2) ? 0: (1 << BTN_INC2 ))
| (digitalRead(pinBtnDec2) ? 0: (1 << BTN_DEC2 ))
| (digitalRead(pinBtnChOn1) ? 0: (1 << BTN_CH_ON1))
| (digitalRead(pinBtnChOn2) ? 0: (1 << BTN_CH_ON2));
BtnNew |= btn & (~BtnPrev);
BtnRel |= (~btn) & BtnPrev;
BtnPrev = btn;
uint8_t mask = 1;
if (BtnNew) {
for (uint_fast8_t i = 0; i < BTN_MAX; i++) {
for (uint_fast8_t i = 0; i < 8; i++) {
if (BtnNew & mask) {
BtnNew &= ~mask; // Bit clr
UI_EventProc(EV_UI_KEY_PRESS + i);
LedBoard.OnTimed(50);
break;
}
mask <<= 1;
}
}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) {
BtnRel &= ~mask; // Bit clr
UI_EventProc(EV_UI_KEY_REL + i);

@ -20,10 +20,14 @@
// Extern variables ============================================================
extern TimedPin LedBoard;
extern TimedPin LedChOn1;
extern TimedPin LedChOn2;
extern MIDI_NAMESPACE::SerialMIDI<HardwareSerial> serialMIDI;
extern MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial>> MIDI;
extern MixerMuteState AirMutes[2];
// Typedefs ====================================================================
struct UI_SM {
@ -110,21 +114,27 @@ void UiSt_MixerStartup(UI_SM* const me, uint16_t event) {
switch (event) {
case EV_STATE_ENTER: { //u MixerStartup: entry:
me->Timer = 0;
LedBoard.Blink(50, 450);
LedBoard.Blink(30, 270, 5);
LedChOn1.Blink(500, 500);
LedChOn2.Blink(500, 500);
}break;
case EV_STATE_EXIT: {
}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;
case EV_UI_TICK_1S: {
if (++me->Timer == 15) {
SM_SET_STATE(&UiSt_Home); //u MixerStartup -left-> Home : timeout
}
static uint8_t MuteVal = 0;
MIDI.sendControlChange(21, MuteVal, 2); // Send Mute: CH2, 21-26: Aux1-6
MuteVal = MuteVal ? 0 : 127;
//static uint8_t MuteVal = 0;
//MIDI.sendControlChange(21, MuteVal, 2); // Send Mute: CH2, 21-26: Aux1-6
//MuteVal = MuteVal ? 0 : 127;
}break;
}
}
@ -136,13 +146,35 @@ void UiSt_MixerStartup(UI_SM* const me, uint16_t event) {
* @brief Standby (home) state
*******************************************************************************/
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) {
case EV_STATE_ENTER: {
LedBoard.Blink(1900, 100);
LedBoard.Blink(30, 270, 5);
}break;
case EV_STATE_EXIT: {
}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: {
}break;
}

43
ui.h

@ -8,17 +8,60 @@ extern "C" {
#include "stdint.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 {
EV_UI_TICK_10MS = EV_USER_FIRST,
EV_UI_TICK_100MS,
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_MAX = 0x01FF,
EV_UI_KEY_REL = 0x0200,
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_EventProc(uint16_t event);

Loading…
Cancel
Save