ubitx-v5d-xcvr/ubitx_iop/menu.h
Rob French 28cbb0363f Semi-functional audio config menu. Correctly links to the audio config
variables.  No update functions currently.  No indication that you're in
the "edit" mode for a given variable.
2020-06-12 14:51:48 -05:00

368 lines
8.5 KiB
C++

//======================================================================
// menu.h
//======================================================================
#ifndef __menu_h__
#define __menu_h__
//#include "etl_profile.h"
//#include <ArduinoSTL.h>
#include "etl/array.h"
#include "etl/cstring.h"
#include "etl/delegate.h"
//#include <vector>
#include <initializer_list>
#include "rig.h"
#include "tx_audio_proc.h"
extern SpeechCompressor speechCompressor; // This should be somewhere else.
// 16 characters on display
const int MAX_TEXT_LEN = 16;
const int max_text_len = 16;
const char MENU_SELECTED_CHAR = '>';
const char menu_selection_char = '>';
const char blankLine[17] = " ";
typedef etl::string<max_text_len> Menu_string;
//======================================================================
// Menu_item
//======================================================================
class Menu_item {
public:
Menu_item(): parent_link(nullptr) {}
virtual ~Menu_item() {}
virtual const Menu_string& title() const = 0;
virtual void get_title(Menu_string& outstr) const = 0;
virtual void get_text(Menu_string& outstr) const = 0;
virtual Menu_item* select() = 0;
virtual Menu_item* altSelect() = 0;
virtual Menu_item* exit() = 0;
virtual Menu_item* prev() = 0;
virtual Menu_item* next() = 0;
void set_parent(Menu_item* item) {
parent_link = item;
}
const Menu_item* parent() const {
return parent_link;
}
private:
Menu_item* parent_link;
};
//======================================================================
// List_menu
//======================================================================
const int MAX_LISTMENU_TITLE_LEN = 15;
//const int max_size_of_list_menu = 20; // arbitrary...
template <const size_t SIZE>
class List_menu : public Menu_item {
public:
List_menu(const char* title, etl::array<const Menu_item*, SIZE> items):
Menu_item(), list_title(title), list_items(items), index(0) {
for (auto element : list_items) {
element->set_parent(this);
}
}
virtual const Menu_string& title() const {
return list_title;
}
virtual void get_title(Menu_string& outstr) const {
outstr.assign(list_title);
}
virtual void get_text(Menu_string& outstr) const {
list_items[index]->get_text(outstr);
}
virtual Menu_item* select()
{
return list_items[index];
}
virtual Menu_item* altSelect()
{
return this;
}
virtual Menu_item* exit()
{
return parent();
}
virtual Menu_item* prev()
{
if (--index < 0) {
index += list_items.size();
}
return this;
}
virtual Menu_item* next()
{
index = ++index % list_items.size();
return this;
}
private:
Menu_string list_title;
etl::array<const Menu_item*, SIZE> list_items;
int index;
};
//======================================================================
// Config_parm
//======================================================================
typedef etl::delegate<void(void)> Update_func;
template<typename T>
class Config_parm : public Menu_item {
public:
Config_parm(const char* title, T& parm, T min, T max, T step, Update_func f):
Menu_item(), parm_title(title), parameter(parm), min_val(min), max_val(max), step_val(step), on_update(f) {}
virtual const Menu_string& title() const {
return parm_title;
}
virtual void get_title(Menu_string& outstr) const {
outstr.assign(parm_title);
}
virtual void get_text(Menu_string& outstr) const = 0;
virtual Menu_item* select() {
on_update();
return parent();
}
virtual Menu_item* altSelect() {
on_update();
return this;
}
virtual Menu_item* exit() {
return parent();
}
virtual Menu_item* prev() {
parameter -= step_val;
if (parameter < min_val) {
parameter = min_val;
}
return this;
}
virtual Menu_item* next() {
parameter += step_val;
if (parameter > max_val) {
parameter = max_val;
}
return this;
}
const T& value() const {
return parameter;
}
private:
Menu_string parm_title;
T& parameter;
T min_val;
T max_val;
T step_val;
Update_func on_update;
};
class Parm_uint8 : public Config_parm<uint8_t> {
public:
Parm_uint8(const char* title, uint8_t& parm, uint8_t min, uint8_t max, uint8_t step, Update_func f):
Config_parm<uint8_t>(title, parm, min, max, step, f) {}
virtual void get_text(Menu_string& outstr) const {
snprintf(outstr.data(), max_text_len+1, "%-*.*s %3d", max_text_len-4, max_text_len-4, title().data(), value());
}
};
class Parm_float : public Config_parm<float> {
public:
Parm_float(const char* title, float& parm, float min, float max, float step, Update_func f):
Config_parm<float>(title, parm, min, max, step, f) {}
virtual void get_text(Menu_string& outstr) const {
snprintf(outstr.data(), max_text_len+1, "%-*.*s %5.2f", max_text_len-6, max_text_len-6, title().data(), value());
}
};
//======================================================================
const char modeID[] = {'s', 'S', 'c', 'C', 'd', 'D', 't', 'T'};
const char* const filterID[NUM_RIG_MODES][NUM_RX_FILTERS] = {
{"2.8", "2.4", "1.8"}, // LSB
{"2.8", "2.4", "1.8"}, // USB
{"1.0", "500", "250"}, // CWL
{"1.0", "500", "250"}, // CWU
{"2.8", "2.4", "500"}, // DGL
{"2.8", "2.4", "500"}, // DGU
{"2.8", "2.4", "1.8"}, // TTL
{"2.8", "2.4", "1.8"}, // TTU
};
//======================================================================
// Top_menu
//======================================================================
class Main_menu : public Menu_item {
public:
Main_menu(Rig& rig): menu_title("Main Menu"), rig(rig), adjust_tx(false), comp_on(false) {}
virtual const Menu_string& title() const {
return menu_title;
}
virtual void get_title(Menu_string& outstr) const {
outstr.assign(menu_title);
}
virtual void get_text(Menu_string& outstr) const {
char text[max_text_len+1];
sprintf(text, "%1cR:%3s %1cT:%3s ",
adjust_tx ? ' ' : menu_selection_char,
filterID[rig.modeNum()][rig.filterNum()],
adjust_tx ? menu_selection_char : ' ',
rig.isSSBMode() && comp_on ? "CMP" : " ");
outstr.assign(text);
}
/*
virtual void update() {
sprintf(_text0, "%1cR:%3s %1cT:%3s ",
_adjust_tx ? ' ' : MENU_SELECTED_CHAR,
filterID[_rig.modeNum()][_rig.filterNum()],
_adjust_tx ? MENU_SELECTED_CHAR : ' ',
_rig.isSSBMode() && _comp_on ? "CMP" : " ");
if ((strcmp(_text0, _text1) != 0) || _dirty) {
if (_visible) {
sendIOPMenuDisplay(_text0);
USBDEBUG("updating menu:");
USBDEBUG(_text0);
} else {
sendIOPMenuInactive();
USBDEBUG("deactivating menu");
}
_dirty = false;
strncpy(_text1, _text0, MAX_TEXT_LEN);
}
}
*/
virtual Menu_item* select() {
adjust_tx = !adjust_tx;
return this;
}
virtual Menu_item* altSelect() {
return this;
}
virtual Menu_item* exit() {
return nullptr;
}
virtual Menu_item* prev() {
if (adjust_tx) {
if (rig.isSSBMode()) {
comp_on = !comp_on;
if (comp_on)
speechCompressor.enable();
else
speechCompressor.disable();
}
} else {
rig.switchRxFilter(true);
}
return this;
}
virtual Menu_item* next() {
if (adjust_tx) {
if (rig.isSSBMode()) {
comp_on = !comp_on;
if (comp_on)
speechCompressor.enable();
else
speechCompressor.disable();
}
} else {
rig.switchRxFilter();
}
return this;
}
private:
Menu_string menu_title;
Rig& rig;
bool adjust_tx;
bool comp_on;
};
/*
public class MenuItem {
public:
MenuItem(bool active = true, int timeout = 0): _active(active), _timeout(timeout), _elapsed(0) {}
void update() {
if ((_timeout > 0) && (_elapsed > _timeout)) {
_active = false;
}
}
inline void activate() { _active = true; _elapsed = 0; }
inline void deactivate() { _active = false; }
virtual MenuItem* accept();
virtual MenuItem* reject();
virtual MenuItem* next();
virtual MenuItem* prev();
private:
bool _active;
int _timeout;
elapsedMillis _elapsed;
};
public class SSBMenu {
public:
private:
};
public class DigiMenu {
public:
private:
}
public class CWMenu {
public:
private:
};
*/
extern const Menu_item* audio_config_menu;
#endif
//======================================================================
// EOF
//======================================================================