ui-new: частота в настройках радио правится по разрядам (МГц шагом 1, кГц по символам)

This commit is contained in:
shade committed 2026-10-12 09:03:02 +03:00
1 parent 24e2e48e1d
commit e59a5f1759
2 files changed
+71 -10

No files matched your search

+8 -5
View File
@@ -60,11 +60,14 @@ git merge upstream/main # правки для upstream отправляю
### Интерфейс (companion_radio / ui-new)
- **Настройка радио прямо с устройства** — страница RADIO, длинное нажатие: частота
(шаг 25 кГц), ширина полосы, SF, CR и мощность передатчика. Значения применяются к радио
сразу, в память пишутся по пункту `Save & exit`; через 5 минут простоя меню закрывается
без сохранения и экран гаснет, а пока меню открыто — входящие сообщения не всплывают
поверх него.
- **Настройка радио прямо с устройства** — страница RADIO, длинное нажатие: частота,
ширина полосы, SF, CR и мощность передатчика. Частота правится **по разрядам** (как в
PosadMesh): целые МГц меняются шагом 1 МГц, а килогерцы — по символам (сотни, десятки,
единицы). Короткое и двойное нажатие меняют активный разряд на ±1, длинное — переводит
на следующий разряд, а после единиц кГц возвращает к списку; активный разряд показан
инверсией. Значения применяются к радио сразу, в память пишутся по пункту `Save & exit`;
через 5 минут простоя меню закрывается без сохранения и экран гаснет, а пока меню открыто —
входящие сообщения не всплывают поверх него.
- **Меню уведомлений** (длинное нажатие на первом экране): `Popups`, `Wake screen`
(запретить автовключение дисплея по входящему сообщению; по кнопке экран работает),
`Alerts` (звук+вибрация / только звук / только вибрация / выключено), `Channels`
+63 -5
View File
@@ -41,7 +41,9 @@
#ifndef UI_RADIO_FREQ_MAX
#define UI_RADIO_FREQ_MAX 960.0f
#endif
#define UI_RADIO_FREQ_STEP_KHZ 25 // шаг перестройки частоты
// Частота правится по разрядам, как в PosadMesh: целые МГц меняются шагом 1 МГц,
// а килогерцы — по символам (сотни, десятки, единицы). Разряд 0 — МГц, 1..3 — кГц.
#define UI_RADIO_FREQ_KHZ_DIGITS 3
#define UI_RADIO_MENU_TIMEOUT_MILLIS 300000UL // 5 минут простоя — выйти из меню без сохранения
#define NOTIFY_MAIN_ROWS 7 // строк в меню уведомлений
@@ -163,6 +165,7 @@ class HomeScreen : public UIScreen {
bool _radio_edit;
bool _radio_val_edit;
uint8_t _radio_sel;
uint8_t _radio_fq_pos; // активный разряд частоты: 0 — МГц, 1..3 — сотни/десятки/единицы кГц
unsigned long _radio_last_activity; // для автовыхода из меню по простою
void radioEditEnter() {
@@ -170,6 +173,7 @@ class HomeScreen : public UIScreen {
_radio_edit = true;
_radio_val_edit = false;
_radio_sel = ROW_FQ;
_radio_fq_pos = 0;
_radio_last_activity = millis();
}
void radioEditLeave(bool save) {
@@ -339,7 +343,7 @@ class HomeScreen : public UIScreen {
public:
HomeScreen(UITask* task, mesh::RTCClock* rtc, SensorManager* sensors, NodePrefs* node_prefs)
: _task(task), _rtc(rtc), _sensors(sensors), _node_prefs(node_prefs), _page(0),
_shutdown_init(false), _radio_edit(false), _radio_val_edit(false), _radio_sel(0),
_shutdown_init(false), _radio_edit(false), _radio_val_edit(false), _radio_sel(0), _radio_fq_pos(0),
_radio_last_activity(0), _theme_edit(false), _theme_sel(0), _theme_last_activity(0),
_notify_screen(NOTIFY_OFF), _notify_sel(0), _notify_val_edit(false), _notify_last_activity(0),
sensors_lpp(200) { }
@@ -655,10 +659,16 @@ public:
}
if (c == KEY_ENTER) {
if (_radio_val_edit) {
_radio_val_edit = false; // назад к списку
// у частоты долгое нажатие перебирает разряды, на последнем — возврат к списку
if (_radio_sel == ROW_FQ && _radio_fq_pos < UI_RADIO_FREQ_KHZ_DIGITS) {
_radio_fq_pos++;
} else {
_radio_val_edit = false; // назад к списку
}
} else if (_radio_sel == ROW_SAVE) {
radioEditLeave(true); // сохранить в память и выйти
} else {
_radio_fq_pos = 0;
_radio_val_edit = true; // править значение
}
return true;
@@ -773,7 +783,16 @@ public:
void HomeScreen::radioValueStep(int8_t dir) {
switch (_radio_sel) {
case ROW_FQ: {
int32_t khz = (int32_t)(_node_prefs->freq * 1000.0f + 0.5f) + dir * UI_RADIO_FREQ_STEP_KHZ;
// разрядное редактирование: целые МГц (±1 МГц), килогерцы — по символам
int32_t khz = (int32_t)(_node_prefs->freq * 1000.0f + 0.5f);
if (_radio_fq_pos == 0) {
khz += dir * 1000;
} else {
int step = 1;
for (uint8_t i = _radio_fq_pos; i < UI_RADIO_FREQ_KHZ_DIGITS; i++) step *= 10; // 100, 10, 1
int digit = (khz / step) % 10;
khz += ((digit + dir + 10) % 10 - digit) * step; // по кругу: 9 + 1 -> 0, 0 - 1 -> 9
}
int32_t lo = (int32_t)(UI_RADIO_FREQ_MIN * 1000.0f), hi = (int32_t)(UI_RADIO_FREQ_MAX * 1000.0f);
if (khz < lo) khz = lo;
if (khz > hi) khz = hi;
@@ -846,8 +865,47 @@ void HomeScreen::renderRadioEditor(DisplayDriver& display) {
char head[32];
if (_radio_val_edit) { // фаза правки значения
if (_radio_sel == ROW_FQ) {
// частота правится по разрядам: активный разряд инвертируем, чтобы было видно,
// что именно меняется (целые МГц или один из разрядов кГц)
int32_t khz = (int32_t)(_node_prefs->freq * 1000.0f + 0.5f);
int mhz = khz / 1000, rem = khz % 1000;
snprintf(buf, sizeof(buf), "%d.%03d", mhz, rem);
snprintf(head, sizeof(head), "FQ %.0f-%.0f MHz", UI_RADIO_FREQ_MIN, UI_RADIO_FREQ_MAX);
display.setColor(UIColor::secondary_txt);
display.setTextSize(1);
display.drawTextLeftAlign(0, 2, head);
display.setColor(UIColor::warning_txt);
display.setTextSize(2);
int w = display.getTextWidth(buf);
int x = (display.width() - w) / 2;
const int y = 20;
display.drawTextLeftAlign(x, y, buf);
char mhz_txt[8];
snprintf(mhz_txt, sizeof(mhz_txt), "%d", mhz);
int sel_len = _radio_fq_pos == 0 ? (int)strlen(mhz_txt) : 1;
int sel_start = _radio_fq_pos == 0 ? 0 : (int)strlen(mhz_txt) + _radio_fq_pos; // +1 — точка
char sel[10];
if (sel_len > (int)sizeof(sel) - 1) sel_len = (int)sizeof(sel) - 1;
memcpy(sel, buf + sel_start, sel_len);
sel[sel_len] = 0;
const int char_w = 6 * 2; // шрифт моноширинный: 6 px на символ при размере 2
display.setColor(UIColor::primary_txt);
display.fillRect(x + sel_start * char_w - 1, y - 2, sel_len * char_w + 2, 20);
display.setColor(UIColor::window_bkg);
display.drawTextLeftAlign(x + sel_start * char_w, y, sel);
display.setColor(UIColor::secondary_txt);
display.setTextSize(1);
display.drawTextCentered(display.width() / 2, 64 - 10, "clk+ dbl- hold=next");
return;
}
switch (_radio_sel) {
case ROW_FQ: snprintf(head, sizeof(head), "FQ %.0f-%.0f MHz", UI_RADIO_FREQ_MIN, UI_RADIO_FREQ_MAX); break;
case ROW_BW: strcpy(head, "BW 7.8-500 kHz"); break;
case ROW_SF: strcpy(head, "SF 5-12"); break;
case ROW_CR: strcpy(head, "CR 5-8"); break;