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++

/***************************************************************************//**
* @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