You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
230 lines
7.2 KiB
C++
230 lines
7.2 KiB
C++
/***************************************************************************//**
|
|
* @file ui.cpp
|
|
*******************************************************************************/
|
|
|
|
#include <Arduino.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <avr/pgmspace.h>
|
|
#include <avr/eeprom.h>
|
|
|
|
//#include "gitinfo.h"
|
|
#include "MIDI.h"
|
|
#include "TimedPin.h"
|
|
#include "ui.h"
|
|
|
|
|
|
#define ELEMCNT(x) (sizeof(x) / sizeof((x)[0]))
|
|
|
|
|
|
|
|
// Extern variables ============================================================
|
|
extern TimedPin LedBoard;
|
|
extern TimedPin LedChOn1;
|
|
extern TimedPin LedChOn2;
|
|
extern TimedPin LedInc1;
|
|
extern TimedPin LedDec1;
|
|
|
|
extern MIDI_NAMESPACE::SerialMIDI<HardwareSerial> serialMIDI;
|
|
extern MIDI_NAMESPACE::MidiInterface<MIDI_NAMESPACE::SerialMIDI<HardwareSerial>> MIDI;
|
|
|
|
extern MixerMuteState AirMutes[2];
|
|
extern MixerFaderState AirFaders[2];
|
|
extern bool ButtonCheck(uint8_t btn);
|
|
|
|
// Typedefs ====================================================================
|
|
struct UI_SM {
|
|
STATE_MACHINE sm;
|
|
uint32_t Events;
|
|
uint16_t Timer;
|
|
uint16_t KeyTimer;
|
|
};
|
|
typedef void UI_STATE_FUNC(UI_SM* me, uint16_t event);
|
|
|
|
|
|
// Local variables =============================================================
|
|
static UI_SM UiSm;
|
|
#define DEFINE_MY_OBJECT() UI_SM* const me = &UiSm;
|
|
TimedPin DummyRelay;
|
|
|
|
|
|
const uint16_t ToutProg = 30; // [s]
|
|
|
|
// Local function declarations =================================================
|
|
static void UiSt_MixerStartup(UI_SM* me, uint16_t event);
|
|
static void UiSt_Home(UI_SM* me, uint16_t event);
|
|
|
|
|
|
// Function definitions ========================================================
|
|
|
|
|
|
//u @startuml
|
|
//u skinparam defaultTextAlignment left
|
|
//u state UserInterface {
|
|
|
|
/***************************************************************************//**
|
|
* @brief Initialize state machine for user interface
|
|
*******************************************************************************/
|
|
void UI_Init() {
|
|
DEFINE_MY_OBJECT();
|
|
me->Events = 0;
|
|
StateMachineInit(&me->sm, (SM_STATE_FUNC*)&UiSt_MixerStartup); //u [*] -> MixerStartup
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief Execute event handler
|
|
*******************************************************************************/
|
|
void UI_EventProc(uint16_t event) {
|
|
DEFINE_MY_OBJECT();
|
|
StateMachine((STATE_MACHINE*)me, event);
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief Check and execute asynchron event (from event buffer)
|
|
*******************************************************************************/
|
|
void UI_CheckEvent() {
|
|
DEFINE_MY_OBJECT();
|
|
|
|
if (me->Events) {
|
|
uint32_t mask = 1;
|
|
uint8_t ev;
|
|
for (ev = 0; ev < 32; ev++) {
|
|
if (me->Events & mask) {
|
|
me->Events &= ~mask;
|
|
StateMachine((STATE_MACHINE*)me, ev);
|
|
break;
|
|
}
|
|
mask <<= 1; // shift left
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************//**
|
|
* @brief Send (asynchron) event to state machine to process it later
|
|
*******************************************************************************/
|
|
static inline void EventSend(UI_SM* const me, uint16_t event) {
|
|
me->Events |= (1 << event);
|
|
}
|
|
|
|
|
|
// State definitions ===========================================================
|
|
|
|
|
|
//u state MixerStartup {
|
|
/***************************************************************************//**
|
|
* @brief MixerStartup
|
|
*******************************************************************************/
|
|
void UiSt_MixerStartup(UI_SM* const me, uint16_t event) {
|
|
switch (event) {
|
|
case EV_STATE_ENTER: { //u MixerStartup: entry:
|
|
me->Timer = 0;
|
|
LedBoard.Blink(30, 270, 5);
|
|
LedChOn1.Blink(10, 1990);
|
|
LedChOn2.Blink(10, 1990);
|
|
LedInc1.Blink(10, 1990);
|
|
LedDec1.Blink(10, 1990);
|
|
}break;
|
|
case EV_STATE_EXIT: {
|
|
}break;
|
|
|
|
case EV_UI_RX_MIDI:
|
|
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 % 2) == 0) {
|
|
MixerFaderState& fader = AirFaders[0];
|
|
MIDI.sendControlChange(fader.MidiCtrlNr, fader.FaderStd - ((me->Timer >> 1) % 2), 1); // ping mixer with changing value (std, std-1, std,...)
|
|
}
|
|
if (++me->Timer == 15) {
|
|
SM_SET_STATE(&UiSt_Home); //u MixerStartup -left-> Home : timeout
|
|
}
|
|
}break;
|
|
}
|
|
}
|
|
//u }
|
|
|
|
|
|
//u state Home {
|
|
/***************************************************************************//**
|
|
* @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(30, 270, 5);
|
|
// initialize mixer
|
|
for (uint_fast8_t i=0; i<ELEMCNT(AirMutes); i++) {
|
|
MixerMuteState& mute = AirMutes[i];
|
|
if (mute.MuteInit <= 1) { // init needed
|
|
mute.MuteLocal = mute.MuteInit;
|
|
MIDI.sendControlChange(mute.MidiCtrlNr, mute.MuteLocal ? 127 : 0, 2);
|
|
mute.LedUpdate();
|
|
}
|
|
}
|
|
for (uint_fast8_t i=0; i<ELEMCNT(AirFaders); i++) {
|
|
MixerFaderState& fader = AirFaders[i];
|
|
fader.FaderLocal = fader.FaderStd; // init: set volume to standard
|
|
MIDI.sendControlChange(fader.MidiCtrlNr, fader.FaderLocal, 1);
|
|
fader.LedUpdate();
|
|
}
|
|
}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.ToggleState();
|
|
MIDI.sendControlChange(mute.MidiCtrlNr, mute.MuteLocal ? 127 : 0, 2);
|
|
}
|
|
}
|
|
for (uint_fast8_t i=0; i<ELEMCNT(AirFaders); i++) {
|
|
MixerFaderState& fader = AirFaders[i];
|
|
if (btn == fader.UiButtonInc) {
|
|
if (ButtonCheck(fader.UiButtonDec)) { // inc+dec button together
|
|
fader.FaderLocal = fader.FaderStd;
|
|
fader.LedUpdate();
|
|
}else {
|
|
fader.VolumeInc();
|
|
}
|
|
MIDI.sendControlChange(fader.MidiCtrlNr, fader.FaderLocal, 1);
|
|
}
|
|
if (btn == fader.UiButtonDec) {
|
|
if (ButtonCheck(fader.UiButtonInc)) { // inc+dec button together
|
|
fader.FaderLocal = fader.FaderStd;
|
|
fader.LedUpdate();
|
|
}else {
|
|
fader.VolumeDec();
|
|
}
|
|
MIDI.sendControlChange(fader.MidiCtrlNr, fader.FaderLocal, 1);
|
|
}
|
|
}
|
|
}break;
|
|
|
|
case EV_UI_TICK_10MS: {
|
|
}break;
|
|
}
|
|
}
|
|
//u }
|
|
|
|
|
|
|
|
|
|
//u }
|
|
|
|
//u @enduml
|