//====================================================================== // menu.h //====================================================================== #ifndef __menu_h__ #define __menu_h__ //#include "etl_profile.h" //#include #include "etl/array.h" #include "etl/cstring.h" #include "etl/delegate.h" //#include #include #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 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 class List_menu : public Menu_item { public: List_menu(const char* title, etl::array 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 list_items; int index; }; //====================================================================== // Config_parm //====================================================================== typedef etl::delegate Update_func; template 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 { public: Parm_uint8(const char* title, uint8_t& parm, uint8_t min, uint8_t max, uint8_t step, Update_func f): Config_parm(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 { public: Parm_float(const char* title, float& parm, float min, float max, float step, Update_func f): Config_parm(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 //======================================================================