ubitx-v5d-xcvr/ubitx_iop/menu.h

300 lines
7.2 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"
// 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[static_cast<int>(rig_mode::count)][static_cast<int>(rx_filter::count)] = {
{"2.8", "2.4", "1.8"}, // SSB
{"1.0", "500", "250"}, // CW
{"2.8", "2.4", "500"}, // DIG
};
//======================================================================
// Top_menu
//======================================================================
class Main_menu : public Menu_item {
public:
Main_menu(basic_rig& rig): menu_title("Main Menu"), rig_(rig), adjust_tx(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[static_cast<size_t>(rig_.get_rig_mode())][static_cast<size_t>(rig_.get_rx_filter())],
adjust_tx ? menu_selection_char : ' ',
rig_.is_ssb_mode() && rig_.config().ssb.comp.enabled ? "CMP" : " ");
outstr.assign(text);
}
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_.is_ssb_mode()) {
rig_.config().ssb.comp.enabled = !rig_.config().ssb.comp.enabled;
if (rig_.config().ssb.comp.enabled)
rig_.enable_comp();
else
rig_.disable_comp();
}
} else {
rig_.prev_rx_filter();
}
return this;
}
virtual Menu_item* next() {
if (adjust_tx) {
if (rig_.is_ssb_mode()) {
rig_.config().ssb.comp.enabled = !rig_.config().ssb.comp.enabled;
if (rig_.config().ssb.comp.enabled)
rig_.enable_comp();
else
rig_.disable_comp();
}
} else {
rig_.next_rx_filter();
}
return this;
}
private:
Menu_string menu_title;
basic_rig& rig_;
bool adjust_tx;
};
extern const Menu_item* audio_config_menu;
#endif
//======================================================================
// EOF
//======================================================================