Files
PortableFuncGen/firmware/shared_libs/controllers/ctrl_app.c

449 lines
12 KiB
C

#include "main.h"
#include "tim.h"
#include "ctrl_bottom_button.h"
#include "ctrl_channel_button.h"
#include "ctrl_encoder.h"
#include "ctrl_disp_button.h"
#include "ctrl_signal_gen.h"
#include "ctrl_app.h"
typedef void (*btn_action_t)(APP_data_t *app_data);
typedef struct
{
btn_action_t command;
BITMAP_buttonName_t bitmap_name;
} CMD_button_t;
static const CMD_button_t btn_command[BTN_STATE_MAX][DISP_BTN_MAX];
static const LAY_dispBtn_t btn_hw_to_disp[BTN_BOT_MAX] = {DISP_BTN_1, DISP_BTN_2, DISP_BTN_3, DISP_BTN_4, DISP_BTN_5};
static const GEN_channel_t btn_ch_to_chan[CHANNEL_MAX] = {CHANNEL1, CHANNEL2, CHANNEL3, CHANNEL4, CHANNEL5, CHANNEL6};
static const uint32_t pow_of_10[7] = {1, 10, 100, 1000, 10000, 100000, 1000000};
static APP_data_t *_app_data;
static dds_gen_t dds_gen[DDS_CH_MAX] = {
{.super.type = GEN_FG_TYPE, .dds_ch = DDS_CH1},
{.super.type = GEN_FG_TYPE, .dds_ch = DDS_CH2},
{.super.type = GEN_FG_TYPE, .dds_ch = DDS_CH3},
};
static pwm_gen_t pwm_gen[PWM_CH_MAX] = {
{.super.type = GEN_PWM_TYPE, .pwm_ch = PWM_CH1},
{.super.type = GEN_PWM_TYPE, .pwm_ch = PWM_CH2},
{.super.type = GEN_PWM_TYPE, .pwm_ch = PWM_CH3},
};
static signal_gen_t *signal_gen[CHANNEL_MAX] = {
&dds_gen[DDS_CH1].super,
&dds_gen[DDS_CH2].super,
&dds_gen[DDS_CH3].super,
&pwm_gen[PWM_CH1].super,
&pwm_gen[PWM_CH2].super,
&pwm_gen[PWM_CH3].super,
};
static void _setGenInitailState(GEN_channel_t channel);
static void _signalGenDefaultValues(void);
static void _changeValueDdsGen(int8_t dir);
static void _changeValuePwmGen(int8_t dir);
//****************************
// Initialization
//****************************
void CTRL_buttonsInit(void)
{
CTRL_bottomButtonInit();
CTRL_channelButtonInit();
}
void APP_init(APP_data_t *app_data)
{
_app_data = app_data;
_app_data->freq_focus_digit = 4;
_app_data->ampl_focus_digit = 1;
_app_data->offs_focus_digit = 1;
_app_data->phas_focus_digit = 0;
_app_data->duty_focus_digit = 0;
_app_data->curr_gen = signal_gen[CHANNEL1];
_app_data->curr_state_lay = LAY_MAIN;
_app_data->curr_state_btn = BTN_MAIN_FG;
_app_data->curr_channel = CHANNEL1;
// _app_data->isChannelChange = 1;
// _app_data->isGraphChange = 1;
// _app_data->isValueChange = 1;
// _app_data->isButtonChange = 1;
// _app_data->isButtonBlink = 1;
_app_data->disp_update |= UPDATE_BUTTON | UPDATE_GRAPH | UPDATE_VALUE | UPDATE_CHANNEL;
CTRL_buttonsInit();
_signalGenDefaultValues();
GEN_init(signal_gen);
_setGenInitailState(CHANNEL1);
_setGenInitailState(CHANNEL2);
}
//****************************
// Handlers
//****************************
void CTRL_buttonsHandler(void)
{
CTRL_bottomButtonsHandler();
CTRL_channelButtonsHandler();
CTRL_encoderHandler();
}
//****************************
// Events
//****************************
void CTRL_pushedDispBtnEvent(ButtonKey_t *key)
{
ULOG_TRACE("Disp btn: %d", key->instance);
_app_data->last_key = btn_hw_to_disp[key->instance];
btn_command[_app_data->curr_state_btn][_app_data->last_key].command(_app_data);
}
void CTRL_encoderEvent(int8_t enc)
{
ULOG_TRACE("Enco event: %i", enc);
switch (_app_data->curr_gen->type)
{
case GEN_FG_TYPE:
_changeValueDdsGen(enc / 2);
break;
case GEN_PWM_TYPE:
_changeValuePwmGen(enc / 2);
break;
default:
ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, _app_data->curr_gen->type);
break;
}
}
void CTRL_pushedChanBtnEvent(ButtonKey_t *key)
{
ULOG_TRACE("Chan btn: %d", key->instance);
GEN_channel_t channel = btn_ch_to_chan[key->instance];
_app_data->curr_gen = signal_gen[channel];
_app_data->curr_state_lay = LAY_MAIN;
_app_data->curr_state_btn = BTN_MAIN_FG;
_app_data->curr_channel = channel;
// _app_data->isChannelChange = 1;
// _app_data->isGraphChange = 1;
// _app_data->isValueChange = 1;
// _app_data->isButtonChange = 1;
// _app_data->isButtonBlink = 1;
_app_data->disp_update |= UPDATE_BUTTON | UPDATE_GRAPH | UPDATE_VALUE | UPDATE_CHANNEL;
}
void CTRL_longPushedChanBtnEvent(ButtonKey_t *key)
{
ULOG_TRACE("Chan btn(long): %d", key->instance);
GEN_channel_t channel = btn_ch_to_chan[key->instance];
switch (signal_gen[channel]->type)
{
case GEN_FG_TYPE:
{
dds_gen_t *dds_gen = (dds_gen_t *)signal_gen[channel];
dds_gen->settings.enabled = dds_gen->settings.enabled ? FALSE : TRUE;
setEnabled(signal_gen[channel]);
break;
}
case GEN_PWM_TYPE:
{
pwm_gen_t *pwm_gen = (pwm_gen_t *)signal_gen[channel];
pwm_gen->settings.enabled = pwm_gen->settings.enabled ? FALSE : TRUE;
setEnabled(signal_gen[channel]);
break;
}
default:
ULOG_ERROR("%s:%d: Unknown generator type: %d", __FILE__, __LINE__, _app_data->curr_gen->type);
break;
}
}
//*******************************************************************
static void _changeValueDdsGen(int8_t dir)
{
dds_gen_t *dds_gen = (dds_gen_t *)_app_data->curr_gen;
switch (_app_data->curr_state_lay)
{
case LAY_FREQ:
{
uint32_t new_freq = dir * pow_of_10[_app_data->freq_focus_digit] + dds_gen->settings.frequency;
ULOG_DEBUG("<FG> New freq: %lu", new_freq);
if (new_freq > MAX_FREQ)
{
return;
}
dds_gen->settings.frequency = new_freq;
setFrequency(&dds_gen->super);
break;
}
case LAY_AMPL:
{
uint16_t new_ampl = dir * pow_of_10[_app_data->ampl_focus_digit] + dds_gen->settings.amplitude;
ULOG_DEBUG("<FG> New ampl: %u", new_ampl);
if (dds_gen->settings.offset + new_ampl > MAX_VOLT_POS || dds_gen->settings.offset - new_ampl < MAX_VOLT_NEG)
{
return;
}
dds_gen->settings.amplitude = new_ampl;
setAmplitude(&dds_gen->super);
break;
}
case LAY_OFFS:
{
int16_t new_offs = dir * pow_of_10[_app_data->offs_focus_digit] + dds_gen->settings.offset;
ULOG_DEBUG("<FG> New offs: %i", new_offs);
if (new_offs + dds_gen->settings.amplitude > MAX_VOLT_POS || new_offs - dds_gen->settings.amplitude < MAX_VOLT_NEG)
{
return;
}
dds_gen->settings.offset = new_offs;
setOfsset(&dds_gen->super);
break;
}
case LAY_PHAS:
{
uint16_t new_phas = dir * pow_of_10[_app_data->phas_focus_digit] + dds_gen->settings.phase;
ULOG_DEBUG("<FG> New phas: %u", new_phas);
if (new_phas > MAX_PHAS)
{
return;
}
dds_gen->settings.phase = new_phas;
setPhase(&dds_gen->super);
break;
}
default:
ULOG_ERROR("%s:%d: Unknown layout: %d", __FILE__, __LINE__, _app_data->curr_state_lay);
return;
}
// _app_data->isValueChange = 1;
// _app_data->isGraphChange = 1;
_app_data->disp_update |= UPDATE_GRAPH | UPDATE_VALUE;
}
static void _changeValuePwmGen(int8_t dir)
{
pwm_gen_t *pwm_gen = (pwm_gen_t *)_app_data->curr_gen;
switch (_app_data->curr_state_lay)
{
case LAY_FREQ:
{
uint32_t new_freq = dir * pow_of_10[_app_data->freq_focus_digit] + pwm_gen->settings.frequency;
ULOG_DEBUG("<PWM> New freq: %lu", new_freq);
if (new_freq > MAX_FREQ)
{
return;
}
pwm_gen->settings.frequency = new_freq;
break;
}
case LAY_AMPL:
{
uint16_t new_ampl = dir * pow_of_10[_app_data->ampl_focus_digit] + pwm_gen->settings.amplitude;
ULOG_DEBUG("<PWM> New ampl: %u", new_ampl);
if (pwm_gen->settings.offset + new_ampl > MAX_VOLT_POS || pwm_gen->settings.offset - new_ampl < MAX_VOLT_NEG)
{
return;
}
pwm_gen->settings.amplitude = new_ampl;
break;
}
case LAY_OFFS:
{
int16_t new_offs = dir * pow_of_10[_app_data->offs_focus_digit] + pwm_gen->settings.offset;
ULOG_DEBUG("<PWM> New offs: %i", new_offs);
if (new_offs + pwm_gen->settings.amplitude > MAX_VOLT_POS || new_offs - pwm_gen->settings.amplitude < MAX_VOLT_NEG)
{
return;
}
pwm_gen->settings.offset = new_offs;
break;
}
case LAY_PHAS:
{
uint16_t new_phas = dir * pow_of_10[_app_data->phas_focus_digit] + pwm_gen->settings.phase;
ULOG_DEBUG("<PWM> New phas: %u", new_phas);
if (new_phas > MAX_PHAS)
{
return;
}
pwm_gen->settings.phase = new_phas;
break;
}
case LAY_DUTY:
{
uint8_t new_duty = dir * pow_of_10[_app_data->duty_focus_digit] + pwm_gen->settings.duty;
ULOG_DEBUG("<PWM> New duty: %u", new_duty);
if (new_duty > MAX_DUTY)
{
return;
}
pwm_gen->settings.duty = new_duty;
break;
}
default:
ULOG_ERROR("%s:%d: Unknown layout: %d", __FILE__, __LINE__, _app_data->curr_state_lay);
return;
}
// _app_data->isValueChange = 1;
// _app_data->isGraphChange = 1;
_app_data->disp_update |= UPDATE_GRAPH | UPDATE_VALUE;
}
void _signalGenDefaultValues(void)
{
for (GEN_channel_t channel = CHANNEL1; channel < CHANNEL_MAX; channel++)
{
switch (signal_gen[channel]->type)
{
case GEN_FG_TYPE:
{
dds_gen_t *dds_gen = (dds_gen_t *)signal_gen[channel];
dds_gen->settings.frequency = 1000;
dds_gen->settings.amplitude = 100;
dds_gen->settings.offset = 165;
dds_gen->settings.phase = 0;
dds_gen->settings.wave = GEN_SIN;
dds_gen->settings.link = 0;
dds_gen->settings.enabled = FALSE;
break;
}
case GEN_PWM_TYPE:
{
pwm_gen_t *pwm_gen = (pwm_gen_t *)signal_gen[channel];
pwm_gen->settings.frequency = 1000;
pwm_gen->settings.amplitude = 100;
pwm_gen->settings.offset = 0;
pwm_gen->settings.phase = 0;
pwm_gen->settings.duty = 50;
pwm_gen->settings.link = 0;
pwm_gen->settings.enabled = FALSE;
break;
}
default:
break;
}
}
}
void _setGenInitailState(GEN_channel_t channel)
{
setFrequency(signal_gen[channel]);
setWave(signal_gen[channel]);
setPhase(signal_gen[channel]);
setAmplitude(signal_gen[channel]);
setEnabled(signal_gen[channel]);
// setOfsset(signal_gen[channel]);
}
inline BITMAP_buttonName_t CTRL_getBitmapName(LAY_dispBtn_t disp_btn)
{
return btn_command[_app_data->curr_state_btn][disp_btn].bitmap_name;
}
static const CMD_button_t btn_command[BTN_STATE_MAX][DISP_BTN_MAX] = {
{
// BTN_MAIN_FG
{enterToFreqLayout, BITMAP_BTN_FREQ},
{enterToAmplLayout, BITMAP_BTN_AMPL},
{enterToOffslLayout, BITMAP_BTN_OFFS},
{enterToPhasLayout, BITMAP_BTN_PHAS},
{enterToWavelLayout, BITMAP_BTN_WAVE},
},
{
// BTN_MAIN_PWM
{enterToFreqLayout, BITMAP_BTN_FREQ},
{enterToAmplLayout, BITMAP_BTN_AMPL},
{enterToOffslLayout, BITMAP_BTN_OFFS},
{enterToPhasLayout, BITMAP_BTN_PHAS},
{enterToDutyLayout, BITMAP_BTN_NONE},
},
{
// BTN_FREQ
{moveToLeftFocusFreqNumber, BITMAP_BTN_LEFT},
{moveToRighttFocusFreqNumber, BITMAP_BTN_RIGHT},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_FREQ_MIN
{moveToLeftFocusFreqNumber, BITMAP_BTN_LEFT},
{doNoting, BITMAP_BTN_EMPTY},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_FREQ_MAX
{doNoting, BITMAP_BTN_EMPTY},
{moveToRighttFocusFreqNumber, BITMAP_BTN_RIGHT},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_AMPL
{setTo1xFocusNumber, BITMAP_BTN_X1},
{setTo0_1xFocusNumber, BITMAP_BTN_X0_1},
{setTo0_01xFocusNumber, BITMAP_BTN_X0_01},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_OFFS
{setTo1xFocusNumber, BITMAP_BTN_X1},
{setTo0_1xFocusNumber, BITMAP_BTN_X0_1},
{setTo0_01xFocusNumber, BITMAP_BTN_X0_01},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_PHAS
{setTo10xFocusNumber, BITMAP_BTN_X10},
{setTo1xFocusNumber, BITMAP_BTN_X1},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_DUTY
{setTo10xFocusNumber, BITMAP_BTN_X10},
{setTo1xFocusNumber, BITMAP_BTN_X1},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
{
// BTN_WAVE
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{doNoting, BITMAP_BTN_NONE},
{backToMain, BITMAP_BTN_BACK},
},
};