Re-implemented BT trainer setup
This commit is contained in:
committed by
Raphael Coeffic
parent
7b053c1c05
commit
e76c7f95be
@@ -700,15 +700,6 @@ PACK(struct ModelData {
|
||||
|
||||
FUNCTION_SWITCHS_FIELDS
|
||||
|
||||
bool isTrainerTraineeEnable() const
|
||||
{
|
||||
#if defined(PCBNV14)
|
||||
return trainerData.mode >= TRAINER_MODE_MASTER_TRAINER_JACK;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t getThrottleStickTrimSource() const
|
||||
{
|
||||
// The order here is TERA, so that 0 (default) means Throttle
|
||||
|
||||
@@ -156,6 +156,10 @@ if(GHOST)
|
||||
add_gui_src(radio_ghost_module_config.cpp)
|
||||
endif()
|
||||
|
||||
if(BLUETOOTH)
|
||||
add_gui_src(trainer_bluetooth.cpp)
|
||||
endif()
|
||||
|
||||
set(SRC ${SRC} storage/modelslist.cpp)
|
||||
|
||||
option(WINDOWS_INSPECT_BORDERS "Draw bounding boxes around windows" OFF)
|
||||
|
||||
@@ -131,7 +131,6 @@ ModuleWindow::ModuleWindow(Window* parent, uint8_t moduleIdx) :
|
||||
{
|
||||
setFlexLayout();
|
||||
updateModule();
|
||||
// updateSubType();
|
||||
}
|
||||
|
||||
void ModuleWindow::updateModule()
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "trainer_bluetooth.h"
|
||||
#include "opentx.h"
|
||||
#include "bluetooth.h"
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
class BTDiscoverMenu : public Menu
|
||||
{
|
||||
uint8_t devCount = 0;
|
||||
|
||||
void checkEvents() override;
|
||||
void selectAddr(const char* addr);
|
||||
|
||||
public:
|
||||
BTDiscoverMenu();
|
||||
};
|
||||
|
||||
BTDiscoverMenu::BTDiscoverMenu() :
|
||||
Menu(Layer::back())
|
||||
{
|
||||
setTitle(STR_BT_SELECT_DEVICE);
|
||||
// TODO: set minimum height
|
||||
|
||||
reusableBuffer.moduleSetup.bt.devicesCount = 0;
|
||||
bluetooth.state = BLUETOOTH_STATE_DISCOVER_REQUESTED;
|
||||
}
|
||||
|
||||
void BTDiscoverMenu::checkEvents()
|
||||
{
|
||||
if (bluetooth.state == BLUETOOTH_STATE_DISCOVER_START ||
|
||||
bluetooth.state == BLUETOOTH_STATE_DISCOVER_END) {
|
||||
int cnt = min<uint8_t>(reusableBuffer.moduleSetup.bt.devicesCount,
|
||||
MAX_BLUETOOTH_DISTANT_ADDR);
|
||||
|
||||
if (devCount < cnt) {
|
||||
for (int i = 0; i < cnt - devCount; i++) {
|
||||
int index = devCount + i;
|
||||
const char* item = reusableBuffer.moduleSetup.bt.devices[index];
|
||||
addLine(item, [=]() { selectAddr(item); });
|
||||
}
|
||||
devCount = cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BTDiscoverMenu::selectAddr(const char* addr)
|
||||
{
|
||||
strncpy(bluetooth.distantAddr, addr, LEN_BLUETOOTH_ADDR);
|
||||
bluetooth.state = BLUETOOTH_STATE_BIND_REQUESTED;
|
||||
SET_DIRTY();
|
||||
}
|
||||
|
||||
BluetoothTrainerWindow::BluetoothTrainerWindow(Window* parent) :
|
||||
FormGroup(parent, rect_t{})
|
||||
{
|
||||
setFlexLayout();
|
||||
FlexGridLayout grid(col_dsc, row_dsc, 2);
|
||||
|
||||
auto line = newLine(&grid);
|
||||
state = new StaticText(line, rect_t{}, "", 0, COLOR_THEME_PRIMARY1);
|
||||
r_addr = new StaticText(line, rect_t{}, "", 0, COLOR_THEME_PRIMARY1);
|
||||
|
||||
btn_line = newLine(&grid);
|
||||
grid.nextCell();
|
||||
|
||||
btn = new TextButton(btn_line, rect_t{}, "");
|
||||
btn->setWidth(LV_DPI_DEF / 2);
|
||||
btn->padAll(lv_dpx(4));
|
||||
}
|
||||
|
||||
void BluetoothTrainerWindow::setMaster(bool master)
|
||||
{
|
||||
if (master) {
|
||||
is_master = true;
|
||||
lv_obj_clear_flag(btn_line->getLvObj(), LV_OBJ_FLAG_HIDDEN);
|
||||
} else {
|
||||
is_master = false;
|
||||
lv_obj_add_flag(btn_line->getLvObj(), LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
static const char _empty_addr[] = "---";
|
||||
|
||||
void BluetoothTrainerWindow::refresh()
|
||||
{
|
||||
if (is_master) {
|
||||
if (bluetooth.distantAddr[0]) {
|
||||
r_addr->setText(bluetooth.distantAddr);
|
||||
btn->setText(STR_CLEAR);
|
||||
btn->setPressHandler([]() {
|
||||
bluetooth.state = BLUETOOTH_STATE_CLEAR_REQUESTED;
|
||||
memclear(bluetooth.distantAddr, sizeof(bluetooth.distantAddr));
|
||||
return 0;
|
||||
});
|
||||
} else if (bluetooth.state < BLUETOOTH_STATE_IDLE) {
|
||||
r_addr->setText(_empty_addr);
|
||||
btn->setText(STR_BLUETOOTH_INIT);
|
||||
btn->setPressHandler([]() {
|
||||
bluetooth.state = BLUETOOTH_STATE_OFF;
|
||||
return 0;
|
||||
});
|
||||
} else {
|
||||
r_addr->setText(_empty_addr);
|
||||
btn->setText(STR_DISCOVER);
|
||||
btn->setPressHandler([=]() {
|
||||
new BTDiscoverMenu();
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
state->setText(STR_CONNECTED);
|
||||
if (!is_master) r_addr->setText(bluetooth.distantAddr);
|
||||
} else {
|
||||
state->setText(STR_NOT_CONNECTED);
|
||||
if (!is_master) r_addr->setText(_empty_addr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) EdgeTX
|
||||
*
|
||||
* Based on code named
|
||||
* opentx - https://github.com/opentx/opentx
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "form.h"
|
||||
#include "static.h"
|
||||
#include "button.h"
|
||||
|
||||
class BluetoothTrainerWindow : public FormGroup
|
||||
{
|
||||
bool is_master = true;
|
||||
StaticText* state;
|
||||
StaticText* r_addr;
|
||||
|
||||
Window* btn_line;
|
||||
TextButton* btn;
|
||||
|
||||
public:
|
||||
BluetoothTrainerWindow(Window* parent);
|
||||
|
||||
void setMaster(bool master);
|
||||
void refresh();
|
||||
};
|
||||
@@ -29,289 +29,139 @@
|
||||
#include "static.h"
|
||||
#include "button.h"
|
||||
#include "numberedit.h"
|
||||
#include "channel_range.h"
|
||||
#include "ppm_settings.h"
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
#include "bluetooth.h"
|
||||
#include "trainer_bluetooth.h"
|
||||
#endif
|
||||
|
||||
static const lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(2),
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
static const lv_coord_t row_dsc[] = {LV_GRID_CONTENT,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
class TrainerModuleWindow : public FormGroup
|
||||
{
|
||||
public:
|
||||
TrainerModuleWindow(FormWindow *parent, const rect_t &rect);
|
||||
TrainerModuleWindow(FormGroup* parent);
|
||||
|
||||
void checkEvents() override;
|
||||
void update();
|
||||
|
||||
protected:
|
||||
NumberEdit *channelStart = nullptr;
|
||||
NumberEdit *channelEnd = nullptr;
|
||||
ChannelRange* chRange = nullptr;
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
StaticText *btChannelEnd = nullptr;
|
||||
StaticText *btDistAddress = nullptr;
|
||||
TextButton *btMasterButton = nullptr;
|
||||
Menu *btPopUpMenu = nullptr;
|
||||
bool btCanceled = false;
|
||||
// StaticText *btChannelEnd = nullptr;
|
||||
// StaticText *btDistAddress = nullptr;
|
||||
// TextButton *btMasterButton = nullptr;
|
||||
// Menu *btPopUpMenu = nullptr;
|
||||
// bool btCanceled = false;
|
||||
|
||||
private:
|
||||
bool popupopen = false;
|
||||
int devicecount = 0;
|
||||
uint8_t lastbluetoothstate = BLUETOOTH_STATE_OFF;
|
||||
// bool popupopen = false;
|
||||
// int devicecount = 0;
|
||||
// uint8_t lastbluetoothstate = BLUETOOTH_STATE_OFF;
|
||||
|
||||
void btDiscoverMenuItemChosen();
|
||||
void btDiscoverMenuAddItem(const char *itm);
|
||||
// void btDiscoverMenuItemChosen();
|
||||
// void btDiscoverMenuAddItem(const char *itm);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
TrainerModuleWindow::TrainerModuleWindow(FormWindow *parent,
|
||||
const rect_t &rect) :
|
||||
FormGroup(parent, rect, FORWARD_SCROLL | NO_FOCUS | FORM_FORWARD_FOCUS)
|
||||
TrainerModuleWindow::TrainerModuleWindow(FormGroup* parent) :
|
||||
FormGroup(parent, rect_t{})
|
||||
{
|
||||
setFlexLayout();
|
||||
update();
|
||||
}
|
||||
|
||||
void TrainerModuleWindow::checkEvents()
|
||||
{
|
||||
#if defined(BLUETOOTH)
|
||||
if (popupopen) {
|
||||
if (bluetooth.state == BLUETOOTH_STATE_DISCOVER_START ||
|
||||
bluetooth.state == BLUETOOTH_STATE_DISCOVER_END) {
|
||||
int cnt = min<uint8_t>(reusableBuffer.moduleSetup.bt.devicesCount,
|
||||
MAX_BLUETOOTH_DISTANT_ADDR);
|
||||
if (devicecount < cnt) {
|
||||
for (int i = 0; i < cnt - devicecount; i++) {
|
||||
int index = devicecount + i;
|
||||
btDiscoverMenuAddItem(reusableBuffer.moduleSetup.bt.devices[index]);
|
||||
}
|
||||
devicecount = cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bluetooth.state != lastbluetoothstate) {
|
||||
// TODO:
|
||||
// if (!popupopen && !trChoiceOpen) update();
|
||||
lastbluetoothstate = bluetooth.state;
|
||||
}
|
||||
#endif
|
||||
// #if defined(BLUETOOTH)
|
||||
// if (popupopen) {
|
||||
// if (bluetooth.state == BLUETOOTH_STATE_DISCOVER_START ||
|
||||
// bluetooth.state == BLUETOOTH_STATE_DISCOVER_END) {
|
||||
// int cnt = min<uint8_t>(reusableBuffer.moduleSetup.bt.devicesCount,
|
||||
// MAX_BLUETOOTH_DISTANT_ADDR);
|
||||
// if (devicecount < cnt) {
|
||||
// for (int i = 0; i < cnt - devicecount; i++) {
|
||||
// int index = devicecount + i;
|
||||
// btDiscoverMenuAddItem(reusableBuffer.moduleSetup.bt.devices[index]);
|
||||
// }
|
||||
// devicecount = cnt;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (bluetooth.state != lastbluetoothstate) {
|
||||
// // TODO:
|
||||
// // if (!popupopen && !trChoiceOpen) update();
|
||||
// lastbluetoothstate = bluetooth.state;
|
||||
// }
|
||||
// #endif
|
||||
FormGroup::checkEvents();
|
||||
}
|
||||
|
||||
void TrainerModuleWindow::update()
|
||||
{
|
||||
FormGridLayout grid;
|
||||
FlexGridLayout grid(col_dsc, row_dsc, 2);
|
||||
clear();
|
||||
|
||||
if (g_model.isTrainerTraineeEnable()) {
|
||||
#if defined(BLUETOOTH)
|
||||
if (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH) {
|
||||
|
||||
btDistAddress = new StaticText(this, grid.getFieldSlot(true), "---", 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
if (bluetooth.state == BLUETOOTH_STATE_CONNECTED)
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_CONNECTED, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
else
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_NOT_CONNECTED, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
|
||||
grid.nextLine();
|
||||
btMasterButton =
|
||||
new TextButton(this, grid.getFieldSlot(), "", [=]() -> uint8_t {
|
||||
if (bluetooth.distantAddr[0]) {
|
||||
bluetooth.state = BLUETOOTH_STATE_CLEAR_REQUESTED;
|
||||
memclear(bluetooth.distantAddr, sizeof(bluetooth.distantAddr));
|
||||
} else if (bluetooth.state < BLUETOOTH_STATE_IDLE) {
|
||||
bluetooth.state = BLUETOOTH_STATE_OFF;
|
||||
} else {
|
||||
reusableBuffer.moduleSetup.bt.devicesCount = 0;
|
||||
devicecount = 0;
|
||||
bluetooth.state = BLUETOOTH_STATE_DISCOVER_REQUESTED;
|
||||
// TODO:
|
||||
// btPopUpMenu = new Menu(parent);
|
||||
// btPopUpMenu->setTitle(STR_BT_SELECT_DEVICE);
|
||||
// popupopen = true;
|
||||
// btPopUpMenu->setCloseHandler([=]() { popupopen = false; });
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (bluetooth.distantAddr[0]) {
|
||||
btDistAddress->setText(bluetooth.distantAddr);
|
||||
btMasterButton->setText(STR_CLEAR);
|
||||
} else if (bluetooth.state < BLUETOOTH_STATE_IDLE) {
|
||||
btMasterButton->setText(STR_BLUETOOTH_INIT);
|
||||
} else {
|
||||
btMasterButton->setText(STR_DISCOVER);
|
||||
}
|
||||
|
||||
grid.nextLine();
|
||||
|
||||
} else if (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH) {
|
||||
if (bluetooth.state == BLUETOOTH_STATE_CONNECTED) {
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_CONNECTED, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
new StaticText(this, grid.getFieldSlot(), bluetooth.distantAddr, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
} else
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_NOT_CONNECTED, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_CHANNELRANGE, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
channelStart =
|
||||
new NumberEdit(this, grid.getFieldSlot(2, 0), 1,
|
||||
MAX_OUTPUT_CHANNELS - BLUETOOTH_TRAINER_CHANNELS + 1,
|
||||
GET_DEFAULT(1 + g_model.trainerData.channelsStart));
|
||||
char chend[6];
|
||||
snprintf(chend, sizeof(chend), "%s%d", STR_CH,
|
||||
g_model.trainerData.channelsStart + BLUETOOTH_TRAINER_CHANNELS);
|
||||
|
||||
btChannelEnd = new StaticText(this, grid.getFieldSlot(2, 1), chend, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
channelStart->setPrefix(STR_CH);
|
||||
channelStart->setSetValueHandler([=](int32_t newValue) {
|
||||
g_model.trainerData.channelsStart = newValue - 1;
|
||||
g_model.trainerData.channelsCount =
|
||||
BLUETOOTH_TRAINER_CHANNELS - DEF_TRAINER_CHANNELS;
|
||||
char chend[6];
|
||||
snprintf(
|
||||
chend, sizeof(chend), "%s%d", STR_CH,
|
||||
g_model.trainerData.channelsStart + BLUETOOTH_TRAINER_CHANNELS);
|
||||
SET_DIRTY();
|
||||
btChannelEnd->setText(chend);
|
||||
});
|
||||
|
||||
grid.nextLine();
|
||||
} else
|
||||
#endif
|
||||
if (g_model.trainerData.mode == TRAINER_MODE_SLAVE) {
|
||||
// TODO: use generic ChannelRange
|
||||
#define PPMCH_START_MIN 1
|
||||
#define PPMCH_START_MAX \
|
||||
(MAX_OUTPUT_CHANNELS - g_model.trainerData.channelsCount + 1 - \
|
||||
DEF_TRAINER_CHANNELS)
|
||||
#define PPMCH_END_MIN (g_model.trainerData.channelsStart + MIN_TRAINER_CHANNELS)
|
||||
#define PPMCH_END_MAX \
|
||||
min<uint8_t>(g_model.trainerData.channelsStart + MAX_TRAINER_CHANNELS, \
|
||||
MAX_OUTPUT_CHANNELS)
|
||||
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_CHANNELRANGE, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
channelStart = new NumberEdit(
|
||||
this, grid.getFieldSlot(2, 0), PPMCH_START_MIN, PPMCH_START_MAX,
|
||||
GET_DEFAULT(1 + g_model.trainerData.channelsStart));
|
||||
channelEnd = new NumberEdit(
|
||||
this, grid.getFieldSlot(2, 1), PPMCH_END_MIN, PPMCH_END_MAX,
|
||||
GET_DEFAULT((g_model.trainerData.channelsStart +
|
||||
DEF_TRAINER_CHANNELS +
|
||||
g_model.trainerData.channelsCount)));
|
||||
channelStart->setPrefix(STR_CH);
|
||||
channelEnd->setPrefix(STR_CH);
|
||||
channelStart->setSetValueHandler([=](int32_t newValue) {
|
||||
g_model.trainerData.channelsStart = newValue - 1;
|
||||
SET_DIRTY();
|
||||
channelEnd->setMin(PPMCH_END_MIN);
|
||||
channelEnd->setMax(PPMCH_END_MAX);
|
||||
channelEnd->invalidate();
|
||||
});
|
||||
channelEnd->setSetValueHandler([=](int32_t newValue) {
|
||||
g_model.trainerData.channelsCount =
|
||||
newValue - g_model.trainerData.channelsStart - DEF_TRAINER_CHANNELS;
|
||||
SET_DIRTY();
|
||||
channelStart->setMax(PPMCH_START_MAX);
|
||||
});
|
||||
|
||||
grid.nextLine();
|
||||
|
||||
// PPM frame
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_PPMFRAME, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
|
||||
// PPM frame length
|
||||
// TODO: use PpmFrameSettings<TrainerModuleData>
|
||||
auto edit = new NumberEdit(
|
||||
this, grid.getFieldSlot(3, 0), 125, 35 * 5 + 225,
|
||||
GET_DEFAULT(g_model.trainerData.frameLength * 5 + 225),
|
||||
SET_VALUE(g_model.trainerData.frameLength, (newValue - 225) / 5), 0,
|
||||
PREC1);
|
||||
edit->setStep(5);
|
||||
edit->setSuffix(STR_MS);
|
||||
|
||||
// PPM frame delay
|
||||
edit = new NumberEdit(
|
||||
this, grid.getFieldSlot(3, 1), 100, 800,
|
||||
GET_DEFAULT(g_model.trainerData.delay * 50 + 300),
|
||||
SET_VALUE(g_model.trainerData.delay, (newValue - 300) / 50));
|
||||
edit->setStep(50);
|
||||
edit->setSuffix(STR_US);
|
||||
|
||||
// PPM Polarity
|
||||
new Choice(this, grid.getFieldSlot(3, 2), STR_PPM_POL, 0, 1,
|
||||
GET_SET_DEFAULT(g_model.trainerData.pulsePol));
|
||||
grid.nextLine();
|
||||
}
|
||||
}
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
new StaticText(this, grid.getLabelSlot(true));
|
||||
#endif
|
||||
auto par = getParent();
|
||||
par->moveWindowsTop(top() + 1, adjustHeight());
|
||||
// par->adjustInnerHeight();
|
||||
}
|
||||
auto td = &g_model.trainerData;
|
||||
if (td->mode == TRAINER_MODE_OFF) return;
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
void TrainerModuleWindow::btDiscoverMenuItemChosen()
|
||||
{
|
||||
if (bluetooth.state == BLUETOOTH_STATE_DISCOVER_SENT ||
|
||||
bluetooth.state == BLUETOOTH_STATE_DISCOVER_END) {
|
||||
int index = btPopUpMenu->selection();
|
||||
if (index >= 0 && index < reusableBuffer.moduleSetup.bt.devicesCount) {
|
||||
strncpy(bluetooth.distantAddr,
|
||||
reusableBuffer.moduleSetup.bt.devices[index], LEN_BLUETOOTH_ADDR);
|
||||
bluetooth.state = BLUETOOTH_STATE_BIND_REQUESTED;
|
||||
SET_DIRTY();
|
||||
}
|
||||
if (td->mode == TRAINER_MODE_MASTER_BLUETOOTH ||
|
||||
td->mode == TRAINER_MODE_SLAVE_BLUETOOTH) {
|
||||
|
||||
auto bt = new BluetoothTrainerWindow(this);
|
||||
if (td->mode == TRAINER_MODE_SLAVE_BLUETOOTH)
|
||||
bt->setMaster(false);
|
||||
|
||||
bt->refresh();
|
||||
// TODO: slave: channel range
|
||||
}
|
||||
#endif
|
||||
|
||||
if (td->mode == TRAINER_MODE_SLAVE) {
|
||||
|
||||
// Channel range
|
||||
auto line = newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_CHANNELRANGE, 0, COLOR_THEME_PRIMARY1);
|
||||
chRange = new TrainerChannelRange(line);
|
||||
|
||||
// PPM frame
|
||||
line = newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_PPMFRAME, 0, COLOR_THEME_PRIMARY1);
|
||||
new PpmFrameSettings<TrainerModuleData>(line, grid, td);
|
||||
}
|
||||
}
|
||||
|
||||
void TrainerModuleWindow::btDiscoverMenuAddItem(const char *itm)
|
||||
{
|
||||
if (btPopUpMenu != nullptr && !btPopUpMenu->deleted())
|
||||
btPopUpMenu->addLine(
|
||||
itm, std::bind(&TrainerModuleWindow::btDiscoverMenuItemChosen, this));
|
||||
}
|
||||
#endif
|
||||
|
||||
TrainerPage::TrainerPage() : Page(ICON_MODEL_SETUP)
|
||||
{
|
||||
new StaticText(&header,
|
||||
{PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT,
|
||||
PAGE_LINE_HEIGHT},
|
||||
STR_TRAINER, 0, COLOR_THEME_PRIMARY2);
|
||||
header.setTitle(STR_TRAINER);
|
||||
|
||||
FormGridLayout grid;
|
||||
auto form = new FormGroup(&body, rect_t{});
|
||||
form->setFlexLayout();
|
||||
form->padAll(lv_dpx(8));
|
||||
|
||||
new StaticText(&body, grid.getLabelSlot(true), STR_MODE, 0,
|
||||
COLOR_THEME_PRIMARY1);
|
||||
FlexGridLayout grid(col_dsc, row_dsc, 2);
|
||||
|
||||
auto trainerChoice = new Choice(
|
||||
&body, grid.getFieldSlot(), STR_VTRAINERMODES, 0, TRAINER_MODE_MAX(),
|
||||
GET_DEFAULT(g_model.trainerData.mode));
|
||||
auto line = form->newLine(&grid);
|
||||
new StaticText(line, rect_t{}, STR_MODE, 0, COLOR_THEME_PRIMARY1);
|
||||
|
||||
auto trainerChoice =
|
||||
new Choice(line, rect_t{}, STR_VTRAINERMODES, 0, TRAINER_MODE_MAX(),
|
||||
GET_SET_DEFAULT(g_model.trainerData.mode));
|
||||
trainerChoice->setAvailableHandler(isTrainerModeAvailable);
|
||||
grid.nextLine();
|
||||
|
||||
coord_t y = grid.getWindowHeight();
|
||||
coord_t h = body.height() - y;
|
||||
coord_t w = body.width();
|
||||
|
||||
auto trainerModule = new TrainerModuleWindow(&body, {0, y, w, h});
|
||||
auto trainerModule = new TrainerModuleWindow(form);
|
||||
|
||||
TrainerModuleData* tr = &g_model.trainerData;
|
||||
trainerChoice->setSetValueHandler([=](int32_t newValue) {
|
||||
|
||||
//TODO: move the BT stuff somewhere else?
|
||||
#if defined(BLUETOOTH)
|
||||
memclear(bluetooth.distantAddr, sizeof(bluetooth.distantAddr));
|
||||
bluetooth.state = BLUETOOTH_STATE_OFF;
|
||||
|
||||
Reference in New Issue
Block a user