28cbb0363f
variables. No update functions currently. No indication that you're in the "edit" mode for a given variable.
368 lines
8.5 KiB
C++
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
|
|
//======================================================================
|