Horus : Tools
This commit is contained in:
@@ -87,6 +87,7 @@ void drawCurveVerticalScale(int x);
|
||||
void drawCurveHorizontalScale();
|
||||
void drawCurveCoord(int x, int y, const char * text, bool active=false);
|
||||
void drawCurvePoint(int x, int y, LcdFlags color);
|
||||
void drawPower(coord_t x, coord_t y, int8_t dBm, LcdFlags att = 0);
|
||||
|
||||
extern Layout * customScreens[MAX_CUSTOM_SCREENS];
|
||||
extern Topbar * topbar;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
@@ -23,6 +23,7 @@
|
||||
const MenuHandlerFunc menuTabGeneral[] = {
|
||||
menuRadioSetup,
|
||||
menuRadioSdManager,
|
||||
menuRadioTools,
|
||||
menuRadioSpecialFunctions,
|
||||
menuRadioTrainer,
|
||||
menuRadioHardware,
|
||||
|
||||
@@ -194,6 +194,7 @@ extern const MenuHandlerFunc menuTabModel[MENU_MODEL_PAGES_COUNT];
|
||||
enum EnumTabRadio {
|
||||
MENU_RADIO_SETUP,
|
||||
MENU_RADIO_SD_MANAGER,
|
||||
MENU_RADIO_TOOLS,
|
||||
MENU_RADIO_SPECIAL_FUNCTIONS,
|
||||
MENU_RADIO_TRAINER,
|
||||
MENU_RADIO_HARDWARE,
|
||||
@@ -203,6 +204,7 @@ enum EnumTabRadio {
|
||||
|
||||
bool menuRadioSetup(event_t event);
|
||||
bool menuRadioSdManager(event_t event);
|
||||
bool menuRadioTools(event_t event);
|
||||
bool menuRadioSpecialFunctions(event_t event);
|
||||
bool menuRadioTrainer(event_t event);
|
||||
bool menuRadioVersion(event_t event);
|
||||
@@ -261,6 +263,8 @@ bool menuAboutView(event_t event);
|
||||
bool menuMainViewChannelsMonitor(event_t event);
|
||||
bool menuTextView(event_t event);
|
||||
bool menuScreensTheme(event_t event);
|
||||
bool menuRadioSpectrumAnalyser(event_t event);
|
||||
bool menuRadioPowerMeter(event_t event);
|
||||
|
||||
typedef uint16_t FlightModesType;
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 <opentx.h>
|
||||
#include "opentx.h"
|
||||
|
||||
extern uint8_t g_moduleIdx;
|
||||
|
||||
enum PowerMeterFields {
|
||||
POWER_METER_FREQ_RANGE,
|
||||
POWER_METER_ATTENUATOR,
|
||||
POWER_METER_MAX,
|
||||
POWER_METER_POWER,
|
||||
POWER_METER_PEAK,
|
||||
POWER_METER_FIELDS_MAX
|
||||
};
|
||||
|
||||
#define POWER_METER_MARGIN_2ND_COLUMN 180
|
||||
|
||||
bool menuRadioPowerMeter(event_t event)
|
||||
{
|
||||
SIMPLE_SUBMENU(STR_MENU_POWER_METER, ICON_RADIO, POWER_METER_FIELDS_MAX-1);
|
||||
|
||||
if (TELEMETRY_STREAMING()) {
|
||||
lcdDrawCenteredText(LCD_H/2, STR_TURN_OFF_RECEIVER);
|
||||
if (event == EVT_KEY_FIRST(KEY_EXIT)) {
|
||||
killEvents(event);
|
||||
popMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (menuEvent) {
|
||||
lcdDrawCenteredText(LCD_H/2, STR_STOPPING);
|
||||
lcdRefresh();
|
||||
moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
/* wait 1s to resume normal operation before leaving */
|
||||
watchdogSuspend(1000);
|
||||
RTOS_WAIT_MS(1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (moduleState[g_moduleIdx].mode != MODULE_MODE_POWER_METER) {
|
||||
memclear(&reusableBuffer.powerMeter, sizeof(reusableBuffer.powerMeter));
|
||||
reusableBuffer.powerMeter.freq = 2400000000;
|
||||
reusableBuffer.powerMeter.attn = 4;
|
||||
moduleState[g_moduleIdx].mode = MODULE_MODE_POWER_METER;
|
||||
}
|
||||
|
||||
// The warning
|
||||
if (reusableBuffer.powerMeter.attn != 0)
|
||||
lcdDrawCenteredText(MENU_CONTENT_TOP, STR_POWERMETER_ATTN_NEEDED, BOLD);
|
||||
|
||||
for (uint8_t i=0; i<POWER_METER_FIELDS_MAX; i++) {
|
||||
LcdFlags attr = (menuVerticalPosition == i ? (s_editMode > 0 ? INVERS | BLINK : INVERS) : 0);
|
||||
coord_t y = MENU_CONTENT_TOP + 30 + i * FH;
|
||||
|
||||
switch (i) {
|
||||
case POWER_METER_FREQ_RANGE:
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_POWERMETER_FREQ);
|
||||
lcdDrawNumber(POWER_METER_MARGIN_2ND_COLUMN, y, reusableBuffer.powerMeter.freq / 1000000, LEFT | attr);
|
||||
lcdDrawText(lcdNextPos, y, " MHz band");
|
||||
if (attr) {
|
||||
reusableBuffer.powerMeter.freq = checkIncDec(event, reusableBuffer.powerMeter.freq == 900000000, 0, 1) ? 900000000 : 2400000000;
|
||||
if (checkIncDec_Ret) {
|
||||
reusableBuffer.powerMeter.power = 0;
|
||||
reusableBuffer.powerMeter.peak = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_METER_ATTENUATOR:
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_POWERMETER_ATTN);
|
||||
lcdDrawNumber(POWER_METER_MARGIN_2ND_COLUMN, y, -10 * reusableBuffer.powerMeter.attn, LEFT | attr);
|
||||
lcdDrawText(lcdNextPos, y, " dB");
|
||||
if (attr) {
|
||||
reusableBuffer.powerMeter.attn = checkIncDec(event, reusableBuffer.powerMeter.attn, 0, 5, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_METER_MAX:
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MAX);
|
||||
lcdDrawNumber(POWER_METER_MARGIN_2ND_COLUMN, y, -10 + 10 * reusableBuffer.powerMeter.attn);
|
||||
lcdDrawText(lcdNextPos, y, "dBm/ ");
|
||||
drawPower(lcdNextPos, y, -10 + 10 * reusableBuffer.powerMeter.attn, 0);
|
||||
if (attr) {
|
||||
reusableBuffer.powerMeter.attn = checkIncDec(event, reusableBuffer.powerMeter.attn, 0, 5, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_METER_POWER:
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_POWERMETER_POWER);
|
||||
if (reusableBuffer.powerMeter.power) {
|
||||
lcdDrawNumber(POWER_METER_MARGIN_2ND_COLUMN, y, reusableBuffer.powerMeter.power + reusableBuffer.powerMeter.attn * 1000, LEFT | PREC2);
|
||||
lcdDrawText(lcdNextPos, y, "dBm");
|
||||
}
|
||||
break;
|
||||
|
||||
case POWER_METER_PEAK:
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_POWERMETER_PEAK);
|
||||
if (reusableBuffer.powerMeter.peak) {
|
||||
lcdDrawNumber(POWER_METER_MARGIN_2ND_COLUMN, y, reusableBuffer.powerMeter.peak + reusableBuffer.powerMeter.attn * 1000, LEFT | PREC2);
|
||||
lcdDrawText(lcdNextPos, y, "dBm");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "opentx.h"
|
||||
|
||||
extern uint8_t g_moduleIdx;
|
||||
|
||||
enum SpectrumFields {
|
||||
SPECTRUM_FREQUENCY,
|
||||
SPECTRUM_SPAN,
|
||||
SPECTRUM_FIELDS_MAX
|
||||
};
|
||||
|
||||
bool menuRadioSpectrumAnalyser(event_t event)
|
||||
{
|
||||
SIMPLE_SUBMENU(STR_MENU_SPECTRUM_ANALYSER, ICON_RADIO, 1);
|
||||
|
||||
if (TELEMETRY_STREAMING()) {
|
||||
lcdDrawCenteredText(LCD_H/2, STR_TURN_OFF_RECEIVER );
|
||||
if (event == EVT_KEY_FIRST(KEY_EXIT)) {
|
||||
killEvents(event);
|
||||
popMenu();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (menuEvent) {
|
||||
lcdDrawCenteredText(LCD_H/2, STR_STOPPING );
|
||||
lcdRefresh();
|
||||
moduleState[g_moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
/* wait 1s to resume normal operation before leaving */
|
||||
watchdogSuspend(1000);
|
||||
RTOS_WAIT_MS(1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (moduleState[g_moduleIdx].mode != MODULE_MODE_SPECTRUM_ANALYSER) {
|
||||
memclear(reusableBuffer.spectrumAnalyser.bars, sizeof(reusableBuffer.spectrumAnalyser.bars));
|
||||
reusableBuffer.spectrumAnalyser.span = 40000000; // 40MHz
|
||||
reusableBuffer.spectrumAnalyser.freq = 2440000000; // 2440MHz
|
||||
reusableBuffer.spectrumAnalyser.step = reusableBuffer.spectrumAnalyser.span / LCD_W;
|
||||
moduleState[g_moduleIdx].mode = MODULE_MODE_SPECTRUM_ANALYSER;
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<SPECTRUM_FIELDS_MAX; i++) {
|
||||
LcdFlags attr = (menuHorizontalPosition == i ? (s_editMode>0 ? INVERS|BLINK : INVERS) : 0);
|
||||
|
||||
switch (i) {
|
||||
case SPECTRUM_FREQUENCY: {
|
||||
uint16_t frequency = reusableBuffer.spectrumAnalyser.freq / 1000000;
|
||||
lcdDrawText(1, MENU_CONTENT_TOP + 10, "F:", 0);
|
||||
lcdDrawNumber(lcdNextPos + 2, 10, frequency, attr);
|
||||
lcdDrawText(lcdNextPos + 2, 10, "MHz", 0);
|
||||
if (attr) {
|
||||
reusableBuffer.spectrumAnalyser.freq = uint32_t(checkIncDec(event, frequency, 2400, 2485, 0)) * 1000000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SPECTRUM_SPAN:
|
||||
uint8_t span = reusableBuffer.spectrumAnalyser.span / 1000000;
|
||||
lcdDrawText(lcdNextPos + 5, MENU_CONTENT_TOP + 10, "S:", 0);
|
||||
lcdDrawNumber(lcdNextPos + 2, MENU_CONTENT_TOP + 10, reusableBuffer.spectrumAnalyser.span/1000000, attr);
|
||||
lcdDrawText(lcdNextPos + 2, MENU_CONTENT_TOP + 10, "MHz", 0);
|
||||
if (attr) {
|
||||
reusableBuffer.spectrumAnalyser.span = checkIncDec(event, span, 1, 80, 0) * 1000000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t peak_y = 1;
|
||||
uint8_t peak_x = 0;
|
||||
for (coord_t i=0; i<LCD_W; i++) {
|
||||
uint8_t h = min<uint8_t >(reusableBuffer.spectrumAnalyser.bars[i] >> 1, 128);
|
||||
if (h > peak_y) {
|
||||
peak_x = i;
|
||||
peak_y = h;
|
||||
}
|
||||
lcdDrawSolidVerticalLine(i, LCD_H - h, h, TEXT_COLOR);
|
||||
}
|
||||
|
||||
int8_t y = max<int8_t>(FH, LCD_H - peak_y - FH);
|
||||
lcdDrawNumber(min<uint8_t>(100, peak_x), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / 128)) / 1000000, TINSIZE);
|
||||
lcdDrawText(lcdNextPos, y, "M", TINSIZE);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* 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 "opentx.h"
|
||||
|
||||
extern uint8_t g_moduleIdx;
|
||||
|
||||
void addRadioTool(uint8_t index, const char * label, bool (* tool)(event_t), uint8_t module)
|
||||
{
|
||||
int8_t sub = menuVerticalPosition;
|
||||
LcdFlags attr = (sub == index ? INVERS : 0);
|
||||
coord_t y = MENU_CONTENT_TOP + index * FH;
|
||||
lcdDrawNumber(3, y, index + 1, LEADING0|LEFT, 2);
|
||||
lcdDrawText(30, y, label, (sub == index ? INVERS : 0));
|
||||
if (attr && s_editMode > 0) {
|
||||
s_editMode = 0;
|
||||
g_moduleIdx = module;
|
||||
pushMenu(tool);
|
||||
}
|
||||
}
|
||||
|
||||
bool menuRadioTools(event_t event)
|
||||
{
|
||||
uint8_t spectrum_modules = 0, power_modules = 0;
|
||||
|
||||
if (event == EVT_ENTRY || event == EVT_ENTRY_UP) {
|
||||
memclear(&reusableBuffer.hardwareAndSettings, sizeof(reusableBuffer.hardwareAndSettings));
|
||||
|
||||
for (uint8_t module = 0; module < NUM_MODULES; module++) {
|
||||
if (isModulePXX2(module) && (module == INTERNAL_MODULE ? IS_INTERNAL_MODULE_ON() : IS_EXTERNAL_MODULE_ON())) {
|
||||
moduleState[module].readModuleInformation(&reusableBuffer.hardwareAndSettings.modules[module], PXX2_HW_INFO_TX_ID, PXX2_HW_INFO_TX_ID);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (uint8_t module = 0; module < NUM_MODULES; module++) {
|
||||
if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[module].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) {
|
||||
spectrum_modules++;
|
||||
}
|
||||
if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[module].information.modelID, MODULE_OPTION_POWER_METER)) {
|
||||
power_modules++;
|
||||
}
|
||||
}
|
||||
|
||||
MENU(STR_MENUTOOLS, RADIO_ICONS, menuTabGeneral, MENU_RADIO_TOOLS, spectrum_modules + power_modules, {0,0,0,0});
|
||||
|
||||
|
||||
uint8_t menu_index = 0;
|
||||
|
||||
if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
|
||||
addRadioTool(menu_index++, "Spectrum (INT)", menuRadioSpectrumAnalyser, INTERNAL_MODULE);
|
||||
|
||||
if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
|
||||
addRadioTool(menu_index++, "Power Meter (INT)", menuRadioPowerMeter, INTERNAL_MODULE);
|
||||
|
||||
if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER))
|
||||
addRadioTool(menu_index++, "Spectrum (EXT)", menuRadioSpectrumAnalyser, EXTERNAL_MODULE);
|
||||
|
||||
if (isModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].information.modelID, MODULE_OPTION_POWER_METER))
|
||||
addRadioTool(menu_index++, "Power Meter (EXT)", menuRadioPowerMeter, EXTERNAL_MODULE);
|
||||
|
||||
}
|
||||
@@ -93,3 +93,29 @@ void runFatalErrorScreen(const char * message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawPower(coord_t x, coord_t y, int8_t dBm, LcdFlags att)
|
||||
{
|
||||
float power_W_PREC1 = pow(10.0, (dBm - 30.0) / 10.0) * 10;
|
||||
if (dBm >= 30) {
|
||||
lcdDrawNumber(x, y, power_W_PREC1, PREC1 | att);
|
||||
lcdDrawText(lcdNextPos, y, "W", att);
|
||||
}
|
||||
else if (dBm < 10) {
|
||||
uint16_t power_MW_PREC1 = round(power_W_PREC1 * 1000);
|
||||
lcdDrawNumber(x, y, power_MW_PREC1, PREC1 | att);
|
||||
lcdDrawText(lcdNextPos, y, "mW", att);
|
||||
}
|
||||
else {
|
||||
uint16_t power_MW = round(power_W_PREC1 * 100);
|
||||
if (power_MW >= 50) {
|
||||
power_MW = (power_MW / 5) * 5;
|
||||
lcdDrawNumber(x, y, power_MW, att);
|
||||
lcdDrawText(lcdNextPos, y, "mW", att);
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(x, y, power_MW, att);
|
||||
lcdDrawText(lcdNextPos, y, "mW", att);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,9 @@ set(GUI_SRC
|
||||
bitmaps.cpp
|
||||
radio_sdmanager.cpp
|
||||
radio_hardware.cpp
|
||||
radio_power_meter.cpp
|
||||
radio_spectrum_analyser.cpp
|
||||
radio_tools.cpp
|
||||
model_inputs.cpp
|
||||
model_mixes.cpp
|
||||
model_curves.cpp
|
||||
|
||||
Reference in New Issue
Block a user