Files
MeshCore-Posadmesh/examples/simple_repeater/UITask.h
T
shade ce1b71d6fd feat: separate radio settings in the on-device setup wizard
- радиопресет заменён на четыре отдельных пункта меню: Frequency, Bandwidth, CR, SF
- частота: целые МГц шагом +-1, кГц правятся по разрядам (принцип как у координат)
- полоса: поразрядный ввод значения с точкой (формат 062.50)
- CR и SF: шаг +-1 с ограничением 5-8 и 5-12
- применение любого из четырёх пунктов отправляет set radio <частота>,<полоса>,<sf>,<cr>
  целиком, остальные значения сохраняются; внизу меню остаётся Save & exit
- документация device-setup.md обновлена, README: раздел и журнал изменений
- проверено сборкой: heltec_v4_repeater_mqtt, Meshadventurer_sx1262_repeater_mqtt,
  Generic_E22_sx1262_repeater_mqtt (без дисплея)
2026-10-11 18:06:55 +03:00

107 lines
3.8 KiB
C++

#pragma once
#include <helpers/ui/DisplayDriver.h>
#include <helpers/CommonCLI.h>
class CommonCLI;
// Локальный мастер настройки репитера. Работает на любой плате, у которой есть
// дисплей (DISPLAY_CLASS) и кнопка (PIN_USER_BTN); на остальных целях код
// полностью исключается препроцессором. Все изменения применяются через тот же
// CommonCLI, что и последовательный порт, поэтому проверка значений и запись в
// флеш выполняются одним и тем же кодом.
class UITask {
public:
enum Screen : uint8_t {
SCREEN_STATUS = 0,
SCREEN_MENU,
SCREEN_VALUE, // числа и переключатели: SF, CR, TX, repeat, path hash, advert, flood
SCREEN_DIGITS, // поразрядный ввод значения с точкой (полоса)
SCREEN_FREQ, // частота: МГц шагом 1, кГц по разрядам
SCREEN_COORDS,
SCREEN_COORDS_SAVE
};
private:
mesh::MainBoard* _board;
DisplayDriver* _display;
unsigned long _next_read, _next_refresh, _auto_off;
int _prevBtnState;
NodePrefs* _node_prefs;
CommonCLI* _cli = nullptr;
char _version_info[32];
unsigned long _powering_off_at = 0;
unsigned long _started_at = 0;
// состояние мастера настройки
uint8_t _screen = SCREEN_STATUS;
uint8_t _menu_index = 0;
uint8_t _menu_top = 0;
int _value = 0;
uint8_t _coord_digit = 0; // 0..5 широта, 6..11 долгота
bool _coord_editing = false; // true: цифра правится, false: применена
bool _coord_applied[12];
char _coord_digits[12];
char _toast[40];
unsigned long _toast_until = 0;
// радиопараметры: рабочая копия, пока мастер открыт
bool _radio_loaded = false;
double _radio_freq = 0;
double _radio_bw = 0;
int _radio_sf = 0;
int _radio_cr = 0;
// поразрядный редактор значения с десятичной точкой (полоса)
uint8_t _digit_count = 0;
uint8_t _digit_int = 0; // цифр до точки
uint8_t _digit_index = 0;
bool _digit_editing = false;
bool _digit_applied[8];
char _digit_digits[8];
// редактор частоты: целые МГц меняются шагом 1, кГц — по разрядам
int _freq_mhz = 0;
char _freq_khz[3] = { '0', '0', '0' };
uint8_t _freq_index = 0; // 0 = МГц, 1..3 = разряды кГц
bool _freq_editing = false;
bool _freq_applied[4];
bool wizardActive() const { return _screen != SCREEN_STATUS; }
void openMenu();
void openField(uint8_t index);
void applyField();
void loadRadio();
void applyRadio();
void beginBwEdit();
void beginFreqEdit();
double digitValue() const;
double freqValue() const;
void coordFromPrefs();
void coordSave();
double coordAxisValue(uint8_t axis) const; // axis 0 = lat, 1 = lon
void setToast(const char* msg);
bool runCommand(const char* command);
void handleButton(int ev);
void renderCurrScreen();
void renderStatus();
void renderMenu();
void renderValue();
void renderDigits();
void renderFreq();
void renderCoords();
void renderCoordsSave();
void renderTitleBar(const char* title);
void renderHint(const char* hint);
void renderToast();
int rowHeight() const;
public:
UITask(mesh::MainBoard& board, DisplayDriver& display) : _board(&board), _display(&display) { _next_read = _next_refresh = 0; }
void begin(NodePrefs* node_prefs, const char* build_date, const char* firmware_version, CommonCLI* cli = nullptr);
void loop();
};