2.4 continued (#8092)
Quite a bit of work on 2.4 Co-authored-by: 3djc <Th1sisfmyofmyo>
This commit is contained in:
co-authored by
3djc <Th1sisfmyofmyo>
parent
cd6aa7af00
commit
87cd9047b1
@@ -193,7 +193,12 @@ if(NOT LUA STREQUAL NO)
|
||||
if(LUA STREQUAL YES)
|
||||
add_definitions(-DLUA_MODEL_SCRIPTS)
|
||||
endif()
|
||||
set(SRC ${SRC} lua/interface.cpp lua/api_general.cpp lua/api_lcd.cpp lua/api_model.cpp)
|
||||
set(SRC ${SRC} lua/interface.cpp lua/api_general.cpp lua/api_model.cpp lua/widgets.cpp)
|
||||
if(GUI_DIR STREQUAL colorlcd)
|
||||
set(SRC ${SRC} lua/api_colorlcd.cpp)
|
||||
else()
|
||||
set(SRC ${SRC} lua/api_stdlcd.cpp)
|
||||
endif()
|
||||
set(LUA_SRC lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c
|
||||
lstate.c lstring.c ltable.c lrotable.c ltm.c lundump.c lvm.c lzio.c linit.c
|
||||
lbaselib.c lmathlib.c lbitlib.c loadlib.c lauxlib.c ltablib.c lcorolib.c liolib.c lstrlib.c
|
||||
|
||||
@@ -199,7 +199,7 @@ enum TrainerMode {
|
||||
TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE,
|
||||
TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE,
|
||||
#endif
|
||||
#if defined(PCBTARANIS) || defined(AUX_SERIAL)
|
||||
#if defined(PCBTARANIS) || defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
TRAINER_MODE_MASTER_BATTERY_COMPARTMENT,
|
||||
#endif
|
||||
TRAINER_MODE_MASTER_BLUETOOTH,
|
||||
|
||||
+14
-4
@@ -543,7 +543,9 @@ typedef uint8_t swarnenable_t;
|
||||
swarnenable_t switchWarningEnable; // TODO remove it in 2.4
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
#if defined(COLORLCD) && defined(BACKUP)
|
||||
#define CUSTOM_SCREENS_DATA
|
||||
#elif defined(COLORLCD)
|
||||
#include "gui/colorlcd/layout.h"
|
||||
#include "gui/colorlcd/topbar.h"
|
||||
#define LAYOUT_NAME_LEN 10
|
||||
@@ -553,7 +555,7 @@ PACK(struct CustomScreenData {
|
||||
});
|
||||
#define CUSTOM_SCREENS_DATA \
|
||||
NOBACKUP(CustomScreenData screenData[MAX_CUSTOM_SCREENS]); \
|
||||
NOBACKUP(Topbar::PersistentData topbarData); \
|
||||
NOBACKUP(TopBar::PersistentData topbarData); \
|
||||
NOBACKUP(uint8_t view);
|
||||
#else
|
||||
#define CUSTOM_SCREENS_DATA \
|
||||
@@ -639,6 +641,14 @@ PACK(struct ModelData {
|
||||
|
||||
char modelRegistrationID[PXX2_LEN_REGISTRATION_ID];
|
||||
|
||||
bool isTrainerTraineeEnable() const
|
||||
{
|
||||
#if defined(PCBNV14)
|
||||
return trainerData.mode >= TRAINER_MODE_MASTER_TRAINER_JACK;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t getThrottleStickTrimSource() const
|
||||
{
|
||||
@@ -748,7 +758,7 @@ PACK(struct TrainerData {
|
||||
#define THEME_NAME_LEN 8
|
||||
#define THEME_DATA \
|
||||
NOBACKUP(char themeName[THEME_NAME_LEN]); \
|
||||
NOBACKUP(ThemeBase::PersistentData themeData);
|
||||
NOBACKUP(OpenTxTheme::PersistentData themeData);
|
||||
#else
|
||||
#define THEME_DATA
|
||||
#endif
|
||||
@@ -909,7 +919,7 @@ static inline void check_struct()
|
||||
CHKSIZE(ModelHeader, 31);
|
||||
CHKSIZE(CurveHeader, 4);
|
||||
CHKSIZE(CustomScreenData, 850);
|
||||
CHKSIZE(Topbar::PersistentData, 300);
|
||||
CHKSIZE(TopBar::PersistentData, 300);
|
||||
#elif defined(PCBNV14)
|
||||
// TODO
|
||||
#elif defined(PCBSKY9X)
|
||||
|
||||
@@ -26,6 +26,6 @@ add_truetype_font_target(17en 17 en none)
|
||||
add_truetype_font_target(bold17 17 ${subset} bold)
|
||||
add_truetype_font_target(24 24 ${subset} none)
|
||||
add_truetype_font_target(32 32 ${subset} bold)
|
||||
add_truetype_font_target(64 64 ${subset} bold)
|
||||
add_truetype_font_target(64 64 en bold)
|
||||
|
||||
add_custom_target(truetype_fonts DEPENDS ${truetype_fonts_targets})
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
+10
-1
@@ -359,9 +359,18 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext
|
||||
|
||||
case FUNC_BACKLIGHT:
|
||||
{
|
||||
newActiveFunctions |= (1u << FUNCTION_BACKLIGHT);
|
||||
if (!CFN_PARAM(cfn)) { // When no source is set, backlight works like original backlight and turn on regardless of backlight settings
|
||||
requiredBacklightBright = BACKLIGHT_FORCED_ON;
|
||||
break;
|
||||
}
|
||||
|
||||
getvalue_t raw = getValue(CFN_PARAM(cfn));
|
||||
#if defined(COLORLCD)
|
||||
requiredBacklightBright = (1024 - raw) * (BACKLIGHT_LEVEL_MAX - BACKLIGHT_LEVEL_MIN) / 2048;
|
||||
if (raw == -1024)
|
||||
requiredBacklightBright = 100;
|
||||
else
|
||||
requiredBacklightBright = (1024 - raw) * (BACKLIGHT_LEVEL_MAX - BACKLIGHT_LEVEL_MIN) / 2048;
|
||||
#else
|
||||
requiredBacklightBright = (1024 - raw) * 100 / 2048;
|
||||
#endif
|
||||
|
||||
@@ -649,26 +649,33 @@ void menuMainView(event_t event)
|
||||
drawSwitch(x, y, sw, 0, false);
|
||||
}
|
||||
}
|
||||
#elif defined(PCBTANGO) || defined(PCBMAMBO)
|
||||
//TODO : move switchReOrder definition in board.h and define SWITCHES_REORDER
|
||||
static const uint8_t switchReOrder[] = {0, 1, 5, 3, 2, 4};
|
||||
|
||||
#elif defined(PCBTANGO)
|
||||
int sw_i;
|
||||
for (int i = 0; i < NUM_SWITCHES; ++i) {
|
||||
if (SWITCH_EXISTS(i)) {
|
||||
#if defined(LCD_H >= 96)
|
||||
uint8_t x = 2 * FW - 2, y = 4 * FH + i * FH + 20;
|
||||
#else
|
||||
uint8_t x = 2 * FW - 2, y = 4 * FH + i * FH + 1;
|
||||
#endif
|
||||
if (i >= NUM_SWITCHES / 2) {
|
||||
x = 16 * FW + 6;
|
||||
y -= (NUM_SWITCHES / 2) * FH;
|
||||
}
|
||||
//TDOD : move switchesReorder definition in board.h
|
||||
static const uint8_t switchesReorder[] = {0, 1, 5, 3, 2, 4};
|
||||
|
||||
#if defined(SWITCHES_REORDER)
|
||||
// re-arrange order according to physical layout
|
||||
i = switchReOrder[i];
|
||||
#endif
|
||||
i = switchesReorder[i];
|
||||
getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + sw_i);
|
||||
getvalue_t sw = ((val < 0) ? 3 * sw_i + 1 : ((val == 0) ? 3 * sw_i + 2 : 3 * sw_i + 3));
|
||||
drawSwitch(x, y, sw, 0);
|
||||
}
|
||||
}
|
||||
#elif defined(PCBMAMBO)
|
||||
for (int i = 0; i < NUM_SWITCHES; ++i) {
|
||||
if (SWITCH_EXISTS(i)) {
|
||||
uint8_t x = 2 * FW - 2, y = 4 * FH + i * FH + 1;
|
||||
if (i >= NUM_SWITCHES / 2) {
|
||||
x = 16 * FW + 6;
|
||||
y -= (NUM_SWITCHES / 2) * FH;
|
||||
}
|
||||
getvalue_t val = getValue(MIXSRC_FIRST_SWITCH + i);
|
||||
getvalue_t sw = ((val < 0) ? 3 * i + 1 : ((val == 0) ? 3 * i + 2 : 3 * i + 3));
|
||||
drawSwitch(x, y, sw, 0);
|
||||
|
||||
@@ -177,34 +177,34 @@ void getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags)
|
||||
if (fontsize == DBLSIZE) {
|
||||
pattern->width = 10;
|
||||
pattern->height = 16;
|
||||
if (c >= 0xC0) {
|
||||
pattern->data = &font_10x14_extra[((uint16_t)(c-0xC0))*20];
|
||||
if (c >= 0x80) {
|
||||
pattern->data = &font_10x14_extra[((uint16_t) (c - 0x80)) * 20];
|
||||
}
|
||||
else {
|
||||
if (c >= 128)
|
||||
if (c >= 0x80)
|
||||
c_remapped = c - 60;
|
||||
pattern->data = &font_10x14[((uint16_t)c_remapped)*20];
|
||||
pattern->data = &font_10x14[((uint16_t) c_remapped) * 20];
|
||||
}
|
||||
}
|
||||
else if (fontsize == XXLSIZE) {
|
||||
pattern->width = 22;
|
||||
pattern->height = 38;
|
||||
pattern->data = &font_22x38_num[((uint16_t)c-'0'+5)*110];
|
||||
pattern->data = &font_22x38_num[((uint16_t) c - '0' + 5) * 110];
|
||||
}
|
||||
else if (fontsize == MIDSIZE) {
|
||||
pattern->width = 8;
|
||||
pattern->height = 12;
|
||||
pattern->data = &font_8x10[((uint16_t)c-0x20)*16];
|
||||
pattern->data = &font_8x10[((uint16_t) c - 0x20) * 16];
|
||||
}
|
||||
else if (fontsize == SMLSIZE) {
|
||||
pattern->width = 5;
|
||||
pattern->height = 6;
|
||||
pattern->data = (c < 0xc0 ? &font_4x6[(c-0x20)*5] : &font_4x6_extra[(c-0xc0)*5]);
|
||||
pattern->data = (c < 0x80 ? &font_4x6[(c - 0x20) * 5] : &font_4x6_extra[(c - 0x80) * 5]);
|
||||
}
|
||||
else if (fontsize == TINSIZE) {
|
||||
pattern->width = 3;
|
||||
pattern->height = 5;
|
||||
pattern->data = &font_3x5[((uint16_t)c-0x20)*3];
|
||||
pattern->data = &font_3x5[((uint16_t) c - 0x20) * 3];
|
||||
}
|
||||
else if (flags & BOLD) {
|
||||
pattern->width = 5;
|
||||
@@ -214,7 +214,7 @@ void getCharPattern(PatternData * pattern, unsigned char c, LcdFlags flags)
|
||||
else {
|
||||
pattern->width = 5;
|
||||
pattern->height = 7;
|
||||
pattern->data = (c < 0x80) ? &font_5x7[(c-0x20)*5] : &font_5x7_extra[(c-0x80)*5];
|
||||
pattern->data = (c < 0x80) ? &font_5x7[(c - 0x20) * 5] : &font_5x7_extra[(c - 0x80) * 5];
|
||||
}
|
||||
#else
|
||||
pattern->width = 5;
|
||||
@@ -232,7 +232,7 @@ uint8_t getCharWidth(char c, LcdFlags flags)
|
||||
|
||||
void lcdDrawChar(coord_t x, coord_t y, char c, LcdFlags flags)
|
||||
{
|
||||
lcdNextPos = x-1;
|
||||
lcdNextPos = x - 1;
|
||||
#if defined(BOOT)
|
||||
const uint8_t * data = &font_5x7[(c-0x20)*5];
|
||||
lcdPutPattern(x, y, data, 5, 7, flags);
|
||||
@@ -852,7 +852,8 @@ void lcdMaskPoint(uint8_t *p, uint8_t mask, LcdFlags att)
|
||||
|
||||
void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att)
|
||||
{
|
||||
if (lcdIsPointOutside(x, y)) return;
|
||||
if (lcdIsPointOutside(x, y))
|
||||
return;
|
||||
uint8_t *p = &displayBuf[ y / 2 * LCD_W + x ];
|
||||
uint8_t mask = PIXEL_GREY_MASK(y, att);
|
||||
lcdMaskPoint(p, mask, att);
|
||||
|
||||
@@ -20,14 +20,12 @@ set(GUI_SRC
|
||||
tabsgroup.cpp
|
||||
page.cpp
|
||||
fab_button.cpp
|
||||
# topbar.cpp
|
||||
topbar.cpp
|
||||
layout.cpp
|
||||
widget.cpp
|
||||
${THEMES_SRC}
|
||||
${LAYOUTS_SRC}
|
||||
# ${WIDGETS_SRC}
|
||||
widgets/text.cpp
|
||||
widgets/value.cpp
|
||||
${WIDGETS_SRC}
|
||||
# popups.cpp
|
||||
draw_functions.cpp
|
||||
# menus.cpp
|
||||
@@ -54,11 +52,12 @@ set(GUI_SRC
|
||||
radio_diaganas.cpp
|
||||
radio_calibration.cpp
|
||||
view_main.cpp
|
||||
view_channels.cpp
|
||||
view_logical_switches.cpp
|
||||
view_statistics.cpp
|
||||
menu_screen.cpp
|
||||
screen_setup.cpp
|
||||
switch_warn_dialog.cpp
|
||||
|
||||
# view_statistics.cpp
|
||||
)
|
||||
|
||||
macro(add_gui_src src)
|
||||
@@ -81,7 +80,7 @@ if(PXX2 OR MULTIMODULE)
|
||||
endif()
|
||||
|
||||
if(LUA STREQUAL YES)
|
||||
# TODO set(SRC ${SRC} lua/widgets.cpp)
|
||||
set(SRC ${SRC} lua/widgets.cpp)
|
||||
# TODO set(GUI_SRC ${GUI_SRC} model_custom_scripts.cpp)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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 width()ill be useful,
|
||||
* but WITHOUT ANY WARRANTY; width()ithout even the implied width()arranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
|
||||
constexpr coord_t ROW_HEIGHT = 42;
|
||||
constexpr coord_t BAR_HEIGHT = 13;
|
||||
constexpr coord_t COLUMN_SIZE = 200;
|
||||
constexpr coord_t X_OFFSET = 25;
|
||||
constexpr coord_t LEG_COLORBOX = 15;
|
||||
|
||||
#define VIEW_CHANNELS_LIMIT_PCT (g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100)
|
||||
|
||||
class ChannelBar : public Window
|
||||
{
|
||||
public:
|
||||
ChannelBar(Window * parent, const rect_t & rect, uint8_t channel):
|
||||
Window(parent, rect),
|
||||
channel(channel)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t channel = 0;
|
||||
};
|
||||
|
||||
class MixerChannelBar : public ChannelBar
|
||||
{
|
||||
public:
|
||||
using ChannelBar::ChannelBar;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
int chanVal = calcRESXto100(ex_chans[channel]);
|
||||
const int displayVal = chanVal;
|
||||
|
||||
// this could be handled nicer, but slower, by checking actual range for this mixer
|
||||
chanVal = limit<int>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
// Draw Background
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), BARGRAPH_BGCOLOR);
|
||||
|
||||
// Draw mixer bar
|
||||
if (chanVal > 0) {
|
||||
dc->drawSolidFilledRect(0 + width() / 2, 0, divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), height(), BARGRAPH2_COLOR);
|
||||
dc->drawNumber(width() / 2 - 10, 0, displayVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
const unsigned endpoint = width() / 2;
|
||||
const unsigned size = divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
dc->drawSolidFilledRect(endpoint - size, 0, size, height(), BARGRAPH2_COLOR);
|
||||
dc->drawNumber(10 + width() / 2, 0, displayVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
|
||||
}
|
||||
|
||||
// Draw middle bar
|
||||
dc->drawSolidVerticalLine(width() / 2, 0, height(), DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Window::checkEvents();
|
||||
int newValue = ex_chans[channel];
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
class OutputChannelBar : public ChannelBar
|
||||
{
|
||||
public:
|
||||
using ChannelBar::ChannelBar;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
int chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
int displayVal = chanVal;
|
||||
|
||||
chanVal = limit<int>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
// Draw Background
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), BARGRAPH_BGCOLOR);
|
||||
|
||||
// Draw output bar
|
||||
if (chanVal > 0) {
|
||||
dc->drawSolidFilledRect(width() / 2, 0, divRoundClosest(chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2), height(), BARGRAPH1_COLOR);
|
||||
dc->drawNumber(width() / 2 - 10, 0, displayVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
unsigned endpoint = width() / 2;
|
||||
unsigned size = divRoundClosest(-chanVal * width(), VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
dc->drawSolidFilledRect(endpoint - size, 0, size, height(), BARGRAPH1_COLOR);
|
||||
dc->drawNumber(width() / 2 + 10, 0, displayVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
|
||||
}
|
||||
|
||||
// Draw middle bar
|
||||
dc->drawSolidVerticalLine(width() / 2, 0, height(), DEFAULT_COLOR);
|
||||
|
||||
// Draw output limits bars
|
||||
LimitData * ld = limitAddress(channel);
|
||||
if (ld && ld->revert) {
|
||||
drawOutputBarLimits(dc, posOnBar(-100 - ld->max / 10), posOnBar(100 - ld->min / 10));
|
||||
//lcd->drawBitmap(x - X_OFFSET + 7, y + 25, chanMonInvertedBitmap);
|
||||
}
|
||||
else if (ld) {
|
||||
drawOutputBarLimits(dc, posOnBar(-100 + ld->min / 10), posOnBar(100 + ld->max / 10));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline unsigned posOnBar(int value_to100)
|
||||
{
|
||||
return divRoundClosest((value_to100 + VIEW_CHANNELS_LIMIT_PCT) * (width() - 1), VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
}
|
||||
|
||||
void drawOutputBarLimits(BitmapBuffer * dc, coord_t left, coord_t right)
|
||||
{
|
||||
dc->drawSolidVerticalLine(left, 0, BAR_HEIGHT, DEFAULT_COLOR);
|
||||
dc->drawSolidHorizontalLine(left, 0, 3, DEFAULT_COLOR);
|
||||
dc->drawSolidHorizontalLine(left, BAR_HEIGHT - 1, 3, DEFAULT_COLOR);
|
||||
|
||||
dc->drawSolidVerticalLine(right, 0, BAR_HEIGHT, DEFAULT_COLOR);
|
||||
dc->drawSolidHorizontalLine(right - 3, 0, 3, DEFAULT_COLOR);
|
||||
dc->drawSolidHorizontalLine(right - 3, BAR_HEIGHT - 1, 3, DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Window::checkEvents();
|
||||
int newValue = channelOutputs[channel];
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
constexpr coord_t lmargin = 25;
|
||||
|
||||
class ComboChannelBar : public ChannelBar
|
||||
{
|
||||
public:
|
||||
using ChannelBar::ChannelBar;
|
||||
ComboChannelBar(Window * parent, const rect_t & rect, uint8_t channel):
|
||||
ChannelBar(parent, rect, channel)
|
||||
{
|
||||
new OutputChannelBar(this, {lmargin, BAR_HEIGHT, width() - lmargin, BAR_HEIGHT}, channel);
|
||||
new MixerChannelBar(this, {lmargin, 2 * BAR_HEIGHT + 1, width() - lmargin, BAR_HEIGHT}, channel);
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
char chanString[] = "CH32 ";
|
||||
int usValue = PPM_CH_CENTER(channel) + channelOutputs[channel] / 2;
|
||||
|
||||
// Channel number
|
||||
strAppendSigned(&chanString[2], channel + 1, 2);
|
||||
dc->drawText(lmargin, 0, chanString, FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
|
||||
// Channel name
|
||||
dc->drawSizedText(lmargin + 45, 0, g_model.limitData[channel].name, sizeof(g_model.limitData[channel].name), FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
|
||||
// Channel value in µS
|
||||
dc->drawNumber(width(), 0, usValue, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, STR_US);
|
||||
|
||||
// Override icon
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED)
|
||||
dc->drawBitmap(0, 1, chanMonLockedBitmap);
|
||||
#endif
|
||||
|
||||
// Channel reverted icon
|
||||
LimitData * ld = limitAddress(channel);
|
||||
if (ld && ld->revert) {
|
||||
lcd->drawBitmap(0, 20, chanMonInvertedBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Window::checkEvents();
|
||||
int newValue = channelOutputs[channel];
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
int value = 0;
|
||||
};
|
||||
@@ -43,12 +43,12 @@
|
||||
#define TEXT_STATUSBAR_COLOR COLOR(TEXT_STATUSBAR_COLOR_INDEX)
|
||||
#define LINE_COLOR COLOR(LINE_COLOR_INDEX)
|
||||
#define HEADER_SEPARATOR_COLOR COLOR(HEADER_SEPARATOR_COLOR_INDEX)
|
||||
#define MENU_BGCOLOR COLOR(MENU_BGCOLOR_INDEX)
|
||||
#define MENU_COLOR COLOR(MENU_COLOR_INDEX)
|
||||
#define MENU_BGCOLOR COLOR(MENU_BGCOLOR_INDEX)
|
||||
#define MENU_COLOR COLOR(MENU_COLOR_INDEX)
|
||||
#define MENU_TITLE_DISABLE_COLOR COLOR(MENU_TITLE_DISABLE_COLOR_INDEX)
|
||||
#define HEADER_COLOR COLOR(HEADER_COLOR_INDEX)
|
||||
#define ALARM_COLOR COLOR(ALARM_COLOR_INDEX)
|
||||
#define HIGHLIGHT_COLOR COLOR(HIGHLIGHT_COLOR_INDEX)
|
||||
#define HIGHLIGHT_COLOR COLOR(HIGHLIGHT_COLOR_INDEX)
|
||||
#define TEXT_DISABLE_COLOR COLOR(TEXT_DISABLE_COLOR_INDEX)
|
||||
#define CURVE_COLOR COLOR(CURVE_COLOR_INDEX)
|
||||
#define CURVE_CURSOR_COLOR COLOR(CURVE_CURSOR_COLOR_INDEX)
|
||||
|
||||
@@ -22,8 +22,70 @@
|
||||
#include "keyboard_curve.h"
|
||||
#include "opentx.h" // TODO for applyCustomCurve
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
CurveDataEdit::CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index) :
|
||||
FormGroup(parent, rect, FORM_FORWARD_FOCUS),
|
||||
index(index)
|
||||
{
|
||||
update();
|
||||
}
|
||||
|
||||
void CurveDataEdit::update()
|
||||
{
|
||||
clear();
|
||||
|
||||
FormGridLayout grid;
|
||||
grid.setLabelWidth(0);
|
||||
grid.setMarginRight(parent->width() - rect.w + 5);
|
||||
|
||||
coord_t boxWidth = rect.w / 5;
|
||||
coord_t boxHeight = (rect.h - 6) / 3;
|
||||
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
uint8_t curvePointsCount = 5 + curve.points;
|
||||
|
||||
// Point number
|
||||
for (uint8_t i = 0; i < curvePointsCount; i++) {
|
||||
new StaticText(this, {i * boxWidth, 10, boxWidth, boxHeight}, std::to_string(i + 1), 0, RIGHT | TEXT_DISABLE_COLOR);
|
||||
}
|
||||
grid.spacer(rect.h / 3);
|
||||
|
||||
// x value
|
||||
for (uint8_t i = 0; i < curvePointsCount; i++) {
|
||||
new StaticText(this, {i * boxWidth, 10 + boxHeight, boxWidth, boxHeight}, std::to_string(-100 + 200 * i / (5 + curve.points - 1)), 0, RIGHT | TEXT_DISABLE_COLOR);
|
||||
}
|
||||
|
||||
// y value
|
||||
for (uint8_t i = 0; i < curvePointsCount; i++) {
|
||||
int8_t * points = curveAddress(index);
|
||||
new NumberEdit(this, {coord_t(PAGE_LINE_SPACING + 1 + i * boxWidth), 10 + 2 * boxHeight, coord_t(boxWidth - PAGE_LINE_SPACING), boxHeight - 12}, -100, 100, GET_SET_DEFAULT(points[i]), 0, RIGHT);
|
||||
}
|
||||
|
||||
setInnerWidth(curvePointsCount * boxWidth);
|
||||
}
|
||||
|
||||
void CurveDataEdit::checkEvents()
|
||||
{
|
||||
Window::checkEvents();
|
||||
CurveHeader & curve = g_model.curves[index];
|
||||
uint8_t newValue = 5 + curve.points;
|
||||
if (previousCurvePointsCount != newValue) {
|
||||
previousCurvePointsCount = newValue;
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveDataEdit::paint(BitmapBuffer * dc)
|
||||
{
|
||||
dc->clear(DEFAULT_BGCOLOR);
|
||||
dc->drawSolidHorizontalLine(0, rect.h / 3, getInnerWidth(), 0);
|
||||
dc->drawSolidHorizontalLine(0, 2 * rect.h / 3, getInnerWidth(), 0);
|
||||
drawHorizontalScrollbar(dc);
|
||||
}
|
||||
|
||||
CurveEdit::CurveEdit(Window * parent, const rect_t & rect, uint8_t index) :
|
||||
FormField(parent, rect),
|
||||
FormField(parent, rect, NO_FOCUS),
|
||||
preview(this, {0, 0, width(), height()}, [=](int x) -> int {
|
||||
return applyCustomCurve(x, index);
|
||||
}),
|
||||
|
||||
@@ -24,6 +24,24 @@
|
||||
#include "form.h"
|
||||
#include "curve.h"
|
||||
|
||||
class CurveDataEdit : public FormGroup
|
||||
{
|
||||
friend class CurveEdit;
|
||||
|
||||
public:
|
||||
CurveDataEdit(Window * parent, const rect_t & rect, uint8_t index);
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
void checkEvents() override;
|
||||
|
||||
void update();
|
||||
|
||||
protected:
|
||||
uint8_t index;
|
||||
uint8_t previousCurvePointsCount;
|
||||
};
|
||||
|
||||
class CurveEdit: public FormField {
|
||||
public:
|
||||
CurveEdit(Window * parent, const rect_t & rect, uint8_t index);
|
||||
|
||||
@@ -48,127 +48,10 @@ void drawVerticalScrollbar(BitmapBuffer * dc, coord_t x, coord_t y, coord_t h, u
|
||||
}
|
||||
}
|
||||
|
||||
void drawTrimSquare(BitmapBuffer * dc, coord_t x, coord_t y)
|
||||
void drawTrimSquare(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags color)
|
||||
{
|
||||
dc->drawSolidFilledRect(x-2, y, 15, 15, TRIM_BGCOLOR);
|
||||
dc->drawBitmapPattern(x-2, y, LBM_TRIM_SHADOW, TRIM_SHADOW_COLOR);
|
||||
}
|
||||
|
||||
void drawHorizontalTrimPosition(BitmapBuffer * dc, coord_t x, coord_t y, int16_t dir)
|
||||
{
|
||||
drawTrimSquare(dc, x, y);
|
||||
if (dir >= 0) {
|
||||
dc->drawSolidVerticalLine(x+8, y+3, 9, FOCUS_COLOR);
|
||||
}
|
||||
if (dir <= 0) {
|
||||
dc->drawSolidVerticalLine(x+2, y+3, 9, FOCUS_COLOR);
|
||||
}
|
||||
// if (exttrim) {
|
||||
// lcdDrawSolidVerticalLine(xm, ym, 9, FOCUS_COLOR);
|
||||
// }
|
||||
}
|
||||
|
||||
void drawVerticalTrimPosition(BitmapBuffer * dc, coord_t x, coord_t y, int16_t dir)
|
||||
{
|
||||
drawTrimSquare(dc, x, y);
|
||||
if (dir >= 0) {
|
||||
dc->drawSolidHorizontalLine(x+1, y+4, 9, FOCUS_COLOR);
|
||||
}
|
||||
if (dir <= 0) {
|
||||
dc->drawSolidHorizontalLine(x+1, y+10, 9, FOCUS_COLOR);
|
||||
}
|
||||
// if (exttrim) {
|
||||
// lcdDrawSolidHorizontalLine(xm-1, ym, 3, FOCUS_COLOR);
|
||||
// }
|
||||
}
|
||||
|
||||
void drawVerticalSlider(BitmapBuffer * dc, coord_t x, coord_t y, int len, int val, int min, int max, uint8_t steps, uint32_t options)
|
||||
{
|
||||
val = limit(min, val, max);
|
||||
if (steps) {
|
||||
int delta = len / steps;
|
||||
for (int i = 0; i <= len; i += delta) {
|
||||
if ((options & OPTION_SLIDER_BIG_TICKS) && (i == 0 || i == len / 2 || i == len))
|
||||
dc->drawSolidHorizontalLine(x, y + i, 13, DEFAULT_COLOR);
|
||||
else
|
||||
dc->drawSolidHorizontalLine(x + 2, y + i, 9, DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dc->drawBitmapPattern(x + 1, y, LBM_VTRIM_FRAME, DEFAULT_COLOR);
|
||||
/* if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && trim != 0) {
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<<i)))) {
|
||||
lcdDrawNumber((stickIndex==0 ? TRIM_LH_X : TRIM_RH_X)+(trim>0 ? -20 : 50), ym+1, trim, TINSIZE);
|
||||
}
|
||||
} */
|
||||
}
|
||||
y += len - divRoundClosest(len * (val - min), max - min) - 5;
|
||||
if (options & OPTION_SLIDER_TRIM_BUTTON) {
|
||||
drawVerticalTrimPosition(dc, x, y - 2, val);
|
||||
}
|
||||
else if (options & OPTION_SLIDER_NUMBER_BUTTON) {
|
||||
drawTrimSquare(dc, x, y - 2);
|
||||
// TODO lcdDrawChar(x + 2, y - 1, '0' + val, FONT(XS) | FOCUS_COLOR);
|
||||
}
|
||||
else {
|
||||
drawTrimSquare(dc, x, y - 2);
|
||||
}
|
||||
}
|
||||
|
||||
void drawHorizontalSlider(BitmapBuffer * dc, coord_t x, coord_t y, int len, int val, int min, int max, uint8_t steps, uint32_t options)
|
||||
{
|
||||
val = limit(min, val, max);
|
||||
int w = divRoundClosest(len * (val - min), max - min);
|
||||
if (options & OPTION_SLIDER_TICKS) {
|
||||
if (steps) {
|
||||
int delta = len / steps;
|
||||
for (int i = 0; i <= len; i += delta) {
|
||||
if ((options & OPTION_SLIDER_BIG_TICKS) && (i == 0 || i == len / 2 || i == len))
|
||||
dc->drawSolidVerticalLine(x + i, y, 13, DEFAULT_COLOR);
|
||||
else
|
||||
dc->drawSolidVerticalLine(x + i, y + 2, 9, DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (options & OPTION_SLIDER_EMPTY_BAR) {
|
||||
dc->drawBitmapPattern(x, y + 1, LBM_HTRIM_FRAME, DEFAULT_COLOR);
|
||||
}
|
||||
else if (options & OPTION_SLIDER_DBL_COLOR) {
|
||||
dc->drawBitmapPattern(x, y + 8, LBM_SLIDER_BAR_LEFT, w <= 0 ? LINE_COLOR : FOCUS_BGCOLOR);
|
||||
if (w > 4)
|
||||
dc->drawSolidFilledRect(x + 4, y + 8, w - 4, 4, FOCUS_BGCOLOR);
|
||||
if (w < len - 4)
|
||||
dc->drawSolidFilledRect(x + w, y + 8, len - w - 4, 4, LINE_COLOR);
|
||||
dc->drawBitmapPattern(x + len - 4, y + 8, LBM_SLIDER_BAR_RIGHT, w >= len ? FOCUS_BGCOLOR : LINE_COLOR);
|
||||
}
|
||||
else {
|
||||
dc->drawBitmapPattern(x, y + 8, LBM_SLIDER_BAR_LEFT, LINE_COLOR);
|
||||
dc->drawSolidFilledRect(x + 4, y + 8, len - 8, 4, LINE_COLOR);
|
||||
dc->drawBitmapPattern(x + len - 4, y + 8, LBM_SLIDER_BAR_RIGHT, LINE_COLOR);
|
||||
//
|
||||
/* if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && trim != 0) {
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<<i)))) {
|
||||
lcdDrawNumber((stickIndex==0 ? TRIM_LH_X : TRIM_RH_X)+(trim>0 ? -20 : 50), ym+1, trim, TINSIZE);
|
||||
}
|
||||
} */
|
||||
}
|
||||
x += w - 5;
|
||||
if (options & OPTION_SLIDER_TRIM_BUTTON) {
|
||||
drawHorizontalTrimPosition(dc, x, y - 1, val);
|
||||
}
|
||||
else if (options & OPTION_SLIDER_NUMBER_BUTTON) {
|
||||
drawTrimSquare(dc, x+2, y - 1);
|
||||
char text[] = { (char)('0' + val), '\0' };
|
||||
dc->drawText(x + 7, y - 1, text, FONT(XS) | CENTERED | FOCUS_COLOR);
|
||||
}
|
||||
else if (options & OPTION_SLIDER_SQUARE_BUTTON) {
|
||||
drawTrimSquare(dc, x, y - 1);
|
||||
}
|
||||
else {
|
||||
dc->drawBitmapPattern(x, y + 2, LBM_SLIDER_POINT_OUT, DEFAULT_COLOR);
|
||||
dc->drawBitmapPattern(x, y + 2, LBM_SLIDER_POINT_MID, DEFAULT_BGCOLOR);
|
||||
dc->drawBitmapPattern(x, y + 2, LBM_SLIDER_POINT_IN, FOCUS_BGCOLOR);
|
||||
}
|
||||
dc->drawSolidFilledRect(x, y, 15, 15, color);
|
||||
dc->drawBitmapPattern(x, y, LBM_TRIM_SHADOW, TRIM_SHADOW_COLOR);
|
||||
}
|
||||
|
||||
void drawGVarValue(BitmapBuffer * dc, coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags)
|
||||
@@ -197,7 +80,7 @@ void drawSleepBitmap()
|
||||
lcd->reset();
|
||||
lcd->clear();
|
||||
|
||||
const BitmapBuffer * bitmap = BitmapBuffer::loadBitmap(static_cast<ThemeBase *>(theme)->getFilePath("sleep.bmp"));
|
||||
const BitmapBuffer * bitmap = BitmapBuffer::loadBitmap(OpenTxTheme::instance()->getFilePath("sleep.bmp"));
|
||||
if (bitmap) {
|
||||
lcd->drawBitmap((LCD_W-bitmap->width())/2, (LCD_H-bitmap->height())/2, bitmap);
|
||||
delete bitmap;
|
||||
@@ -212,13 +95,13 @@ void drawShutdownAnimation(uint32_t duration, uint32_t totalDuration, const char
|
||||
if (totalDuration == 0)
|
||||
return;
|
||||
|
||||
static const BitmapBuffer * shutdown = BitmapBuffer::loadBitmap(static_cast<ThemeBase *>(theme)->getFilePath("shutdown.bmp"));
|
||||
static const BitmapBuffer * shutdown = BitmapBuffer::loadBitmap(OpenTxTheme::instance()->getFilePath("shutdown.bmp"));
|
||||
|
||||
lcdNextLayer();
|
||||
lcd->reset();
|
||||
|
||||
if (shutdown) {
|
||||
static_cast<ThemeBase *>(theme)->drawBackground(lcd);
|
||||
OpenTxTheme::instance()->drawBackground(lcd);
|
||||
lcd->drawBitmap((LCD_W - shutdown->width()) / 2, (LCD_H - shutdown->height()) / 2, shutdown);
|
||||
int quarter = duration / (totalDuration / 5);
|
||||
if (quarter >= 1) lcd->drawBitmapPattern(LCD_W/2, (LCD_H-SHUTDOWN_CIRCLE_DIAMETER)/2, LBM_SHUTDOWN_CIRCLE, DEFAULT_COLOR, 0, SHUTDOWN_CIRCLE_DIAMETER/2);
|
||||
|
||||
@@ -56,7 +56,7 @@ void drawFlightMode(coord_t x, coord_t y, int8_t idx, LcdFlags att);
|
||||
void drawStatusText(BitmapBuffer * dc, const char * text);
|
||||
void drawVerticalScrollbar(BitmapBuffer * dc, coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
|
||||
void drawProgressScreen(BitmapBuffer * dc, const char * title, const char * message, int num, int den);
|
||||
void drawTrimSquare(BitmapBuffer * dc, coord_t x, coord_t y);
|
||||
void drawTrimSquare(BitmapBuffer * dc, coord_t x, coord_t y, LcdFlags color = TRIM_BGCOLOR);
|
||||
void drawHorizontalTrimPosition(BitmapBuffer * dc, coord_t x, coord_t y, int16_t dir);
|
||||
void drawVerticalTrimPosition(BitmapBuffer * dc, coord_t x, coord_t y, int16_t dir);
|
||||
void drawVerticalSlider(BitmapBuffer * dc, coord_t x, coord_t y, int len, int val, int min, int max, uint8_t steps, uint32_t options);
|
||||
|
||||
@@ -22,19 +22,19 @@
|
||||
#include "mainwindow.h"
|
||||
#include "opentx.h"
|
||||
|
||||
FullScreenDialog::FullScreenDialog(uint8_t type, std::string title, std::string message, std::string action, std::function<void(void)> confirmHandler):
|
||||
FullScreenDialog::FullScreenDialog(uint8_t type, std::string title, std::string message, std::string action, const std::function<void(void)> & confirmHandler):
|
||||
FormGroup(&mainWindow, {0, 0, LCD_W, LCD_H}, OPAQUE),
|
||||
type(type),
|
||||
title(std::move(title)),
|
||||
message(std::move(message)),
|
||||
action(std::move(action)),
|
||||
confirmHandler(confirmHandler)
|
||||
#if !defined(HARDWARE_TOUCH)
|
||||
#if defined(HARDWARE_KEYS)
|
||||
, previousFocus(focusWindow)
|
||||
#endif
|
||||
{
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
new FabButton(this, LCD_W - 50, ALERT_BUTTON_TOP, ICON_NEXT,
|
||||
new FabButton(this, LCD_W - 50, LCD_H - 50, ICON_NEXT,
|
||||
[=]() -> uint8_t {
|
||||
if (confirmHandler)
|
||||
confirmHandler();
|
||||
@@ -47,16 +47,16 @@ FullScreenDialog::FullScreenDialog(uint8_t type, std::string title, std::string
|
||||
|
||||
void FullScreenDialog::paint(BitmapBuffer * dc)
|
||||
{
|
||||
static_cast<ThemeBase *>(theme)->drawBackground(dc);
|
||||
OpenTxTheme::instance()->drawBackground(dc);
|
||||
|
||||
dc->drawFilledRect(0, ALERT_FRAME_TOP, LCD_W, ALERT_FRAME_HEIGHT, SOLID, FOCUS_COLOR | OPACITY(8));
|
||||
|
||||
if (type == WARNING_TYPE_ALERT || type == WARNING_TYPE_ASTERISK)
|
||||
dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, static_cast<ThemeBase *>(theme)->asterisk);
|
||||
dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->asterisk);
|
||||
else if (type == WARNING_TYPE_INFO)
|
||||
dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, static_cast<ThemeBase *>(theme)->busy);
|
||||
dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->busy);
|
||||
else // confirmation
|
||||
dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, static_cast<ThemeBase *>(theme)->question);
|
||||
dc->drawBitmap(ALERT_BITMAP_LEFT, ALERT_BITMAP_TOP, OpenTxTheme::instance()->question);
|
||||
|
||||
if (type == WARNING_TYPE_ALERT) {
|
||||
#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ)
|
||||
@@ -113,9 +113,9 @@ void FullScreenDialog::checkEvents()
|
||||
}
|
||||
}
|
||||
|
||||
void FullScreenDialog::deleteLater()
|
||||
void FullScreenDialog::deleteLater(bool detach)
|
||||
{
|
||||
#if !defined(HARDWARE_TOUCH)
|
||||
#if defined(HARDWARE_KEYS)
|
||||
if (previousFocus) {
|
||||
previousFocus->setFocus(SET_FOCUS_DEFAULT);
|
||||
}
|
||||
@@ -125,7 +125,7 @@ void FullScreenDialog::deleteLater()
|
||||
running = false;
|
||||
}
|
||||
else {
|
||||
Window::deleteLater();
|
||||
Window::deleteLater(detach);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,10 @@ enum DialogType {
|
||||
WARNING_TYPE_INFO
|
||||
};
|
||||
|
||||
class FullScreenDialog : public FormGroup {
|
||||
class FullScreenDialog : public FormGroup
|
||||
{
|
||||
public:
|
||||
FullScreenDialog(uint8_t type, std::string title, std::string message = "", std::string action = "", std::function<void(void)> confirmHandler = nullptr);
|
||||
FullScreenDialog(uint8_t type, std::string title, std::string message = "", std::string action = "", const std::function<void(void)> & confirmHandler = nullptr);
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
std::string getName() const override
|
||||
@@ -58,7 +59,7 @@ class FullScreenDialog : public FormGroup {
|
||||
bool onTouchEnd(coord_t x, coord_t y) override;
|
||||
#endif
|
||||
|
||||
void deleteLater();
|
||||
void deleteLater(bool detach=true) override;
|
||||
|
||||
void checkEvents() override;
|
||||
|
||||
@@ -77,7 +78,7 @@ class FullScreenDialog : public FormGroup {
|
||||
bool running = false;
|
||||
std::function<bool(void)> closeCondition;
|
||||
std::function<void(void)> confirmHandler;
|
||||
#if !defined(HARDWARE_TOUCH)
|
||||
#if defined(HARDWARE_KEYS)
|
||||
Window * previousFocus = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -48,7 +48,6 @@ void drawCurveCoord(int x, int y, const char * text, bool active=false);
|
||||
void drawCurvePoint(int x, int y, LcdFlags color);
|
||||
|
||||
extern Layout * customScreens[MAX_CUSTOM_SCREENS];
|
||||
extern Topbar * topbar;
|
||||
|
||||
void drawAlertBox(const char * title, const char * text, const char * action);
|
||||
void showAlertBox(const char * title, const char * text, const char * action, uint8_t sound);
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "view_main.h"
|
||||
#include "layouts/trims.h"
|
||||
#include "layouts/sliders.h"
|
||||
|
||||
std::list<const LayoutFactory *> & getRegisteredLayouts()
|
||||
{
|
||||
@@ -66,7 +69,97 @@ void loadCustomScreens()
|
||||
customScreens[0] = getRegisteredLayouts().front()->create(&g_model.screenData[0].layoutData);
|
||||
}
|
||||
|
||||
// if (topbar) {
|
||||
// topbar->load();
|
||||
// }
|
||||
customScreens[g_model.view]->attach(ViewMain::instance);
|
||||
}
|
||||
|
||||
void Layout::decorate(bool topbar, bool sliders, bool trims, bool flightMode)
|
||||
{
|
||||
if (topbar) {
|
||||
topBar = new TopBar(this);
|
||||
topBar->load();
|
||||
}
|
||||
|
||||
if (sliders) {
|
||||
#if defined(HARDWARE_EXT1) || defined(HARDWARE_EXT2)
|
||||
coord_t yOffset = (trims ? - TRIM_SQUARE_SIZE : 0) + (topbar ? TOPBAR_HEIGHT / 2 : 0);
|
||||
#endif
|
||||
|
||||
new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT1]; });
|
||||
|
||||
if (IS_POT_MULTIPOS(POT2)) {
|
||||
new MainView6POS(this, {LCD_W / 2 - MULTIPOS_W / 2, LCD_H - TRIM_SQUARE_SIZE, MULTIPOS_W + 1, MULTIPOS_H},
|
||||
[=] { return (1 + (potsPos[1] & 0x0f)); });
|
||||
}
|
||||
else if (IS_POT(POT2)) {
|
||||
new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT2]; });
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_POT3)
|
||||
new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT3]; });
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_EXT1)
|
||||
if (IS_POT_SLIDER_AVAILABLE(EXT1)) {
|
||||
new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(topbar) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(topbar) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; });
|
||||
new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(topbar) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT_EXT1]; });
|
||||
}
|
||||
else {
|
||||
new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(topbar) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(topbar)},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; });
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_EXT2)
|
||||
if (IS_POT_SLIDER_AVAILABLE(EXT2)) {
|
||||
new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(topbar) / 2 + yOffset, TRIM_SQUARE_SIZE,
|
||||
VERTICAL_SLIDERS_HEIGHT(topbar) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; });
|
||||
new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE,
|
||||
VERTICAL_SLIDERS_HEIGHT(topbar) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT_EXT2]; });
|
||||
}
|
||||
else {
|
||||
new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(topbar) / 2 + yOffset, TRIM_SQUARE_SIZE,
|
||||
VERTICAL_SLIDERS_HEIGHT(topbar)},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; });
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (trims) {
|
||||
#if defined(HARDWARE_POT3) || defined(HARDWARE_EXT1)
|
||||
coord_t xOffset = sliders? TRIM_SQUARE_SIZE : 0;
|
||||
#else
|
||||
coord_t xOffset = 0;
|
||||
#endif
|
||||
coord_t yOffset = (trims ? - TRIM_SQUARE_SIZE : 0);
|
||||
|
||||
// Trim order TRIM_LH, TRIM_LV, TRIM_RV, TRIM_RH
|
||||
|
||||
// Left
|
||||
new MainViewHorizontalTrim(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE + yOffset, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return getTrimValue(mixerCurrentFlightMode, 0); });
|
||||
// Right
|
||||
new MainViewHorizontalTrim(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE + yOffset, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return getTrimValue(mixerCurrentFlightMode, 3); });
|
||||
|
||||
|
||||
// Left
|
||||
new MainViewVerticalTrim(this, {HMARGIN + xOffset, LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(topbar) / 2 + yOffset + (topbar ? TOPBAR_HEIGHT / 2 : 0), TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(topbar)},
|
||||
[=] { return getTrimValue(mixerCurrentFlightMode, 1); });
|
||||
// Right
|
||||
new MainViewVerticalTrim(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE - xOffset, LCD_H /2 - VERTICAL_SLIDERS_HEIGHT(topbar) / 2 + yOffset + (topbar ? TOPBAR_HEIGHT / 2 : 0), TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(topbar)},
|
||||
[=] { return getTrimValue(mixerCurrentFlightMode, 2); });
|
||||
}
|
||||
|
||||
if (flightMode) {
|
||||
new DynamicText(this, {50, LCD_H - 4 - (sliders? 2 * TRIM_SQUARE_SIZE: TRIM_SQUARE_SIZE), LCD_W - 100, 20}, [=] {
|
||||
return g_model.flightModeData[mixerCurrentFlightMode].name;
|
||||
}, CENTERED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#include <list>
|
||||
#include "widgets_container.h"
|
||||
#include "lcd.h"
|
||||
#include "topbar.h"
|
||||
|
||||
#define MAX_LAYOUT_ZONES 10
|
||||
#define MAX_LAYOUT_OPTIONS 10
|
||||
constexpr coord_t TRIM_LINE_WIDTH = 8;
|
||||
constexpr coord_t TRIM_SQUARE_SIZE = 17;
|
||||
|
||||
class LayoutFactory;
|
||||
|
||||
@@ -45,12 +48,11 @@ class Layout: public WidgetsContainer<MAX_LAYOUT_ZONES, MAX_LAYOUT_OPTIONS>
|
||||
return factory;
|
||||
}
|
||||
|
||||
virtual void update()
|
||||
{
|
||||
}
|
||||
void decorate(bool topbar, bool sliders, bool trims, bool flightMode);
|
||||
|
||||
protected:
|
||||
const LayoutFactory * factory;
|
||||
TopBar * topBar = nullptr;
|
||||
};
|
||||
|
||||
void registerLayout(const LayoutFactory * factory);
|
||||
@@ -123,4 +125,6 @@ class BaseLayoutFactory: public LayoutFactory
|
||||
Layout * loadLayout(const char * name, Layout::PersistentData * persistentData);
|
||||
void loadCustomScreens();
|
||||
|
||||
void drawTrimsAndSliders(Layout::PersistentData * persistentData);
|
||||
|
||||
std::list<const LayoutFactory *> & getRegisteredLayouts();
|
||||
|
||||
@@ -19,6 +19,13 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "trims.h"
|
||||
|
||||
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
|
||||
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
|
||||
#define HAS_SLIDERS() (persistentData->options[2].value.boolValue == true)
|
||||
#define HAS_TRIMS() (persistentData->options[3].value.boolValue == true)
|
||||
#define IS_MIRRORED() (persistentData->options[4].value.boolValue == true)
|
||||
|
||||
const uint8_t LBM_LAYOUT_1x1[] = {
|
||||
#include "mask_layout1x1.lbm"
|
||||
@@ -26,7 +33,10 @@ const uint8_t LBM_LAYOUT_1x1[] = {
|
||||
|
||||
const ZoneOption OPTIONS_LAYOUT_1x1[] = {
|
||||
{ STR_TOP_BAR, ZoneOption::Bool },
|
||||
{ STR_SLIDERS_TRIMS, ZoneOption::Bool },
|
||||
{ STR_FLIGHT_MODE, ZoneOption::Bool },
|
||||
{ STR_SLIDERS, ZoneOption::Bool },
|
||||
{ STR_TRIMS, ZoneOption::Bool },
|
||||
{ STR_MIRROR, ZoneOption::Bool },
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
@@ -36,15 +46,27 @@ class Layout1x1: public Layout
|
||||
Layout1x1(const LayoutFactory * factory, Layout::PersistentData * persistentData):
|
||||
Layout(factory, persistentData)
|
||||
{
|
||||
decorate();
|
||||
}
|
||||
|
||||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[1] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[0].value.boolValue = true;
|
||||
persistentData->options[1].value.boolValue = true;
|
||||
persistentData->options[2].value.boolValue = true;
|
||||
persistentData->options[3].value.boolValue = true;
|
||||
persistentData->options[4].value.boolValue = false;
|
||||
persistentData->options[5].value.boolValue = false;
|
||||
decorate();
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM());
|
||||
}
|
||||
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
{
|
||||
return 1;
|
||||
@@ -65,28 +87,20 @@ class Layout1x1: public Layout
|
||||
return zone;
|
||||
}
|
||||
|
||||
// virtual void refresh();
|
||||
void checkEvents() override
|
||||
{
|
||||
Layout::checkEvents();
|
||||
uint8_t newValue = persistentData->options[4].value.boolValue << 4 | persistentData->options[3].value.boolValue << 3 | persistentData->options[2].value.boolValue << 2
|
||||
| persistentData->options[1].value.boolValue << 1 | persistentData->options[0].value.boolValue;
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
// TODO call this from the Layout config window
|
||||
this->clear();
|
||||
decorate();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
uint8_t value = 0;
|
||||
};
|
||||
|
||||
//void Layout1x1::refresh()
|
||||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[1].value.boolValue) {
|
||||
// // Sliders + Trims + Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | FONT(XS)) / 2,
|
||||
// 232,
|
||||
// g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | FONT(XS));
|
||||
// drawMainPots();
|
||||
// drawTrims(mixerCurrentFlightMode);
|
||||
// }
|
||||
//
|
||||
// Layout::refresh();
|
||||
//}
|
||||
|
||||
BaseLayoutFactory<Layout1x1> layout1x1("Layout1x1", "Fullscreen", LBM_LAYOUT_1x1, OPTIONS_LAYOUT_1x1);
|
||||
|
||||
@@ -19,16 +19,25 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "sliders.h"
|
||||
#include "trims.h"
|
||||
|
||||
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
|
||||
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
|
||||
#define HAS_SLIDERS() (persistentData->options[2].value.boolValue == true)
|
||||
#define HAS_TRIMS() (persistentData->options[3].value.boolValue == true)
|
||||
#define IS_MIRRORED() (persistentData->options[4].value.boolValue == true)
|
||||
|
||||
const uint8_t LBM_LAYOUT_2P1[] = {
|
||||
#include "mask_layout2+1.lbm"
|
||||
};
|
||||
|
||||
const ZoneOption OPTIONS_LAYOUT_2P1[] = {
|
||||
{ "Top bar", ZoneOption::Bool },
|
||||
{ "Flight mode", ZoneOption::Bool },
|
||||
{ "Sliders", ZoneOption::Bool },
|
||||
{ "Trims", ZoneOption::Bool },
|
||||
{ STR_TOP_BAR, ZoneOption::Bool },
|
||||
{ STR_FLIGHT_MODE, ZoneOption::Bool },
|
||||
{ STR_SLIDERS, ZoneOption::Bool },
|
||||
{ STR_TRIMS, ZoneOption::Bool },
|
||||
{ STR_MIRROR, ZoneOption::Bool },
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
@@ -44,17 +53,27 @@ class Layout2P1: public Layout
|
||||
Layout2P1(const LayoutFactory * factory, Layout::PersistentData * persistentData):
|
||||
Layout(factory, persistentData)
|
||||
{
|
||||
decorate();
|
||||
}
|
||||
|
||||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[1] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[2] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[3] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[0].value.boolValue = true;
|
||||
persistentData->options[1].value.boolValue = true;
|
||||
persistentData->options[2].value.boolValue = true;
|
||||
persistentData->options[3].value.boolValue = true;
|
||||
persistentData->options[4].value.boolValue = false;
|
||||
persistentData->options[5].value.boolValue = false;
|
||||
decorate();
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM());
|
||||
}
|
||||
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
{
|
||||
return DIM(ZONES_LAYOUT_2P1);
|
||||
@@ -65,39 +84,21 @@ class Layout2P1: public Layout
|
||||
return ZONES_LAYOUT_2P1[index];
|
||||
}
|
||||
|
||||
// virtual void refresh();
|
||||
void checkEvents() override
|
||||
{
|
||||
Layout::checkEvents();
|
||||
uint8_t newValue = persistentData->options[4].value.boolValue << 4 | persistentData->options[3].value.boolValue << 3 | persistentData->options[2].value.boolValue << 2
|
||||
| persistentData->options[1].value.boolValue << 1 | persistentData->options[0].value.boolValue;
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
// TODO call this from the Layout config window
|
||||
this->clear();
|
||||
decorate();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
uint8_t value = 0;
|
||||
};
|
||||
|
||||
//void Layout2P1::refresh()
|
||||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[1].value.boolValue) {
|
||||
// // Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name),
|
||||
// ZCHAR | FONT(XS)) / 2,
|
||||
// 232,
|
||||
// g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | FONT(XS));
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[2].value.boolValue) {
|
||||
// // Pots and rear sliders positions
|
||||
// drawMainPots();
|
||||
// }
|
||||
//
|
||||
// if (persistentData->options[3].value.boolValue) {
|
||||
// // Trims
|
||||
// drawTrims(mixerCurrentFlightMode);
|
||||
// }
|
||||
//
|
||||
// Layout::refresh();
|
||||
//}
|
||||
|
||||
BaseLayoutFactory<Layout2P1> layout2P1("Layout2P1", "2 + 1", LBM_LAYOUT_2P1, OPTIONS_LAYOUT_2P1);
|
||||
const LayoutFactory * defaultLayout = &layout2P1;
|
||||
|
||||
@@ -19,13 +19,25 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "sliders.h"
|
||||
#include "trims.h"
|
||||
|
||||
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
|
||||
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
|
||||
#define HAS_SLIDERS() (persistentData->options[2].value.boolValue == true)
|
||||
#define HAS_TRIMS() (persistentData->options[3].value.boolValue == true)
|
||||
#define IS_MIRRORED() (persistentData->options[4].value.boolValue == true)
|
||||
|
||||
const uint8_t LBM_LAYOUT_2x1[] = {
|
||||
#include "mask_layout2x1.lbm"
|
||||
};
|
||||
|
||||
const ZoneOption OPTIONS_LAYOUT_2x1[] = {
|
||||
const ZoneOption OPTIONS_LAYOUT_2x1[] = {
|
||||
{ STR_TOP_BAR, ZoneOption::Bool },
|
||||
{ STR_FLIGHT_MODE, ZoneOption::Bool },
|
||||
{ STR_SLIDERS, ZoneOption::Bool },
|
||||
{ STR_TRIMS, ZoneOption::Bool },
|
||||
{ STR_MIRROR, ZoneOption::Bool },
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
@@ -35,14 +47,27 @@ class Layout2x1: public Layout
|
||||
Layout2x1(const LayoutFactory * factory, Layout::PersistentData * persistentData):
|
||||
Layout(factory, persistentData)
|
||||
{
|
||||
decorate();
|
||||
}
|
||||
|
||||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[0].value.boolValue = true;
|
||||
persistentData->options[1].value.boolValue = true;
|
||||
persistentData->options[2].value.boolValue = true;
|
||||
persistentData->options[3].value.boolValue = true;
|
||||
persistentData->options[4].value.boolValue = false;
|
||||
persistentData->options[5].value.boolValue = false;
|
||||
decorate();
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM());
|
||||
}
|
||||
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
{
|
||||
return 2;
|
||||
@@ -64,18 +89,20 @@ class Layout2x1: public Layout
|
||||
return zone;
|
||||
}
|
||||
|
||||
// virtual void refresh();
|
||||
void checkEvents() override
|
||||
{
|
||||
Layout::checkEvents();
|
||||
uint8_t newValue = persistentData->options[4].value.boolValue << 4 | persistentData->options[3].value.boolValue << 3 | persistentData->options[2].value.boolValue << 2
|
||||
| persistentData->options[1].value.boolValue << 1 | persistentData->options[0].value.boolValue;
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
// TODO call this from the Layout config window
|
||||
this->clear();
|
||||
decorate();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
uint8_t value = 0;
|
||||
};
|
||||
|
||||
//void Layout2x1::refresh()
|
||||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// Layout::refresh();
|
||||
//}
|
||||
|
||||
BaseLayoutFactory<Layout2x1> Layout2x1("Layout2x1", "2 x 1", LBM_LAYOUT_2x1, OPTIONS_LAYOUT_2x1);
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "sliders.h"
|
||||
#include "trims.h"
|
||||
|
||||
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
|
||||
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
|
||||
#define HAS_SLIDERS() (persistentData->options[2].value.boolValue == true)
|
||||
#define HAS_TRIMS() (persistentData->options[3].value.boolValue == true)
|
||||
#define IS_MIRRORED() (persistentData->options[4].value.boolValue == true)
|
||||
|
||||
const uint8_t LBM_LAYOUT_2x2[] = {
|
||||
#include "mask_layout2x2.lbm"
|
||||
@@ -26,6 +34,10 @@ const uint8_t LBM_LAYOUT_2x2[] = {
|
||||
|
||||
const ZoneOption OPTIONS_LAYOUT_2x2[] = {
|
||||
{ STR_TOP_BAR, ZoneOption::Bool },
|
||||
{ STR_FLIGHT_MODE, ZoneOption::Bool },
|
||||
{ STR_SLIDERS, ZoneOption::Bool },
|
||||
{ STR_TRIMS, ZoneOption::Bool },
|
||||
{ STR_MIRROR, ZoneOption::Bool },
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
@@ -35,12 +47,24 @@ class Layout2x2: public Layout
|
||||
Layout2x2(const LayoutFactory * factory, Layout::PersistentData * persistentData):
|
||||
Layout(factory, persistentData)
|
||||
{
|
||||
decorate();
|
||||
}
|
||||
|
||||
void create() override
|
||||
{
|
||||
Layout::create();
|
||||
persistentData->options[0] = ZoneOptionValueTyped { ZOV_Bool, OPTION_VALUE_BOOL(true) };
|
||||
persistentData->options[0].value.boolValue = true;
|
||||
persistentData->options[1].value.boolValue = true;
|
||||
persistentData->options[2].value.boolValue = true;
|
||||
persistentData->options[3].value.boolValue = true;
|
||||
persistentData->options[4].value.boolValue = false;
|
||||
persistentData->options[5].value.boolValue = false;
|
||||
decorate();
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM());
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
@@ -67,18 +91,20 @@ class Layout2x2: public Layout
|
||||
return zone;
|
||||
}
|
||||
|
||||
// virtual void refresh();
|
||||
void checkEvents() override
|
||||
{
|
||||
Layout::checkEvents();
|
||||
uint8_t newValue = persistentData->options[4].value.boolValue << 4 | persistentData->options[3].value.boolValue << 3 | persistentData->options[2].value.boolValue << 2
|
||||
| persistentData->options[1].value.boolValue << 1 | persistentData->options[0].value.boolValue;
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
// TODO call this from the Layout config window
|
||||
this->clear();
|
||||
decorate();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
uint8_t value = 0;
|
||||
};
|
||||
|
||||
//void Layout2x2::refresh()
|
||||
//{
|
||||
// theme->drawBackground();
|
||||
//
|
||||
// if (persistentData->options[0].value.boolValue) {
|
||||
// drawTopBar();
|
||||
// }
|
||||
//
|
||||
// Layout::refresh();
|
||||
//}
|
||||
|
||||
BaseLayoutFactory<Layout2x2> layout2x2("Layout2x2", "2 x 2", LBM_LAYOUT_2x2, OPTIONS_LAYOUT_2x2);
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "opentx.h"
|
||||
#include "sliders.h"
|
||||
#include "trims.h"
|
||||
|
||||
#define HAS_TOPBAR() (persistentData->options[0].value.boolValue == true)
|
||||
#define HAS_FM() (persistentData->options[1].value.boolValue == true)
|
||||
@@ -37,14 +38,9 @@ const ZoneOption OPTIONS_LAYOUT_4P2[] = {
|
||||
{ STR_SLIDERS, ZoneOption::Bool },
|
||||
{ STR_TRIMS, ZoneOption::Bool },
|
||||
{ STR_MIRROR, ZoneOption::Bool },
|
||||
{ NULL, ZoneOption::Bool }
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
constexpr coord_t HTRIM_W = 120;
|
||||
constexpr coord_t HTRIM_H = 40;
|
||||
constexpr coord_t HSLIDER_W = 120;
|
||||
constexpr coord_t HSLIDER_H = 40;
|
||||
|
||||
class Layout4P2: public Layout
|
||||
{
|
||||
public:
|
||||
@@ -63,66 +59,47 @@ class Layout4P2: public Layout
|
||||
persistentData->options[3].value.boolValue = true;
|
||||
persistentData->options[4].value.boolValue = false;
|
||||
persistentData->options[5].value.boolValue = false;
|
||||
|
||||
decorate();
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
Layout::decorate(HAS_TOPBAR(), HAS_SLIDERS(), HAS_TRIMS(), HAS_FM());
|
||||
}
|
||||
|
||||
unsigned int getZonesCount() const override
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
||||
void decorate()
|
||||
{
|
||||
if (1 /*HAS_SLIDERS()*/) {
|
||||
new MainViewHorizontalSlider(this, {0, LCD_H - HTRIM_H - 1, HTRIM_W, HSLIDER_H}, [=] { return calibratedAnalogs[CALIBRATED_POT1]; }, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
new MainViewHorizontalSlider(this, {LCD_W - HTRIM_W, LCD_H - HTRIM_H, HTRIM_W, HSLIDER_H}, [=] { return calibratedAnalogs[CALIBRATED_POT3]; }, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
}
|
||||
}
|
||||
|
||||
rect_t getZone(unsigned int index) const override
|
||||
{
|
||||
coord_t areaw = LCD_W - (HAS_SLIDERS() ? 55 : 8) - (HAS_TRIMS() ? 55 : 8);
|
||||
coord_t areah = LCD_H - 4 - (HAS_TOPBAR() ? 55 : 8) - (HAS_SLIDERS() ? HSLIDER_H + 4 : 4) - (HAS_TRIMS() ? HTRIM_H + 4 : 4);
|
||||
coord_t areaw = LCD_W - (HAS_SLIDERS() ? 2 * TRIM_SQUARE_SIZE : 0) - (HAS_TRIMS() ? 2 * TRIM_SQUARE_SIZE : 0) - 10;
|
||||
coord_t areah = LCD_H - (HAS_TOPBAR() ? TOPBAR_HEIGHT : 0) - (HAS_SLIDERS() ? TRIM_SQUARE_SIZE : 0) - (HAS_TRIMS() ? TRIM_SQUARE_SIZE : 0) - 10;
|
||||
areah = 4 * (areah % 4);
|
||||
|
||||
rect_t zone;
|
||||
zone.x = IS_MIRRORED() ? ((index >= 4) ? (LCD_W - areaw) / 2 - 4 : 245) : ((index >= 4) ? 245 : (LCD_W - areaw) / 2 - 4);
|
||||
zone.h = (index >= 4) ? (areah / 2) : (areah / 4) - 2;
|
||||
zone.y = (index >= 4) ? (HAS_TOPBAR() ? 52 : 6) + (index == 5 ? zone.h + ((HAS_TRIMS() + HAS_SLIDERS() == 1) ? 8 : 10): 0): (HAS_TOPBAR() ? 52 : 6) + (index % 4) * (zone.h + 6);
|
||||
zone.w = areaw / 2;
|
||||
|
||||
return zone;
|
||||
return {
|
||||
IS_MIRRORED() ? ((index >= 4) ? (LCD_W - areaw) / 2 : 240) : ((index >= 4) ? 240 : (LCD_W - areaw) / 2),
|
||||
static_cast<coord_t>((index >= 4) ? (HAS_TOPBAR() ? TOPBAR_HEIGHT + 1 : 1) + (index == 5 ? areah / 4 : 0) : (HAS_TOPBAR() ? TOPBAR_HEIGHT + 1 : 1) + (index % 4) * (areah / 4)),
|
||||
areaw / 2,
|
||||
(index >= 4) ? (areah / 2) : (areah / 4)
|
||||
};
|
||||
}
|
||||
|
||||
//virtual void refresh();
|
||||
void checkEvents() override
|
||||
{
|
||||
Layout::checkEvents();
|
||||
uint8_t newValue = persistentData->options[4].value.boolValue << 4 | persistentData->options[3].value.boolValue << 3 | persistentData->options[2].value.boolValue << 2
|
||||
| persistentData->options[1].value.boolValue << 1 | persistentData->options[0].value.boolValue;
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
// TODO call this from the Layout config window
|
||||
this->clear();
|
||||
decorate();
|
||||
}
|
||||
}
|
||||
protected:
|
||||
uint8_t value = 0;
|
||||
};
|
||||
|
||||
//void Layout4P2::refresh()
|
||||
//{
|
||||
//theme->drawBackground();
|
||||
|
||||
//if (HAS_TOPBAR()) {
|
||||
// drawTopBar();
|
||||
//}
|
||||
//
|
||||
//if (HAS_FM()) {
|
||||
// // Flight mode
|
||||
// lcdDrawSizedText(LCD_W / 2 - getTextWidth(g_model.flightModeData[mixerCurrentFlightMode].name, sizeof(g_model.flightModeData[mixerCurrentFlightMode].name),
|
||||
// ZCHAR | SMLSIZE) / 2, 232, g_model.flightModeData[mixerCurrentFlightMode].name,
|
||||
// sizeof(g_model.flightModeData[mixerCurrentFlightMode].name), ZCHAR | SMLSIZE);
|
||||
//}
|
||||
//
|
||||
//if (HAS_SLIDERS()) {
|
||||
// // Pots and rear sliders positions
|
||||
// drawMainPots();
|
||||
//}
|
||||
//
|
||||
//if (HAS_TRIMS()) {
|
||||
// // Trims
|
||||
// drawTrims(mixerCurrentFlightMode, HAS_SLIDERS());
|
||||
//}
|
||||
|
||||
//Layout::refresh();
|
||||
//}
|
||||
|
||||
BaseLayoutFactory<Layout4P2> layout4P2("Layout4P2", "4 + 2", LBM_LAYOUT_4P2, OPTIONS_LAYOUT_4P2);
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 3.1 KiB |
@@ -21,13 +21,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "libopenui.h"
|
||||
#include "trims.h"
|
||||
|
||||
#if defined(PCBNV14)
|
||||
constexpr uint8_t SLIDER_TICKS_COUNT = 30;
|
||||
#else
|
||||
constexpr uint8_t SLIDER_TICKS_COUNT = 40;
|
||||
#endif
|
||||
constexpr coord_t HMARGIN = 5;
|
||||
constexpr coord_t HORIZONTAL_SLIDERS_WIDTH = SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE;
|
||||
constexpr coord_t MULTIPOS_H = 20;
|
||||
constexpr coord_t MULTIPOS_W = 50;
|
||||
inline coord_t VERTICAL_SLIDERS_HEIGHT(bool topbar)
|
||||
{
|
||||
return topbar ? SLIDER_TICKS_COUNT * 4 + TRIM_SQUARE_SIZE : SLIDER_TICKS_COUNT * 5 + TRIM_SQUARE_SIZE;
|
||||
}
|
||||
|
||||
class MainViewSlider : public Window
|
||||
{
|
||||
public:
|
||||
MainViewSlider(Window * parent, const rect_t & rect, std::function<int8_t()> getValue, uint32_t options):
|
||||
MainViewSlider(Window * parent, const rect_t & rect, std::function<int16_t()> getValue):
|
||||
Window(parent, rect),
|
||||
options(options),
|
||||
getValue(std::move(getValue))
|
||||
{
|
||||
}
|
||||
@@ -43,8 +57,7 @@ class MainViewSlider : public Window
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t options = 0;
|
||||
std::function<int8_t()> getValue;
|
||||
std::function<int16_t()> getValue;
|
||||
int8_t value = 0;
|
||||
};
|
||||
|
||||
@@ -55,6 +68,69 @@ class MainViewHorizontalSlider : public MainViewSlider
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
drawHorizontalSlider(dc, 0, 0, width(), getValue(), -RESX, RESX, 40, options);
|
||||
// The ticks
|
||||
int delta = (width() - TRIM_SQUARE_SIZE) / SLIDER_TICKS_COUNT;
|
||||
coord_t x = TRIM_SQUARE_SIZE / 2;
|
||||
for (uint8_t i = 0; i <= SLIDER_TICKS_COUNT; i++) {
|
||||
if (i == 0 || i == SLIDER_TICKS_COUNT / 2 || i == SLIDER_TICKS_COUNT)
|
||||
dc->drawSolidVerticalLine(x, 2, 13, DEFAULT_COLOR);
|
||||
else
|
||||
dc->drawSolidVerticalLine(x, 4, 9, DEFAULT_COLOR);
|
||||
x += delta;
|
||||
}
|
||||
|
||||
// The square
|
||||
auto value = - getValue();
|
||||
x = width() - TRIM_SQUARE_SIZE - divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX);
|
||||
drawTrimSquare(dc, x, 0, TRIM_BGCOLOR);
|
||||
}
|
||||
};
|
||||
|
||||
class MainView6POS : public MainViewSlider
|
||||
{
|
||||
public:
|
||||
using MainViewSlider::MainViewSlider;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// The ticks
|
||||
int delta = (width() - TRIM_SQUARE_SIZE) / (XPOTS_MULTIPOS_COUNT - 1);
|
||||
coord_t x = TRIM_SQUARE_SIZE / 2;
|
||||
for (uint8_t i = 0; i <= XPOTS_MULTIPOS_COUNT; i++) {
|
||||
dc->drawSolidVerticalLine(x, 4, 9, DEFAULT_COLOR);
|
||||
x += delta;
|
||||
}
|
||||
|
||||
// The square
|
||||
auto value = getValue();
|
||||
x = TRIM_SQUARE_SIZE / 2 + divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value -1) , 6);
|
||||
drawTrimSquare(dc, x, 0, TRIM_BGCOLOR);
|
||||
dc->drawNumber(x + 1, 0, value, FOCUS_COLOR);
|
||||
}
|
||||
};
|
||||
|
||||
class MainViewVerticalSlider : public MainViewSlider
|
||||
{
|
||||
public:
|
||||
using MainViewSlider::MainViewSlider;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
uint8_t slidersTick = height() / 5;
|
||||
// The ticks
|
||||
int delta = (height() - TRIM_SQUARE_SIZE) / slidersTick;
|
||||
coord_t y = TRIM_SQUARE_SIZE / 2;
|
||||
for (uint8_t i = 0; i <= slidersTick; i++) {
|
||||
if (i == 0 || i == slidersTick / 2 || i == slidersTick)
|
||||
dc->drawSolidHorizontalLine(2, y, 13, DEFAULT_COLOR);
|
||||
else
|
||||
dc->drawSolidHorizontalLine(4, y, 9, DEFAULT_COLOR);
|
||||
y += delta;
|
||||
}
|
||||
|
||||
// The square
|
||||
auto value = getValue();
|
||||
y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value + RESX), 2 * RESX);
|
||||
drawTrimSquare(dc, 0, y, TRIM_BGCOLOR);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libopenui.h"
|
||||
|
||||
class MainViewTrim : public Window
|
||||
{
|
||||
public:
|
||||
MainViewTrim(Window * parent, const rect_t & rect, std::function<int16_t()> getValue):
|
||||
Window(parent, rect),
|
||||
getValue(std::move(getValue))
|
||||
{
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
Window::checkEvents();
|
||||
int8_t newValue = getValue();
|
||||
if (value != newValue) {
|
||||
value = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<int16_t()> getValue;
|
||||
int8_t value = 0;
|
||||
};
|
||||
|
||||
class MainViewHorizontalTrim : public MainViewTrim
|
||||
{
|
||||
public:
|
||||
using MainViewTrim::MainViewTrim;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
int32_t trimMin, trimMax;
|
||||
if (g_model.extendedTrims) {
|
||||
trimMin = TRIM_EXTENDED_MIN;
|
||||
trimMax = TRIM_EXTENDED_MAX;
|
||||
}
|
||||
else {
|
||||
trimMin = TRIM_MIN;
|
||||
trimMax = TRIM_MAX;
|
||||
}
|
||||
|
||||
// Trim line
|
||||
lcdSetColor(GREY); // TODO add a color
|
||||
dc->drawSolidFilledRect(TRIM_SQUARE_SIZE / 2, (height() - TRIM_LINE_WIDTH - 1) / 2, width() - TRIM_SQUARE_SIZE + 1, TRIM_LINE_WIDTH, CUSTOM_COLOR);
|
||||
|
||||
// Trim square
|
||||
auto value = getValue();
|
||||
coord_t x = divRoundClosest((width() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin);
|
||||
drawTrimSquare(dc, x, 0, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR);
|
||||
|
||||
// Trim value / small lines on the square
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) {
|
||||
// TODO DISPLAY_TRIMS_CHANGE
|
||||
dc->drawNumber(x + (TRIM_SQUARE_SIZE + 1) / 2, 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED);
|
||||
}
|
||||
else {
|
||||
if (value >= 0) {
|
||||
dc->drawSolidVerticalLine(x + 4, 3, 9, FOCUS_COLOR);
|
||||
}
|
||||
if (value <= 0) {
|
||||
dc->drawSolidVerticalLine(x + 10, 3, 9, FOCUS_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MainViewVerticalTrim : public MainViewTrim
|
||||
{
|
||||
public:
|
||||
using MainViewTrim::MainViewTrim;
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
int32_t trimMin, trimMax;
|
||||
if (g_model.extendedTrims) {
|
||||
trimMin = TRIM_EXTENDED_MIN;
|
||||
trimMax = TRIM_EXTENDED_MAX;
|
||||
}
|
||||
else {
|
||||
trimMin = TRIM_MIN;
|
||||
trimMax = TRIM_MAX;
|
||||
}
|
||||
|
||||
// Trim line
|
||||
lcdSetColor(GREY); // TODO add a color
|
||||
dc->drawSolidFilledRect((width() - TRIM_LINE_WIDTH) / 2, TRIM_SQUARE_SIZE / 2, TRIM_LINE_WIDTH, height() - TRIM_SQUARE_SIZE + 1, CUSTOM_COLOR);
|
||||
|
||||
// Trim square
|
||||
auto value = getValue();
|
||||
coord_t y = height() - TRIM_SQUARE_SIZE - divRoundClosest((height() - TRIM_SQUARE_SIZE) * (value - trimMin), trimMax - trimMin);
|
||||
drawTrimSquare(dc, 0, y, (value < TRIM_MIN || value > TRIM_MAX) ? HIGHLIGHT_COLOR /* TODO add a color */ : TRIM_BGCOLOR);
|
||||
|
||||
// Trim value / small lines on the square
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS) {
|
||||
// TODO DISPLAY_TRIMS_CHANGE
|
||||
dc->drawNumber((TRIM_SQUARE_SIZE + 1) / 2, y + 3, divRoundClosest(value * 100, trimMax), FONT(XXS) | FOCUS_COLOR | CENTERED);
|
||||
}
|
||||
else {
|
||||
if (value >= 0) {
|
||||
dc->drawSolidHorizontalLine(3, y + 4, 9, FOCUS_COLOR);
|
||||
}
|
||||
if (value <= 0) {
|
||||
dc->drawSolidHorizontalLine(3, y + 10, 9, FOCUS_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "lcd.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#if defined(SIMU)
|
||||
pixel_t displayBuf[DISPLAY_BUFFER_SIZE];
|
||||
@@ -73,7 +74,7 @@ int getTextWidth(const char * s, int len, LcdFlags flags)
|
||||
result += getFontPatternWidth(specs, c) + 1;
|
||||
}
|
||||
else if (c >= 0x20) {
|
||||
result += getCharWidth(c, specs) + 1;
|
||||
result += getCharWidth(c, specs);
|
||||
}
|
||||
|
||||
++s;
|
||||
|
||||
@@ -37,6 +37,7 @@ class CurveEditWindow : public Page {
|
||||
protected:
|
||||
uint8_t index;
|
||||
CurveEdit * curveEdit = nullptr;
|
||||
CurveDataEdit * curveDataEdit = nullptr;
|
||||
|
||||
void buildHeader(Window * window)
|
||||
{
|
||||
@@ -108,21 +109,23 @@ class CurveEditWindow : public Page {
|
||||
curve.points = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->update();
|
||||
curveDataEdit->invalidate();
|
||||
}
|
||||
});
|
||||
edit->setSuffix(STR_PTS);
|
||||
grid.nextLine();
|
||||
|
||||
// Smooth
|
||||
new StaticText(window, grid.getFieldSlot(), STR_SMOOTH);
|
||||
grid.nextLine();
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_DEFAULT(g_model.curves[index].smooth),
|
||||
new StaticText(window, grid.getFieldSlot(2, 0), STR_SMOOTH);
|
||||
new CheckBox(window, grid.getFieldSlot(2, 1), GET_DEFAULT(g_model.curves[index].smooth),
|
||||
[=](int32_t newValue) {
|
||||
g_model.curves[index].smooth = newValue;
|
||||
SET_DIRTY();
|
||||
curveEdit->update();
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
curveDataEdit = new CurveDataEdit(window, {0, grid.getWindowHeight(), coord_t(LCD_W - curveWidth - PAGE_PADDING - 1), window->height() - grid.getWindowHeight() - PAGE_PADDING}, index);
|
||||
}
|
||||
#else
|
||||
void buildBody(FormWindow * window)
|
||||
|
||||
@@ -74,8 +74,12 @@ void ModelFlightModesPage::build(FormWindow * window)
|
||||
|
||||
FormGridLayout grid;
|
||||
grid.setMarginRight(15);
|
||||
grid.spacer();
|
||||
#if LCD_W > LCD_H
|
||||
grid.setLabelWidth(140);
|
||||
#else
|
||||
grid.setLabelWidth(110);
|
||||
#endif
|
||||
grid.spacer();
|
||||
|
||||
char label[16];
|
||||
getFlightModeString(label, i+1);
|
||||
|
||||
@@ -18,15 +18,15 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef _MODEL_GVARS_H
|
||||
#define _MODEL_GVARS_H
|
||||
#pragma once
|
||||
|
||||
#include "tabsgroup.h"
|
||||
#include "page.h"
|
||||
#include "window.h"
|
||||
#include "numberedit.h"
|
||||
|
||||
class GVarButton: public Button {
|
||||
class GVarButton: public Button
|
||||
{
|
||||
public:
|
||||
GVarButton(FormGroup * parent, const rect_t & rect, uint8_t gvar);
|
||||
|
||||
@@ -38,11 +38,12 @@ class GVarButton: public Button {
|
||||
void drawFlightMode(BitmapBuffer * dc, coord_t x, coord_t y, int fm, LcdFlags attr);
|
||||
uint8_t gvarIdx;
|
||||
int lines;
|
||||
int32_t gvarSum; //used for invalidation
|
||||
uint8_t currentFlightMode; //used for invalidation
|
||||
int32_t gvarSum = 0; // used for invalidation
|
||||
uint8_t currentFlightMode = 0; // used for invalidation
|
||||
};
|
||||
|
||||
class ModelGVarsPage: public PageTab {
|
||||
class ModelGVarsPage: public PageTab
|
||||
{
|
||||
public:
|
||||
ModelGVarsPage():
|
||||
PageTab(STR_MENU_GLOBAL_VARS, ICON_MODEL_GVARS)
|
||||
@@ -54,7 +55,8 @@ class ModelGVarsPage: public PageTab {
|
||||
void rebuild(FormWindow * window);
|
||||
};
|
||||
|
||||
class GVarRenderer: public Window {
|
||||
class GVarRenderer: public Window
|
||||
{
|
||||
friend class GVarEditWindow;
|
||||
|
||||
public:
|
||||
@@ -77,7 +79,8 @@ class GVarRenderer: public Window {
|
||||
};
|
||||
|
||||
|
||||
class GVarEditWindow: public Page {
|
||||
class GVarEditWindow: public Page
|
||||
{
|
||||
public:
|
||||
explicit GVarEditWindow(uint8_t gvarIndex) :
|
||||
Page(ICON_MODEL_GVARS),
|
||||
@@ -98,4 +101,3 @@ class GVarEditWindow: public Page {
|
||||
void setProperties(int onlyForFlightMode = -1);
|
||||
void checkEvents() override;
|
||||
};
|
||||
#endif
|
||||
@@ -332,7 +332,7 @@ class InputLineButton : public CommonInputOrMixButton {
|
||||
}
|
||||
}
|
||||
|
||||
bool isActive() override
|
||||
bool isActive() const override
|
||||
{
|
||||
return isExpoActive(index);
|
||||
}
|
||||
@@ -382,6 +382,7 @@ void ModelInputsPage::rebuild(FormWindow * window, int8_t focusIndex)
|
||||
|
||||
void ModelInputsPage::editInput(FormWindow * window, uint8_t input, uint8_t index)
|
||||
{
|
||||
Window::clearFocus();
|
||||
Window * editWindow = new InputEditWindow(input, index);
|
||||
editWindow->setCloseHandler([=]() {
|
||||
rebuild(window, index);
|
||||
@@ -394,8 +395,6 @@ void ModelInputsPage::build(FormWindow * window, int8_t focusIndex)
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(66);
|
||||
|
||||
Window::clearFocus();
|
||||
|
||||
int inputIndex = 0;
|
||||
ExpoData * line = g_model.expoData;
|
||||
for (uint8_t input = 0; input < MAX_INPUTS; input++) {
|
||||
|
||||
@@ -52,7 +52,7 @@ class CommonInputOrMixButton : public Button {
|
||||
});
|
||||
}
|
||||
|
||||
virtual bool isActive() = 0;
|
||||
virtual bool isActive() const = 0;
|
||||
|
||||
void checkEvents() override;
|
||||
|
||||
|
||||
@@ -24,21 +24,23 @@
|
||||
|
||||
#define SET_DIRTY() storageDirty(EE_MODEL)
|
||||
|
||||
//void putsEdgeDelayParam(coord_t x, coord_t y, LogicalSwitchData * ls)
|
||||
//{
|
||||
// lcdDrawChar(x, y, '[');
|
||||
// lcdDrawNumber(lcdNextPos+2, y, lswTimerValue(ls->v2), LEFT|PREC1);
|
||||
// lcdDrawChar(lcdNextPos, y, ':');
|
||||
// if (ls->v3 < 0)
|
||||
// lcdDrawText(lcdNextPos+3, y, "<<");
|
||||
// else if (ls->v3 == 0)
|
||||
// lcdDrawText(lcdNextPos+3, y, "--");
|
||||
// else
|
||||
// lcdDrawNumber(lcdNextPos+3, y, lswTimerValue(ls->v2+ls->v3), LEFT|PREC1);
|
||||
// lcdDrawChar(lcdNextPos, y, ']');
|
||||
//}
|
||||
void putsEdgeDelayParam(BitmapBuffer * dc, coord_t x, coord_t y, LogicalSwitchData * ls, LcdFlags flags = 0)
|
||||
{
|
||||
coord_t lcdNextPos = 0;
|
||||
lcdNextPos = dc->drawText(x, y, "[", flags);
|
||||
lcdNextPos = dc->drawNumber(lcdNextPos+2, y, lswTimerValue(ls->v2), LEFT | PREC1 | flags);
|
||||
lcdNextPos = dc->drawText(lcdNextPos, y, ":", flags);
|
||||
if (ls->v3 < 0)
|
||||
lcdNextPos = dc->drawText(lcdNextPos+3, y, "<<", flags);
|
||||
else if (ls->v3 == 0)
|
||||
lcdNextPos = dc->drawText(lcdNextPos+3, y, "--", flags);
|
||||
else
|
||||
lcdNextPos = dc->drawNumber(lcdNextPos+3, y, lswTimerValue(ls->v2+ls->v3), LEFT | PREC1 | flags);
|
||||
dc->drawText(lcdNextPos, y, "]", flags);
|
||||
}
|
||||
|
||||
class LogicalSwitchEditPage: public Page {
|
||||
class LogicalSwitchEditPage: public Page
|
||||
{
|
||||
public:
|
||||
explicit LogicalSwitchEditPage(uint8_t index):
|
||||
Page(ICON_MODEL_LOGICAL_SWITCHES),
|
||||
@@ -51,11 +53,11 @@ class LogicalSwitchEditPage: public Page {
|
||||
protected:
|
||||
uint8_t index;
|
||||
bool active = false;
|
||||
Window * logicalSwitchOneWindow = nullptr;
|
||||
FormGroup * logicalSwitchOneWindow = nullptr;
|
||||
StaticText * headerSwitchName = nullptr;
|
||||
NumberEdit * v2Edit = nullptr;
|
||||
|
||||
bool isActive()
|
||||
bool isActive() const
|
||||
{
|
||||
return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + index);
|
||||
}
|
||||
@@ -75,7 +77,7 @@ class LogicalSwitchEditPage: public Page {
|
||||
headerSwitchName = new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT }, getSwitchPositionName(SWSRC_SW1 + index), 0, MENU_COLOR);
|
||||
}
|
||||
|
||||
void updateLogicalSwitchOneWindow(FormField * functionChoice)
|
||||
void updateLogicalSwitchOneWindow()
|
||||
{
|
||||
FormGridLayout grid;
|
||||
logicalSwitchOneWindow->clear();
|
||||
@@ -112,7 +114,7 @@ class LogicalSwitchEditPage: public Page {
|
||||
edit1->setDisplayHandler([](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
|
||||
dc->drawNumber(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, lswTimerValue(value), flags | PREC1);
|
||||
});
|
||||
edit2->setDisplayHandler([=](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
|
||||
edit2->setDisplayHandler([cs](BitmapBuffer * dc, LcdFlags flags, int32_t value) {
|
||||
if (value < 0)
|
||||
dc->drawText(FIELD_PADDING_LEFT, FIELD_PADDING_TOP, "<<", flags);
|
||||
else if (value == 0)
|
||||
@@ -214,13 +216,13 @@ class LogicalSwitchEditPage: public Page {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
SET_DIRTY();
|
||||
updateLogicalSwitchOneWindow(functionChoice);
|
||||
updateLogicalSwitchOneWindow();
|
||||
});
|
||||
functionChoice->setAvailableHandler(isLogicalSwitchFunctionAvailable);
|
||||
grid.nextLine();
|
||||
|
||||
logicalSwitchOneWindow = new Window(window, { 0, grid.getWindowHeight(), LCD_W, 0 });
|
||||
updateLogicalSwitchOneWindow(functionChoice);
|
||||
logicalSwitchOneWindow = new FormGroup(window, { 0, grid.getWindowHeight(), LCD_W, 0 }, FORM_FORWARD_FOCUS);
|
||||
updateLogicalSwitchOneWindow();
|
||||
grid.addWindow(logicalSwitchOneWindow);
|
||||
}
|
||||
};
|
||||
@@ -246,7 +248,7 @@ class LogicalSwitchButton : public Button {
|
||||
setHeight(height() + 20);
|
||||
}
|
||||
|
||||
bool isActive()
|
||||
bool isActive() const
|
||||
{
|
||||
return getSwitch(SWSRC_FIRST_LOGICAL_SWITCH + lsIndex);
|
||||
}
|
||||
@@ -276,7 +278,7 @@ class LogicalSwitchButton : public Button {
|
||||
}
|
||||
else if (lsFamily == LS_FAMILY_EDGE) {
|
||||
drawSwitch(dc, col1, line2, ls->v1);
|
||||
// TODO putsEdgeDelayParam(col2, line2, ls);
|
||||
putsEdgeDelayParam(dc, col2, line2, ls);
|
||||
}
|
||||
else if (lsFamily == LS_FAMILY_COMP) {
|
||||
drawSource(dc, col2, line1, ls->v1, 0);
|
||||
|
||||
@@ -237,7 +237,7 @@ class MixLineButton : public CommonInputOrMixButton {
|
||||
}
|
||||
}
|
||||
|
||||
bool isActive() override
|
||||
bool isActive() const override
|
||||
{
|
||||
return isMixActive(index);
|
||||
}
|
||||
@@ -306,6 +306,7 @@ void ModelMixesPage::rebuild(FormWindow * window, int8_t focusMixIndex)
|
||||
|
||||
void ModelMixesPage::editMix(FormWindow * window, uint8_t channel, uint8_t mixIndex)
|
||||
{
|
||||
Window::clearFocus();
|
||||
Window * editWindow = new MixEditWindow(channel, mixIndex);
|
||||
editWindow->setCloseHandler([=]() {
|
||||
rebuild(window, mixIndex);
|
||||
@@ -318,8 +319,6 @@ void ModelMixesPage::build(FormWindow * window, int8_t focusMixIndex)
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(66);
|
||||
|
||||
Window::clearFocus();
|
||||
|
||||
const BitmapBuffer * const mixerMultiplexBitmap[] = {
|
||||
mixerSetupAddBitmap,
|
||||
mixerSetupMultiBitmap,
|
||||
|
||||
@@ -79,7 +79,7 @@ class OutputEditWindow : public Page {
|
||||
grid.nextLine();
|
||||
|
||||
// Direction
|
||||
new StaticText(window, grid.getLabelSlot(), "Inverted"); // TODO translation
|
||||
new StaticText(window, grid.getLabelSlot(), STR_INVERTED);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_DEFAULT(output->revert));
|
||||
grid.nextLine();
|
||||
|
||||
@@ -98,9 +98,9 @@ class OutputEditWindow : public Page {
|
||||
SET_VALUE(output->ppmCenter, newValue - PPM_CENTER));
|
||||
grid.nextLine();
|
||||
|
||||
// PPM center
|
||||
// Subtrims mode
|
||||
new StaticText(window, grid.getLabelSlot(), TR_LIMITS_HEADERS_SUBTRIMMODE);
|
||||
new Choice(window, grid.getFieldSlot(), "\001\306=", 0, 1, GET_SET_DEFAULT(output->symetrical));
|
||||
new Choice(window, grid.getFieldSlot(), STR_SUBTRIMMODES, 0, 1, GET_SET_DEFAULT(output->symetrical));
|
||||
grid.nextLine();
|
||||
|
||||
window->setInnerHeight(grid.getWindowHeight());
|
||||
@@ -125,7 +125,7 @@ class OutputLineButton : public Button {
|
||||
dc->drawNumber(68, FIELD_PADDING_TOP, output->max + 1000, PREC1);
|
||||
dc->drawNumber(132, FIELD_PADDING_TOP, output->offset, PREC1);
|
||||
dc->drawNumber(226, FIELD_PADDING_TOP, PPM_CENTER + output->ppmCenter, RIGHT);
|
||||
dc->drawText(228, FIELD_PADDING_TOP, output->symetrical ? "=" : "\306");
|
||||
dc->drawText(228, FIELD_PADDING_TOP, output->symetrical ? "=" : "\206");
|
||||
|
||||
// second line
|
||||
if (output->revert) {
|
||||
@@ -218,6 +218,7 @@ void ModelOutputsPage::build(FormWindow * window, int8_t focusChannel)
|
||||
|
||||
void ModelOutputsPage::editOutput(FormWindow * window, uint8_t channel)
|
||||
{
|
||||
Window::clearFocus();
|
||||
Window * editWindow = new OutputEditWindow(channel);
|
||||
editWindow->setCloseHandler([=]() {
|
||||
rebuild(window, channel);
|
||||
|
||||
@@ -404,6 +404,7 @@ class ReceiverButton: public TextButton {
|
||||
memclear(&reusableBuffer.moduleSetup.bindInformation, sizeof(BindInformation));
|
||||
reusableBuffer.moduleSetup.bindInformation.rxUid = receiverIdx;
|
||||
if (isModuleR9MAccess(moduleIdx)) {
|
||||
reusableBuffer.moduleSetup.bindInformation.step = BIND_MODULE_TX_INFORMATION_REQUEST;
|
||||
#if defined(SIMU)
|
||||
reusableBuffer.moduleSetup.pxx2.moduleInformation.information.modelID = 1;
|
||||
reusableBuffer.moduleSetup.pxx2.moduleInformation.information.variant = 2;
|
||||
@@ -462,7 +463,7 @@ class TrainerModuleWindow : public FormGroup {
|
||||
trainerChoice->setAvailableHandler(isTrainerModeAvailable);
|
||||
grid.nextLine();
|
||||
|
||||
if (g_model.trainerData.mode >= TRAINER_MODE_MASTER_TRAINER_JACK) {
|
||||
if (g_model.isTrainerTraineeEnable()) {
|
||||
new StaticText(this, grid.getLabelSlot(true), STR_CHANNELRANGE);
|
||||
channelStart = new NumberEdit(this, grid.getFieldSlot(2, 0), 1,
|
||||
MAX_OUTPUT_CHANNELS - 8 + g_model.trainerData.channelsCount + 1,
|
||||
@@ -808,11 +809,13 @@ class ModuleWindow : public FormGroup {
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_NORMAL;
|
||||
return 0;
|
||||
}
|
||||
#if defined(MULTIMODULE)
|
||||
else {
|
||||
setMultiBindStatus(moduleIdx, MULTI_BIND_INITIATED);
|
||||
moduleState[moduleIdx].mode = MODULE_MODE_BIND;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
});
|
||||
bindButton->setCheckHandler([=]() {
|
||||
if (moduleState[moduleIdx].mode != MODULE_MODE_BIND) {
|
||||
|
||||
@@ -44,14 +44,14 @@ PageHeader::~PageHeader()
|
||||
|
||||
void PageHeader::paint(BitmapBuffer * dc)
|
||||
{
|
||||
static_cast<ThemeBase *>(theme)->drawMenuBackground(dc, getIcon(), "");
|
||||
OpenTxTheme::instance()->drawMenuBackground(dc, getIcon(), "");
|
||||
dc->drawSolidFilledRect(MENU_HEADER_HEIGHT, 0, LCD_W - MENU_HEADER_HEIGHT, MENU_HEADER_HEIGHT, MENU_BGCOLOR);
|
||||
}
|
||||
|
||||
Page::Page(unsigned icon):
|
||||
Window(&mainWindow, {0, 0, LCD_W, LCD_H}, OPAQUE),
|
||||
header(this, icon),
|
||||
body(this, { 0, MENU_HEADER_HEIGHT, LCD_W, LCD_H - MENU_HEADER_HEIGHT }),
|
||||
body(this, { 0, MENU_HEADER_HEIGHT, LCD_W, LCD_H - MENU_HEADER_HEIGHT }, FORM_FORWARD_FOCUS),
|
||||
previousFocus(focusWindow)
|
||||
{
|
||||
clearFocus();
|
||||
@@ -67,13 +67,13 @@ Page::~Page()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Page::deleteLater()
|
||||
void Page::deleteLater(bool detach)
|
||||
{
|
||||
if (previousFocus) {
|
||||
previousFocus->setFocus(SET_FOCUS_DEFAULT);
|
||||
}
|
||||
|
||||
Window::deleteLater();
|
||||
Window::deleteLater(detach);
|
||||
}
|
||||
|
||||
void Page::paint(BitmapBuffer * dc)
|
||||
|
||||
@@ -78,7 +78,7 @@ class Page: public Window {
|
||||
}
|
||||
#endif
|
||||
|
||||
void deleteLater();
|
||||
void deleteLater(bool detach=true) override;
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "radio_calibration.h"
|
||||
#include "opentx.h"
|
||||
#include "radio_calibration.h"
|
||||
#include "sliders.h"
|
||||
|
||||
#define XPOT_DELTA 10
|
||||
#define XPOT_DELAY 5 /* cycles */
|
||||
@@ -48,56 +49,6 @@ class StickCalibrationWindow: public Window {
|
||||
uint8_t stickX, stickY;
|
||||
};
|
||||
|
||||
class MultiPosCalibrationWindow: public Window {
|
||||
public:
|
||||
MultiPosCalibrationWindow(Window * parent, const rect_t & rect, uint8_t potIndex):
|
||||
Window(parent, rect),
|
||||
potIndex(potIndex)
|
||||
{
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
// will always force a full monitor window refresh
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
drawHorizontalSlider(dc, 5, 8, rect.w - 18, 1 + (potsPos[potIndex] & 0x0f), 1, XPOTS_MULTIPOS_COUNT+1, XPOTS_MULTIPOS_COUNT, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_NUMBER_BUTTON);
|
||||
}
|
||||
|
||||
protected:
|
||||
static constexpr coord_t bitmapSize = 68;
|
||||
uint8_t potIndex;
|
||||
};
|
||||
|
||||
class PotCalibrationWindow: public Window {
|
||||
public:
|
||||
PotCalibrationWindow(Window * parent, const rect_t & rect, uint8_t potIndex):
|
||||
Window(parent, rect),
|
||||
potIndex(potIndex)
|
||||
{
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
// will always force a full monitor window refresh
|
||||
invalidate();
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
if (rect.h > rect.w)
|
||||
drawVerticalSlider(dc, 5, 8, rect.h - 18, calibratedAnalogs[potIndex], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
else
|
||||
drawHorizontalSlider(dc, 5, 8, rect.w - 18, calibratedAnalogs[potIndex], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
}
|
||||
|
||||
protected:
|
||||
uint8_t potIndex;
|
||||
};
|
||||
|
||||
RadioCalibrationPage::RadioCalibrationPage(bool initial):
|
||||
Page(ICON_RADIO_CALIBRATION),
|
||||
initial(initial)
|
||||
@@ -110,7 +61,7 @@ RadioCalibrationPage::RadioCalibrationPage(bool initial):
|
||||
void RadioCalibrationPage::buildHeader(Window * window)
|
||||
{
|
||||
new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUCALIBRATION, 0, MENU_COLOR);
|
||||
text = new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUTOSTART, 0, MENU_COLOR);
|
||||
text = new StaticText(window, {PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, PAGE_LINE_HEIGHT}, STR_MENUTOSTART, 0,MENU_COLOR);
|
||||
}
|
||||
|
||||
void RadioCalibrationPage::buildBody(FormWindow * window)
|
||||
@@ -131,17 +82,59 @@ void RadioCalibrationPage::buildBody(FormWindow * window)
|
||||
new StickCalibrationWindow(window, {LCD_W - 130, 20, 90, 90}, STICK4, STICK3);
|
||||
|
||||
#if defined(PCBHORUS)
|
||||
// The 2 main sliders
|
||||
new PotCalibrationWindow(window, {0, 2, 20, 150}, SLIDER1);
|
||||
new PotCalibrationWindow(window, {LCD_W-20, 2, 20, 150}, SLIDER2);
|
||||
|
||||
// The 3 pots
|
||||
new PotCalibrationWindow(window, {0, window->height()-25, 150, 20}, POT1);
|
||||
new MultiPosCalibrationWindow(window, {LCD_W/2-25,window->height()-25, 50, 20}, POT2);
|
||||
new PotCalibrationWindow(window, {LCD_W-150, window->height()-25, 150, 20}, POT3);
|
||||
new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT1]; });
|
||||
|
||||
if (IS_POT_MULTIPOS(POT2)) {
|
||||
new MainView6POS(this, {LCD_W / 2 - MULTIPOS_W / 2, LCD_H - TRIM_SQUARE_SIZE, MULTIPOS_W + 1, MULTIPOS_H},
|
||||
[=] { return (1 + (potsPos[1] & 0x0f)); });
|
||||
}
|
||||
|
||||
new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT3]; });
|
||||
#if defined(HARDWARE_EXT1)
|
||||
coord_t yOffset = TOPBAR_HEIGHT / 2;
|
||||
|
||||
if (IS_POT_SLIDER_AVAILABLE(EXT1)) {
|
||||
new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; });
|
||||
new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT_EXT1]; });
|
||||
}
|
||||
else {
|
||||
new MainViewVerticalSlider(this, {HMARGIN, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE, VERTICAL_SLIDERS_HEIGHT(true)},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT]; });
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HARDWARE_EXT2)
|
||||
if (IS_POT_SLIDER_AVAILABLE(EXT2)) {
|
||||
new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE,
|
||||
VERTICAL_SLIDERS_HEIGHT(true) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; });
|
||||
new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 + yOffset, TRIM_SQUARE_SIZE,
|
||||
VERTICAL_SLIDERS_HEIGHT(true) / 2},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT_EXT2]; });
|
||||
}
|
||||
else {
|
||||
new MainViewVerticalSlider(this, {LCD_W - HMARGIN - TRIM_SQUARE_SIZE, LCD_H / 2 - VERTICAL_SLIDERS_HEIGHT(true) / 2 + yOffset, TRIM_SQUARE_SIZE,
|
||||
VERTICAL_SLIDERS_HEIGHT(true)},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT]; });
|
||||
}
|
||||
#endif
|
||||
#elif defined(PCBNV14)
|
||||
new PotCalibrationWindow(window, {0, window->height()-25, 150, 20}, POT1);
|
||||
new PotCalibrationWindow(window, {LCD_W-150, window->height()-25, 150, 20}, POT2);
|
||||
new MainViewHorizontalSlider(this, {HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT1]; });
|
||||
|
||||
new MainViewHorizontalSlider(this, {LCD_W - HORIZONTAL_SLIDERS_WIDTH - HMARGIN, LCD_H - TRIM_SQUARE_SIZE, HORIZONTAL_SLIDERS_WIDTH, TRIM_SQUARE_SIZE},
|
||||
[=] { return calibratedAnalogs[CALIBRATED_POT2]; });
|
||||
|
||||
new TextButton(window, {LCD_W - 120, LCD_H - 140, 90, 40}, "Next",
|
||||
[=]() -> uint8_t {
|
||||
nextStep();
|
||||
return 0;
|
||||
}, BUTTON_BACKGROUND | NO_FOCUS);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -149,8 +142,8 @@ void RadioCalibrationPage::checkEvents()
|
||||
{
|
||||
Page::checkEvents();
|
||||
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS; i++) { // get low and high vals for sticks and trims
|
||||
int16_t vt = i<TX_VOLTAGE ? anaIn(i) : anaIn(i+1);
|
||||
for (uint8_t i = 0; i < NUM_STICKS + NUM_POTS + NUM_SLIDERS + NUM_MOUSE_ANALOGS; i++) { // get low and high vals for sticks and trims
|
||||
int16_t vt = i < TX_VOLTAGE ? anaIn(i) : anaIn(i + 1);
|
||||
reusableBuffer.calib.loVals[i] = min(vt, reusableBuffer.calib.loVals[i]);
|
||||
reusableBuffer.calib.hiVals[i] = max(vt, reusableBuffer.calib.hiVals[i]);
|
||||
if (i >= POT1 && i <= POT_LAST) {
|
||||
@@ -163,7 +156,8 @@ void RadioCalibrationPage::checkEvents()
|
||||
if (IS_POT_MULTIPOS(i) && count <= XPOTS_MULTIPOS_COUNT) {
|
||||
// use raw analog value for multipos calibraton, anaIn() already has multipos decoded value
|
||||
vt = getAnalogValue(i) >> 1;
|
||||
if (reusableBuffer.calib.xpotsCalib[idx].lastCount == 0 || vt < reusableBuffer.calib.xpotsCalib[idx].lastPosition - XPOT_DELTA || vt > reusableBuffer.calib.xpotsCalib[idx].lastPosition + XPOT_DELTA) {
|
||||
if (reusableBuffer.calib.xpotsCalib[idx].lastCount == 0 || vt < reusableBuffer.calib.xpotsCalib[idx].lastPosition - XPOT_DELTA ||
|
||||
vt > reusableBuffer.calib.xpotsCalib[idx].lastPosition + XPOT_DELTA) {
|
||||
reusableBuffer.calib.xpotsCalib[idx].lastPosition = vt;
|
||||
reusableBuffer.calib.xpotsCalib[idx].lastCount = 1;
|
||||
}
|
||||
@@ -175,9 +169,9 @@ void RadioCalibrationPage::checkEvents()
|
||||
if (reusableBuffer.calib.xpotsCalib[idx].lastCount == XPOT_DELAY) {
|
||||
int16_t position = reusableBuffer.calib.xpotsCalib[idx].lastPosition;
|
||||
bool found = false;
|
||||
for (int j=0; j<count; j++) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
int16_t step = reusableBuffer.calib.xpotsCalib[idx].steps[j];
|
||||
if (position >= step-XPOT_DELTA && position <= step+XPOT_DELTA) {
|
||||
if (position >= step - XPOT_DELTA && position <= step + XPOT_DELTA) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -218,13 +212,13 @@ void RadioCalibrationPage::checkEvents()
|
||||
}
|
||||
}
|
||||
#if NUM_XPOTS > 0
|
||||
for (int i=POT1; i<=POT_LAST; i++) {
|
||||
for (int i = POT1; i <= POT_LAST; i++) {
|
||||
int idx = i - POT1;
|
||||
int count = reusableBuffer.calib.xpotsCalib[idx].stepsCount;
|
||||
if (IS_POT_MULTIPOS(i)) {
|
||||
if (count > 1 && count <= XPOTS_MULTIPOS_COUNT) {
|
||||
for (int j=0; j<count; j++) {
|
||||
for (int k=j+1; k<count; k++) {
|
||||
for (int j = 0; j < count; j++) {
|
||||
for (int k = j + 1; k < count; k++) {
|
||||
if (reusableBuffer.calib.xpotsCalib[idx].steps[k] < reusableBuffer.calib.xpotsCalib[idx].steps[j]) {
|
||||
SWAP(reusableBuffer.calib.xpotsCalib[idx].steps[j], reusableBuffer.calib.xpotsCalib[idx].steps[k]);
|
||||
}
|
||||
@@ -232,8 +226,8 @@ void RadioCalibrationPage::checkEvents()
|
||||
}
|
||||
StepsCalibData * calib = (StepsCalibData *) &g_eeGeneral.calib[i];
|
||||
calib->count = count - 1;
|
||||
for (int j=0; j<calib->count; j++) {
|
||||
calib->steps[j] = (reusableBuffer.calib.xpotsCalib[idx].steps[j+1] + reusableBuffer.calib.xpotsCalib[idx].steps[j]) >> 5;
|
||||
for (int j = 0; j < calib->count; j++) {
|
||||
calib->steps[j] = (reusableBuffer.calib.xpotsCalib[idx].steps[j + 1] + reusableBuffer.calib.xpotsCalib[idx].steps[j]) >> 5;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -253,8 +247,7 @@ void RadioCalibrationPage::onEvent(event_t event)
|
||||
if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
nextStep();
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_EXIT) && menuCalibrationState != CALIB_START)
|
||||
{
|
||||
else if (event == EVT_KEY_BREAK(KEY_EXIT) && menuCalibrationState != CALIB_START) {
|
||||
menuCalibrationState = CALIB_START;
|
||||
text->setText(STR_MENUTOSTART);
|
||||
|
||||
|
||||
@@ -184,7 +184,34 @@ void RadioHardwarePage::build(FormWindow * window)
|
||||
for (int i = 0; i < NUM_POTS; i++) {
|
||||
new StaticText(window, grid.getLabelSlot(true), TEXT_AT_INDEX(STR_VSRCRAW, (i + NUM_STICKS + 1)));
|
||||
new TextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i + NUM_STICKS], LEN_ANA_NAME);
|
||||
new Choice(window, grid.getFieldSlot(2,1), STR_POTTYPES, POT_NONE, POT_WITHOUT_DETENT, GET_SET_BF(g_eeGeneral.potsConfig, 2 * i, 2));
|
||||
new Choice(window, grid.getFieldSlot(2,1), STR_POTTYPES, POT_NONE, POT_WITHOUT_DETENT,
|
||||
[=]() -> int {
|
||||
return bfGet<uint32_t>(g_eeGeneral.potsConfig, 2*i, 2);
|
||||
},
|
||||
[=](int newValue) {
|
||||
g_eeGeneral.potsConfig = bfSet<uint32_t>(g_eeGeneral.potsConfig, newValue, 2*i, 2);
|
||||
SET_DIRTY();
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
// Sliders
|
||||
new Subtitle(window, grid.getLineSlot(), STR_SLIDERS);
|
||||
grid.nextLine();
|
||||
for (int i = 0; i < NUM_SLIDERS; i++) {
|
||||
new StaticText(window, grid.getLabelSlot(true), TEXT_AT_INDEX(STR_VSRCRAW, (i + NUM_STICKS + NUM_POTS + 1)));
|
||||
new TextEdit(window, grid.getFieldSlot(2,0), g_eeGeneral.anaNames[i + NUM_STICKS], LEN_ANA_NAME);
|
||||
new Choice(window, grid.getFieldSlot(2,1), STR_SLIDERTYPES, SLIDER_NONE, SLIDER_WITH_DETENT,
|
||||
[=]() -> int {
|
||||
uint8_t mask = (0x01 << i);
|
||||
return (g_eeGeneral.slidersConfig & mask) >> i;
|
||||
},
|
||||
[=](int newValue) {
|
||||
uint8_t mask = (0x01 << i);
|
||||
g_eeGeneral.slidersConfig &= ~mask;
|
||||
g_eeGeneral.slidersConfig |= (newValue << i);
|
||||
SET_DIRTY();
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
@@ -248,6 +275,29 @@ void RadioHardwarePage::build(FormWindow * window)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
new StaticText(window, grid.getLabelSlot(), STR_AUX_SERIAL_MODE);
|
||||
auto aux = new Choice(window, grid.getFieldSlot(1,0), STR_AUX_SERIAL_MODES, 0, UART_MODE_MAX, GET_SET_DEFAULT(g_eeGeneral.auxSerialMode));
|
||||
aux->setAvailableHandler([=](int value) {
|
||||
return isAuxModeAvailable;
|
||||
});
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
new StaticText(window, grid.getLabelSlot(), STR_AUX2_SERIAL_MODE);
|
||||
auto aux2 = new Choice(window, grid.getFieldSlot(1,0), STR_AUX_SERIAL_MODES, 0, UART_MODE_MAX, GET_SET_DEFAULT(g_eeGeneral.aux2SerialMode));
|
||||
aux2->setAvailableHandler([=](int value) {
|
||||
return isAux2ModeAvailable;
|
||||
});
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL) || defined(AUX2_SERIAL)
|
||||
new StaticText(window, grid.getFieldSlot(1,0), STR_TTL_WARNING, 0, ALARM_COLOR);
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
// ADC filter
|
||||
new StaticText(window, grid.getLabelSlot(), STR_JITTER_FILTER);
|
||||
new CheckBox(window, grid.getFieldSlot(), GET_SET_INVERTED(g_eeGeneral.jitterFilter));
|
||||
|
||||
@@ -23,56 +23,12 @@
|
||||
#include "radio_spectrum_analyser.h"
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
#include "lua/lua_api.h"
|
||||
|
||||
extern uint8_t g_moduleIdx;
|
||||
|
||||
#define TOOL_NAME_MAXLEN 16
|
||||
|
||||
#if defined(LUA) || defined(DEBUG)
|
||||
bool readToolName(const char * filename, char * name)
|
||||
{
|
||||
FIL file;
|
||||
char buffer[1024];
|
||||
UINT count;
|
||||
|
||||
if (f_open(&file, filename, FA_READ) != FR_OK) {
|
||||
return "Error opening file";
|
||||
}
|
||||
|
||||
if (f_read(&file, &buffer, sizeof(buffer), &count) != FR_OK) {
|
||||
f_close(&file);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * tns = "TNS|";
|
||||
auto * start = std::search(buffer, buffer + sizeof(buffer), tns, tns + 4);
|
||||
if (start >= buffer + sizeof(buffer))
|
||||
return false;
|
||||
|
||||
start += 4;
|
||||
|
||||
const char * tne = "|TNE";
|
||||
auto * end = std::search(buffer, buffer + sizeof(buffer), tne, tne + 4);
|
||||
if (end >= buffer + sizeof(buffer) || end <= start)
|
||||
return false;
|
||||
|
||||
uint8_t len = end - start;
|
||||
if (len > TOOL_NAME_MAXLEN)
|
||||
return false;
|
||||
|
||||
strncpy(name, start, len);
|
||||
memclear(name + len, TOOL_NAME_MAXLEN + 1 - len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isRadioScriptTool(const char * filename)
|
||||
{
|
||||
const char * ext = getFileExtension(filename);
|
||||
return ext && !strcasecmp(ext, SCRIPT_EXT);
|
||||
}
|
||||
#endif
|
||||
|
||||
RadioToolsPage::RadioToolsPage():
|
||||
PageTab(STR_MENUTOOLS, ICON_RADIO_TOOLS)
|
||||
{
|
||||
@@ -168,7 +124,7 @@ void RadioToolsPage::rebuild(FormWindow * window)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PXX2)
|
||||
#if defined(INTERNAL_MODULE_PXX2)
|
||||
// PXX2 modules tools
|
||||
if (isPXX2ModuleOptionAvailable(reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].information.modelID, MODULE_OPTION_SPECTRUM_ANALYSER)) {
|
||||
new StaticText(window, grid.getLabelSlot(), "access", BUTTON_BACKGROUND, CENTERED);
|
||||
@@ -187,7 +143,8 @@ void RadioToolsPage::rebuild(FormWindow * window)
|
||||
}, 0);
|
||||
grid.nextLine();
|
||||
}
|
||||
#elif defined(INTERNAL_MODULE_MULTI)
|
||||
#endif
|
||||
#if defined(INTERNAL_MODULE_MULTI)
|
||||
new StaticText(window, grid.getLabelSlot(), "multi", BUTTON_BACKGROUND, CENTERED);
|
||||
new TextButton(window, grid.getFieldSlot(1), STR_SPECTRUM_ANALYSER_INT, [=]() -> uint8_t {
|
||||
new RadioSpectrumAnalyser(INTERNAL_MODULE);
|
||||
|
||||
@@ -23,6 +23,148 @@
|
||||
#include "options.h"
|
||||
#include "libopenui.h"
|
||||
|
||||
char * getVersion(char * str, PXX2Version version)
|
||||
{
|
||||
if (version.major == 0xFF && version.minor == 0x0F && version.revision == 0x0F) {
|
||||
return strAppend(str, "---", 4);
|
||||
}
|
||||
else {
|
||||
sprintf(str, "%u.%u.%u", (1 + version.major) % 0xFF, version.minor, version.revision);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
class versionDialog: public Dialog
|
||||
{
|
||||
public:
|
||||
versionDialog(Window * parent, rect_t rect) :
|
||||
Dialog(parent, STR_MODULES_RX_VERSION, rect)
|
||||
{
|
||||
memclear(&reusableBuffer.hardwareAndSettings.modules, sizeof(reusableBuffer.hardwareAndSettings.modules));
|
||||
reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms();
|
||||
|
||||
// Query modules
|
||||
if (isModulePXX2(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) {
|
||||
moduleState[INTERNAL_MODULE].readModuleInformation(&reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE], PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1);
|
||||
}
|
||||
|
||||
if (isModulePXX2(EXTERNAL_MODULE) && IS_EXTERNAL_MODULE_ON()) {
|
||||
moduleState[EXTERNAL_MODULE].readModuleInformation(&reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE], PXX2_HW_INFO_TX_ID, PXX2_MAX_RECEIVERS_PER_MODULE - 1);
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
FormGroup * form = &content->form;
|
||||
FormGridLayout grid(content->form.width());
|
||||
form->clear();
|
||||
|
||||
grid.setLabelWidth(100);
|
||||
|
||||
// Internal module
|
||||
drawModuleVersion(form, &grid, INTERNAL_MODULE);
|
||||
grid.nextLine();
|
||||
|
||||
// external module
|
||||
drawModuleVersion(form, &grid, EXTERNAL_MODULE);
|
||||
grid.nextLine();
|
||||
|
||||
// Exit
|
||||
exitButton = new TextButton(form, grid.getLabelSlot(), "EXIT",
|
||||
[=]() -> int8_t {
|
||||
this->deleteLater();
|
||||
return 0;
|
||||
});
|
||||
exitButton->setFocus(SET_FOCUS_DEFAULT);
|
||||
grid.nextLine();
|
||||
|
||||
grid.spacer(PAGE_PADDING);
|
||||
form->setHeight(grid.getWindowHeight());
|
||||
content->adjustHeight();
|
||||
}
|
||||
|
||||
void drawModuleVersion(FormGroup * form, FormGridLayout *grid, uint8_t module)
|
||||
{
|
||||
char tmp[20];
|
||||
|
||||
// Module
|
||||
if (module == INTERNAL_MODULE)
|
||||
new StaticText(form, grid->getLineSlot(), STR_INTERNAL_MODULE);
|
||||
else
|
||||
new StaticText(form, grid->getLineSlot(), STR_EXTERNAL_MODULE);
|
||||
grid->nextLine();
|
||||
|
||||
new StaticText(form, grid->getLabelSlot(true), STR_MODULE);
|
||||
if (g_model.moduleData[module].type == MODULE_TYPE_NONE) {
|
||||
new StaticText(form, grid->getFieldSlot(1, 0), STR_OFF);
|
||||
}
|
||||
#if defined(HARDWARE_EXTERNAL_ACCESS_MOD)
|
||||
else if (isModuleMultimodule(module)) {
|
||||
char statusText[64];
|
||||
new StaticText(form, grid->getFieldSlot(2, 0), "Multimodule");
|
||||
getMultiModuleStatus(module).getStatusString(statusText);
|
||||
new StaticText(form, grid->getFieldSlot(2, 1), statusText);
|
||||
}
|
||||
#endif
|
||||
else if (!isModulePXX2(module)) {
|
||||
new StaticText(form, grid->getFieldSlot(1, 0), STR_NO_INFORMATION);
|
||||
}
|
||||
else {
|
||||
// PXX2 Module
|
||||
new StaticText(form, grid->getFieldSlot(4, 0), getPXX2ModuleName(reusableBuffer.hardwareAndSettings.modules[module].information.modelID));
|
||||
if (reusableBuffer.hardwareAndSettings.modules[module].information.modelID) {
|
||||
new StaticText(form, grid->getFieldSlot(4, 1), getVersion(tmp, reusableBuffer.hardwareAndSettings.modules[module].information.hwVersion));
|
||||
new StaticText(form, grid->getFieldSlot(4, 2), getVersion(tmp, reusableBuffer.hardwareAndSettings.modules[module].information.swVersion));
|
||||
static const char * variants[] = {"FCC", "EU", "FLEX"};
|
||||
uint8_t variant = reusableBuffer.hardwareAndSettings.modules[module].information.variant - 1;
|
||||
if (variant < DIM(variants)) {
|
||||
new StaticText(form, grid->getFieldSlot(4, 3), variants[variant]);
|
||||
}
|
||||
}
|
||||
grid->nextLine();
|
||||
|
||||
// PXX2 Receivers
|
||||
for (uint8_t receiver=0; receiver<PXX2_MAX_RECEIVERS_PER_MODULE; receiver++) {
|
||||
if (reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.modelID) {
|
||||
// Receiver model
|
||||
new StaticText(form, grid->getLabelSlot(true), STR_RECEIVER);
|
||||
uint8_t modelId = reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.modelID;
|
||||
new StaticText(form, grid->getFieldSlot(4, 0), getPXX2ReceiverName(modelId));
|
||||
|
||||
// Receiver version
|
||||
new StaticText(form, grid->getFieldSlot(4, 1), getVersion(tmp, reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.hwVersion));
|
||||
new StaticText(form, grid->getFieldSlot(4, 2), getVersion(tmp, reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.swVersion));
|
||||
grid->nextLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
if (get_tmr10ms() >= reusableBuffer.hardwareAndSettings.updateTime) {
|
||||
// Query modules
|
||||
if (isModulePXX2(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) {
|
||||
moduleState[INTERNAL_MODULE].readModuleInformation(&reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE], PXX2_HW_INFO_TX_ID,
|
||||
PXX2_MAX_RECEIVERS_PER_MODULE - 1);
|
||||
}
|
||||
if (isModulePXX2(EXTERNAL_MODULE) && IS_EXTERNAL_MODULE_ON()) {
|
||||
moduleState[EXTERNAL_MODULE].readModuleInformation(&reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE], PXX2_HW_INFO_TX_ID,
|
||||
PXX2_MAX_RECEIVERS_PER_MODULE - 1);
|
||||
}
|
||||
reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms() + 500 /* 5s*/;
|
||||
}
|
||||
update();
|
||||
Dialog::checkEvents();
|
||||
}
|
||||
|
||||
protected:
|
||||
rect_t rect;
|
||||
TextButton * exitButton;
|
||||
};
|
||||
|
||||
class OptionsText: public StaticText {
|
||||
public:
|
||||
OptionsText(Window * parent, const rect_t &rect) :
|
||||
@@ -41,7 +183,7 @@ class OptionsText: public StaticText {
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
coord_t y = 0;
|
||||
coord_t y = 2;
|
||||
coord_t x = 0;
|
||||
for (uint8_t i = 0; options[i]; i++) {
|
||||
const char * option = options[i];
|
||||
@@ -66,12 +208,14 @@ RadioVersionPage::RadioVersionPage():
|
||||
void RadioVersionPage::build(FormWindow * window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.setLabelWidth(120);
|
||||
grid.setLabelWidth(60);
|
||||
grid.spacer(PAGE_PADDING);
|
||||
|
||||
new StaticText(window, grid.getLabelSlot(), "FW Version");
|
||||
// Radio type
|
||||
new StaticText(window, grid.getLineSlot(), fw_stamp);
|
||||
grid.nextLine();
|
||||
#if LCD_W > LCD_H
|
||||
new StaticText(window, grid.getFieldSlot(), vers_stamp);
|
||||
new StaticText(window, grid.getLineSlot(), vers_stamp);
|
||||
#else
|
||||
memcpy(reusableBuffer.version.id, vers_stamp, strcspn(vers_stamp, " "));
|
||||
new StaticText(window, grid.getFieldSlot(), reusableBuffer.version.id);
|
||||
@@ -82,30 +226,29 @@ void RadioVersionPage::build(FormWindow * window)
|
||||
#endif
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(window, grid.getLabelSlot(), "FW Options");
|
||||
auto firmwareOptions = new OptionsText(window, grid.getFieldSlot());
|
||||
grid.spacer(firmwareOptions->height() + PAGE_LINE_SPACING);
|
||||
|
||||
new StaticText(window, grid.getLabelSlot(), "FW Date");
|
||||
new StaticText(window, grid.getFieldSlot(), date_stamp);
|
||||
// Firmware date
|
||||
new StaticText(window, grid.getLineSlot(), date_stamp);
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(window, grid.getLabelSlot(), "FW Time");
|
||||
new StaticText(window, grid.getFieldSlot(), time_stamp);
|
||||
// Firmware time
|
||||
new StaticText(window, grid.getLineSlot(), time_stamp);
|
||||
grid.nextLine();
|
||||
|
||||
new StaticText(window, grid.getLabelSlot(), "Data version");
|
||||
new StaticText(window, grid.getFieldSlot(), eeprom_stamp);
|
||||
// EEprom version
|
||||
new StaticText(window, grid.getLineSlot(), eeprom_stamp);
|
||||
grid.nextLine();
|
||||
|
||||
getCPUUniqueID(reusableBuffer.version.id);
|
||||
new StaticText(window, grid.getLabelSlot(), "CPU UID");
|
||||
#if LCD_W > LCD_H
|
||||
new StaticText(window, grid.getFieldSlot(), reusableBuffer.version.id);
|
||||
#else
|
||||
grid.nextLine();
|
||||
new StaticText(window, {PAGE_PADDING, static_cast<coord_t>(grid.getWindowHeight() + PAGE_LINE_SPACING), static_cast<coord_t>(window->width() - PAGE_PADDING),
|
||||
PAGE_LINE_HEIGHT}, reusableBuffer.version.id);
|
||||
// Firmware options
|
||||
new StaticText(window, grid.getLabelSlot(), "OPTS:");
|
||||
auto options = new OptionsText(window, grid.getFieldSlot(1,0));
|
||||
grid.nextLine(options->height() + 4);
|
||||
|
||||
#if defined(PXX2)
|
||||
// Module and receivers versions
|
||||
auto moduleVersions = new TextButton(window, grid.getLineSlot(), STR_MODULES_RX_VERSION);
|
||||
moduleVersions->setPressHandler([=]() -> uint8_t {
|
||||
new versionDialog(window, {50, 30, LCD_W - 100, 0});
|
||||
return 0;
|
||||
});
|
||||
#endif
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class SourceChoiceMenuToolbar : public MenuToolbar<SourceChoice> {
|
||||
#if defined(LUA_MODEL_SCRIPTS)
|
||||
addButton(CHAR_LUA, MIXSRC_LAST_LUA, MIXSRC_FIRST_LUA);
|
||||
#endif
|
||||
addButton(char(CHAR_STICK), MIXSRC_FIRST_STICK, MIXSRC_LAST_STICK);
|
||||
addButton(CHAR_STICK, MIXSRC_FIRST_STICK, MIXSRC_LAST_STICK);
|
||||
addButton(CHAR_POT, MIXSRC_FIRST_POT, MIXSRC_LAST_POT);
|
||||
addButton(CHAR_FUNCTION, MIXSRC_MAX, MIXSRC_MAX);
|
||||
#if defined(HELI)
|
||||
@@ -48,7 +48,7 @@ class SourceChoiceMenuToolbar : public MenuToolbar<SourceChoice> {
|
||||
addButton(CHAR_TRAINER, MIXSRC_FIRST_TRAINER, MIXSRC_LAST_TRAINER);
|
||||
addButton(CHAR_CHANNEL, MIXSRC_FIRST_CH, MIXSRC_LAST_CH);
|
||||
#if defined(GVARS)
|
||||
addButton(CHAR_GVAR, MIXSRC_LAST_GVAR, MIXSRC_FIRST_GVAR);
|
||||
addButton(CHAR_SLIDER, MIXSRC_LAST_GVAR, MIXSRC_FIRST_GVAR);
|
||||
#endif
|
||||
addButton(CHAR_TELEMETRY, MIXSRC_FIRST_TELEM, MIXSRC_LAST_TELEM);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ void SourceChoice::paint(BitmapBuffer * dc)
|
||||
drawSource(dc, FIELD_PADDING_LEFT, FIELD_PADDING_TOP, value, textColor);
|
||||
}
|
||||
|
||||
void SourceChoice::fillMenu(Menu * menu, std::function<bool(int16_t)> filter)
|
||||
void SourceChoice::fillMenu(Menu * menu, const std::function<bool(int16_t)> & filter)
|
||||
{
|
||||
auto value = getValue();
|
||||
int count = 0;
|
||||
|
||||
@@ -68,7 +68,7 @@ class SourceChoice : public FormField {
|
||||
std::function<int16_t()> getValue;
|
||||
std::function<void(int16_t)> setValue;
|
||||
std::function<bool(int)> isValueAvailable = isSourceAvailable;
|
||||
void fillMenu(Menu * menu, std::function<bool(int16_t)> condition=nullptr);
|
||||
void fillMenu(Menu * menu, const std::function<bool(int16_t)> & condition=nullptr);
|
||||
void openMenu();
|
||||
};
|
||||
|
||||
|
||||
@@ -37,11 +37,11 @@ class SpecialFunctionEditPage : public Page {
|
||||
protected:
|
||||
CustomFunctionData * functions;
|
||||
uint8_t index;
|
||||
FormWindow * specialFunctionOneWindow = nullptr;
|
||||
FormGroup * specialFunctionOneWindow = nullptr;
|
||||
StaticText * headerSF = nullptr;
|
||||
bool active = false;
|
||||
|
||||
bool isActive()
|
||||
bool isActive() const
|
||||
{
|
||||
return ((functions == g_model.customFn ? modelFunctionsContext.activeSwitches : globalFunctionsContext.activeSwitches) & ((MASK_CFN_TYPE)1 << index) ? 1 : 0);
|
||||
}
|
||||
@@ -62,7 +62,7 @@ class SpecialFunctionEditPage : public Page {
|
||||
headerSF = new StaticText(window, { PAGE_TITLE_LEFT, PAGE_TITLE_TOP + PAGE_LINE_HEIGHT, LCD_W - PAGE_TITLE_LEFT, 20 }, (functions == g_model.customFn ? "SF" : "GF" ) + std::to_string(index), 0, MENU_COLOR);
|
||||
}
|
||||
|
||||
void updateSpecialFunctionOneWindow(FormField * previousField, FormField * nextField)
|
||||
void updateSpecialFunctionOneWindow()
|
||||
{
|
||||
FormGridLayout grid;
|
||||
specialFunctionOneWindow->clear();
|
||||
@@ -111,6 +111,12 @@ class SpecialFunctionEditPage : public Page {
|
||||
grid.nextLine();
|
||||
break;
|
||||
|
||||
case FUNC_BACKLIGHT:
|
||||
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
|
||||
new SourceChoice(specialFunctionOneWindow, grid.getFieldSlot(), 0, MIXSRC_LAST_CH, GET_SET_DEFAULT(CFN_PARAM(cfn)));
|
||||
grid.nextLine();
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_SOUND:
|
||||
new StaticText(specialFunctionOneWindow, grid.getLabelSlot(), STR_VALUE);
|
||||
new Choice(specialFunctionOneWindow, grid.getFieldSlot(), STR_FUNCSOUNDS, 0,
|
||||
@@ -195,7 +201,10 @@ class SpecialFunctionEditPage : public Page {
|
||||
else
|
||||
dc->drawNumber(3, 0, value * CFN_PLAY_REPEAT_MUL, flags, 0, nullptr, "s");
|
||||
});
|
||||
grid.nextLine();
|
||||
}
|
||||
|
||||
specialFunctionOneWindow->adjustHeight();
|
||||
}
|
||||
|
||||
void buildBody(FormWindow * window)
|
||||
@@ -223,15 +232,15 @@ class SpecialFunctionEditPage : public Page {
|
||||
CFN_FUNC(cfn) = newValue;
|
||||
CFN_RESET(cfn);
|
||||
SET_DIRTY();
|
||||
updateSpecialFunctionOneWindow(functionChoice, switchChoice);
|
||||
updateSpecialFunctionOneWindow();
|
||||
});
|
||||
functionChoice->setAvailableHandler([=](int value) {
|
||||
return isAssignableFunctionAvailable(value, functions);
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
specialFunctionOneWindow = new FormWindow(window, {0, grid.getWindowHeight(), LCD_W, 0});
|
||||
updateSpecialFunctionOneWindow(functionChoice, switchChoice);
|
||||
specialFunctionOneWindow = new FormGroup(window, {0, grid.getWindowHeight(), LCD_W, 0}, FORM_FORWARD_FOCUS);
|
||||
updateSpecialFunctionOneWindow();
|
||||
grid.addWindow(specialFunctionOneWindow);
|
||||
}
|
||||
};
|
||||
@@ -264,7 +273,7 @@ class SpecialFunctionButton : public Button {
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isActive()
|
||||
bool isActive() const
|
||||
{
|
||||
return ((functions == g_model.customFn ? modelFunctionsContext.activeSwitches : globalFunctionsContext.activeSwitches) & ((MASK_CFN_TYPE)1 << index) ? 1 : 0);
|
||||
}
|
||||
@@ -319,6 +328,10 @@ class SpecialFunctionButton : public Button {
|
||||
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
|
||||
break;
|
||||
|
||||
case FUNC_BACKLIGHT:
|
||||
drawSource(dc, col1, line2, CFN_PARAM(cfn), 0);
|
||||
break;
|
||||
|
||||
case FUNC_PLAY_SOUND:
|
||||
dc->drawTextAtIndex(col1, line2, STR_FUNCSOUNDS, CFN_PARAM(cfn));
|
||||
break;
|
||||
|
||||
@@ -25,15 +25,17 @@
|
||||
#include "draw_functions.h"
|
||||
#include "strhelpers.h"
|
||||
#include "dataconstants.h"
|
||||
#include "opentx.h"
|
||||
|
||||
class SwitchChoiceMenuToolbar : public MenuToolbar<SwitchChoice> {
|
||||
class SwitchChoiceMenuToolbar : public MenuToolbar<SwitchChoice>
|
||||
{
|
||||
public:
|
||||
SwitchChoiceMenuToolbar(SwitchChoice * choice, Menu * menu):
|
||||
MenuToolbar<SwitchChoice>(choice, menu)
|
||||
{
|
||||
addButton(char('\312'), SWSRC_FIRST_SWITCH, SWSRC_LAST_SWITCH);
|
||||
addButton(char('\313'), SWSRC_FIRST_TRIM, SWSRC_LAST_TRIM);
|
||||
addButton(char('\312'), SWSRC_FIRST_LOGICAL_SWITCH, SWSRC_LAST_LOGICAL_SWITCH);
|
||||
addButton(CHAR_SWITCH, SWSRC_FIRST_SWITCH, SWSRC_LAST_SWITCH);
|
||||
addButton(CHAR_TRIM, SWSRC_FIRST_TRIM, SWSRC_LAST_TRIM);
|
||||
addButton(CHAR_SWITCH, SWSRC_FIRST_LOGICAL_SWITCH, SWSRC_LAST_LOGICAL_SWITCH);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ TabsGroupHeader::TabsGroupHeader(TabsGroup * parent, uint8_t icon):
|
||||
back(this, { 0, 0, MENU_HEADER_BUTTON_WIDTH, MENU_HEADER_BUTTON_WIDTH }, ICON_BACK,
|
||||
[=]() -> uint8_t {
|
||||
parent->deleteLater();
|
||||
ViewMain::instance->setFocus((SET_FOCUS_DEFAULT));
|
||||
return 1;
|
||||
}, NO_FOCUS),
|
||||
#endif
|
||||
@@ -51,7 +52,7 @@ TabsGroupHeader::~TabsGroupHeader()
|
||||
|
||||
void TabsGroupHeader::paint(BitmapBuffer * dc)
|
||||
{
|
||||
static_cast<ThemeBase *>(theme)->drawMenuBackground(dc, icon, title);
|
||||
OpenTxTheme::instance()->drawMenuBackground(dc, icon, title);
|
||||
}
|
||||
|
||||
TabsCarousel::TabsCarousel(Window * parent, TabsGroup * menu):
|
||||
@@ -67,7 +68,7 @@ void TabsCarousel::updateInnerWidth()
|
||||
|
||||
void TabsCarousel::paint(BitmapBuffer * dc)
|
||||
{
|
||||
static_cast<ThemeBase *>(theme)->drawMenuHeader(dc, menu->tabs, currentIndex);
|
||||
OpenTxTheme::instance()->drawMenuHeader(dc, menu->tabs, currentIndex);
|
||||
}
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
@@ -163,7 +164,11 @@ void TabsGroup::onEvent(event_t event)
|
||||
uint8_t current = header.carousel.getCurrentIndex() + 1;
|
||||
setCurrentTab(current >= tabs.size() ? 0 : current);
|
||||
}
|
||||
#if defined(KEYS_GPIO_REG_UP)
|
||||
else if (event == EVT_KEY_BREAK(KEY_PGUP)) {
|
||||
#else
|
||||
else if (event == EVT_KEY_LONG(KEY_PGDN)) {
|
||||
#endif
|
||||
killEvents(event);
|
||||
uint8_t current = header.carousel.getCurrentIndex();
|
||||
setCurrentTab(current == 0 ? tabs.size() - 1 : current - 1);
|
||||
|
||||
@@ -22,10 +22,10 @@
|
||||
//#include "checkbox.h"
|
||||
//#include "modal_window.h"
|
||||
|
||||
extern ThemeBase * defaultTheme;
|
||||
const BitmapBuffer * ThemeBase::asterisk = nullptr;
|
||||
const BitmapBuffer * ThemeBase::question = nullptr;
|
||||
const BitmapBuffer * ThemeBase::busy = nullptr;
|
||||
extern OpenTxTheme * defaultTheme;
|
||||
const BitmapBuffer * OpenTxTheme::asterisk = nullptr;
|
||||
const BitmapBuffer * OpenTxTheme::question = nullptr;
|
||||
const BitmapBuffer * OpenTxTheme::busy = nullptr;
|
||||
|
||||
const uint8_t LBM_FOLDER[] = {
|
||||
#include "mask_folder.lbm"
|
||||
@@ -35,21 +35,21 @@ const uint8_t LBM_DROPDOWN[] = {
|
||||
#include "mask_dropdown.lbm"
|
||||
};
|
||||
|
||||
std::list<ThemeBase *> & getRegisteredThemes()
|
||||
std::list<OpenTxTheme *> & getRegisteredThemes()
|
||||
{
|
||||
static std::list<ThemeBase *> themes;
|
||||
static std::list<OpenTxTheme *> themes;
|
||||
return themes;
|
||||
}
|
||||
|
||||
void registerTheme(ThemeBase * theme)
|
||||
void registerTheme(OpenTxTheme * theme)
|
||||
{
|
||||
TRACE("register theme %s", theme->getName());
|
||||
getRegisteredThemes().push_back(theme);
|
||||
}
|
||||
|
||||
void ThemeBase::init() const
|
||||
void OpenTxTheme::init() const
|
||||
{
|
||||
memset(&g_eeGeneral.themeData, 0, sizeof(ThemeBase::PersistentData));
|
||||
memset(&g_eeGeneral.themeData, 0, sizeof(OpenTxTheme::PersistentData));
|
||||
if (options) {
|
||||
int i = 0;
|
||||
for (const ZoneOption * option = options; option->name; option++, i++) {
|
||||
@@ -60,7 +60,7 @@ void ThemeBase::init() const
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeBase::load() const
|
||||
void OpenTxTheme::load() const
|
||||
{
|
||||
if (!asterisk)
|
||||
asterisk = BitmapBuffer::loadBitmap(getFilePath("asterisk.bmp"));
|
||||
@@ -70,12 +70,12 @@ void ThemeBase::load() const
|
||||
busy = BitmapBuffer::loadBitmap(getFilePath("busy.bmp"));
|
||||
}
|
||||
|
||||
ZoneOptionValue * ThemeBase::getOptionValue(unsigned int index) const
|
||||
ZoneOptionValue * OpenTxTheme::getOptionValue(unsigned int index) const
|
||||
{
|
||||
return &g_eeGeneral.themeData.options[index].value;
|
||||
}
|
||||
|
||||
const char * ThemeBase::getFilePath(const char * filename) const
|
||||
const char * OpenTxTheme::getFilePath(const char * filename) const
|
||||
{
|
||||
static char path[FF_MAX_LFN+1] = THEMES_PATH "/";
|
||||
strcpy(path + sizeof(THEMES_PATH), getName());
|
||||
@@ -85,7 +85,7 @@ const char * ThemeBase::getFilePath(const char * filename) const
|
||||
return path;
|
||||
}
|
||||
|
||||
void ThemeBase::drawThumb(BitmapBuffer * dc, coord_t x, coord_t y, uint32_t flags)
|
||||
void OpenTxTheme::drawThumb(BitmapBuffer * dc, coord_t x, coord_t y, uint32_t flags)
|
||||
{
|
||||
#define THUMB_WIDTH 51
|
||||
#define THUMB_HEIGHT 31
|
||||
@@ -98,12 +98,12 @@ void ThemeBase::drawThumb(BitmapBuffer * dc, coord_t x, coord_t y, uint32_t flag
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeBase::drawBackground(BitmapBuffer * dc) const
|
||||
void OpenTxTheme::drawBackground(BitmapBuffer * dc) const
|
||||
{
|
||||
dc->drawSolidFilledRect(0, 0, LCD_W, LCD_H, DEFAULT_BGCOLOR);
|
||||
}
|
||||
|
||||
void ThemeBase::drawMessageBox(const char * title, const char * text, const char * action, uint32_t type) const
|
||||
void OpenTxTheme::drawMessageBox(const char * title, const char * text, const char * action, uint32_t type) const
|
||||
{
|
||||
|
||||
}
|
||||
@@ -142,7 +142,7 @@ void ThemeBase::drawMessageBox(const char * title, const char * text, const char
|
||||
// }
|
||||
//}
|
||||
|
||||
void ThemeBase::drawCheckBox(BitmapBuffer * dc, bool checked, coord_t x, coord_t y, bool focus) const
|
||||
void OpenTxTheme::drawCheckBox(BitmapBuffer * dc, bool checked, coord_t x, coord_t y, bool focus) const
|
||||
{
|
||||
if (focus) {
|
||||
dc->drawSolidFilledRect(x + 0, y + 2, 16, 16, FOCUS_BGCOLOR);
|
||||
@@ -162,7 +162,7 @@ void ThemeBase::drawCheckBox(BitmapBuffer * dc, bool checked, coord_t x, coord_t
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeBase::drawChoice(BitmapBuffer * dc, ChoiceBase * choice, const char * str) const
|
||||
void OpenTxTheme::drawChoice(BitmapBuffer * dc, ChoiceBase * choice, const char * str) const
|
||||
{
|
||||
LcdFlags textColor;
|
||||
if (choice->isEditMode())
|
||||
@@ -178,7 +178,7 @@ void ThemeBase::drawChoice(BitmapBuffer * dc, ChoiceBase * choice, const char *
|
||||
dc->drawBitmapPattern(choice->getRect().w - 20, (choice->getRect().h - 11) / 2, choice->getType() == CHOICE_TYPE_FOLDER ? LBM_FOLDER : LBM_DROPDOWN, textColor);
|
||||
}
|
||||
|
||||
void ThemeBase::drawSlider(BitmapBuffer * dc, int vmin, int vmax, int value, const rect_t & rect, bool edit, bool focus) const
|
||||
void OpenTxTheme::drawSlider(BitmapBuffer * dc, int vmin, int vmax, int value, const rect_t & rect, bool edit, bool focus) const
|
||||
{
|
||||
int val = limit(vmin, value, vmax);
|
||||
int w = divRoundClosest((rect.w - 16) * (val - vmin), vmax - vmin);
|
||||
@@ -202,9 +202,9 @@ void ThemeBase::drawSlider(BitmapBuffer * dc, int vmin, int vmax, int value, con
|
||||
}
|
||||
}
|
||||
|
||||
ThemeBase * getTheme(const char * name)
|
||||
OpenTxTheme * getTheme(const char * name)
|
||||
{
|
||||
std::list<ThemeBase *>::const_iterator it = getRegisteredThemes().cbegin();
|
||||
std::list<OpenTxTheme *>::const_iterator it = getRegisteredThemes().cbegin();
|
||||
for (; it != getRegisteredThemes().cend(); ++it) {
|
||||
if (!strcmp(name, (*it)->getName())) {
|
||||
return (*it);
|
||||
@@ -213,7 +213,7 @@ ThemeBase * getTheme(const char * name)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void loadTheme(ThemeBase * newTheme)
|
||||
void loadTheme(OpenTxTheme * newTheme)
|
||||
{
|
||||
TRACE("load theme %s", newTheme->getName());
|
||||
theme = newTheme;
|
||||
@@ -225,7 +225,7 @@ void loadTheme()
|
||||
char name[THEME_NAME_LEN + 1];
|
||||
memset(name, 0, sizeof(name));
|
||||
strncpy(name, g_eeGeneral.themeName, THEME_NAME_LEN);
|
||||
ThemeBase * newTheme = getTheme(name);
|
||||
OpenTxTheme * newTheme = getTheme(name);
|
||||
if (newTheme)
|
||||
loadTheme(newTheme);
|
||||
else
|
||||
|
||||
@@ -31,22 +31,22 @@ class PageTab;
|
||||
|
||||
#define MAX_THEME_OPTIONS 5
|
||||
|
||||
class ThemeBase;
|
||||
void registerTheme(ThemeBase * theme);
|
||||
class OpenTxTheme;
|
||||
void registerTheme(OpenTxTheme * theme);
|
||||
|
||||
// YAML_GENERATOR defs
|
||||
#if !defined(USE_IDX)
|
||||
#define USE_IDX
|
||||
#endif
|
||||
|
||||
class ThemeBase: public Theme
|
||||
class OpenTxTheme: public Theme
|
||||
{
|
||||
public:
|
||||
struct PersistentData {
|
||||
ZoneOptionValueTyped options[MAX_THEME_OPTIONS] USE_IDX;
|
||||
};
|
||||
|
||||
ThemeBase(const char * name, const ZoneOption * options = nullptr):
|
||||
explicit OpenTxTheme(const char * name, const ZoneOption * options = nullptr):
|
||||
name(name),
|
||||
options(options),
|
||||
thumb(nullptr)
|
||||
@@ -54,6 +54,11 @@ class ThemeBase: public Theme
|
||||
registerTheme(this);
|
||||
}
|
||||
|
||||
static OpenTxTheme * instance()
|
||||
{
|
||||
return static_cast<OpenTxTheme *>(theme);
|
||||
}
|
||||
|
||||
inline const char * getName() const
|
||||
{
|
||||
return name;
|
||||
@@ -93,6 +98,8 @@ class ThemeBase: public Theme
|
||||
|
||||
void drawSlider(BitmapBuffer * dc, int vmin, int vmax, int value, const rect_t & rect, bool edit, bool focus) const override;
|
||||
|
||||
virtual void drawTopLeftBitmap(BitmapBuffer * dc) const = 0;
|
||||
|
||||
protected:
|
||||
const char * name;
|
||||
const ZoneOption * options;
|
||||
@@ -104,10 +111,10 @@ class ThemeBase: public Theme
|
||||
static const BitmapBuffer * busy;
|
||||
};
|
||||
|
||||
ThemeBase * getTheme(const char * name);
|
||||
void loadTheme(ThemeBase * theme);
|
||||
OpenTxTheme * getTheme(const char * name);
|
||||
void loadTheme(OpenTxTheme * theme);
|
||||
void loadTheme();
|
||||
|
||||
std::list<ThemeBase *> & getRegisteredThemes();
|
||||
std::list<OpenTxTheme *> & getRegisteredThemes();
|
||||
|
||||
#endif // _COLORLCD_THEME_H_
|
||||
|
||||
+25
-17
@@ -27,18 +27,18 @@ const ZoneOption OPTIONS_THEME_DEFAULT[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
class FrskyTheme: public ThemeBase
|
||||
class Theme480: public OpenTxTheme
|
||||
{
|
||||
public:
|
||||
FrskyTheme():
|
||||
ThemeBase("FrSky", OPTIONS_THEME_DEFAULT)
|
||||
Theme480():
|
||||
OpenTxTheme("480_default", OPTIONS_THEME_DEFAULT)
|
||||
{
|
||||
loadColors();
|
||||
}
|
||||
|
||||
void loadColors() const
|
||||
{
|
||||
TRACE("Load FrSky theme colors");
|
||||
TRACE("Load Theme480 theme colors");
|
||||
lcdColorTable[DEFAULT_COLOR_INDEX] = BLACK;
|
||||
lcdColorTable[DEFAULT_BGCOLOR_INDEX] = WHITE;
|
||||
lcdColorTable[FOCUS_COLOR_INDEX] = WHITE;
|
||||
@@ -230,10 +230,10 @@ class FrskyTheme: public ThemeBase
|
||||
|
||||
// Channels monitor screen
|
||||
delete chanMonLockedBitmap;
|
||||
chanMonLockedBitmap = BitmapBuffer::loadMaskOnBackground("mask_monitor_lockch.png", DEFAULT_COLOR, DEFAULT_BGCOLOR);
|
||||
chanMonLockedBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_monitor_lockch.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
|
||||
|
||||
delete chanMonInvertedBitmap;
|
||||
chanMonInvertedBitmap = BitmapBuffer::loadMaskOnBackground("mask_monitor_inver.png", DEFAULT_COLOR, DEFAULT_BGCOLOR);
|
||||
chanMonInvertedBitmap = BitmapBuffer::loadMaskOnBackground(getFilePath("mask_monitor_inver.png"), DEFAULT_COLOR, DEFAULT_BGCOLOR);
|
||||
|
||||
// Mixer setup screen
|
||||
delete mixerSetupMixerBitmap;
|
||||
@@ -279,7 +279,7 @@ class FrskyTheme: public ThemeBase
|
||||
void load() const override
|
||||
{
|
||||
loadColors();
|
||||
ThemeBase::load();
|
||||
OpenTxTheme::load();
|
||||
if (!backgroundBitmap) {
|
||||
backgroundBitmap = BitmapBuffer::loadBitmap(getFilePath("background.png"));
|
||||
}
|
||||
@@ -324,6 +324,14 @@ class FrskyTheme: public ThemeBase
|
||||
}
|
||||
}
|
||||
|
||||
void drawTopLeftBitmap(BitmapBuffer * dc) const override
|
||||
{
|
||||
if (topleftBitmap) {
|
||||
dc->drawBitmap(0, 0, topleftBitmap);
|
||||
dc->drawBitmap(4, 10, menuIconSelected[ICON_OPENTX]);
|
||||
}
|
||||
}
|
||||
|
||||
void drawMenuBackground(BitmapBuffer * dc, uint8_t icon, const char * title) const override
|
||||
{
|
||||
if (topleftBitmap) {
|
||||
@@ -406,16 +414,16 @@ class FrskyTheme: public ThemeBase
|
||||
static BitmapBuffer * currentMenuBackground;
|
||||
};
|
||||
|
||||
const BitmapBuffer * FrskyTheme::backgroundBitmap = nullptr;
|
||||
BitmapBuffer * FrskyTheme::topleftBitmap = nullptr;
|
||||
BitmapBuffer * FrskyTheme::iconMask[MENUS_ICONS_COUNT] = { nullptr };
|
||||
BitmapBuffer * FrskyTheme::menuIconNormal[MENUS_ICONS_COUNT] = { nullptr };
|
||||
BitmapBuffer * FrskyTheme::menuIconSelected[MENUS_ICONS_COUNT] = { nullptr };
|
||||
BitmapBuffer * FrskyTheme::currentMenuBackground = nullptr;
|
||||
const BitmapBuffer * Theme480::backgroundBitmap = nullptr;
|
||||
BitmapBuffer * Theme480::topleftBitmap = nullptr;
|
||||
BitmapBuffer * Theme480::iconMask[MENUS_ICONS_COUNT] = { nullptr };
|
||||
BitmapBuffer * Theme480::menuIconNormal[MENUS_ICONS_COUNT] = { nullptr };
|
||||
BitmapBuffer * Theme480::menuIconSelected[MENUS_ICONS_COUNT] = { nullptr };
|
||||
BitmapBuffer * Theme480::currentMenuBackground = nullptr;
|
||||
|
||||
FrskyTheme frskyTheme;
|
||||
Theme480 Theme480;
|
||||
|
||||
#if defined(PCBFRSKY)
|
||||
ThemeBase * defaultTheme = &frskyTheme;
|
||||
Theme * theme = &frskyTheme;
|
||||
#if LCD_W == 480
|
||||
OpenTxTheme * defaultTheme = &Theme480;
|
||||
Theme * theme = &Theme480;
|
||||
#endif
|
||||
@@ -27,11 +27,11 @@ const ZoneOption OPTIONS_THEME_DEFAULT[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
class FlyskyTheme: public ThemeBase
|
||||
class FlyskyTheme: public OpenTxTheme
|
||||
{
|
||||
public:
|
||||
FlyskyTheme():
|
||||
ThemeBase("FlySky", OPTIONS_THEME_DEFAULT)
|
||||
OpenTxTheme("FlySky", OPTIONS_THEME_DEFAULT)
|
||||
{
|
||||
loadColors();
|
||||
}
|
||||
@@ -296,7 +296,7 @@ class FlyskyTheme: public ThemeBase
|
||||
void load() const override
|
||||
{
|
||||
loadColors();
|
||||
ThemeBase::load();
|
||||
OpenTxTheme::load();
|
||||
if (!backgroundBitmap) {
|
||||
backgroundBitmap = BitmapBuffer::loadBitmap(getFilePath("background.png"));
|
||||
}
|
||||
@@ -342,6 +342,15 @@ class FlyskyTheme: public ThemeBase
|
||||
}
|
||||
}
|
||||
|
||||
void drawTopLeftBitmap(BitmapBuffer * dc) const override
|
||||
{
|
||||
if (topleftBitmap) {
|
||||
dc->drawBitmap(0, 0, topleftBitmap);
|
||||
uint16_t width = topleftBitmap->width();
|
||||
dc->drawSolidFilledRect(width, 0, LCD_W - width, MENU_HEADER_HEIGHT, MENU_BGCOLOR);
|
||||
}
|
||||
}
|
||||
|
||||
void drawMenuBackground(BitmapBuffer * dc, uint8_t icon, const char * title) const override
|
||||
{
|
||||
// if (topleftBitmap) {
|
||||
@@ -439,6 +448,6 @@ BitmapBuffer * FlyskyTheme::currentMenuBackground = nullptr;
|
||||
FlyskyTheme flyskyTheme;
|
||||
|
||||
#if defined(PCBFLYSKY)
|
||||
ThemeBase * defaultTheme = &flyskyTheme;
|
||||
OpenTxTheme * defaultTheme = &flyskyTheme;
|
||||
Theme * theme = &flyskyTheme;
|
||||
#endif
|
||||
|
||||
@@ -18,33 +18,50 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "opentx.h"
|
||||
|
||||
unsigned int Topbar::getZonesCount() const
|
||||
TopBar::TopBar(Window * parent) :
|
||||
WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>({0, 0, LCD_W, MENU_HEADER_HEIGHT}, &g_model.topbarData)
|
||||
{
|
||||
attach(parent);
|
||||
}
|
||||
|
||||
unsigned int TopBar::getZonesCount() const
|
||||
{
|
||||
return MAX_TOPBAR_ZONES;
|
||||
}
|
||||
|
||||
rect_t Topbar::getZone(unsigned int index) const
|
||||
rect_t TopBar::getZone(unsigned int index) const
|
||||
{
|
||||
rect_t rect;
|
||||
rect.x = 49 + (TOPBAR_ZONE_WIDTH + 2*TOPBAR_ZONE_MARGIN) * index;
|
||||
rect.y = TOPBAR_ZONE_MARGIN;
|
||||
rect.w = TOPBAR_ZONE_WIDTH;
|
||||
rect.h = TOPBAR_HEIGHT;
|
||||
return rect;
|
||||
return {
|
||||
coord_t(49 + (TOPBAR_ZONE_WIDTH + 2 * TOPBAR_ZONE_MARGIN) * index),
|
||||
TOPBAR_ZONE_MARGIN,
|
||||
TOPBAR_ZONE_WIDTH,
|
||||
TOPBAR_HEIGHT
|
||||
};
|
||||
}
|
||||
|
||||
const char * const STR_MONTHS[] = TR_MONTHS;
|
||||
|
||||
void drawTopBar()
|
||||
void TopBar::paint(BitmapBuffer * dc)
|
||||
{
|
||||
theme->drawTopbarBackground(0);
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), MENU_BGCOLOR);
|
||||
OpenTxTheme::instance()->drawTopLeftBitmap(dc);
|
||||
|
||||
struct gtm t;
|
||||
gettime(&t);
|
||||
char str[10];
|
||||
|
||||
sprintf(str, "%d %s", t.tm_mday, STR_MONTHS[t.tm_mon]);
|
||||
dc->drawSolidVerticalLine(DATETIME_SEPARATOR_X, 7, 31, MENU_COLOR);
|
||||
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE1, str, FONT(XS) | CENTERED| MENU_COLOR);
|
||||
|
||||
getTimerString(str, getValue(MIXSRC_TX_TIME));
|
||||
dc->drawText(DATETIME_MIDDLE, DATETIME_LINE2, str, FONT(XS) | CENTERED | MENU_COLOR);
|
||||
|
||||
// USB icon
|
||||
if (usbPlugged()) {
|
||||
lcdDrawBitmapPattern(LCD_W-98, 8, LBM_TOPMENU_USB, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 98, 8, LBM_TOPMENU_USB, MENU_COLOR);
|
||||
}
|
||||
|
||||
// RSSI
|
||||
@@ -52,44 +69,43 @@ void drawTopBar()
|
||||
const uint8_t rssiBarsHeight[] = {5, 10, 15, 21, 31};
|
||||
for (unsigned int i = 0; i < DIM(rssiBarsHeight); i++) {
|
||||
uint8_t height = rssiBarsHeight[i];
|
||||
lcdDrawSolidFilledRect(LCD_W-90 + i * 6, 38 - height, 4, height, TELEMETRY_RSSI() >= rssiBarsValue[i] ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR);
|
||||
dc->drawSolidFilledRect(LCD_W - 90 + i * 6, 38 - height, 4, height, TELEMETRY_RSSI() >= rssiBarsValue[i] ? MENU_COLOR : MENU_TITLE_DISABLE_COLOR);
|
||||
}
|
||||
|
||||
#if defined(INTERNAL_MODULE_PXX1) && defined(EXTERNAL_ANTENNA)
|
||||
if (isModuleXJT(INTERNAL_MODULE) && isExternalAntennaEnabled()) {
|
||||
lcdDrawBitmapPattern(LCD_W-94, 4, LBM_TOPMENU_ANTENNA, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W-94, 4, LBM_TOPMENU_ANTENNA, MENU_COLOR);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Audio volume */
|
||||
lcdDrawBitmapPattern(LCD_W-130, 4, LBM_TOPMENU_VOLUME_SCALE, MENU_TITLE_DISABLE_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_SCALE, MENU_TITLE_DISABLE_COLOR);
|
||||
if (requiredSpeakerVolume == 0 || g_eeGeneral.beepMode == e_mode_quiet)
|
||||
lcdDrawBitmapPattern(LCD_W-130, 4, LBM_TOPMENU_VOLUME_0, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_0, MENU_COLOR);
|
||||
else if (requiredSpeakerVolume < 7)
|
||||
lcdDrawBitmapPattern(LCD_W-130, 4, LBM_TOPMENU_VOLUME_1, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_1, MENU_COLOR);
|
||||
else if (requiredSpeakerVolume < 13)
|
||||
lcdDrawBitmapPattern(LCD_W-130, 4, LBM_TOPMENU_VOLUME_2, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_2, MENU_COLOR);
|
||||
else if (requiredSpeakerVolume < 19)
|
||||
lcdDrawBitmapPattern(LCD_W-130, 4, LBM_TOPMENU_VOLUME_3, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_3, MENU_COLOR);
|
||||
else
|
||||
lcdDrawBitmapPattern(LCD_W-130, 4, LBM_TOPMENU_VOLUME_4, MENU_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 4, LBM_TOPMENU_VOLUME_4, MENU_COLOR);
|
||||
|
||||
/* Tx battery */
|
||||
uint8_t bars = GET_TXBATT_BARS(5);
|
||||
#if defined(USB_CHARGER)
|
||||
if (usbChargerLed()) {
|
||||
lcdDrawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, MENU_TITLE_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT_CHARGING, MENU_COLOR);
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_TITLE_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR);
|
||||
}
|
||||
#else
|
||||
lcdDrawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_TITLE_COLOR);
|
||||
dc->drawBitmapPattern(LCD_W - 130, 25, LBM_TOPMENU_TXBATT, MENU_COLOR);
|
||||
#endif
|
||||
for (unsigned int i = 0; i < 5; i++) {
|
||||
lcdDrawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_COLOR);
|
||||
dc->drawSolidFilledRect(LCD_W - 128 + 4 * i, 30, 2, 8, i >= bars ? MENU_TITLE_DISABLE_COLOR : MENU_COLOR);
|
||||
}
|
||||
topbar->refresh();
|
||||
|
||||
#if 0
|
||||
// Radio battery - TODO
|
||||
@@ -133,5 +149,4 @@ void drawTopBar()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@@ -29,17 +29,21 @@
|
||||
constexpr coord_t TOPBAR_ZONE_MARGIN = 3;
|
||||
constexpr coord_t TOPBAR_HEIGHT = MENU_HEADER_HEIGHT - 2 * TOPBAR_ZONE_MARGIN;
|
||||
|
||||
class Topbar: public WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>
|
||||
class TopBar: public WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>
|
||||
{
|
||||
public:
|
||||
explicit Topbar(PersistentData * persistentData):
|
||||
WidgetsContainer<MAX_TOPBAR_ZONES, MAX_TOPBAR_OPTIONS>({0, 0, LCD_W, TOPBAR_ZONE_WIDTH}, persistentData)
|
||||
{
|
||||
}
|
||||
explicit TopBar(Window * parent);
|
||||
|
||||
unsigned int getZonesCount() const override;
|
||||
|
||||
rect_t getZone(unsigned int index) const override;
|
||||
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _TOPBAR_H_
|
||||
|
||||
@@ -19,172 +19,61 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "libopenui.h"
|
||||
#include "view_channels.h"
|
||||
#include "channel_bar.h"
|
||||
#include "view_logical_switches.h"
|
||||
|
||||
#define ROW_HEIGHT 42
|
||||
#define BAR_HEIGHT 13
|
||||
#define COLUMN_SIZE 200
|
||||
#define X_OFFSET 25
|
||||
#define Y_OFFSET 75
|
||||
#define Y_OUTBAR 15
|
||||
#define Y_MIXBAR 28
|
||||
#define LEG_COLORBOX 15
|
||||
constexpr coord_t CHANNEL_VIEW_FOOTER_HEIGHT = 16;
|
||||
|
||||
#define VIEW_CHANNELS_LIMIT_PCT (g_model.extendedLimits ? LIMIT_EXT_PERCENT : 100)
|
||||
|
||||
bool menuChannelsMonitor(event_t event, uint8_t page);
|
||||
bool menuLogicalSwitches(event_t);
|
||||
|
||||
template<int index>
|
||||
bool menuChannelsMonitor(event_t event)
|
||||
ChannelsViewMenu::ChannelsViewMenu():
|
||||
TabsGroup(ICON_MONITOR)
|
||||
{
|
||||
lastMonitorPage = e_MonChannelsFirst + index;
|
||||
MENU(STR_MONITOR_CHANNELS[index], MONITOR_ICONS, menuTabMonitors, lastMonitorPage, 0, { 0 });
|
||||
return menuChannelsMonitor(event, index);
|
||||
addTab(new ChannelsViewPage(0));
|
||||
addTab(new ChannelsViewPage(1));
|
||||
addTab(new ChannelsViewPage(2));
|
||||
addTab(new ChannelsViewPage(3));
|
||||
addTab(new LogicalSwitchesViewPage());
|
||||
}
|
||||
|
||||
const MenuHandlerFunc menuTabMonitors[] = {
|
||||
menuChannelsMonitor<0>,
|
||||
menuChannelsMonitor<1>,
|
||||
menuChannelsMonitor<2>,
|
||||
menuChannelsMonitor<3>,
|
||||
menuLogicalSwitches
|
||||
class ChannelsViewFooter: public Window {
|
||||
public:
|
||||
explicit ChannelsViewFooter(Window * parent):
|
||||
Window(parent, {0, parent->height() - MODEL_SELECT_FOOTER_HEIGHT, LCD_W, MODEL_SELECT_FOOTER_HEIGHT}, OPAQUE)
|
||||
{
|
||||
}
|
||||
|
||||
// Draw single legend
|
||||
coord_t drawChannelsMonitorLegend(BitmapBuffer * dc, coord_t x, const char * s, int color)
|
||||
{
|
||||
dc->drawSolidFilledRect(x, 2, LEG_COLORBOX + 2, LEG_COLORBOX + 2, BARGRAPH_BGCOLOR);
|
||||
dc->drawSolidFilledRect(x + 1, 3, LEG_COLORBOX, LEG_COLORBOX, color);
|
||||
dc->drawText(x + 20, 2, s, TEXT_STATUSBAR_COLOR);
|
||||
return x + 25 + getTextWidth(s);
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// Draw legend bar
|
||||
coord_t x = 10;
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), TITLE_BGCOLOR);
|
||||
x = drawChannelsMonitorLegend(dc, MENUS_MARGIN_LEFT, STR_MONITOR_OUTPUT_DESC, BARGRAPH1_COLOR);
|
||||
drawChannelsMonitorLegend(dc, x, STR_MONITOR_MIXER_DESC, BARGRAPH2_COLOR);
|
||||
}
|
||||
};
|
||||
|
||||
uint8_t lastMonitorPage = 0;
|
||||
|
||||
uint16_t posOnBar(int16_t value_to100)
|
||||
void ChannelsViewPage::build(FormWindow * window)
|
||||
{
|
||||
return divRoundClosest((value_to100 + VIEW_CHANNELS_LIMIT_PCT) * COLUMN_SIZE, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
}
|
||||
constexpr coord_t hmargin = 5;
|
||||
|
||||
void drawOutputBarLimits(coord_t left, coord_t right, coord_t y)
|
||||
{
|
||||
lcd->drawSolidVerticalLine(left, y, BAR_HEIGHT, DEFAULT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(left, y, 3, DEFAULT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(left, y + BAR_HEIGHT - 1, 3, DEFAULT_COLOR);
|
||||
|
||||
lcd->drawSolidVerticalLine(--right, y, BAR_HEIGHT, DEFAULT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(right - 3, y, 3, DEFAULT_COLOR);
|
||||
lcd->drawSolidHorizontalLine(right - 3, y + BAR_HEIGHT - 1, 3, DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
void drawSingleMixerBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
int16_t chanVal = calcRESXto100(ex_chans[channel]);
|
||||
const int16_t displayVal = chanVal;
|
||||
|
||||
// this could be handled nicer, but slower, by checking actual range for this mixer
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y, w, h, BARGRAPH_BGCOLOR);
|
||||
if (chanVal > 0) {
|
||||
lcdDrawSolidFilledRect(x + w / 2, y, divRoundClosest(chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2), h, BARGRAPH2_COLOR);
|
||||
lcdDrawNumber(x - 10 + w / 2, y - 2, displayVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
const uint16_t endpoint = x + w / 2;
|
||||
const uint16_t size = divRoundClosest(-chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
lcdDrawSolidFilledRect(endpoint - size, y, size, h, BARGRAPH2_COLOR);
|
||||
lcdDrawNumber(x + 10 + w / 2, y - 2, displayVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
|
||||
}
|
||||
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y, h, DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
void drawSingleOutputBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
int16_t chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
int16_t displayVal = chanVal;
|
||||
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y, w, h, BARGRAPH_BGCOLOR);
|
||||
if (chanVal > 0) {
|
||||
lcdDrawSolidFilledRect(x + w / 2, y, divRoundClosest(chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2), h, BARGRAPH1_COLOR);
|
||||
lcdDrawNumber(x - 10 + w / 2, y - 2, displayVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
}
|
||||
else if (chanVal < 0) {
|
||||
uint16_t endpoint = x + w / 2;
|
||||
uint16_t size = divRoundClosest(-chanVal * w, VIEW_CHANNELS_LIMIT_PCT * 2);
|
||||
lcdDrawSolidFilledRect(endpoint - size, y, size, h, BARGRAPH1_COLOR);
|
||||
lcdDrawNumber(x + 10 + w / 2, y - 2, displayVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
|
||||
// Channels bars
|
||||
for (uint8_t chan = pageIndex * 8; chan < 8 + pageIndex * 8; chan++) {
|
||||
coord_t width = window->width() / 2 - hmargin;
|
||||
coord_t xPos = (chan % 8) >= 4 ? width + hmargin : hmargin;
|
||||
coord_t yPos = (chan % 4) * ((window->height() - CHANNEL_VIEW_FOOTER_HEIGHT - 4) / 4);
|
||||
new ComboChannelBar(window, {xPos, yPos, width, 3 * BAR_HEIGHT + 1}, chan);
|
||||
}
|
||||
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y, h, DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
void drawComboOutputBar(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t channel)
|
||||
{
|
||||
char chanString[] = "Ch32 ";
|
||||
int16_t chanVal = calcRESXto100(channelOutputs[channel]);
|
||||
LimitData * ld = limitAddress(channel);
|
||||
int usValue = PPM_CH_CENTER(channel) + channelOutputs[channel] / 2;
|
||||
const uint16_t limPos = ld ? posOnBar(calcRESXto100((ld && ld->revert) ? -ld->offset : ld->offset)) : 0;
|
||||
uint16_t valPos;
|
||||
|
||||
strAppendSigned(&chanString[2], channel + 1, 2);
|
||||
lcdDrawText(x, y, chanString, FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
|
||||
lcdDrawSizedText(x + 45, y, g_model.limitData[channel].name, sizeof(g_model.limitData[channel].name), FONT(XS) | DEFAULT_COLOR | LEFT | ZCHAR);
|
||||
lcdDrawNumber(x + w, y, usValue, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, STR_US);
|
||||
|
||||
lcdDrawSolidFilledRect(x, y + Y_OUTBAR, w, h, BARGRAPH_BGCOLOR);
|
||||
lcd->drawSolidVerticalLine(x + limPos, y + Y_OUTBAR, h, MAINVIEW_GRAPHICS_COLOR);
|
||||
|
||||
chanVal = limit<int16_t>(-VIEW_CHANNELS_LIMIT_PCT, chanVal, VIEW_CHANNELS_LIMIT_PCT);
|
||||
valPos = posOnBar(chanVal);
|
||||
|
||||
if (valPos > limPos) {
|
||||
lcdDrawSolidFilledRect(x + limPos, y + Y_OUTBAR, valPos - limPos, h, BARGRAPH1_COLOR);
|
||||
}
|
||||
else if (valPos < limPos) {
|
||||
uint16_t endpoint = x + limPos;
|
||||
uint16_t size = limPos - valPos;
|
||||
lcdDrawSolidFilledRect(endpoint - size, y + Y_OUTBAR, size, h, BARGRAPH1_COLOR);
|
||||
}
|
||||
|
||||
if (ld && ld->revert) {
|
||||
drawOutputBarLimits(x + posOnBar(-100 - ld->max / 10), x + posOnBar(100 - ld->min / 10), y + Y_OUTBAR);
|
||||
lcd->drawBitmap(x - X_OFFSET + 7, y + 25, chanMonInvertedBitmap);
|
||||
}
|
||||
else if (ld) {
|
||||
drawOutputBarLimits(x + posOnBar(-100 + ld->min / 10), x + posOnBar(100 + ld->max / 10), y + Y_OUTBAR);
|
||||
}
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
if (safetyCh[channel] != OVERRIDE_CHANNEL_UNDEFINED)
|
||||
lcd->drawBitmap(x - X_OFFSET + 7, y + 7, chanMonLockedBitmap);
|
||||
#endif
|
||||
lcd->drawSolidVerticalLine(x + w / 2, y + Y_OUTBAR, h, DEFAULT_COLOR);
|
||||
if (chanVal > calcRESXto100((ld && ld->revert) ? -ld->offset : ld->offset))
|
||||
lcdDrawNumber(x + limPos, y + h, chanVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
else
|
||||
lcdDrawNumber(x + limPos, y + h, chanVal, FONT(XS) | DEFAULT_COLOR, 0, nullptr, "%");
|
||||
}
|
||||
|
||||
coord_t drawChannelsMonitorLegend(coord_t x, const char * s, int color)
|
||||
{
|
||||
lcdDrawSolidFilledRect(x, MENU_FOOTER_TOP + 2, LEG_COLORBOX + 2, LEG_COLORBOX + 2, BARGRAPH_BGCOLOR);
|
||||
lcdDrawSolidFilledRect(x + 1, MENU_FOOTER_TOP + 3, LEG_COLORBOX, LEG_COLORBOX, color);
|
||||
lcdDrawText(x + 20, MENU_FOOTER_TOP, s, TEXT_STATUSBAR_COLOR);
|
||||
return x + 25 + getTextWidth(s);
|
||||
}
|
||||
|
||||
bool menuChannelsMonitor(event_t event, uint8_t page)
|
||||
{
|
||||
uint8_t channel = 8 * page;
|
||||
coord_t x, y = Y_OFFSET;
|
||||
|
||||
x = drawChannelsMonitorLegend(MENUS_MARGIN_LEFT, STR_MONITOR_OUTPUT_DESC, BARGRAPH1_COLOR);
|
||||
drawChannelsMonitorLegend(x, STR_MONITOR_MIXER_DESC, BARGRAPH2_COLOR);
|
||||
|
||||
x = X_OFFSET;
|
||||
for (uint8_t i = 0; i < 8; i++, channel++, y += ROW_HEIGHT) {
|
||||
if (i == 4) {
|
||||
x = 1 + LCD_W / 2 + X_OFFSET;
|
||||
y = Y_OFFSET;
|
||||
}
|
||||
drawComboOutputBar(x, y, COLUMN_SIZE, BAR_HEIGHT, channel);
|
||||
drawSingleMixerBar(x, y + Y_MIXBAR + 1, COLUMN_SIZE, BAR_HEIGHT, channel);
|
||||
}
|
||||
return true;
|
||||
// Footer
|
||||
new ChannelsViewFooter(window);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opentx.h"
|
||||
#include "tabsgroup.h"
|
||||
|
||||
class ChannelsViewPage: public PageTab
|
||||
{
|
||||
public:
|
||||
explicit ChannelsViewPage(uint8_t pageIndex = 0):
|
||||
PageTab(STR_MONITOR_CHANNELS[pageIndex], ICON_MONITOR_CHANNELS1 + pageIndex),
|
||||
pageIndex(pageIndex)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window) override;
|
||||
uint8_t pageIndex = 0;
|
||||
};
|
||||
|
||||
class ChannelsViewMenu: public TabsGroup {
|
||||
public:
|
||||
ChannelsViewMenu();
|
||||
};
|
||||
@@ -19,99 +19,62 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "view_logical_switches.h"
|
||||
|
||||
#define X_OFF 45
|
||||
#define Y_OFF 70
|
||||
#define HLINE_Y_OFF 215
|
||||
#define LS_COL_WIDTH 50
|
||||
#define LS_LINE_HEIGHT 17
|
||||
#define X_FUNC 50
|
||||
#define Y_FUNC 225
|
||||
#include <utility>
|
||||
|
||||
#define CSW_1ST_COLUMN 50
|
||||
#define CSW_2ND_COLUMN 120
|
||||
#define CSW_3RD_COLUMN 200
|
||||
#define CSW_4TH_COLUMN 280
|
||||
#define CSW_5TH_COLUMN 340
|
||||
#define CSW_6TH_COLUMN 390
|
||||
#define MAX_LOGICAL_SWITCHES 64
|
||||
|
||||
extern void putsEdgeDelayParam(coord_t, coord_t, LogicalSwitchData *, uint8_t, uint8_t);
|
||||
|
||||
void displayLogicalSwitchedDetails(coord_t x, coord_t y, uint8_t idx)
|
||||
class LogicalSwitchDisplayButton : public TextButton
|
||||
{
|
||||
LogicalSwitchData * cs = lswAddress(idx);
|
||||
lcdDrawTextAtIndex(x, y, STR_VCSWFUNC, cs->func, 0);
|
||||
// CSW params
|
||||
unsigned int cstate = lswFamily(cs->func);
|
||||
public:
|
||||
LogicalSwitchDisplayButton(FormGroup * parent, const rect_t & rect, std::string text, unsigned index):
|
||||
TextButton(parent, rect, std::move(text)),
|
||||
index(index)
|
||||
{
|
||||
}
|
||||
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
drawSwitch(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
drawSwitch(CSW_3RD_COLUMN, y, cs->v2, 0);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
drawSwitch(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, 0, 0);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
drawSource(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
drawSource(CSW_3RD_COLUMN, y, cs->v2, 0);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
lcdDrawNumber(CSW_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT | PREC1);
|
||||
lcdDrawNumber(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT | PREC1);
|
||||
}
|
||||
else {
|
||||
drawSource(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
drawSourceCustomValue(CSW_3RD_COLUMN, y, cs->v1, cs->v1 <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2, LEFT);
|
||||
}
|
||||
void checkEvents() override
|
||||
{
|
||||
bool newvalue = getSwitch(SWSRC_SW1 + index);
|
||||
if (value != newvalue) {
|
||||
if (newvalue) {
|
||||
setTextFlags(FONT(BOLD) | HIGHLIGHT_COLOR);
|
||||
}
|
||||
else {
|
||||
setTextFlags(FONT(STD) | DEFAULT_COLOR);
|
||||
}
|
||||
value = newvalue;
|
||||
invalidate();
|
||||
}
|
||||
Button::checkEvents();
|
||||
}
|
||||
|
||||
// CSW AND switch
|
||||
drawSwitch(CSW_4TH_COLUMN, y, cs->andsw, 0);
|
||||
protected:
|
||||
unsigned index = 0;
|
||||
bool value = false;
|
||||
};
|
||||
|
||||
// CSW duration
|
||||
if (cs->duration > 0)
|
||||
lcdDrawNumber(CSW_5TH_COLUMN, y, cs->duration, PREC1 | LEFT);
|
||||
else
|
||||
lcdDrawMMM(CSW_5TH_COLUMN, y, 0);
|
||||
|
||||
// CSW delay
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
lcdDrawText(CSW_6TH_COLUMN, y, STR_NA);
|
||||
}
|
||||
else if (cs->delay > 0) {
|
||||
lcdDrawNumber(CSW_6TH_COLUMN, y, cs->delay, PREC1 | LEFT);
|
||||
}
|
||||
else {
|
||||
lcdDrawMMM(CSW_6TH_COLUMN, y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool menuLogicalSwitchesMonitor(event_t event)
|
||||
void LogicalSwitchesViewPage::build(FormWindow * window)
|
||||
{
|
||||
char lsString[] = "L64";
|
||||
constexpr coord_t LSW_VIEW_FOOTER_HEIGHT = 20;
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(8);
|
||||
|
||||
// LSW table
|
||||
std::string lsString ("LS64");
|
||||
lcdColorTable[CUSTOM_COLOR_INDEX] = RGB(160, 160, 160);
|
||||
for (uint8_t i = 0; i < MAX_LOGICAL_SWITCHES; i++) {
|
||||
LcdFlags attr = (menuHorizontalPosition == i ? INVERS : 0) | LEFT;
|
||||
LogicalSwitchData * cs = lswAddress(i);
|
||||
strAppendSigned(&lsString[1], i + 1, 2);
|
||||
if (cs->func == LS_FUNC_NONE)
|
||||
attr += CUSTOM_COLOR;
|
||||
else if (getSwitch(SWSRC_SW1 + i))
|
||||
attr += BOLD;
|
||||
lcdDrawText(X_OFF + (i & 0x07) * LS_COL_WIDTH, Y_OFF + (i >> 3) * LS_LINE_HEIGHT, lsString, attr);
|
||||
auto button = new LogicalSwitchDisplayButton(window, grid.getFieldSlot(8, i % 8), lsString, i);
|
||||
button->setPressHandler([=]() {
|
||||
footer->setIndex(i);
|
||||
footer->invalidate();
|
||||
return 0;
|
||||
});
|
||||
if ((i + 1) % 8 == 0)
|
||||
grid.nextLine();
|
||||
}
|
||||
lcdDrawHorizontalLine(0, HLINE_Y_OFF, LCD_W, SOLID);
|
||||
if (lswAddress(menuHorizontalPosition)->func != LS_FUNC_NONE) {
|
||||
displayLogicalSwitchedDetails(X_FUNC, Y_FUNC, menuHorizontalPosition);
|
||||
}
|
||||
s_editMode = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool menuLogicalSwitches(event_t event)
|
||||
{
|
||||
MENU(STR_MONITOR_SWITCHES, MONITOR_ICONS, menuTabMonitors, e_MonLogicalSwitches, 1, { MAX_LOGICAL_SWITCHES - 1 });
|
||||
lastMonitorPage = e_MonLogicalSwitches;
|
||||
return menuLogicalSwitchesMonitor(event);
|
||||
// Footer
|
||||
footer = new LogicalSwitchDisplayFooter(window, {0,window->height() - LSW_VIEW_FOOTER_HEIGHT, window->width(), LSW_VIEW_FOOTER_HEIGHT});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
constexpr coord_t CSW_1ST_COLUMN = 50;
|
||||
constexpr coord_t CSW_2ND_COLUMN = 120;
|
||||
constexpr coord_t CSW_3RD_COLUMN = 200;
|
||||
constexpr coord_t CSW_4TH_COLUMN = 280;
|
||||
constexpr coord_t CSW_5TH_COLUMN = 340;
|
||||
constexpr coord_t CSW_6TH_COLUMN = 390;
|
||||
|
||||
void putsEdgeDelayParam(BitmapBuffer * dc, coord_t x, coord_t y, LogicalSwitchData * ls, LcdFlags flags);
|
||||
|
||||
class LogicalSwitchDisplayFooter: public Window {
|
||||
public:
|
||||
explicit LogicalSwitchDisplayFooter(Window * parent, rect_t rect):
|
||||
Window(parent, rect, OPAQUE),
|
||||
rect(rect)
|
||||
{
|
||||
}
|
||||
|
||||
void setIndex(unsigned value)
|
||||
{
|
||||
index = value;
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
dc->clear(TITLE_BGCOLOR);
|
||||
LogicalSwitchData * cs = lswAddress(index);
|
||||
dc->drawTextAtIndex(10, 1, STR_VCSWFUNC, cs->func, MENU_COLOR);
|
||||
// CSW params
|
||||
unsigned int cstate = lswFamily(cs->func);
|
||||
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
|
||||
drawSwitch(dc, CSW_3RD_COLUMN, 1, cs->v2, MENU_COLOR);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
drawSwitch(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
|
||||
putsEdgeDelayParam(dc, CSW_3RD_COLUMN, 1, cs, MENU_COLOR);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
|
||||
drawSource(dc, CSW_3RD_COLUMN, 1, cs->v2, MENU_COLOR);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
dc->drawNumber(CSW_2ND_COLUMN, 1, lswTimerValue(cs->v1), LEFT | PREC1 | MENU_COLOR);
|
||||
dc->drawNumber(CSW_3RD_COLUMN, 1, lswTimerValue(cs->v2), LEFT | PREC1 | MENU_COLOR);
|
||||
}
|
||||
else {
|
||||
drawSource(dc, CSW_2ND_COLUMN, 1, cs->v1, MENU_COLOR);
|
||||
drawSourceCustomValue(dc, CSW_3RD_COLUMN, 1, cs->v1, cs->v1 <= MIXSRC_LAST_CH ? calc100toRESX(cs->v2) : cs->v2, LEFT | MENU_COLOR);
|
||||
}
|
||||
|
||||
// CSW AND switch
|
||||
drawSwitch(dc, CSW_4TH_COLUMN, 1, cs->andsw, MENU_COLOR);
|
||||
|
||||
// CSW duration
|
||||
if (cs->duration > 0)
|
||||
dc->drawNumber(CSW_5TH_COLUMN, 1, cs->duration, PREC1 | LEFT | MENU_COLOR);
|
||||
else
|
||||
dc->drawTextAtIndex(CSW_5TH_COLUMN, 1, STR_MMMINV, 0, MENU_COLOR);
|
||||
|
||||
// CSW delay
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
dc->drawText(CSW_6TH_COLUMN, 1, STR_NA, MENU_COLOR);
|
||||
}
|
||||
else if (cs->delay > 0) {
|
||||
dc->drawNumber(CSW_6TH_COLUMN, 1, cs->delay, PREC1 | LEFT | MENU_COLOR);
|
||||
}
|
||||
else {
|
||||
dc->drawTextAtIndex(CSW_6TH_COLUMN, 1, STR_MMMINV, 0, MENU_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
rect_t rect;
|
||||
unsigned index = 0;
|
||||
};
|
||||
|
||||
|
||||
class LogicalSwitchesViewPage : public PageTab
|
||||
{
|
||||
public:
|
||||
LogicalSwitchesViewPage() :
|
||||
PageTab(STR_MONITOR_SWITCHES, ICON_MONITOR_LOGICAL_SWITCHES)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window) override;
|
||||
LogicalSwitchDisplayFooter * footer = nullptr;
|
||||
};
|
||||
@@ -23,84 +23,12 @@
|
||||
#include "menu_radio.h"
|
||||
#include "menu_screen.h"
|
||||
// #include "menu_screens.h"
|
||||
#include "model_select.h"
|
||||
// #include "view_channels.h"
|
||||
// #include "view_statistics.h"
|
||||
#include "model_select.h"
|
||||
#include "view_channels.h"
|
||||
#include "view_statistics.h"
|
||||
#include "opentx.h"
|
||||
|
||||
#define TRIM_WIDTH 121
|
||||
#define TRIM_LH_X 10
|
||||
#define TRIM_LV_X 14
|
||||
#define TRIM_RV_X (LCD_W-25)
|
||||
#define TRIM_RH_X (LCD_W-TRIM_LH_X-TRIM_WIDTH)
|
||||
#define TRIM_V_Y 285
|
||||
#define TRIM_H_Y (LCD_H-37)
|
||||
#define TRIM_LEN 80
|
||||
#define POTS_LINE_Y (LCD_H-20)
|
||||
|
||||
Layout * customScreens[MAX_CUSTOM_SCREENS] = { 0, 0, 0, 0, 0 };
|
||||
Topbar * topbar;
|
||||
|
||||
#if 0
|
||||
void drawMainPots()
|
||||
{
|
||||
// The 3 pots
|
||||
#if defined(PCBHORUS)
|
||||
drawHorizontalSlider(TRIM_LH_X, POTS_LINE_Y, TRIM_WIDTH, calibratedAnalogs[CALIBRATED_POT1], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
drawHorizontalSlider(LCD_W/2-20, POTS_LINE_Y, XPOTS_MULTIPOS_COUNT*5, 1 + (potsPos[1] & 0x0f), 1, XPOTS_MULTIPOS_COUNT + 1, XPOTS_MULTIPOS_COUNT, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_NUMBER_BUTTON);
|
||||
drawHorizontalSlider(TRIM_RH_X, POTS_LINE_Y, TRIM_WIDTH, calibratedAnalogs[CALIBRATED_POT3], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
|
||||
// The 2 rear sliders
|
||||
drawVerticalSlider(6, TRIM_V_Y, 160, calibratedAnalogs[CALIBRATED_SLIDER_REAR_LEFT], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
drawVerticalSlider(LCD_W-18, TRIM_V_Y, 160, calibratedAnalogs[CALIBRATED_SLIDER_REAR_RIGHT], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
#elif defined(PCBNV14)
|
||||
drawHorizontalSlider(TRIM_LH_X, POTS_LINE_Y, TRIM_WIDTH, calibratedAnalogs[CALIBRATED_POT1], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
drawHorizontalSlider(TRIM_LH_X, POTS_LINE_Y, TRIM_WIDTH, calibratedAnalogs[CALIBRATED_POT2], -RESX, RESX, 40, OPTION_SLIDER_TICKS | OPTION_SLIDER_BIG_TICKS | OPTION_SLIDER_SQUARE_BUTTON);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
void drawTrims(uint8_t flightMode)
|
||||
{
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
static const coord_t x[4] = { TRIM_LH_X, TRIM_LV_X, TRIM_RV_X, TRIM_RH_X };
|
||||
static uint8_t vert[4] = {0, 1, 1, 0};
|
||||
unsigned int stickIndex = CONVERT_MODE(i);
|
||||
coord_t xm = x[stickIndex];
|
||||
int32_t trim = getTrimValue(flightMode, i);
|
||||
|
||||
if (vert[i]) {
|
||||
if (g_model.extendedTrims == 1) {
|
||||
drawVerticalSlider(xm, TRIM_V_Y, 120, trim, TRIM_EXTENDED_MIN, TRIM_EXTENDED_MAX, 0, OPTION_SLIDER_EMPTY_BAR|OPTION_SLIDER_TRIM_BUTTON);
|
||||
}
|
||||
else {
|
||||
drawVerticalSlider(xm, TRIM_V_Y, 120, trim, TRIM_MIN, TRIM_MAX, 0, OPTION_SLIDER_EMPTY_BAR|OPTION_SLIDER_TRIM_BUTTON);
|
||||
}
|
||||
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && trim != 0) {
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<<i)))) {
|
||||
uint16_t y = TRIM_V_Y + TRIM_LEN + (trim<0 ? -TRIM_LEN/2 : TRIM_LEN/2);
|
||||
lcdDrawNumber(xm+2, y, trim, TINSIZE | CENTERED | VERTICAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (g_model.extendedTrims == 1) {
|
||||
drawHorizontalSlider(xm, TRIM_H_Y, 120, trim, TRIM_EXTENDED_MIN, TRIM_EXTENDED_MAX, 0, OPTION_SLIDER_EMPTY_BAR|OPTION_SLIDER_TRIM_BUTTON);
|
||||
}
|
||||
else {
|
||||
drawHorizontalSlider(xm, TRIM_H_Y, 120, trim, TRIM_MIN, TRIM_MAX, 0, OPTION_SLIDER_EMPTY_BAR|OPTION_SLIDER_TRIM_BUTTON);
|
||||
}
|
||||
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && trim != 0) {
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<<i)))) {
|
||||
uint16_t x = xm + TRIM_LEN + (trim>0 ? -TRIM_LEN/2 : TRIM_LEN/2);
|
||||
lcdDrawNumber(x, TRIM_H_Y+2, trim, TINSIZE | CENTERED);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Layout * customScreens[MAX_CUSTOM_SCREENS] = {};
|
||||
|
||||
void onMainViewMenu(const char *result)
|
||||
{
|
||||
@@ -134,9 +62,8 @@ ViewMain::ViewMain(bool icons):
|
||||
FormWindow(&mainWindow, { 0, 0, LCD_W, LCD_H })
|
||||
{
|
||||
instance = this;
|
||||
focusWindow = this;
|
||||
|
||||
#if defined(HARDWARE_TOUCH)
|
||||
#if defined(HARDWARE_TOUCH) && !defined(HARDWARE_KEYS)
|
||||
if (icons) {
|
||||
new FabButton(this, 50, 100, ICON_MODEL,
|
||||
[=]() -> uint8_t {
|
||||
@@ -163,6 +90,8 @@ ViewMain::ViewMain(bool icons):
|
||||
return 0;
|
||||
}, NO_FOCUS);
|
||||
#endif
|
||||
|
||||
focusWindow = this;
|
||||
}
|
||||
|
||||
ViewMain::~ViewMain()
|
||||
@@ -199,7 +128,7 @@ void ViewMain::onEvent(event_t event)
|
||||
void ViewMain::openMenu()
|
||||
{
|
||||
Menu * menu = new Menu(this);
|
||||
menu->addLine(STR_MODEL_SELECT, [=]() {
|
||||
menu->addLine(STR_MODEL_SELECT, []() {
|
||||
new ModelSelectMenu();
|
||||
});
|
||||
if (modelHasNotes()) {
|
||||
@@ -207,54 +136,39 @@ void ViewMain::openMenu()
|
||||
// TODO
|
||||
});
|
||||
}
|
||||
menu->addLine(STR_MONITOR_SCREENS, [=]() {
|
||||
// new ChannelsMonitorMenu();
|
||||
menu->addLine(STR_MONITOR_SCREENS, []() {
|
||||
new ChannelsViewMenu();
|
||||
});
|
||||
menu->addLine(STR_RESET_SUBMENU, [=]() {
|
||||
Menu * menu = new Menu(this);
|
||||
menu->addLine(STR_RESET_FLIGHT, [=]() {
|
||||
menu->addLine(STR_RESET_SUBMENU, [menu, this]() {
|
||||
menu->revertPreviousFocus();
|
||||
Menu * resetMenu = new Menu(this);
|
||||
resetMenu->addLine(STR_RESET_FLIGHT, []() {
|
||||
flightReset();
|
||||
});
|
||||
menu->addLine(STR_RESET_TIMER1, [=]() {
|
||||
resetMenu->addLine(STR_RESET_TIMER1, []() {
|
||||
timerReset(0);
|
||||
});
|
||||
menu->addLine(STR_RESET_TIMER2, [=]() {
|
||||
resetMenu->addLine(STR_RESET_TIMER2, []() {
|
||||
timerReset(1);
|
||||
});
|
||||
menu->addLine(STR_RESET_TIMER3, [=]() {
|
||||
resetMenu->addLine(STR_RESET_TIMER3, []() {
|
||||
timerReset(2);
|
||||
});
|
||||
menu->addLine(STR_RESET_TELEMETRY, [=]() {
|
||||
resetMenu->addLine(STR_RESET_TELEMETRY, []() {
|
||||
telemetryReset();
|
||||
});
|
||||
});
|
||||
menu->addLine(STR_STATISTICS, [=]() {
|
||||
// new StatisticsMenu();
|
||||
menu->addLine(STR_STATISTICS, []() {
|
||||
new StatisticsViewPageGroup();
|
||||
});
|
||||
menu->addLine(STR_ABOUT_US, [=]() {
|
||||
menu->addLine(STR_ABOUT_US, []() {
|
||||
// TODO
|
||||
});
|
||||
}
|
||||
|
||||
void ViewMain::checkEvents()
|
||||
{
|
||||
Window::checkEvents();
|
||||
|
||||
// TODO attach elsewhere
|
||||
for (uint8_t i=0; i<MAX_CUSTOM_SCREENS; i++) {
|
||||
if (customScreens[i]) {
|
||||
if (i == g_model.view && !customScreens[i]->getParent()) {
|
||||
customScreens[i]->attach(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewMain::paint(BitmapBuffer * dc)
|
||||
{
|
||||
static_cast<ThemeBase *>(theme)->drawBackground(dc);
|
||||
|
||||
// drawMainPots();
|
||||
OpenTxTheme::instance()->drawBackground(dc);
|
||||
|
||||
if (g_model.view >= getMainViewsCount()) {
|
||||
g_model.view = 0;
|
||||
|
||||
@@ -30,7 +30,7 @@ class ViewMain: public FormWindow {
|
||||
~ViewMain() override;
|
||||
|
||||
#if defined(DEBUG_WINDOWS)
|
||||
virtual std::string getName()
|
||||
std::string getName() const override
|
||||
{
|
||||
return "ViewMain";
|
||||
}
|
||||
@@ -43,9 +43,7 @@ class ViewMain: public FormWindow {
|
||||
void onEvent(event_t event) override;
|
||||
#endif
|
||||
void paint(BitmapBuffer * dc) override;
|
||||
void checkEvents() override;
|
||||
void openMenu();
|
||||
};
|
||||
|
||||
#endif // _VIEW_MAIN_H_
|
||||
|
||||
|
||||
@@ -19,262 +19,220 @@
|
||||
*/
|
||||
|
||||
#include "opentx.h"
|
||||
#include "stamp.h"
|
||||
#include "libopenui.h"
|
||||
#include "view_statistics.h"
|
||||
|
||||
#define MENU_STATS_COLUMN1 (MENUS_MARGIN_LEFT + 120)
|
||||
#define MENU_STATS_COLUMN2 (LCD_W/2)
|
||||
#define MENU_STATS_COLUMN3 (LCD_W/2 + 120)
|
||||
|
||||
bool menuStatsGraph(event_t event)
|
||||
StatisticsViewPageGroup::StatisticsViewPageGroup():
|
||||
TabsGroup(ICON_STATS)
|
||||
{
|
||||
switch (event) {
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
g_eeGeneral.globalTimer = 0;
|
||||
storageDirty(EE_GENERAL);
|
||||
sessionTimer = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
|
||||
SIMPLE_MENU(STR_STATISTICS, STATS_ICONS, menuTabStats, e_StatsGraph, 1);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP, "Session");
|
||||
drawTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP, sessionTimer, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP, "Battery");
|
||||
drawTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP, g_eeGeneral.globalTimer+sessionTimer, TIMEHOUR);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+FH, "Throttle");
|
||||
drawTimer(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+FH, s_timeCumThr, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+FH, "Throttle %", TIMEHOUR);
|
||||
drawTimer(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+FH, s_timeCum16ThrP/16, TIMEHOUR);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+2*FH, "Timers");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, MENU_CONTENT_TOP+2*FH, "[1]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[0].val, TIMEHOUR);
|
||||
lcdDrawText(MENU_STATS_COLUMN2, MENU_CONTENT_TOP+2*FH, "[2]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[1].val, TIMEHOUR);
|
||||
#if TIMERS > 2
|
||||
lcdDrawText(MENU_STATS_COLUMN3, MENU_CONTENT_TOP+2*FH, "[3]", HEADER_COLOR);
|
||||
drawTimer(lcdNextPos+5, MENU_CONTENT_TOP+2*FH, timersStates[2].val, TIMEHOUR);
|
||||
#endif
|
||||
|
||||
const coord_t x = 10;
|
||||
const coord_t y = 240;
|
||||
lcdDrawHorizontalLine(x-3, y, MAXTRACE+3+3, SOLID, DEFAULT_COLOR);
|
||||
lcdDrawVerticalLine(x, y-96, 96+3, SOLID, DEFAULT_COLOR);
|
||||
for (coord_t i=0; i<MAXTRACE; i+=6) {
|
||||
lcdDrawVerticalLine(x+i, y-1, 3, SOLID, DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
uint16_t traceRd = s_traceWr > MAXTRACE ? s_traceWr - MAXTRACE : 0;
|
||||
coord_t prev_yv = (coord_t)-1;
|
||||
for (coord_t i=1; i<=MAXTRACE && traceRd<s_traceWr; i++, traceRd++) {
|
||||
uint8_t h = s_traceBuf[traceRd % MAXTRACE];
|
||||
coord_t yv = y - 2 - 3*h;
|
||||
if (prev_yv != (coord_t)-1) {
|
||||
if (prev_yv < yv) {
|
||||
for (int y=prev_yv; y<=yv; y++) {
|
||||
lcdDrawBitmapPattern(x + i - 3, y, LBM_POINT, DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y=yv; y<=prev_yv; y++) {
|
||||
lcdDrawBitmapPattern(x + i - 3, y, LBM_POINT, DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(x + i - 3, yv, LBM_POINT, DEFAULT_COLOR);
|
||||
}
|
||||
prev_yv = yv;
|
||||
}
|
||||
|
||||
lcdDrawText(LCD_W/2, MENU_FOOTER_TOP, STR_MENUTORESET, MENU_COLOR | CENTERED);
|
||||
return true;
|
||||
addTab(new StatisticsViewPage());
|
||||
addTab(new DebugViewPage());
|
||||
}
|
||||
|
||||
bool menuStatsDebug(event_t event)
|
||||
class ThrottleCurveWindow : public Window
|
||||
{
|
||||
switch(event) {
|
||||
case EVT_ENTRY:
|
||||
case EVT_ENTRY_UP:
|
||||
break;
|
||||
public:
|
||||
ThrottleCurveWindow(Window * parent, const rect_t &rect) :
|
||||
Window(parent, rect)
|
||||
{
|
||||
}
|
||||
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
maxMixerDuration = 0;
|
||||
#if defined(LUA)
|
||||
maxLuaInterval = 0;
|
||||
maxLuaDuration = 0;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
void checkEvents() override
|
||||
{
|
||||
Window::checkEvents();
|
||||
if (previousTraceWr != s_traceWr) {
|
||||
previousTraceWr = s_traceWr;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// Axis
|
||||
dc->drawHorizontalLine(0, height() - 2, width(), SOLID | DEFAULT_COLOR);
|
||||
dc->drawVerticalLine(0, 0, height(), SOLID, DEFAULT_COLOR);
|
||||
for (coord_t i=0; i < width(); i+=6) {
|
||||
dc->drawVerticalLine(i,height() - 4, 3, SOLID | DEFAULT_COLOR);
|
||||
}
|
||||
|
||||
if (!check_simple(event, e_StatsDebug, menuTabStats, DIM(menuTabStats), 1)) {
|
||||
disableVBatBridge();
|
||||
return false;
|
||||
}
|
||||
// Curve
|
||||
uint16_t traceRd = s_traceWr > width() ? s_traceWr - width() : 0;
|
||||
coord_t prev_yv = (coord_t)-1;
|
||||
for (coord_t i=1; i<=width() && traceRd<s_traceWr; i++, traceRd++) {
|
||||
uint8_t h = s_traceBuf[traceRd % width()];
|
||||
coord_t yv = height() - 2 - 3*h;
|
||||
if (prev_yv != (coord_t)-1) {
|
||||
if (prev_yv < yv) {
|
||||
for (int y=prev_yv; y<=yv; y++) {
|
||||
dc->drawBitmapPattern(i, y, LBM_POINT, DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y=yv; y<=prev_yv; y++) {
|
||||
dc->drawBitmapPattern(i, y, LBM_POINT, DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
dc->drawBitmapPattern(i, yv, LBM_POINT, DEFAULT_COLOR);
|
||||
}
|
||||
prev_yv = yv;
|
||||
}
|
||||
};
|
||||
|
||||
drawMenuTemplate("Debug", 0, STATS_ICONS, OPTION_MENU_TITLE_BAR);
|
||||
protected:
|
||||
unsigned previousTraceWr = 0;
|
||||
};
|
||||
|
||||
coord_t y = MENU_CONTENT_TOP;
|
||||
void StatisticsViewPage::build(FormWindow * window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(LCD_W / 4);
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Free Mem");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, y, availableMemory(), LEFT, 0, nullptr, "b");
|
||||
y += FH;
|
||||
// Session data
|
||||
new StaticText(window, grid.getLabelSlot(), STR_SESSION);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 0), [] {
|
||||
return getTimerString(sessionTimer, TIMEHOUR);
|
||||
});
|
||||
|
||||
// Battery data
|
||||
new StaticText(window, grid.getFieldSlot(3, 1), STR_BATT_LABEL);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 2), [] {
|
||||
return getTimerString(g_eeGeneral.globalTimer + sessionTimer, TIMEHOUR);
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle
|
||||
new StaticText(window, grid.getLabelSlot(), STR_THROTTLE_LABEL);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 0), [] {
|
||||
return getTimerString(s_timeCumThr, TIMEHOUR);
|
||||
});
|
||||
|
||||
// Throttle % data
|
||||
new StaticText(window, grid.getFieldSlot(3, 1), STR_THROTTLE_PERCENT_LABEL);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 2), [] {
|
||||
return getTimerString(s_timeCum16ThrP/16, TIMEHOUR);
|
||||
});
|
||||
grid.nextLine();
|
||||
|
||||
// Timers
|
||||
new StaticText(window, grid.getLabelSlot(), STR_TIMER_LABEL);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 0), [] {
|
||||
return getTimerString(timersStates[0].val, TIMEHOUR);
|
||||
}, 0);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 1), [] {
|
||||
return getTimerString(timersStates[1].val, TIMEHOUR);
|
||||
}, 0);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 2), [] {
|
||||
return getTimerString(timersStates[2].val, TIMEHOUR);
|
||||
}, 0);
|
||||
grid.nextLine();
|
||||
|
||||
// Throttle curve
|
||||
auto curve = new ThrottleCurveWindow(window, {5, grid.getWindowHeight(), window->width() - 10, window->height() / 2});
|
||||
grid.spacer(curve->height() + 3);
|
||||
|
||||
// Reset
|
||||
new TextButton (window, grid.getLineSlot(), STR_MENUTORESET,
|
||||
[=]() -> uint8_t {
|
||||
g_eeGeneral.globalTimer = 0;
|
||||
storageDirty(EE_GENERAL);
|
||||
sessionTimer = 0;
|
||||
return 0;
|
||||
}, BUTTON_BACKGROUND | NO_FOCUS);
|
||||
}
|
||||
|
||||
void DebugViewPage::build(FormWindow * window)
|
||||
{
|
||||
FormGridLayout grid;
|
||||
grid.spacer(PAGE_PADDING);
|
||||
grid.setLabelWidth(LCD_W / 4);
|
||||
|
||||
// Mixer data
|
||||
new StaticText(window, grid.getLabelSlot(), STR_TMIXMAXMS);
|
||||
new DynamicNumber<uint16_t>(window, grid.getFieldSlot(), [] {
|
||||
return DURATION_MS_PREC2(maxMixerDuration);
|
||||
}, PREC2, nullptr, "ms");
|
||||
grid.nextLine();
|
||||
|
||||
// Free mem
|
||||
new StaticText(window, grid.getLabelSlot(), STR_FREE_MEM_LABEL);
|
||||
new DynamicNumber<int>(window, grid.getFieldSlot(), [] {
|
||||
return availableMemory();
|
||||
}, 0, nullptr, "b");
|
||||
grid.nextLine();
|
||||
|
||||
#if defined(LUA)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Lua scripts");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, y+1, "[Duration]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, 10*maxLuaDuration, LEFT, 0, nullptr, "ms");
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[Interval]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, 10*maxLuaDuration, LEFT, 0, nullptr, "ms");
|
||||
y += FH;
|
||||
// LUA timing data
|
||||
new StaticText(window, grid.getLabelSlot(), STR_LUA_SCRIPTS_LABEL);
|
||||
new DebugInfoNumber<uint16_t>(window, grid.getFieldSlot(3, 0), [] {
|
||||
return 10 * maxLuaDuration;
|
||||
}, 0, "[Dur] ", "ms");
|
||||
new DebugInfoNumber<uint16_t>(window, grid.getFieldSlot(3, 1), [] {
|
||||
return 10 * maxLuaInterval;
|
||||
}, 0, "[Int] ", "ms");
|
||||
grid.nextLine();
|
||||
|
||||
// lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+line*FH, "Lua memory");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, y+1, "[S]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, luaGetMemUsed(lsScripts), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[W]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, luaGetMemUsed(lsWidgets), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[B]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, luaExtraMemoryUsage, LEFT);
|
||||
y += FH;
|
||||
// lUA memory data
|
||||
new DebugInfoNumber<uint32_t>(window, grid.getFieldSlot(3, 0), [] {
|
||||
return 10 * luaGetMemUsed(lsScripts);
|
||||
}, 0, "[S] ", nullptr);
|
||||
new DebugInfoNumber<uint32_t>(window, grid.getFieldSlot(3, 1), [] {
|
||||
return 10 * luaGetMemUsed(lsWidgets);
|
||||
}, 0, "[W] ", nullptr);
|
||||
new DebugInfoNumber<uint32_t>(window, grid.getFieldSlot(3, 2), [] {
|
||||
return luaExtraMemoryUsage;
|
||||
}, 0, "[B] ", nullptr);
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_TMIXMAXMS);
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, y, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT, 0, nullptr, "ms");
|
||||
y += FH;
|
||||
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FREE_STACK);
|
||||
lcdDrawText(MENU_STATS_COLUMN1, y+1, "[Menus]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, menusStack.available(), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[Mix]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, mixerStack.available(), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[Audio]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, audioStack.available(), LEFT);
|
||||
y += FH;
|
||||
|
||||
#if defined(DISK_CACHE) && defined(DEBUG)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "SD cache hits");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, y, diskCache.getHitRate(), PREC1|LEFT, 0, nullptr, "%");
|
||||
y += FH;
|
||||
#endif
|
||||
// Stacks data
|
||||
new StaticText(window, grid.getLabelSlot(), STR_FREE_STACK);
|
||||
new DebugInfoNumber<uint32_t>(window, grid.getFieldSlot(3, 0), [] {
|
||||
return menusStack.available();
|
||||
}, 0, "[Menu] ", nullptr);
|
||||
new DebugInfoNumber<uint32_t>(window, grid.getFieldSlot(3, 1), [] {
|
||||
return mixerStack.available();
|
||||
}, 0, "[Mix] ", nullptr);
|
||||
new DebugInfoNumber<uint32_t>(window, grid.getFieldSlot(3, 2), [] {
|
||||
return audioStack.available();
|
||||
}, 0, "[Audio] ", nullptr);
|
||||
grid.nextLine();
|
||||
|
||||
#if defined(DEBUG_LATENCY)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Heartbeat");
|
||||
new StaticText(window, grid.getLabelSlot(), STR_HEARTBEAT_LABEL);
|
||||
if (heartbeatCapture.valid)
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, y, heartbeatCapture.count, LEFT);
|
||||
new DebugInfoNumber<uint16_t>(window, grid.getFieldSlot(3, 0), [] {
|
||||
return heartbeatCapture.count;
|
||||
});
|
||||
else
|
||||
lcdDrawText(MENU_STATS_COLUMN1, y, "---");
|
||||
y += FH;
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Telem RX Errs");
|
||||
lcdDrawNumber(MENU_STATS_COLUMN1, y, telemetryErrors, LEFT);
|
||||
y += FH;
|
||||
new StaticText(window, grid.getFieldSlot(),"---");
|
||||
#endif
|
||||
|
||||
#if defined(INTERNAL_GPS)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, y, "Internal GPS");
|
||||
lcdDrawText(MENU_STATS_COLUMN1, y+1, "[Fix]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawText(lcdNextPos+2, y, (gpsData.fix ? "Yes" : "No"), LEFT);
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[Sats]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, gpsData.numSat, LEFT);
|
||||
lcdDrawText(lcdNextPos+20, y+1, "[Hdop]", HEADER_COLOR|FONT(XS));
|
||||
lcdDrawNumber(lcdNextPos+5, y, gpsData.hdop, PREC2|LEFT);
|
||||
new StaticText(window, grid.getLabelSlot(), STR_INT_GPS_LABEL);
|
||||
new DynamicText(window, grid.getFieldSlot(3, 0), [] {
|
||||
return std::string(gpsData.fix ? "[Fix] Yes" : "[Fix] No");
|
||||
});
|
||||
new DebugInfoNumber<uint8_t>(window, grid.getFieldSlot(3, 1), [] {
|
||||
return gpsData.numSat;
|
||||
}, 0, "[Sats] ", nullptr);
|
||||
new DebugInfoNumber<uint16_t>(window, grid.getFieldSlot(3, 2), [] {
|
||||
return gpsData.hdop;
|
||||
}, 0, "[Hdop] ", nullptr);
|
||||
grid.nextLine();
|
||||
#endif
|
||||
|
||||
lcdDrawText(LCD_W/2, MENU_FOOTER_TOP, STR_MENUTORESET, MENU_COLOR | CENTERED);
|
||||
return true;
|
||||
// Reset
|
||||
grid.nextLine();
|
||||
new TextButton (window, grid.getLineSlot(), STR_MENUTORESET,
|
||||
[=]() -> uint8_t {
|
||||
maxMixerDuration = 0;
|
||||
#if defined(LUA)
|
||||
maxLuaInterval = 0;
|
||||
maxLuaDuration = 0;
|
||||
#endif
|
||||
return 0;
|
||||
}, BUTTON_BACKGROUND | NO_FOCUS);
|
||||
}
|
||||
|
||||
bool menuStatsAnalogs(event_t event)
|
||||
{
|
||||
SIMPLE_MENU("Analogs", STATS_ICONS, menuTabStats, e_StatsAnalogs, 1);
|
||||
|
||||
for (uint8_t i=0; i<NUM_ANALOGS; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + (i/2)*FH;
|
||||
coord_t x = MENUS_MARGIN_LEFT + (i & 1 ? LCD_W/2 : 0);
|
||||
lcdDrawNumber(x, y, i+1, LEADING0|LEFT, 2, nullptr, ":");
|
||||
lcdDrawHexNumber(x+40, y, anaIn(i));
|
||||
#if defined(JITTER_MEASURE)
|
||||
lcdDrawNumber(x+100, y, rawJitter[i].get());
|
||||
lcdDrawNumber(x+140, y, avgJitter[i].get());
|
||||
lcdDrawNumber(x+180, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*250/256, PREC1);
|
||||
#else
|
||||
if (i < NUM_STICKS+NUM_POTS+NUM_SLIDERS)
|
||||
lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CONVERT_MODE(i)]*25/256);
|
||||
#if NUM_MOUSE_ANALOGS > 0
|
||||
else if (i >= MOUSE1)
|
||||
lcdDrawNumber(x+100, y, (int16_t)calibratedAnalogs[CALIBRATED_MOUSE1+i-MOUSE1]*25/256);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// RAS
|
||||
if ((isModuleXJT(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) || (isModulePXX1(EXTERNAL_MODULE) && !IS_INTERNAL_MODULE_ON())) {
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+7*FH, "RAS");
|
||||
lcdDrawNumber(MENUS_MARGIN_LEFT+100, MENU_CONTENT_TOP+7*FH, telemetryData.swrInternal.value());
|
||||
lcdDrawText(MENUS_MARGIN_LEFT + LCD_W/2, MENU_CONTENT_TOP+7*FH, "XJTVER");
|
||||
lcdDrawNumber(LCD_W/2 + MENUS_MARGIN_LEFT+100, MENU_CONTENT_TOP+7*FH, telemetryData.xjtVersion);
|
||||
}
|
||||
|
||||
#if (NUM_PWMSTICKS > 0) && !defined(SIMU)
|
||||
lcdDrawText(MENUS_MARGIN_LEFT, MENU_CONTENT_TOP+8*FH, STICKS_PWM_ENABLED() ? "Sticks: PWM" : "Sticks: ANA");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
#define STATS_TRACES_INDEX_POS MENUS_MARGIN_LEFT
|
||||
#define STATS_TRACES_TIME_POS MENUS_MARGIN_LEFT + 4*10
|
||||
#define STATS_TRACES_EVENT_POS MENUS_MARGIN_LEFT + 14*10
|
||||
#define STATS_TRACES_DATA_POS MENUS_MARGIN_LEFT + 20*10
|
||||
|
||||
bool menuStatsTraces(event_t event)
|
||||
{
|
||||
switch(event)
|
||||
{
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
dumpTraceBuffer();
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
|
||||
SIMPLE_MENU("", STATS_ICONS, menuTabStats, e_StatsTraces, TRACE_BUFFER_LEN);
|
||||
|
||||
uint8_t k = 0;
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
lcdDrawChar(STATS_TRACES_INDEX_POS, MENU_TITLE_TOP+2, '#', MENU_COLOR);
|
||||
lcdDrawText(STATS_TRACES_TIME_POS, MENU_TITLE_TOP+2, "Time", MENU_COLOR);
|
||||
lcdDrawText(STATS_TRACES_EVENT_POS, MENU_TITLE_TOP+2, "Event", MENU_COLOR);
|
||||
lcdDrawText(STATS_TRACES_DATA_POS, MENU_TITLE_TOP+2, "Data", MENU_COLOR);
|
||||
|
||||
for (uint8_t i=0; i<NUM_BODY_LINES; i++) {
|
||||
coord_t y = MENU_CONTENT_TOP + i * FH;
|
||||
k = i+menuVerticalOffset;
|
||||
|
||||
// item
|
||||
lcdDrawNumber(STATS_TRACES_INDEX_POS, y, k, LEFT | (sub==k ? INVERS : 0));
|
||||
|
||||
const struct TraceElement * te = getTraceElement(k);
|
||||
if (te) {
|
||||
// time
|
||||
int32_t tme = te->time % SECS_PER_DAY;
|
||||
drawTimer(STATS_TRACES_TIME_POS, y, tme, TIMEHOUR|LEFT);
|
||||
// event
|
||||
lcdDrawNumber(STATS_TRACES_EVENT_POS, y, te->event, LEADING0|LEFT, 3);
|
||||
// data
|
||||
lcdDrawSizedText(STATS_TRACES_DATA_POS, y, "0x", 2);
|
||||
lcdDrawHexNumber(lcdNextPos, y, (uint16_t)(te->data >> 16));
|
||||
lcdDrawHexNumber(lcdNextPos, y, (uint16_t)(te->data & 0xFFFF));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // defined(DEBUG_TRACE_BUFFER)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opentx.h"
|
||||
#include "tabsgroup.h"
|
||||
#include "static.h"
|
||||
|
||||
template <class T>
|
||||
class DebugInfoNumber : public Window
|
||||
{
|
||||
public:
|
||||
DebugInfoNumber(Window * parent, const rect_t & rect, std::function<T()> numberHandler, LcdFlags textFlags = 0, const char * prefix = nullptr, const char * suffix = nullptr):
|
||||
Window(parent, rect, 0, textFlags),
|
||||
numberHandler(std::move(numberHandler)),
|
||||
prefix(prefix),
|
||||
suffix(suffix)
|
||||
{
|
||||
coord_t prefixSize = getTextWidth(prefix, 0,HEADER_COLOR | FONT(XS));
|
||||
new StaticText(this, {0, 0, prefixSize, rect.h}, prefix, 0, HEADER_COLOR | FONT(XS));
|
||||
new DynamicNumber<uint32_t>(this, {prefixSize, 0, rect.w - prefixSize, rect.h}, [] {
|
||||
return menusStack.available();
|
||||
});
|
||||
}
|
||||
|
||||
protected:
|
||||
std::function<T()> numberHandler;
|
||||
const char * prefix;
|
||||
const char * suffix;
|
||||
};
|
||||
|
||||
class StatisticsViewPage : public PageTab
|
||||
{
|
||||
public:
|
||||
StatisticsViewPage() :
|
||||
PageTab(STR_STATISTICS, ICON_STATS_THROTTLE_GRAPH)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window) override;
|
||||
};
|
||||
|
||||
class StatisticsViewPageGroup: public TabsGroup {
|
||||
public:
|
||||
StatisticsViewPageGroup();
|
||||
};
|
||||
|
||||
class DebugViewPage : public PageTab
|
||||
{
|
||||
public:
|
||||
DebugViewPage() :
|
||||
PageTab(STR_DEBUG, ICON_STATS_DEBUG)
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void build(FormWindow * window) override;
|
||||
};
|
||||
|
||||
class DebugViewMenu: public TabsGroup {
|
||||
public:
|
||||
DebugViewMenu();
|
||||
};
|
||||
@@ -23,14 +23,51 @@
|
||||
class GaugeWidget: public Widget
|
||||
{
|
||||
public:
|
||||
GaugeWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData)
|
||||
GaugeWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData):
|
||||
Widget(factory, parent, rect, persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void refresh();
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
mixsrc_t index = persistentData->options[0].value.unsignedValue;
|
||||
int32_t min = persistentData->options[1].value.signedValue;
|
||||
int32_t max = persistentData->options[2].value.signedValue;
|
||||
uint16_t color = persistentData->options[3].value.unsignedValue;
|
||||
|
||||
int32_t value = getValue(index);
|
||||
|
||||
if (min > max) {
|
||||
SWAP(min, max);
|
||||
value = value - min - max;
|
||||
}
|
||||
|
||||
value = limit(min, value, max);
|
||||
|
||||
int w = divRoundClosest(width() * (value - min), (max - min));
|
||||
int percent = divRoundClosest(100 * (value - min), (max - min));
|
||||
|
||||
// Gauge label
|
||||
drawSource(dc, 0, 0, index, FONT(XS) | FOCUS_COLOR);
|
||||
|
||||
// Gauge
|
||||
lcdSetColor(color);
|
||||
dc->drawSolidFilledRect(0, 16, width(), 16, FOCUS_COLOR);
|
||||
dc->drawNumber(0+width()/2, 17, percent, FONT(XS) | CUSTOM_COLOR | CENTERED, 0, nullptr, "%");
|
||||
dc->invertRect(w, 16, width() - w, 16, CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
auto newValue = getValue(persistentData->options[0].value.unsignedValue);
|
||||
if (lastValue != newValue) {
|
||||
lastValue = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
static const ZoneOption options[];
|
||||
int32_t lastValue = 0;
|
||||
};
|
||||
|
||||
const ZoneOption GaugeWidget::options[] = {
|
||||
@@ -41,33 +78,4 @@ const ZoneOption GaugeWidget::options[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
void GaugeWidget::refresh()
|
||||
{
|
||||
mixsrc_t index = persistentData->options[0].value.unsignedValue;
|
||||
int32_t min = persistentData->options[1].value.signedValue;
|
||||
int32_t max = persistentData->options[2].value.signedValue;
|
||||
uint16_t color = persistentData->options[3].value.unsignedValue;
|
||||
|
||||
int32_t value = getValue(index);
|
||||
|
||||
if (min > max) {
|
||||
SWAP(min, max);
|
||||
value = value - min - max;
|
||||
}
|
||||
|
||||
value = limit(min, value, max);
|
||||
|
||||
int w = divRoundClosest(zone.w * (value - min), (max - min));
|
||||
int percent = divRoundClosest(100 * (value - min), (max - min));
|
||||
|
||||
// Gauge label
|
||||
drawSource(zone.x, zone.y, index, FONT(XS) | FOCUS_COLOR);
|
||||
|
||||
// Gauge
|
||||
lcdSetColor(color);
|
||||
lcdDrawSolidFilledRect(zone.x, zone.y + 16, zone.w, 16, FOCUS_COLOR);
|
||||
lcdDrawNumber(zone.x+zone.w/2, zone.y + 17, percent, FONT(XS) | CUSTOM_COLOR | CENTERED, 0, nullptr, "%");
|
||||
lcd->invertRect(zone.x + w, zone.y + 16, zone.w - w, 16, CUSTOM_COLOR);
|
||||
}
|
||||
|
||||
BaseWidgetFactory<GaugeWidget> gaugeWidget("Gauge", GaugeWidget::options);
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
class ModelBitmapWidget: public Widget
|
||||
{
|
||||
public:
|
||||
ModelBitmapWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData),
|
||||
ModelBitmapWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData):
|
||||
Widget(factory, parent, rect, persistentData),
|
||||
buffer(nullptr),
|
||||
deps_hash(0)
|
||||
{
|
||||
@@ -35,46 +35,46 @@ class ModelBitmapWidget: public Widget
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
void refreshBuffer()
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
delete buffer;
|
||||
buffer = new BitmapBuffer(BMP_RGB565, zone.w, zone.h);
|
||||
buffer = new BitmapBuffer(BMP_RGB565, rect.w, rect.h);
|
||||
|
||||
if (buffer) {
|
||||
buffer->drawBitmap(0, 0, lcd, zone.x, zone.y, zone.w, zone.h);
|
||||
buffer->drawBitmap(0, 0, lcd, rect.x, rect.y, rect.w, rect.h);
|
||||
GET_FILENAME(filename, BITMAPS_PATH, g_model.header.bitmap, "");
|
||||
BitmapBuffer * bitmap = BitmapBuffer::load(filename);
|
||||
if (zone.h >= 96 && zone.w >= 120) {
|
||||
buffer->drawFilledRect(0, 0, zone.w, zone.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
static BitmapBuffer * icon = BitmapBuffer::loadMask(getThemePath("mask_menu_model.png"));
|
||||
BitmapBuffer * bitmap = BitmapBuffer::loadBitmap(filename);
|
||||
if (rect.h >= 96 && rect.w >= 120) {
|
||||
buffer->drawFilledRect(0, 0, rect.w, rect.h, SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
static BitmapBuffer * icon = BitmapBuffer::loadMask(OpenTxTheme::instance()->getFilePath("mask_menu_model.png"));
|
||||
buffer->drawMask(6, 4, icon, MAINVIEW_GRAPHICS_COLOR);
|
||||
buffer->drawSizedText(45, 10, g_model.header.name, LEN_MODEL_NAME, ZCHAR | FONT(XS));
|
||||
buffer->drawSolidFilledRect(39, 27, zone.w - 48, 2, MAINVIEW_GRAPHICS_COLOR);
|
||||
buffer->drawSizedText(45, 10, g_model.header.name, LEN_MODEL_NAME, FONT(XS));
|
||||
buffer->drawSolidFilledRect(39, 27, rect.w - 48, 2, MAINVIEW_GRAPHICS_COLOR);
|
||||
if (bitmap) {
|
||||
buffer->drawScaledBitmap(bitmap, 0, 38, zone.w, zone.h - 38);
|
||||
buffer->drawScaledBitmap(bitmap, 0, 38, rect.w, rect.h - 38);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (bitmap) {
|
||||
buffer->drawScaledBitmap(bitmap, 0, 0, zone.w, zone.h);
|
||||
buffer->drawScaledBitmap(bitmap, 0, 0, rect.w, rect.h);
|
||||
}
|
||||
}
|
||||
delete bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
void refresh() override
|
||||
void checkEvents() override
|
||||
{
|
||||
uint32_t new_hash = hash(g_model.header.bitmap, sizeof(g_model.header.bitmap));
|
||||
new_hash ^= hash(g_model.header.name, sizeof(g_model.header.name));
|
||||
new_hash ^= hash(g_eeGeneral.themeName, sizeof(g_eeGeneral.themeName));
|
||||
if (new_hash != deps_hash) {
|
||||
deps_hash = new_hash;
|
||||
refreshBuffer();
|
||||
invalidate();
|
||||
}
|
||||
|
||||
if (buffer) {
|
||||
lcd->drawBitmap(zone.x, zone.y, buffer);
|
||||
lcd->drawBitmap(rect.x, rect.y, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,14 +28,20 @@
|
||||
class OutputsWidget: public Widget
|
||||
{
|
||||
public:
|
||||
OutputsWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData)
|
||||
OutputsWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData):
|
||||
Widget(factory, parent, rect, persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
void refresh() override;
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
if (width() > 300 && height() > 20)
|
||||
twoColumns(dc);
|
||||
else if (width() > 150 && height() > 20)
|
||||
oneColumn(dc);
|
||||
}
|
||||
|
||||
uint8_t drawChannels(const uint16_t & x, const uint16_t & y, const uint16_t & w, const uint16_t & h, const uint8_t & firstChan, const bool & bg_shown, const uint16_t & bg_color)
|
||||
uint8_t drawChannels(BitmapBuffer * dc, const uint16_t & x, const uint16_t & y, const uint16_t & w, const uint16_t & h, const uint8_t & firstChan, const bool & bg_shown, const uint16_t & bg_color)
|
||||
{
|
||||
const uint8_t numChan = h / ROW_HEIGHT;
|
||||
const uint8_t lastChan = firstChan + numChan;
|
||||
@@ -53,44 +59,50 @@ class OutputsWidget: public Widget
|
||||
|
||||
if (bg_shown) {
|
||||
lcdSetColor(bg_color);
|
||||
lcdDrawSolidFilledRect(barLft, barTop, barW , barH, CUSTOM_COLOR);
|
||||
dc->drawSolidFilledRect(barLft, barTop, barW , barH, CUSTOM_COLOR);
|
||||
}
|
||||
if (fillW)
|
||||
lcdDrawSolidFilledRect((chanVal > 0 ? barMid : barMid - fillW), barTop, fillW, barH, MAINVIEW_GRAPHICS_COLOR);
|
||||
dc->drawSolidFilledRect((chanVal > 0 ? barMid : barMid - fillW), barTop, fillW, barH, BARGRAPH1_COLOR);
|
||||
lcd->drawSolidVerticalLine(barMid, barTop, barH, MAINVIEW_GRAPHICS_COLOR);
|
||||
lcdDrawRect(x, rowTop, w, rowH + 1);
|
||||
lcdDrawNumber(x + barW - 10, barTop, chanVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
dc->drawRect(x, rowTop, w, rowH + 1);
|
||||
dc->drawNumber(x + barW - 10, barTop, chanVal, FONT(XS) | DEFAULT_COLOR | RIGHT, 0, nullptr, "%");
|
||||
if (g_model.limitData[curChan - 1].name[0] != 0) {
|
||||
lcdDrawNumber(barLft + 1, barTop, curChan, FONT(XS) | DEFAULT_COLOR | LEFT | LEADING0, 2);
|
||||
lcdDrawSizedText(barLft + 23, barTop, g_model.limitData[curChan - 1].name, sizeof(g_model.limitData[curChan - 1].name), FONT(XS) | DEFAULT_COLOR | LEFT | ZCHAR);
|
||||
dc->drawNumber(barLft + 1, barTop, curChan, FONT(XS) | DEFAULT_COLOR | LEFT | LEADING0, 2);
|
||||
dc->drawSizedText(barLft + 23, barTop, g_model.limitData[curChan - 1].name, sizeof(g_model.limitData[curChan - 1].name), FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
}
|
||||
else {
|
||||
putsChn(barLft + 1, barTop, curChan, FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
drawSource(dc, barLft + 1, barTop, curChan, FONT(XS) | DEFAULT_COLOR | LEFT);
|
||||
}
|
||||
}
|
||||
return lastChan - 1;
|
||||
}
|
||||
|
||||
void twoColumns()
|
||||
void twoColumns(BitmapBuffer * dc)
|
||||
{
|
||||
uint8_t endColumn = drawChannels(zone.x, zone.y, zone.w / 2, zone.h,
|
||||
uint8_t endColumn = drawChannels(dc, 0, 0, width() / 2, height(),
|
||||
persistentData->options[0].value.unsignedValue,
|
||||
persistentData->options[1].value.boolValue,
|
||||
persistentData->options[2].value.unsignedValue);
|
||||
|
||||
drawChannels(zone.x + zone.w / 2 + 2, zone.y, zone.w / 2, zone.h, endColumn + 1,
|
||||
drawChannels(dc, width() / 2 + 2, 0, width() / 2, height(), endColumn + 1,
|
||||
persistentData->options[1].value.boolValue,
|
||||
persistentData->options[2].value.unsignedValue);
|
||||
}
|
||||
|
||||
void oneColumn()
|
||||
void oneColumn(BitmapBuffer * dc)
|
||||
{
|
||||
drawChannels(zone.x, zone.y, zone.w, zone.h,
|
||||
drawChannels(dc, 0, 0, width(), height(),
|
||||
persistentData->options[0].value.unsignedValue,
|
||||
persistentData->options[1].value.boolValue,
|
||||
persistentData->options[2].value.unsignedValue);
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
static const ZoneOption options[];
|
||||
};
|
||||
|
||||
@@ -101,13 +113,4 @@ const ZoneOption OutputsWidget::options[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
|
||||
void OutputsWidget::refresh()
|
||||
{
|
||||
if (zone.w > 300 && zone.h > 20)
|
||||
twoColumns();
|
||||
else if (zone.w > 150 && zone.h > 20)
|
||||
oneColumn();
|
||||
};
|
||||
|
||||
BaseWidgetFactory<OutputsWidget> outputsWidget("Outputs", OutputsWidget::options);
|
||||
|
||||
@@ -32,11 +32,6 @@ class TextWidget: public Widget
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// TODO DELETE THOSE TEST INIT VALUE !!
|
||||
strcpy(persistentData->options[0].value.stringValue, "This is a test string");
|
||||
persistentData->options[3].value.boolValue = true; // shadow
|
||||
// TODO END TEST INIT VALUE
|
||||
|
||||
// clear the background
|
||||
dc->clear(DEFAULT_BGCOLOR);
|
||||
|
||||
|
||||
@@ -23,14 +23,80 @@
|
||||
class TimerWidget: public Widget
|
||||
{
|
||||
public:
|
||||
TimerWidget(const WidgetFactory * factory, const Zone & zone, Widget::PersistentData * persistentData):
|
||||
Widget(factory, zone, persistentData)
|
||||
TimerWidget(const WidgetFactory * factory, Window * parent, const rect_t & rect, Widget::PersistentData * persistentData):
|
||||
Widget(factory, parent, rect, persistentData)
|
||||
{
|
||||
}
|
||||
|
||||
void refresh() override;
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
uint32_t index = persistentData->options[0].value.unsignedValue;
|
||||
TimerData & timerData = g_model.timers[index];
|
||||
TimerState & timerState = timersStates[index];
|
||||
|
||||
if (width() >= 180 && height() >= 70) {
|
||||
if (timerState.val >= 0 || !(timerState.val % 2)) {
|
||||
dc->drawBitmapPattern(0, 0, LBM_TIMER_BACKGROUND, MAINVIEW_PANES_COLOR);
|
||||
}
|
||||
else {
|
||||
dc->drawBitmapPattern(0, 0, LBM_TIMER_BACKGROUND, MENU_BGCOLOR);
|
||||
}
|
||||
if (timerData.start && timerState.val >= 0) {
|
||||
dc->drawBitmapPatternPie(
|
||||
2, 3, LBM_RSCALE, MAINVIEW_GRAPHICS_COLOR, 0,
|
||||
timerState.val <= 0 ? 360 : 360 * (timerData.start - timerState.val) / timerData.start);
|
||||
}
|
||||
else {
|
||||
dc->drawBitmapPattern(3, 4, LBM_TIMER, MAINVIEW_GRAPHICS_COLOR);
|
||||
}
|
||||
if (abs(timerState.val) >= 3600) {
|
||||
drawTimer(dc, 70, 31, abs(timerState.val), DEFAULT_COLOR | FONT(STD) | LEFT | TIMEHOUR);
|
||||
}
|
||||
else {
|
||||
drawTimer(dc,76, 31, abs(timerState.val), DEFAULT_COLOR | FONT(XL) | LEFT);
|
||||
}
|
||||
if (ZLEN(timerData.name) > 0) {
|
||||
dc->drawSizedText(78, 20, timerData.name, LEN_TIMER_NAME, FONT(XS) | DEFAULT_COLOR);
|
||||
}
|
||||
else {
|
||||
drawStringWithIndex(dc, 137, 17, "TMR", index + 1, FONT(XS) | DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (timerState.val < 0 && timerState.val % 2) {
|
||||
dc->drawSolidFilledRect(0, 0, width(), height(), HEADER_ICON_BGCOLOR);
|
||||
}
|
||||
drawStringWithIndex(dc, 2, 0, "TMR", index + 1, FONT(XS) | FOCUS_COLOR);
|
||||
if (width() > 100 && height() > 40) {
|
||||
if (abs(timerState.val) >= 3600) {
|
||||
drawTimer(dc,3, 16, abs(timerState.val), FOCUS_COLOR | LEFT | TIMEHOUR);
|
||||
}
|
||||
else {
|
||||
drawTimer(dc, 3, 16, abs(timerState.val), FOCUS_COLOR | LEFT | FONT(STD));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (abs(timerState.val) >= 3600) {
|
||||
drawTimer(dc,3, 14, abs(timerState.val), FOCUS_COLOR | LEFT | FONT(XS) | TIMEHOUR);
|
||||
}
|
||||
else {
|
||||
drawTimer(dc, 3, 14, abs(timerState.val), FOCUS_COLOR | LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkEvents() override
|
||||
{
|
||||
auto newValue = timersStates[persistentData->options[0].value.unsignedValue].val;
|
||||
if (lastValue != newValue) {
|
||||
lastValue = newValue;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
static const ZoneOption options[];
|
||||
tmrval_t lastValue = 0;
|
||||
};
|
||||
|
||||
const ZoneOption TimerWidget::options[] = {
|
||||
@@ -38,63 +104,5 @@ const ZoneOption TimerWidget::options[] = {
|
||||
{ nullptr, ZoneOption::Bool }
|
||||
};
|
||||
|
||||
void TimerWidget::refresh()
|
||||
{
|
||||
uint32_t index = persistentData->options[0].value.unsignedValue;
|
||||
TimerData & timerData = g_model.timers[index];
|
||||
TimerState & timerState = timersStates[index];
|
||||
|
||||
if (zone.w >= 180 && zone.h >= 70) {
|
||||
if (timerState.val >= 0 || !(timerState.val % 2)) {
|
||||
lcdDrawBitmapPattern(zone.x, zone.y, LBM_TIMER_BACKGROUND, MAINVIEW_PANES_COLOR);
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(zone.x, zone.y, LBM_TIMER_BACKGROUND, MENU_BGCOLOR);
|
||||
}
|
||||
if (timerData.start && timerState.val >= 0) {
|
||||
lcdDrawBitmapPatternPie(
|
||||
zone.x + 2,
|
||||
zone.y + 3, LBM_RSCALE, MAINVIEW_GRAPHICS_COLOR, 0,
|
||||
timerState.val <= 0 ? 360 : 360 * (timerData.start - timerState.val) / timerData.start);
|
||||
}
|
||||
else {
|
||||
lcdDrawBitmapPattern(zone.x + 3, zone.y + 4, LBM_TIMER, MAINVIEW_GRAPHICS_COLOR);
|
||||
}
|
||||
if (abs(timerState.val) >= 3600) {
|
||||
drawTimer(zone.x + 70, zone.y + 31, abs(timerState.val), DEFAULT_COLOR | MIDSIZE | LEFT | TIMEHOUR);
|
||||
}
|
||||
else {
|
||||
drawTimer(zone.x + 76, zone.y + 31, abs(timerState.val), DEFAULT_COLOR | FONT(XL) | LEFT);
|
||||
}
|
||||
if (ZLEN(timerData.name) > 0) {
|
||||
lcdDrawSizedText(zone.x + 78, zone.y + 20, timerData.name, LEN_TIMER_NAME, ZCHAR | FONT(XS) | DEFAULT_COLOR);
|
||||
}
|
||||
else {
|
||||
drawStringWithIndex(zone.x + 137, zone.y + 17, "TMR", index + 1, FONT(XS) | DEFAULT_COLOR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (timerState.val < 0 && timerState.val % 2) {
|
||||
lcdDrawSolidFilledRect(zone.x, zone.y, zone.w, zone.h, HEADER_ICON_BGCOLOR);
|
||||
}
|
||||
drawStringWithIndex(zone.x + 2, zone.y, "TMR", index + 1, FONT(XS) | FOCUS_COLOR);
|
||||
if (zone.w > 100 && zone.h > 40) {
|
||||
if (abs(timerState.val) >= 3600) {
|
||||
drawTimer(zone.x + 3, zone.y + 16, abs(timerState.val), FOCUS_COLOR | LEFT | TIMEHOUR);
|
||||
}
|
||||
else {
|
||||
drawTimer(zone.x + 3, zone.y + 16, abs(timerState.val), FOCUS_COLOR | LEFT | MIDSIZE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (abs(timerState.val) >= 3600) {
|
||||
drawTimer(zone.x + 3, zone.y + 14, abs(timerState.val), FOCUS_COLOR | LEFT | FONT(XS) | TIMEHOUR);
|
||||
}
|
||||
else {
|
||||
drawTimer(zone.x + 3, zone.y + 14, abs(timerState.val), FOCUS_COLOR | LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseWidgetFactory<TimerWidget> timerWidget("Timer", TimerWidget::options);
|
||||
|
||||
@@ -32,10 +32,6 @@ class ValueWidget: public Widget
|
||||
|
||||
void paint(BitmapBuffer * dc) override
|
||||
{
|
||||
// TODO DELETE THOSE TEST INIT VALUE !!
|
||||
persistentData->options[0].value.unsignedValue = 1;
|
||||
// TODO END TEST INIT VALUE
|
||||
|
||||
// draw the background and border
|
||||
dc->clear(DEFAULT_BGCOLOR);
|
||||
dc->drawFilledRect(0,0, width(), height(), SOLID, MAINVIEW_PANES_COLOR | OPACITY(5));
|
||||
|
||||
@@ -72,15 +72,13 @@ class WidgetsContainer: public Window, public WidgetsContainerInterface
|
||||
|
||||
void createWidget(unsigned int index, const WidgetFactory * factory) override
|
||||
{
|
||||
if (widgets) {
|
||||
memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName));
|
||||
if (factory) {
|
||||
strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(persistentData->zones[index].widgetName));
|
||||
widgets[index] = factory->create(this, getZone(index), &persistentData->zones[index].widgetData);
|
||||
}
|
||||
else {
|
||||
widgets[index] = nullptr;
|
||||
}
|
||||
memset(persistentData->zones[index].widgetName, 0, sizeof(persistentData->zones[index].widgetName));
|
||||
if (factory) {
|
||||
strncpy(persistentData->zones[index].widgetName, factory->getName(), sizeof(persistentData->zones[index].widgetName));
|
||||
widgets[index] = factory->create(this, getZone(index), &persistentData->zones[index].widgetData);
|
||||
}
|
||||
else {
|
||||
widgets[index] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,26 +89,17 @@ class WidgetsContainer: public Window, public WidgetsContainerInterface
|
||||
|
||||
virtual void load()
|
||||
{
|
||||
if (widgets) {
|
||||
unsigned int count = getZonesCount();
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
delete widgets[i];
|
||||
if (i == 0) {
|
||||
char name[WIDGET_NAME_LEN + 1] = "Text";
|
||||
widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData);
|
||||
} else if (i == 1) {
|
||||
char name[WIDGET_NAME_LEN + 1] = "Value";
|
||||
widgets[i] = loadWidget(name, this, getZone(i), &persistentData->zones[i].widgetData);
|
||||
}
|
||||
else if (persistentData->zones[i].widgetName[0]) {
|
||||
char name[WIDGET_NAME_LEN + 1];
|
||||
memset(name, 0, sizeof(name));
|
||||
strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN);
|
||||
// TODO widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData);
|
||||
}
|
||||
else {
|
||||
widgets[i] = nullptr;
|
||||
}
|
||||
unsigned int count = getZonesCount();
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
delete widgets[i];
|
||||
if (persistentData->zones[i].widgetName[0]) {
|
||||
char name[WIDGET_NAME_LEN + 1];
|
||||
memset(name, 0, sizeof(name));
|
||||
strncpy(name, persistentData->zones[i].widgetName, WIDGET_NAME_LEN);
|
||||
// TODO widgets[i] = loadWidget(name, getZone(i), &persistentData->zones[i].widgetData);
|
||||
}
|
||||
else {
|
||||
widgets[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,32 +24,31 @@
|
||||
#if defined(MULTIMODULE)
|
||||
void lcdDrawMultiProtocolString(coord_t x, coord_t y, uint8_t moduleIdx, uint8_t protocol, LcdFlags flags)
|
||||
{
|
||||
if (protocol <= MODULE_SUBTYPE_MULTI_LAST) {
|
||||
MultiModuleStatus & status = getMultiModuleStatus(moduleIdx);
|
||||
if (status.protocolName[0] && status.isValid()) {
|
||||
lcdDrawText(x, y, status.protocolName, flags);
|
||||
}
|
||||
else if (protocol <= MODULE_SUBTYPE_MULTI_LAST) {
|
||||
lcdDrawTextAtIndex(x, y, STR_MULTI_PROTOCOLS, protocol, flags);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
|
||||
if (status.protocolName[0] && status.isValid())
|
||||
lcdDrawText(x, y, status.protocolName, flags);
|
||||
else
|
||||
lcdDrawNumber(x, y, protocol + 3, flags); // Convert because of OpenTX FrSky fidling (OpenTX protocol tables and Multiprotocol tables don't match)
|
||||
lcdDrawNumber(x, y, protocol + 3, flags); // Convert because of OpenTX FrSky fidling (OpenTX protocol tables and Multiprotocol tables don't match)
|
||||
}
|
||||
}
|
||||
|
||||
void lcdDrawMultiSubProtocolString(coord_t x, coord_t y, uint8_t moduleIdx, uint8_t subType, LcdFlags flags)
|
||||
{
|
||||
const mm_protocol_definition *pdef = getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol());
|
||||
if (subType <= pdef->maxSubtype && pdef->subTypeString != nullptr) {
|
||||
MultiModuleStatus & status = getMultiModuleStatus(moduleIdx);
|
||||
const mm_protocol_definition * pdef = getMultiProtocolDefinition(g_model.moduleData[moduleIdx].getMultiProtocol());
|
||||
|
||||
if (status.protocolName[0] && status.isValid()) {
|
||||
lcdDrawText(x, y, status.protocolSubName, flags);
|
||||
}
|
||||
else if (subType <= pdef->maxSubtype && pdef->subTypeString != nullptr) {
|
||||
lcdDrawTextAtIndex(x, y, pdef->subTypeString, subType, flags);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
MultiModuleStatus &status = getMultiModuleStatus(moduleIdx);
|
||||
if (status.protocolName[0] && status.isValid())
|
||||
lcdDrawText(x, y, status.protocolSubName, flags);
|
||||
else
|
||||
lcdDrawNumber(x, y, subType, flags);
|
||||
lcdDrawNumber(x, y, subType, flags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -387,7 +387,7 @@ bool isSwitchAvailable(int swtch, SwitchContext context)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isAux1ModeAvailable(int mode)
|
||||
bool isAuxModeAvailable(int mode)
|
||||
{
|
||||
#if defined(AUX2_SERIAL)
|
||||
if (mode == UART_MODE_SBUS_TRAINER)
|
||||
@@ -798,7 +798,7 @@ bool isTrainerModeAvailable(int mode)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(RADIO_TX16S)
|
||||
#if defined(RADIO_TX16S) && defined(TRAINER_BATTERY_COMPARTMENT)
|
||||
if (mode == TRAINER_MODE_MASTER_BATTERY_COMPARTMENT)
|
||||
return (g_eeGeneral.auxSerialMode == UART_MODE_SBUS_TRAINER || g_eeGeneral.aux2SerialMode == UART_MODE_SBUS_TRAINER);
|
||||
#elif defined(PCBTARANIS) && !defined(TRAINER_BATTERY_COMPARTMENT)
|
||||
|
||||
@@ -85,7 +85,7 @@ bool isSourceAvailableInCustomSwitches(int source);
|
||||
bool isSourceAvailableInResetSpecialFunction(int index);
|
||||
bool isSourceAvailableInGlobalResetSpecialFunction(int index);
|
||||
bool isSwitchAvailable(int swtch, SwitchContext context);
|
||||
bool isAux1ModeAvailable(int mode);
|
||||
bool isAuxModeAvailable(int mode);
|
||||
bool isAux2ModeAvailable(int mode);
|
||||
bool isSwitchAvailableInLogicalSwitches(int swtch);
|
||||
bool isSwitchAvailableInCustomFunctions(int swtch);
|
||||
@@ -303,7 +303,7 @@ inline uint8_t MULTIMODULE_HASOPTIONS(uint8_t moduleIdx)
|
||||
#endif
|
||||
|
||||
#if defined(AFHDS3)
|
||||
#define AFHDS3_PROTOCOL_ROW(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW,
|
||||
#define AFHDS3_PROTOCOL_ROW(moduleIdx) isModuleAFHDS3(moduleIdx) ? 0 : HIDDEN_ROW,
|
||||
#define AFHDS3_MODE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? TITLE_ROW : HIDDEN_ROW,
|
||||
#define AFHDS3_MODULE_ROWS(moduleIdx) isModuleAFHDS3(moduleIdx) ? (uint8_t) 0 : HIDDEN_ROW, isModuleAFHDS3(moduleIdx) ? (uint8_t) TITLE_ROW : HIDDEN_ROW,
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,783 @@
|
||||
/*
|
||||
* 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 <cctype>
|
||||
#include <cstdio>
|
||||
#include "opentx.h"
|
||||
#include "lua_api.h"
|
||||
|
||||
/*luadoc
|
||||
@function lcd.refresh()
|
||||
|
||||
Refresh the LCD screen
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
|
||||
@notice This function only works in stand-alone and telemetry scripts.
|
||||
*/
|
||||
static int luaLcdRefresh(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (luaLcdAllowed) lcdRefresh();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.clear([color])
|
||||
|
||||
Clear the LCD screen
|
||||
|
||||
@param color (optional, only on color screens)
|
||||
|
||||
@status current Introduced in 2.0.0, `color` parameter introduced in 2.2.0 RC12
|
||||
|
||||
@notice This function only works in stand-alone and telemetry scripts.
|
||||
*/
|
||||
static int luaLcdClear(lua_State * L)
|
||||
{
|
||||
#if 0
|
||||
if (luaLcdAllowed) {
|
||||
#if defined(COLORLCD)
|
||||
LcdFlags color = luaL_optunsigned(L, 1, TEXT_BGCOLOR);
|
||||
lcd->clear(color);
|
||||
#else
|
||||
lcdClear();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.resetBacklightTimeout()
|
||||
|
||||
Reset the backlight timeout
|
||||
|
||||
@status current Introduced in 2.3.6
|
||||
*/
|
||||
static int luaLcdResetBacklightTimeout(lua_State * L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
resetBacklightTimeout();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawPoint(x, y)
|
||||
|
||||
Draw a single pixel at (x,y) position
|
||||
|
||||
@param x (positive number) x position
|
||||
|
||||
@param y (positive number) y position
|
||||
|
||||
@param flags (optional) lcdflags
|
||||
|
||||
@notice Taranis has an LCD display width of 212 pixels and height of 64 pixels.
|
||||
Position (0,0) is at top left. Y axis is negative, top line is 0,
|
||||
bottom line is 63. Drawing on an existing black pixel produces white pixel (TODO check this!)
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawPoint(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
LcdFlags att = luaL_optunsigned(L, 3, 0);
|
||||
lcdDrawPoint(x, y, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawLine(x1, y1, x2, y2, pattern, flags)
|
||||
|
||||
Draw a straight line on LCD
|
||||
|
||||
@param x1,y1 (positive numbers) starting coordinate
|
||||
|
||||
@param x2,y2 (positive numbers) end coordinate
|
||||
|
||||
@param pattern SOLID or DOTTED
|
||||
|
||||
@param flags lcdflags
|
||||
|
||||
@notice If the start or the end of the line is outside the LCD dimensions, then the
|
||||
whole line will not be drawn (starting from OpenTX 2.1.5)
|
||||
|
||||
@status current Introduced in 2.0.0, flags introduced in 2.3.6
|
||||
*/
|
||||
static int luaLcdDrawLine(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
coord_t x1 = luaL_checkunsigned(L, 1);
|
||||
coord_t y1 = luaL_checkunsigned(L, 2);
|
||||
coord_t x2 = luaL_checkunsigned(L, 3);
|
||||
coord_t y2 = luaL_checkunsigned(L, 4);
|
||||
uint8_t pat = luaL_checkunsigned(L, 5);
|
||||
LcdFlags flags = luaL_checkunsigned(L, 6);
|
||||
|
||||
if (x1 > LCD_W || y1 > LCD_H || x2 > LCD_W || y2 > LCD_H)
|
||||
return 0;
|
||||
|
||||
if (pat == SOLID) {
|
||||
if (x1 == x2) {
|
||||
lcdDrawSolidVerticalLine(x1, y1<y2 ? y1 : y2, y1<y2 ? (y2-y1)+1 : (y1-y2)+1, flags);
|
||||
return 0;
|
||||
}
|
||||
else if (y1 == y2) {
|
||||
lcdDrawSolidHorizontalLine(x1<x2 ? x1 : x2, y1, x1<x2 ? (x2-x1)+1 : (x1-x2)+1, flags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lcdDrawLine(x1, y1, x2, y2, pat, flags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawText(x, y, text [, flags])
|
||||
|
||||
Draw a text beginning at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param text (string) text to display
|
||||
|
||||
@param flags (unsigned number) drawing flags. All values can be
|
||||
combined together using the + character. ie BLINK + DBLSIZE.
|
||||
See the [Appendix](../appendix/fonts.md) for available characters in each font set.
|
||||
* `0 or not specified` normal font
|
||||
* `XXLSIZE` jumbo sized font
|
||||
* `DBLSIZE` double size font
|
||||
* `MIDSIZE` mid sized font
|
||||
* `SMLSIZE` small font
|
||||
* `INVERS` inverted display
|
||||
* `BLINK` blinking text
|
||||
* `SHADOWED` Horus only, apply a shadow effect
|
||||
|
||||
@status current Introduced in 2.0.0, `SHADOWED` introduced in 2.2.1
|
||||
*/
|
||||
static int luaLcdDrawText(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
const char * s = luaL_checkstring(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
#if defined(COLORLCD)
|
||||
if ((att&SHADOWED) && !(att&INVERS)) lcdDrawText(x+1, y+1, s, att&0xFFFF);
|
||||
#endif
|
||||
lcdDrawText(x, y, s, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawTimer(x, y, value [, flags])
|
||||
|
||||
Display a value formatted as time at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param value (number) time in seconds
|
||||
|
||||
@param flags (unsigned number) drawing flags:
|
||||
* `0 or not specified` normal representation (minutes and seconds)
|
||||
* `TIMEHOUR` display hours
|
||||
* other general LCD flag also apply
|
||||
* `SHADOWED` Horus only, apply a shadow effect
|
||||
|
||||
@status current Introduced in 2.0.0, `SHADOWED` introduced in 2.2.1
|
||||
*/
|
||||
static int luaLcdDrawTimer(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int seconds = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
#if defined(COLORLCD)
|
||||
if (att&SHADOWED) drawTimer(x+1, y+1, seconds, (att&0xFFFF)|LEFT);
|
||||
drawTimer(x, y, seconds, att|LEFT);
|
||||
#else
|
||||
drawTimer(x, y, seconds, att|LEFT, att);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawNumber(x, y, value [, flags])
|
||||
|
||||
Display a number at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param value (number) value to display
|
||||
|
||||
@param flags (unsigned number) drawing flags:
|
||||
* `0 or not specified` display with no decimal (like abs())
|
||||
* `PREC1` display with one decimal place (number 386 is displayed as 38.6)
|
||||
* `PREC2` display with tow decimal places (number 386 is displayed as 3.86)
|
||||
* other general LCD flag also apply
|
||||
* `SHADOWED` Horus only, apply a shadow effect
|
||||
|
||||
@status current Introduced in 2.0.0, `SHADOWED` introduced in 2.2.1
|
||||
*/
|
||||
static int luaLcdDrawNumber(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int val = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
#if defined(COLORLCD)
|
||||
if ((att&SHADOWED) && !(att&INVERS)) lcdDrawNumber(x, y, val, att&0xFFFF);
|
||||
#endif
|
||||
lcdDrawNumber(x, y, val, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawChannel(x, y, source, flags)
|
||||
|
||||
Display a telemetry value at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param source can be a source identifier (number) or a source name (string).
|
||||
See getValue()
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.6, changed in 2.1.0 (only telemetry sources are valid)
|
||||
*/
|
||||
static int luaLcdDrawChannel(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int channel = -1;
|
||||
if (lua_isnumber(L, 3)) {
|
||||
channel = luaL_checkinteger(L, 3);
|
||||
}
|
||||
else {
|
||||
const char * what = luaL_checkstring(L, 3);
|
||||
LuaField field;
|
||||
bool found = luaFindFieldByName(what, field);
|
||||
if (found) {
|
||||
channel = field.id;
|
||||
}
|
||||
}
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
getvalue_t value = getValue(channel);
|
||||
drawSensorCustomValue(x, y, (channel-MIXSRC_FIRST_TELEM)/3, value, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawSwitch(x, y, switch, flags)
|
||||
|
||||
Draw a text representation of switch at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param switch (number) number of switch to display, negative number
|
||||
displays negated switch
|
||||
|
||||
@param flags (unsigned number) drawing flags, only SMLSIZE, BLINK and INVERS.
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawSwitch(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int s = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
drawSwitch(x, y, s, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawSource(x, y, source [, flags])
|
||||
|
||||
Displays the name of the corresponding input as defined by the source at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param source (number) source index
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawSource(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int s = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
drawSource(x, y, s, att);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define LUA_BITMAPHANDLE "BITMAP*"
|
||||
|
||||
/*luadoc
|
||||
@function Bitmap.open(name)
|
||||
|
||||
Loads a bitmap in memory, for later use with lcd.drawBitmap(). Bitmaps should be loaded only
|
||||
once, returned object should be stored and used for drawing. If loading fails for whatever
|
||||
reason the resulting bitmap object will have width and height set to zero.
|
||||
|
||||
Bitmap loading can fail if:
|
||||
* File is not found or contains invalid image
|
||||
* System is low on memory
|
||||
* Combined memory usage of all Lua script bitmaps exceeds certain value
|
||||
|
||||
@param name (string) full path to the bitmap on SD card (i.e. “/IMAGES/test.bmp”)
|
||||
|
||||
@retval bitmap (object) a bitmap object that can be used with other bitmap functions
|
||||
|
||||
@notice Only available on Horus
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
static int luaOpenBitmap(lua_State * L)
|
||||
{
|
||||
#if 0
|
||||
const char * filename = luaL_checkstring(L, 1);
|
||||
|
||||
BitmapBuffer ** b = (BitmapBuffer **)lua_newuserdata(L, sizeof(BitmapBuffer *));
|
||||
|
||||
if (luaExtraMemoryUsage > LUA_MEM_EXTRA_MAX) {
|
||||
// already allocated more than max allowed, fail
|
||||
TRACE("luaOpenBitmap: Error, using too much memory %u/%u", luaExtraMemoryUsage, LUA_MEM_EXTRA_MAX);
|
||||
*b = 0;
|
||||
}
|
||||
else {
|
||||
*b = BitmapBuffer::load(filename);
|
||||
if (*b == NULL && G(L)->gcrunning) {
|
||||
luaC_fullgc(L, 1); /* try to free some memory... */
|
||||
*b = BitmapBuffer::load(filename); /* try again */
|
||||
}
|
||||
}
|
||||
|
||||
if (*b) {
|
||||
uint32_t size = (*b)->getDataSize();
|
||||
luaExtraMemoryUsage += size;
|
||||
TRACE("luaOpenBitmap: %p (%u)", *b, size);
|
||||
}
|
||||
|
||||
luaL_getmetatable(L, LUA_BITMAPHANDLE);
|
||||
lua_setmetatable(L, -2);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BitmapBuffer * checkBitmap(lua_State * L, int index)
|
||||
{
|
||||
BitmapBuffer ** b = (BitmapBuffer **)luaL_checkudata(L, index, LUA_BITMAPHANDLE);
|
||||
return *b;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function Bitmap.getSize(name)
|
||||
|
||||
Return width, height of a bitmap object
|
||||
|
||||
@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open()
|
||||
|
||||
@retval multiple returns 2 values:
|
||||
* (number) width in pixels
|
||||
* (number) height in pixels
|
||||
|
||||
@notice Only available on Horus
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
static int luaGetBitmapSize(lua_State * L)
|
||||
{
|
||||
#if 0
|
||||
const BitmapBuffer * b = checkBitmap(L, 1);
|
||||
if (b) {
|
||||
lua_pushinteger(L, b->getWidth());
|
||||
lua_pushinteger(L, b->getHeight());
|
||||
}
|
||||
else {
|
||||
lua_pushinteger(L, 0);
|
||||
lua_pushinteger(L, 0);
|
||||
}
|
||||
#endif
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int luaDestroyBitmap(lua_State * L)
|
||||
{
|
||||
BitmapBuffer * b = checkBitmap(L, 1);
|
||||
if (b) {
|
||||
uint32_t size = b->getDataSize();
|
||||
TRACE("luaDestroyBitmap: %p (%u)", b, size);
|
||||
if (luaExtraMemoryUsage >= size) {
|
||||
luaExtraMemoryUsage -= size;
|
||||
}
|
||||
else {
|
||||
luaExtraMemoryUsage = 0;
|
||||
}
|
||||
delete b;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg bitmapFuncs[] = {
|
||||
{ "open", luaOpenBitmap },
|
||||
{ "getSize", luaGetBitmapSize },
|
||||
{ "__gc", luaDestroyBitmap },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
void registerBitmapClass(lua_State * L)
|
||||
{
|
||||
luaL_newmetatable(L, LUA_BITMAPHANDLE);
|
||||
luaL_setfuncs(L, bitmapFuncs, 0);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_setglobal(L, "Bitmap");
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawBitmap(bitmap, x, y [, scale])
|
||||
|
||||
Displays a bitmap at (x,y)
|
||||
|
||||
@param bitmap (pointer) point to a bitmap previously opened with Bitmap.open()
|
||||
|
||||
@param x,y (positive numbers) starting coordinates
|
||||
|
||||
@param scale (positive numbers) scale in %, 50 divides size by two, 100 is unchanged, 200 doubles size.
|
||||
Omitting scale draws image in 1:1 scale and is faster than specifying 100 for scale.
|
||||
|
||||
@notice Only available on Horus
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
static int luaLcdDrawBitmap(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
const BitmapBuffer * b = checkBitmap(L, 1);
|
||||
|
||||
if (b) {
|
||||
unsigned int x = luaL_checkunsigned(L, 2);
|
||||
unsigned int y = luaL_checkunsigned(L, 3);
|
||||
unsigned int scale = luaL_optunsigned(L, 4, 0);
|
||||
if (scale) {
|
||||
lcd->drawBitmap(x, y, b, 0, 0, 0, 0, scale/100.0f);
|
||||
}
|
||||
else {
|
||||
lcd->drawBitmap(x, y, b);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawRectangle(x, y, w, h [, flags [, t]])
|
||||
|
||||
Draw a rectangle from top left corner (x,y) of specified width and height
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width in pixels
|
||||
|
||||
@param h (number) height in pixels
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@param t (number) thickness in pixels, defaults to 1 (only on Horus)
|
||||
|
||||
@status current Introduced in 2.0.0, changed in 2.2.0
|
||||
*/
|
||||
static int luaLcdDrawRectangle(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
int h = luaL_checkinteger(L, 4);
|
||||
unsigned int flags = luaL_optunsigned(L, 5, 0);
|
||||
#if defined(PCBHORUS)
|
||||
unsigned int t = luaL_optunsigned(L, 6, 1);
|
||||
lcdDrawRect(x, y, w, h, t, 0xff, flags);
|
||||
#else
|
||||
lcdDrawRect(x, y, w, h, 0xff, flags);
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawFilledRectangle(x, y, w, h [, flags])
|
||||
|
||||
Draw a solid rectangle from top left corner (x,y) of specified width and height
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width in pixels
|
||||
|
||||
@param h (number) height in pixels
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawFilledRectangle(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
int h = luaL_checkinteger(L, 4);
|
||||
unsigned int flags = luaL_optunsigned(L, 5, 0);
|
||||
lcdDrawFilledRect(x, y, w, h, SOLID, flags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawGauge(x, y, w, h, fill, maxfill [, flags])
|
||||
|
||||
Draw a simple gauge that is filled based upon fill value
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width in pixels
|
||||
|
||||
@param h (number) height in pixels
|
||||
|
||||
@param fill (number) amount of fill to apply
|
||||
|
||||
@param maxfill (number) total value of fill
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.0, changed in 2.2.0
|
||||
*/
|
||||
static int luaLcdDrawGauge(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
int h = luaL_checkinteger(L, 4);
|
||||
int num = luaL_checkinteger(L, 5);
|
||||
int den = luaL_checkinteger(L, 6);
|
||||
unsigned int flags = luaL_optunsigned(L, 7, 0);
|
||||
#if defined(PCBHORUS)
|
||||
lcdDrawRect(x, y, w, h, 1, 0xff, flags);
|
||||
#else
|
||||
lcdDrawRect(x, y, w, h, 0xff, flags);
|
||||
#endif
|
||||
uint8_t len = limit((uint8_t)1, uint8_t(w*num/den), uint8_t(w));
|
||||
lcdDrawSolidFilledRect(x+1, y+1, len, h-2, flags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.setColor(area, color)
|
||||
|
||||
Set a color for specific area
|
||||
|
||||
@param area (unsigned number) specific screen area in the list bellow
|
||||
* `TEXT_COLOR`
|
||||
* `TEXT_BGCOLOR`
|
||||
* `TEXT_INVERTED_COLOR`
|
||||
* `TEXT_INVERTED_BGCOLOR`
|
||||
* `LINE_COLOR`
|
||||
* `SCROLLBOX_COLOR`
|
||||
* `MENU_TITLE_BGCOLOR`
|
||||
* `MENU_TITLE_COLOR`
|
||||
* `MENU_TITLE_DISABLE_COLOR`
|
||||
* `HEADER_COLOR`
|
||||
* `ALARM_COLOR`
|
||||
* `WARNING_COLOR`
|
||||
* `TEXT_DISABLE_COLOR`
|
||||
* `CURVE_AXIS_COLOR`
|
||||
* `CURVE_COLOR`
|
||||
* `CURVE_CURSOR_COLOR`
|
||||
* `TITLE_BGCOLOR`
|
||||
* `TRIM_BGCOLOR`
|
||||
* `TRIM_SHADOW_COLOR`
|
||||
* `HEADER_BGCOLOR`
|
||||
* `HEADER_ICON_BGCOLOR`
|
||||
* `HEADER_CURRENT_BGCOLOR`
|
||||
* `MAINVIEW_PANES_COLOR`
|
||||
* `MAINVIEW_GRAPHICS_COLOR`
|
||||
* `OVERLAY_COLOR`
|
||||
* `BARGRAPH1_COLOR`
|
||||
* `BARGRAPH2_COLOR`
|
||||
* `BARGRAPH_BGCOLOR`
|
||||
* `CUSTOM_COLOR`
|
||||
|
||||
@param color (number) color in 5/6/5 rgb format. The following prefined colors are available
|
||||
* `WHITE`
|
||||
* `GREY`
|
||||
* `LIGHTGREY`
|
||||
* `DARKGREY`
|
||||
* `BLACK`
|
||||
* `YELLOW`
|
||||
* `BLUE`
|
||||
* `RED`
|
||||
* `DARKRED`
|
||||
|
||||
@notice Only available on Colorlcd radios
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
static int luaLcdSetColor(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
unsigned int index = luaL_checkunsigned(L, 1) >> 16;
|
||||
unsigned int color = luaL_checkunsigned(L, 2);
|
||||
lcdColorTable[index] = color;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.getColor(area)
|
||||
|
||||
Get the color for specific area : see lcd.setColor for area list
|
||||
|
||||
@notice Only available on Colorlcd radios
|
||||
|
||||
@status current Introduced in 2.3.11
|
||||
*/
|
||||
|
||||
static int luaLcdGetColor(lua_State *L)
|
||||
{
|
||||
#if 0
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
|
||||
unsigned int index = luaL_checkunsigned(L, 1) >> 16;
|
||||
lua_pushunsigned(L, lcdColorTable[index]);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.RGB(r, g, b)
|
||||
|
||||
Returns a 5/6/5 rgb color code, that can be used with lcd.setColor
|
||||
|
||||
@param r (integer) a number between 0x00 and 0xff that expresses te amount of red in the color
|
||||
|
||||
@param g (integer) a number between 0x00 and 0xff that expresses te amount of green in the color
|
||||
|
||||
@param b (integer) a number between 0x00 and 0xff that expresses te amount of blue in the color
|
||||
|
||||
@retval number (integer) rgb color expressed in 5/6/5 format
|
||||
|
||||
@notice Only available on Colorlcd radios
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
static int luaRGB(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int r = luaL_checkinteger(L, 1);
|
||||
int g = luaL_checkinteger(L, 2);
|
||||
int b = luaL_checkinteger(L, 3);
|
||||
lua_pushinteger(L, RGB(r, g, b));
|
||||
return 1;
|
||||
}
|
||||
|
||||
const luaL_Reg lcdLib[] = {
|
||||
{ "refresh", luaLcdRefresh },
|
||||
{ "clear", luaLcdClear },
|
||||
{ "resetBacklightTimeout", luaLcdResetBacklightTimeout },
|
||||
{ "drawPoint", luaLcdDrawPoint },
|
||||
{ "drawLine", luaLcdDrawLine },
|
||||
{ "drawRectangle", luaLcdDrawRectangle },
|
||||
{ "drawFilledRectangle", luaLcdDrawFilledRectangle },
|
||||
{ "drawText", luaLcdDrawText },
|
||||
{ "drawTimer", luaLcdDrawTimer },
|
||||
{ "drawNumber", luaLcdDrawNumber },
|
||||
{ "drawChannel", luaLcdDrawChannel },
|
||||
{ "drawSwitch", luaLcdDrawSwitch },
|
||||
{ "drawSource", luaLcdDrawSource },
|
||||
{ "drawGauge", luaLcdDrawGauge },
|
||||
#if defined(COLORLCD)
|
||||
{ "drawBitmap", luaLcdDrawBitmap },
|
||||
{ "setColor", luaLcdSetColor },
|
||||
{ "getColor", luaLcdGetColor },
|
||||
{ "RGB", luaRGB },
|
||||
#else
|
||||
{ "getLastPos", luaLcdGetLastPos },
|
||||
{ "getLastRightPos", luaLcdGetLastPos },
|
||||
{ "getLastLeftPos", luaLcdGetLeftPos },
|
||||
{ "drawPixmap", luaLcdDrawPixmap },
|
||||
{ "drawScreenTitle", luaLcdDrawScreenTitle },
|
||||
{ "drawCombobox", luaLcdDrawCombobox },
|
||||
#endif
|
||||
{ NULL, NULL } /* sentinel */
|
||||
};
|
||||
@@ -1745,16 +1745,25 @@ const luaL_Reg opentxLib[] = {
|
||||
|
||||
const luaR_value_entry opentxConstants[] = {
|
||||
{ "FULLSCALE", RESX },
|
||||
#if defined(COLORLCD)
|
||||
{ "XXLSIZE", FONT(XXL) },
|
||||
{ "DBLSIZE", FONT(XL) },
|
||||
{ "MIDSIZE", FONT(L) },
|
||||
{ "SMLSIZE", FONT(XS) },
|
||||
{ "TINSIZE", FONT(XXS) },
|
||||
#else
|
||||
{ "XXLSIZE", XXLSIZE },
|
||||
{ "DBLSIZE", DBLSIZE },
|
||||
{ "MIDSIZE", MIDSIZE },
|
||||
{ "SMLSIZE", SMLSIZE },
|
||||
#if defined(COLORLCD)
|
||||
{ "TINSIZE", TINSIZE },
|
||||
#endif
|
||||
{ "INVERS", INVERS },
|
||||
{ "BOLD", BOLD },
|
||||
{ "BLINK", BLINK },
|
||||
{ "INVERS", INVERS },
|
||||
#endif
|
||||
#if defined(COLORLCD)
|
||||
{ "BOLD", FONT(BOLD) },
|
||||
#else
|
||||
{ "BOLD", BOLD },
|
||||
#endif
|
||||
{ "RIGHT", RIGHT },
|
||||
{ "LEFT", LEFT },
|
||||
{ "CENTER", CENTERED },
|
||||
@@ -1789,32 +1798,24 @@ const luaR_value_entry opentxConstants[] = {
|
||||
{ "COLOR", ZoneOption::Color },
|
||||
{ "BOOL", ZoneOption::Bool },
|
||||
{ "STRING", ZoneOption::String },
|
||||
{ "CUSTOM_COLOR", CUSTOM_COLOR },
|
||||
{ "DEFAULT_COLOR", DEFAULT_COLOR },
|
||||
{ "DEFAULT_BGCOLOR", DEFAULT_BGCOLOR },
|
||||
{ "FOCUS_COLOR", FOCUS_COLOR },
|
||||
{ "FOCUS_BGCOLOR", FOCUS_BGCOLOR },
|
||||
{ "LINE_COLOR", LINE_COLOR },
|
||||
{ "CHECKBOX_COLOR", CHECKBOX_COLOR },
|
||||
{ "MENU_BGCOLOR", MENU_BGCOLOR },
|
||||
{ "MENU_COLOR", MENU_COLOR },
|
||||
{ "MENU_TITLE_DISABLE_COLOR", MENU_TITLE_DISABLE_COLOR },
|
||||
{ "ALARM_COLOR", ALARM_COLOR },
|
||||
{ "HIGHLIGHT_COLOR", HIGHLIGHT_COLOR },
|
||||
{ "TEXT_DISABLE_COLOR", TEXT_DISABLE_COLOR },
|
||||
{ "HEADER_COLOR", HEADER_COLOR },
|
||||
{ "DISABLE_COLOR", DISABLE_COLOR },
|
||||
{ "CURVE_COLOR", CURVE_COLOR },
|
||||
{ "CURVE_CURSOR_COLOR", CURVE_CURSOR_COLOR },
|
||||
{ "TITLE_BGCOLOR", TITLE_BGCOLOR },
|
||||
{ "TRIM_BGCOLOR", TRIM_BGCOLOR },
|
||||
{ "TRIM_SHADOW_COLOR", TRIM_SHADOW_COLOR },
|
||||
{ "MAINVIEW_PANES_COLOR", MAINVIEW_PANES_COLOR },
|
||||
{ "MAINVIEW_GRAPHICS_COLOR", MAINVIEW_GRAPHICS_COLOR },
|
||||
{ "HEADER_BGCOLOR", HEADER_BGCOLOR },
|
||||
{ "HEADER_ICON_BGCOLOR", HEADER_ICON_BGCOLOR },
|
||||
{ "HEADER_CURRENT_BGCOLOR", HEADER_CURRENT_BGCOLOR },
|
||||
{ "HIGHLIGHT_COLOR", HIGHLIGHT_COLOR },
|
||||
{ "CHECKBOX_COLOR", CHECKBOX_COLOR },
|
||||
{ "SCROLLBAR_COLOR", SCROLLBAR_COLOR },
|
||||
{ "MENU_COLOR", MENU_COLOR },
|
||||
{ "MENU_BGCOLOR", MENU_BGCOLOR },
|
||||
// TODO : FIX { "MENU_TITLE_BGCOLOR", MENU_TITLE_BGCOLOR },
|
||||
{ "MENU_LINE_COLOR", MENU_LINE_COLOR },
|
||||
{ "MENU_HIGHLIGHT_COLOR", MENU_HIGHLIGHT_COLOR },
|
||||
{ "MENU_HIGHLIGHT_BGCOLOR", MENU_HIGHLIGHT_BGCOLOR },
|
||||
{ "OVERLAY_COLOR", OVERLAY_COLOR },
|
||||
{ "TABLE_BGCOLOR", TABLE_BGCOLOR },
|
||||
{ "TABLE_HEADER_BGCOLOR", TABLE_HEADER_BGCOLOR },
|
||||
{ "CUSTOM_COLOR", CUSTOM_COLOR },
|
||||
{ "MENU_HEADER_HEIGHT", MENU_HEADER_HEIGHT },
|
||||
{ "WHITE", (double)WHITE },
|
||||
{ "GREY", (double)GREY },
|
||||
|
||||
+10
-43
@@ -514,9 +514,9 @@ Return input data for given input and line number
|
||||
* `curveType` (number) curve type (function, expo, custom curve)
|
||||
* `curveValue` (number) curve index
|
||||
* `carryTrim` (boolean) input trims applied
|
||||
* 'flightModes' (table) table of enabled flightModes {0,2,7} means that the input is enabled for FM0, FM2 and FM7
|
||||
* 'flightModes' (number) bit-mask of active flight modes
|
||||
|
||||
@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, flightModes, inputName added 2.3.10
|
||||
@status current Introduced in 2.0.0, curveType/curveValue/carryTrim added in 2.3, inputName added 2.3.10, flighmode reworked in 2.3.11
|
||||
*/
|
||||
static int luaModelGetInput(lua_State *L)
|
||||
{
|
||||
@@ -536,16 +536,7 @@ static int luaModelGetInput(lua_State *L)
|
||||
lua_pushtableinteger(L, "curveType", expo->curve.type);
|
||||
lua_pushtableinteger(L, "curveValue", expo->curve.value);
|
||||
lua_pushtableinteger(L, "carryTrim", expo->carryTrim);
|
||||
lua_pushstring(L, "flightModes");
|
||||
lua_newtable(L);
|
||||
for (int i = 0, cnt = 0; i < MAX_FLIGHT_MODES; i++) {
|
||||
if (!(expo->flightModes & (1 << i))) {
|
||||
lua_pushinteger(L, cnt++);
|
||||
lua_pushinteger(L, i);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
lua_pushtableinteger(L, "flightModes", expo->flightModes);
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
@@ -577,7 +568,11 @@ static int luaModelInsertInput(lua_State *L)
|
||||
if (chn<MAX_INPUTS && getExposCount()<MAX_EXPOS && idx<=count) {
|
||||
idx = first + idx;
|
||||
s_currCh = chn + 1;
|
||||
#if defined(COLORLCD)
|
||||
insertExpo(idx, chn);
|
||||
#else
|
||||
insertExpo(idx);
|
||||
#endif
|
||||
ExpoData * expo = expoAddress(idx);
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||
@@ -613,14 +608,7 @@ static int luaModelInsertInput(lua_State *L)
|
||||
expo->carryTrim = lua_toboolean(L, -1);
|
||||
}
|
||||
else if (!strcmp(key, "flightModes")) {
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int flighModes = 0x1FF;
|
||||
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||
uint16_t val = luaL_checkinteger(L, -1);
|
||||
if (val < MAX_FLIGHT_MODES)
|
||||
flighModes &= ~(1 << val);
|
||||
}
|
||||
expo->flightModes = flighModes;
|
||||
expo->flightModes = luaL_checkinteger(L, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -753,9 +741,8 @@ Get configuration for specified Mix
|
||||
* `delayDown` (number) delay down
|
||||
* `speedUp` (number) speed up
|
||||
* `speedDown` (number) speed down
|
||||
* 'flightModes' (table) table of enabled flightModes {0,2,7} means that the input is enabled for FM0, FM2 and FM7
|
||||
|
||||
@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13, flightModes added 2.3.10
|
||||
@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13
|
||||
*/
|
||||
static int luaModelGetMix(lua_State *L)
|
||||
{
|
||||
@@ -781,16 +768,6 @@ static int luaModelGetMix(lua_State *L)
|
||||
lua_pushtableinteger(L, "delayDown", mix->delayDown);
|
||||
lua_pushtableinteger(L, "speedUp", mix->speedUp);
|
||||
lua_pushtableinteger(L, "speedDown", mix->speedDown);
|
||||
lua_pushstring(L, "flightModes");
|
||||
lua_newtable(L);
|
||||
for (int i = 0, cnt = 0; i < MAX_FLIGHT_MODES; i++) {
|
||||
if (!(mix->flightModes & (1 << i))) {
|
||||
lua_pushinteger(L, cnt++);
|
||||
lua_pushinteger(L, i);
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
}
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
else {
|
||||
lua_pushnil(L);
|
||||
@@ -809,7 +786,7 @@ Insert a mixer line into Channel
|
||||
|
||||
@param value (table) see model.getMix() for table format
|
||||
|
||||
@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13, flightModes added 2.3.10
|
||||
@status current Introduced in 2.0.0, parameters below `multiplex` added in 2.0.13
|
||||
*/
|
||||
static int luaModelInsertMix(lua_State *L)
|
||||
{
|
||||
@@ -874,16 +851,6 @@ static int luaModelInsertMix(lua_State *L)
|
||||
else if (!strcmp(key, "speedDown")) {
|
||||
mix->speedDown = luaL_checkinteger(L, -1);
|
||||
}
|
||||
else if (!strcmp(key, "flightModes")) {
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
int flighModes = 0x1FF;
|
||||
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
|
||||
uint16_t val = luaL_checkinteger(L, -1);
|
||||
if (val < MAX_FLIGHT_MODES)
|
||||
flighModes &= ~(1 << val);
|
||||
}
|
||||
mix->flightModes = flighModes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* 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 <cctype>
|
||||
#include <cstdio>
|
||||
#include "opentx.h"
|
||||
#include "lua_api.h"
|
||||
|
||||
/*luadoc
|
||||
@function lcd.refresh()
|
||||
|
||||
Refresh the LCD screen
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
|
||||
@notice This function only works in stand-alone and telemetry scripts.
|
||||
*/
|
||||
static int luaLcdRefresh(lua_State *L)
|
||||
{
|
||||
if (luaLcdAllowed) lcdRefresh();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.clear([color])
|
||||
|
||||
Clear the LCD screen
|
||||
|
||||
@param color (optional, only on color screens)
|
||||
|
||||
@status current Introduced in 2.0.0, `color` parameter introduced in 2.2.0 RC12
|
||||
|
||||
@notice This function only works in stand-alone and telemetry scripts.
|
||||
*/
|
||||
static int luaLcdClear(lua_State *L)
|
||||
{
|
||||
if (luaLcdAllowed) {
|
||||
lcdClear();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.resetBacklightTimeout()
|
||||
|
||||
Reset the backlight timeout
|
||||
|
||||
@status current Introduced in 2.3.6
|
||||
*/
|
||||
static int luaLcdResetBacklightTimeout(lua_State * L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
resetBacklightTimeout();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawPoint(x, y)
|
||||
|
||||
Draw a single pixel at (x,y) position
|
||||
|
||||
@param x (positive number) x position
|
||||
|
||||
@param y (positive number) y position
|
||||
|
||||
@param flags (optional) lcdflags
|
||||
|
||||
@notice Taranis has an LCD display width of 212 pixels and height of 64 pixels.
|
||||
Position (0,0) is at top left. Y axis is negative, top line is 0,
|
||||
bottom line is 63. Drawing on an existing black pixel produces white pixel (TODO check this!)
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawPoint(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
LcdFlags att = luaL_optunsigned(L, 3, 0);
|
||||
lcdDrawPoint(x, y, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawLine(x1, y1, x2, y2, pattern, flags)
|
||||
|
||||
Draw a straight line on LCD
|
||||
|
||||
@param x1,y1 (positive numbers) starting coordinate
|
||||
|
||||
@param x2,y2 (positive numbers) end coordinate
|
||||
|
||||
@param pattern SOLID or DOTTED
|
||||
|
||||
@param flags lcdflags
|
||||
|
||||
@notice If the start or the end of the line is outside the LCD dimensions, then the
|
||||
whole line will not be drawn (starting from OpenTX 2.1.5)
|
||||
|
||||
@status current Introduced in 2.0.0, flags introduced in 2.3.6
|
||||
*/
|
||||
static int luaLcdDrawLine(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
coord_t x1 = luaL_checkunsigned(L, 1);
|
||||
coord_t y1 = luaL_checkunsigned(L, 2);
|
||||
coord_t x2 = luaL_checkunsigned(L, 3);
|
||||
coord_t y2 = luaL_checkunsigned(L, 4);
|
||||
uint8_t pat = luaL_checkunsigned(L, 5);
|
||||
LcdFlags flags = luaL_checkunsigned(L, 6);
|
||||
|
||||
if (x1 > LCD_W || y1 > LCD_H || x2 > LCD_W || y2 > LCD_H)
|
||||
return 0;
|
||||
|
||||
if (pat == SOLID) {
|
||||
if (x1 == x2) {
|
||||
lcdDrawSolidVerticalLine(x1, y1<y2 ? y1 : y2, y1<y2 ? (y2-y1)+1 : (y1-y2)+1, flags);
|
||||
return 0;
|
||||
}
|
||||
else if (y1 == y2) {
|
||||
lcdDrawSolidHorizontalLine(x1<x2 ? x1 : x2, y1, x1<x2 ? (x2-x1)+1 : (x1-x2)+1, flags);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lcdDrawLine(x1, y1, x2, y2, pat, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.getLastPos()
|
||||
|
||||
Returns the rightmost x position from previous output
|
||||
|
||||
@retval number (integer) x position
|
||||
|
||||
@notice Only available on Taranis
|
||||
|
||||
@notice For added clarity, it is recommended to use lcd.getLastRightPos()
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
|
||||
/*luadoc
|
||||
@function lcd.getLastRightPos()
|
||||
|
||||
Returns the rightest x position from previous drawtext or drawNumber output
|
||||
|
||||
@retval number (integer) x position
|
||||
|
||||
@notice Only available on Taranis
|
||||
|
||||
@notice This is strictly equivalent to former lcd.getLastPos()
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
|
||||
static int luaLcdGetLastPos(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, lcdLastRightPos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.getLastLeftPos()
|
||||
|
||||
Returns the leftmost x position from previous drawtext or drawNumber output
|
||||
|
||||
@retval number (integer) x position
|
||||
|
||||
@notice Only available on Taranis
|
||||
|
||||
@status current Introduced in 2.2.0
|
||||
*/
|
||||
static int luaLcdGetLeftPos(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, lcdLastLeftPos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawText(x, y, text [, flags])
|
||||
|
||||
Draw a text beginning at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param text (string) text to display
|
||||
|
||||
@param flags (unsigned number) drawing flags. All values can be
|
||||
combined together using the + character. ie BLINK + DBLSIZE.
|
||||
See the [Appendix](../appendix/fonts.md) for available characters in each font set.
|
||||
* `0 or not specified` normal font
|
||||
* `XXLSIZE` jumbo sized font
|
||||
* `DBLSIZE` double size font
|
||||
* `MIDSIZE` mid sized font
|
||||
* `SMLSIZE` small font
|
||||
* `INVERS` inverted display
|
||||
* `BLINK` blinking text
|
||||
* `SHADOWED` Horus only, apply a shadow effect
|
||||
|
||||
@status current Introduced in 2.0.0, `SHADOWED` introduced in 2.2.1
|
||||
*/
|
||||
static int luaLcdDrawText(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
const char * s = luaL_checkstring(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
lcdDrawText(x, y, s, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawTimer(x, y, value [, flags])
|
||||
|
||||
Display a value formatted as time at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param value (number) time in seconds
|
||||
|
||||
@param flags (unsigned number) drawing flags:
|
||||
* `0 or not specified` normal representation (minutes and seconds)
|
||||
* `TIMEHOUR` display hours
|
||||
* other general LCD flag also apply
|
||||
* `SHADOWED` Horus only, apply a shadow effect
|
||||
|
||||
@status current Introduced in 2.0.0, `SHADOWED` introduced in 2.2.1
|
||||
*/
|
||||
static int luaLcdDrawTimer(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int seconds = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
drawTimer(x, y, seconds, att|LEFT, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawNumber(x, y, value [, flags])
|
||||
|
||||
Display a number at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param value (number) value to display
|
||||
|
||||
@param flags (unsigned number) drawing flags:
|
||||
* `0 or not specified` display with no decimal (like abs())
|
||||
* `PREC1` display with one decimal place (number 386 is displayed as 38.6)
|
||||
* `PREC2` display with tow decimal places (number 386 is displayed as 3.86)
|
||||
* other general LCD flag also apply
|
||||
* `SHADOWED` Horus only, apply a shadow effect
|
||||
|
||||
@status current Introduced in 2.0.0, `SHADOWED` introduced in 2.2.1
|
||||
*/
|
||||
static int luaLcdDrawNumber(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int val = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
lcdDrawNumber(x, y, val, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawChannel(x, y, source, flags)
|
||||
|
||||
Display a telemetry value at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param source can be a source identifier (number) or a source name (string).
|
||||
See getValue()
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.6, changed in 2.1.0 (only telemetry sources are valid)
|
||||
*/
|
||||
static int luaLcdDrawChannel(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int channel = -1;
|
||||
if (lua_isnumber(L, 3)) {
|
||||
channel = luaL_checkinteger(L, 3);
|
||||
}
|
||||
else {
|
||||
const char * what = luaL_checkstring(L, 3);
|
||||
LuaField field;
|
||||
bool found = luaFindFieldByName(what, field);
|
||||
if (found) {
|
||||
channel = field.id;
|
||||
}
|
||||
}
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
getvalue_t value = getValue(channel);
|
||||
drawSensorCustomValue(x, y, (channel-MIXSRC_FIRST_TELEM)/3, value, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawSwitch(x, y, switch, flags)
|
||||
|
||||
Draw a text representation of switch at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param switch (number) number of switch to display, negative number
|
||||
displays negated switch
|
||||
|
||||
@param flags (unsigned number) drawing flags, only SMLSIZE, BLINK and INVERS.
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawSwitch(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int s = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
drawSwitch(x, y, s, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawSource(x, y, source [, flags])
|
||||
|
||||
Displays the name of the corresponding input as defined by the source at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinate
|
||||
|
||||
@param source (number) source index
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawSource(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int s = luaL_checkinteger(L, 3);
|
||||
unsigned int att = luaL_optunsigned(L, 4, 0);
|
||||
drawSource(x, y, s, att);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawPixmap(x, y, name)
|
||||
|
||||
Draw a bitmap at (x,y)
|
||||
|
||||
@param x,y (positive numbers) starting coordinates
|
||||
|
||||
@param name (string) full path to the bitmap on SD card (i.e. “/IMAGES/test.bmp”)
|
||||
|
||||
@notice Maximum image size is [display width / 2] x [display height] pixels.
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawPixmap(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
const char * filename = luaL_checkstring(L, 3);
|
||||
|
||||
uint8_t bitmap[BITMAP_BUFFER_SIZE(LCD_W/2, LCD_H)]; // width max is LCD_W/2 pixels for saving stack and avoid a malloc here
|
||||
if (lcdLoadBitmap(bitmap, filename, LCD_W/2, LCD_H)) {
|
||||
lcdDrawBitmap(x, y, bitmap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawRectangle(x, y, w, h [, flags [, t]])
|
||||
|
||||
Draw a rectangle from top left corner (x,y) of specified width and height
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width in pixels
|
||||
|
||||
@param h (number) height in pixels
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@param t (number) thickness in pixels, defaults to 1 (only on Horus)
|
||||
|
||||
@status current Introduced in 2.0.0, changed in 2.2.0
|
||||
*/
|
||||
static int luaLcdDrawRectangle(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
int h = luaL_checkinteger(L, 4);
|
||||
unsigned int flags = luaL_optunsigned(L, 5, 0);
|
||||
#if defined(PCBHORUS)
|
||||
unsigned int t = luaL_optunsigned(L, 6, 1);
|
||||
lcdDrawRect(x, y, w, h, t, 0xff, flags);
|
||||
#else
|
||||
lcdDrawRect(x, y, w, h, 0xff, flags);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawFilledRectangle(x, y, w, h [, flags])
|
||||
|
||||
Draw a solid rectangle from top left corner (x,y) of specified width and height
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width in pixels
|
||||
|
||||
@param h (number) height in pixels
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawFilledRectangle(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
int h = luaL_checkinteger(L, 4);
|
||||
unsigned int flags = luaL_optunsigned(L, 5, 0);
|
||||
lcdDrawFilledRect(x, y, w, h, SOLID, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawGauge(x, y, w, h, fill, maxfill [, flags])
|
||||
|
||||
Draw a simple gauge that is filled based upon fill value
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width in pixels
|
||||
|
||||
@param h (number) height in pixels
|
||||
|
||||
@param fill (number) amount of fill to apply
|
||||
|
||||
@param maxfill (number) total value of fill
|
||||
|
||||
@param flags (unsigned number) drawing flags
|
||||
|
||||
@status current Introduced in 2.0.0, changed in 2.2.0
|
||||
*/
|
||||
static int luaLcdDrawGauge(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
int h = luaL_checkinteger(L, 4);
|
||||
int num = luaL_checkinteger(L, 5);
|
||||
int den = luaL_checkinteger(L, 6);
|
||||
unsigned int flags = luaL_optunsigned(L, 7, 0);
|
||||
#if defined(PCBHORUS)
|
||||
lcdDrawRect(x, y, w, h, 1, 0xff, flags);
|
||||
#else
|
||||
lcdDrawRect(x, y, w, h, 0xff, flags);
|
||||
#endif
|
||||
uint8_t len = limit((uint8_t)1, uint8_t(w*num/den), uint8_t(w));
|
||||
lcdDrawSolidFilledRect(x+1, y+1, len, h-2, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawScreenTitle(title, page, pages)
|
||||
|
||||
Draw a title bar
|
||||
|
||||
@param title (string) text for the title
|
||||
|
||||
@param page (number) page number
|
||||
|
||||
@param pages (number) total number of pages. Only used as indicator on
|
||||
the right side of title bar. (i.e. idx=2, cnt=5, display `2/5`)
|
||||
|
||||
@notice Only available on Taranis
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawScreenTitle(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
const char * str = luaL_checkstring(L, 1);
|
||||
int idx = luaL_checkinteger(L, 2);
|
||||
int cnt = luaL_checkinteger(L, 3);
|
||||
|
||||
if (cnt) drawScreenIndex(idx-1, cnt, 0);
|
||||
#if LCD_DEPTH > 1
|
||||
lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
|
||||
#endif
|
||||
title(str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*luadoc
|
||||
@function lcd.drawCombobox(x, y, w, list, idx [, flags])
|
||||
|
||||
Draw a combo box
|
||||
|
||||
@param x,y (positive numbers) top left corner position
|
||||
|
||||
@param w (number) width of combo box in pixels
|
||||
|
||||
@param list (table) combo box elements, each element is a string
|
||||
|
||||
@param idx (integer) index of entry to highlight
|
||||
|
||||
@param flags (unsigned number) drawing flags, the flags can not be combined:
|
||||
* `BLINK` combo box is expanded
|
||||
* `INVERS` combo box collapsed, text inversed
|
||||
* `0 or not present` combo box collapsed, text normal
|
||||
|
||||
@notice Only available on Taranis
|
||||
|
||||
@status current Introduced in 2.0.0
|
||||
*/
|
||||
static int luaLcdDrawCombobox(lua_State *L)
|
||||
{
|
||||
if (!luaLcdAllowed)
|
||||
return 0;
|
||||
int x = luaL_checkinteger(L, 1);
|
||||
int y = luaL_checkinteger(L, 2);
|
||||
int w = luaL_checkinteger(L, 3);
|
||||
luaL_checktype(L, 4, LUA_TTABLE);
|
||||
int count = luaL_len(L, 4); /* get size of table */
|
||||
int idx = luaL_checkinteger(L, 5);
|
||||
unsigned int flags = luaL_optunsigned(L, 6, 0);
|
||||
if (idx >= count) {
|
||||
// TODO error
|
||||
}
|
||||
if (flags & BLINK) {
|
||||
lcdDrawFilledRect(x, y, w-9, count*9+2, SOLID, ERASE);
|
||||
lcdDrawRect(x, y, w-9, count*9+2);
|
||||
for (int i=0; i<count; i++) {
|
||||
lua_rawgeti(L, 4, i+1);
|
||||
const char * item = luaL_checkstring(L, -1);
|
||||
lcdDrawText(x+2, y+2+9*i, item, 0);
|
||||
}
|
||||
lcdDrawFilledRect(x+1, y+1+9*idx, w-11, 9);
|
||||
lcdDrawFilledRect(x+w-10, y, 10, 11, SOLID, ERASE);
|
||||
lcdDrawRect(x+w-10, y, 10, 11);
|
||||
}
|
||||
else if (flags & INVERS) {
|
||||
lcdDrawFilledRect(x, y, w, 11);
|
||||
lcdDrawFilledRect(x+w-9, y+1, 8, 9, SOLID, ERASE);
|
||||
lua_rawgeti(L, 4, idx+1);
|
||||
const char * item = luaL_checkstring(L, -1);
|
||||
lcdDrawText(x+2, y+2, item, INVERS);
|
||||
}
|
||||
else {
|
||||
lcdDrawFilledRect(x, y, w, 11, SOLID, ERASE);
|
||||
lcdDrawRect(x, y, w, 11);
|
||||
lcdDrawFilledRect(x+w-10, y+1, 9, 9, SOLID);
|
||||
lua_rawgeti(L, 4, idx+1);
|
||||
const char * item = luaL_checkstring(L, -1);
|
||||
lcdDrawText(x+2, y+2, item, 0);
|
||||
}
|
||||
|
||||
lcdDrawSolidHorizontalLine(x+w-8, y+3, 6);
|
||||
lcdDrawSolidHorizontalLine(x+w-8, y+5, 6);
|
||||
lcdDrawSolidHorizontalLine(x+w-8, y+7, 6);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const luaL_Reg lcdLib[] = {
|
||||
{ "refresh", luaLcdRefresh },
|
||||
{ "clear", luaLcdClear },
|
||||
{ "resetBacklightTimeout", luaLcdResetBacklightTimeout },
|
||||
{ "drawPoint", luaLcdDrawPoint },
|
||||
{ "drawLine", luaLcdDrawLine },
|
||||
{ "drawRectangle", luaLcdDrawRectangle },
|
||||
{ "drawFilledRectangle", luaLcdDrawFilledRectangle },
|
||||
{ "drawText", luaLcdDrawText },
|
||||
{ "drawTimer", luaLcdDrawTimer },
|
||||
{ "drawNumber", luaLcdDrawNumber },
|
||||
{ "drawChannel", luaLcdDrawChannel },
|
||||
{ "drawSwitch", luaLcdDrawSwitch },
|
||||
{ "drawSource", luaLcdDrawSource },
|
||||
{ "drawGauge", luaLcdDrawGauge },
|
||||
{ "getLastPos", luaLcdGetLastPos },
|
||||
{ "getLastRightPos", luaLcdGetLastPos },
|
||||
{ "getLastLeftPos", luaLcdGetLeftPos },
|
||||
{ "drawPixmap", luaLcdDrawPixmap },
|
||||
{ "drawScreenTitle", luaLcdDrawScreenTitle },
|
||||
{ "drawCombobox", luaLcdDrawCombobox },
|
||||
{ NULL, NULL } /* sentinel */
|
||||
};
|
||||
@@ -55,7 +55,12 @@ extern uint32_t luaExtraMemoryUsage;
|
||||
|
||||
void luaInit();
|
||||
void luaInitThemesAndWidgets();
|
||||
//TODO FIXME
|
||||
#if 1
|
||||
#define LUA_INIT_THEMES_AND_WIDGETS()
|
||||
#else
|
||||
#define LUA_INIT_THEMES_AND_WIDGETS() luaInitThemesAndWidgets()
|
||||
#endif
|
||||
|
||||
#define lua_registernumber(L, n, i) (lua_pushnumber(L, (i)), lua_setglobal(L, (n)))
|
||||
#define lua_registerint(L, n, i) (lua_pushinteger(L, (i)), lua_setglobal(L, (n)))
|
||||
|
||||
@@ -28,7 +28,9 @@
|
||||
#define MANUAL_SCRIPTS_MAX_INSTRUCTIONS (20000/100)
|
||||
#define LUA_WARNING_INFO_LEN 64
|
||||
|
||||
lua_State *lsWidgets = NULL;
|
||||
lua_State * lsWidgets = NULL;
|
||||
|
||||
#if 0
|
||||
extern int custom_lua_atpanic(lua_State *L);
|
||||
|
||||
#define LUA_WIDGET_FILENAME "/main.lua"
|
||||
@@ -559,3 +561,4 @@ void luaInitThemesAndWidgets()
|
||||
luaDoGc(lsWidgets, true);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+2
-1
@@ -204,8 +204,9 @@ void checkEeprom()
|
||||
{
|
||||
#if defined(RTC_BACKUP_RAM) && !defined(SIMU)
|
||||
if (TIME_TO_BACKUP_RAM()) {
|
||||
if (!globalData.unexpectedShutdown)
|
||||
if (!globalData.unexpectedShutdown) {
|
||||
rambackupWrite();
|
||||
}
|
||||
rambackupDirtyMsk = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
+20
-12
@@ -336,8 +336,8 @@ void generalDefault()
|
||||
#endif
|
||||
|
||||
#if defined(COLORLCD)
|
||||
strcpy(g_eeGeneral.themeName, static_cast<ThemeBase *>(theme)->getName());
|
||||
static_cast<ThemeBase *>(theme)->init();
|
||||
strcpy(g_eeGeneral.themeName, static_cast<OpenTxTheme *>(theme)->getName());
|
||||
static_cast<OpenTxTheme *>(theme)->init();
|
||||
#endif
|
||||
|
||||
#if defined(PXX2)
|
||||
@@ -700,18 +700,26 @@ void checkBacklight()
|
||||
}
|
||||
}
|
||||
|
||||
bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || (g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter));
|
||||
|
||||
if (flashCounter) {
|
||||
backlightOn = !backlightOn;
|
||||
}
|
||||
|
||||
if (backlightOn) {
|
||||
currentBacklightBright = requiredBacklightBright;
|
||||
if (requiredBacklightBright == BACKLIGHT_FORCED_ON) {
|
||||
currentBacklightBright = g_eeGeneral.backlightBright;
|
||||
BACKLIGHT_ENABLE();
|
||||
}
|
||||
else {
|
||||
BACKLIGHT_DISABLE();
|
||||
bool backlightOn = ((g_eeGeneral.backlightMode == e_backlight_mode_on) ||
|
||||
(g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter) ||
|
||||
(g_eeGeneral.backlightMode == e_backlight_mode_off && isFunctionActive(FUNCTION_BACKLIGHT)));
|
||||
|
||||
if (flashCounter) {
|
||||
backlightOn = !backlightOn;
|
||||
}
|
||||
|
||||
if (backlightOn) {
|
||||
currentBacklightBright = requiredBacklightBright;
|
||||
BACKLIGHT_ENABLE();
|
||||
}
|
||||
else {
|
||||
BACKLIGHT_DISABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2004,7 +2012,7 @@ void opentxInit()
|
||||
if (globalData.unexpectedShutdown) {
|
||||
// SDCARD not available, try to restore last model from RAM
|
||||
TRACE("rambackupRestore");
|
||||
rambackupRestore();
|
||||
// rambackupRestore();
|
||||
}
|
||||
else {
|
||||
storageReadAll();
|
||||
|
||||
@@ -828,6 +828,7 @@ enum FunctionsActive {
|
||||
#endif
|
||||
FUNCTION_BACKGND_MUSIC,
|
||||
FUNCTION_BACKGND_MUSIC_PAUSE,
|
||||
FUNCTION_BACKLIGHT,
|
||||
};
|
||||
|
||||
#define VARIO_FREQUENCY_ZERO 700/*Hz*/
|
||||
|
||||
@@ -31,6 +31,18 @@ inline T sgn(T a)
|
||||
{
|
||||
return a > 0 ? 1 : (a < 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
template<class t> inline t min(t a, t b) { return a<b?a:b; }
|
||||
template<class t> inline t max(t a, t b) { return a>b?a:b; }
|
||||
template<class t> inline t limit(t mi, t x, t ma) { return min(max(mi,x),ma); }
|
||||
|
||||
inline int divRoundClosest(const int n, const int d)
|
||||
{
|
||||
if (d == 0)
|
||||
return 0;
|
||||
else
|
||||
return ((n < 0) ^ (d < 0)) ? ((n - d/2)/d) : ((n + d/2)/d);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -26,6 +26,9 @@ static const char * const options[] = {
|
||||
#if defined(AUTOUPDATE)
|
||||
"autoupdate",
|
||||
#endif
|
||||
#if defined(BLUETOOTH)
|
||||
"bluetooth",
|
||||
#endif
|
||||
#if defined(CROSSFIRE)
|
||||
"crossfire",
|
||||
#endif
|
||||
@@ -91,6 +94,9 @@ static const char * const options[] = {
|
||||
#endif
|
||||
#if defined(SHUTDOWN_CONFIRMATION)
|
||||
"shutdownconfirm",
|
||||
#endif
|
||||
#if defined(HARDWARE_EXTERNAL_ACCESS_MOD)
|
||||
"externalaccessmod",
|
||||
#endif
|
||||
nullptr //sentinel
|
||||
};
|
||||
|
||||
@@ -336,7 +336,7 @@ void convertModelData_218_to_219(ModelData &model)
|
||||
}
|
||||
|
||||
for (int zone=0; zone<MAX_LAYOUT_ZONES; zone++) {
|
||||
Topbar::ZonePersistentData * zoneData = &g_model.topbarData.zones[zone];
|
||||
TopBar::ZonePersistentData * zoneData = &g_model.topbarData.zones[zone];
|
||||
if (strcmp("Value", zoneData->widgetName))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ PACK(struct TelemetrySensor_218 {
|
||||
});
|
||||
#define VIEW_DATA \
|
||||
CustomScreenData screenData[MAX_CUSTOM_SCREENS]; \
|
||||
Topbar::PersistentData topbarData; \
|
||||
TopBar::PersistentData topbarData; \
|
||||
uint8_t view;
|
||||
#elif defined(PCBTARANIS)
|
||||
#define VIEW_DATA uint8_t view;
|
||||
@@ -527,7 +527,7 @@ PACK(struct ModelData_v218 {
|
||||
#define THEME_NAME_LEN 8
|
||||
#define THEME_DATA \
|
||||
char themeName[THEME_NAME_LEN]; \
|
||||
ThemeBase::PersistentData themeData;
|
||||
OpenTxTheme::PersistentData themeData;
|
||||
#else
|
||||
#define THEME_DATA
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ void storageEraseAll(bool warn)
|
||||
|
||||
#if defined(LIBOPENUI)
|
||||
// the theme has not been loaded before
|
||||
static_cast<ThemeBase*>(theme)->load();
|
||||
static_cast<OpenTxTheme*>(theme)->load();
|
||||
#endif
|
||||
|
||||
generalDefault();
|
||||
|
||||
@@ -359,7 +359,7 @@ char * getSwitchPositionName(char * dest, swsrc_t idx)
|
||||
if (idx <= SWSRC_LAST_SWITCH) {
|
||||
div_t swinfo = switchInfo(idx);
|
||||
s = getSwitchName(s, idx);
|
||||
*s++ = "\200-\201"[swinfo.rem];
|
||||
*s++ = (STR_CHAR_UP "-" STR_CHAR_DOWN)[swinfo.rem];
|
||||
*s = '\0';
|
||||
}
|
||||
#endif // PCBSKY9X
|
||||
|
||||
@@ -14,10 +14,6 @@ uint8_t popupMenuOffsetType = 0;
|
||||
void (*popupMenuHandler)(const char * result);
|
||||
uint8_t noHighlightCounter;
|
||||
|
||||
void checkLuaMemoryUsage()
|
||||
{
|
||||
}
|
||||
|
||||
void runPopupWarning(uint16_t event)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ extern Fifo<uint8_t, 32> trainerSbusFifo;
|
||||
#endif
|
||||
|
||||
#if defined(AUX_SERIAL)
|
||||
uint8_t auxSerialMode = 0;
|
||||
uint8_t auxSerialMode = UART_MODE_COUNT; // Prevent debug output before port is setup
|
||||
Fifo<uint8_t, 512> auxSerialTxFifo;
|
||||
|
||||
#if defined(AUX_SERIAL_DMA_Stream_RX)
|
||||
@@ -250,7 +250,7 @@ extern "C" void AUX_SERIAL_USART_IRQHandler(void)
|
||||
#endif // AUX_SERIAL
|
||||
|
||||
#if defined(AUX2_SERIAL)
|
||||
uint8_t aux2SerialMode = 0;
|
||||
uint8_t aux2SerialMode = UART_MODE_COUNT; // Prevent debug output before port is setup
|
||||
Fifo<uint8_t, 512> aux2SerialTxFifo;
|
||||
AuxSerialRxFifo aux2SerialRxFifo __DMA (AUX2_SERIAL_DMA_Stream_RX);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ option(PXX2 "PXX2 protocol support" OFF)
|
||||
option(AFHDS3 "AFHDS3 TX Module" ON)
|
||||
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" ON)
|
||||
option(GHOST "Ghost TX Module" ON)
|
||||
option(HARDWARE_EXTERNAL_ACCESS_MOD "Support for R9M 2019 hardware mod" OFF)
|
||||
|
||||
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
|
||||
set(CPU_TYPE STM32F4)
|
||||
@@ -50,9 +51,12 @@ if (PCB STREQUAL X10)
|
||||
set(TARGET_SRC
|
||||
${TARGET_SRC}
|
||||
../common/arm/stm32/audio_dac_driver.cpp
|
||||
../common/arm/stm32/adc_driver.cpp
|
||||
../common/arm/stm32/sticks_pwm_driver.cpp
|
||||
)
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
../common/arm/stm32/adc_driver.cpp
|
||||
)
|
||||
set(BITMAPS_TARGET x10_bitmaps)
|
||||
set(FONTS_TARGET x10_fonts)
|
||||
set(LCD_DRIVER lcd_driver.cpp)
|
||||
@@ -86,7 +90,7 @@ if (PCB STREQUAL X10)
|
||||
set(SBUS_TRAINER ON)
|
||||
set(AUX_SERIAL ON)
|
||||
if (NOT BLUETOOTH AND NOT INTERNAL_GPS)
|
||||
set(AUX2_SERIAL OFF) # todo ON
|
||||
set(AUX2_SERIAL ON)
|
||||
endif()
|
||||
set(INTERNAL_GPS_BAUDRATE "9600" CACHE STRING "Baud rate for internal GPS")
|
||||
elseif (PCBREV STREQUAL T18)
|
||||
@@ -121,6 +125,9 @@ elseif (PCB STREQUAL X12S)
|
||||
set(TARGET_SRC
|
||||
${TARGET_SRC}
|
||||
audio_spi_driver.cpp
|
||||
)
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
x12s_adc_driver.cpp
|
||||
)
|
||||
set(BITMAPS_TARGET x12s_bitmaps)
|
||||
@@ -156,6 +163,12 @@ if(NOT UNEXPECTED_SHUTDOWN)
|
||||
add_definitions(-DNO_UNEXPECTED_SHUTDOWN)
|
||||
endif()
|
||||
|
||||
if(HARDWARE_EXTERNAL_ACCESS_MOD)
|
||||
set(PXX2 ON)
|
||||
set(AUX_SERIAL OFF)
|
||||
add_definitions(-DHARDWARE_EXTERNAL_ACCESS_MOD)
|
||||
endif()
|
||||
|
||||
if(INTERNAL_MODULE_PXX1)
|
||||
add_definitions(-DHARDWARE_INTERNAL_MODULE)
|
||||
add_definitions(-DINTERNAL_MODULE_PXX1)
|
||||
@@ -312,6 +325,7 @@ if(PYTHONINTERP_FOUND)
|
||||
COMMAND ${PYTHON_EXECUTABLE} ${RADIO_DIRECTORY}/util/generate_datacopy.py datastructs.h -DPCBHORUS -DPCBX10 -DCPUARM -DSTM32F4 -DSTM32F429_439xx -DCOLORLCD -DBACKUP -DSIMU -I. -Igui/colorlcd -Itargets/horus -Itargets/common/arm/stm32 -I${THIRDPARTY_DIR} -I${THIRDPARTY_DIR}/libopenui/src -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/STM32F4xx_StdPeriph_Driver/inc -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/CMSIS/Device/ST/STM32F4xx/Include -I${THIRDPARTY_DIR}/STM32F4xx_DSP_StdPeriph_Lib_V1.8.0/Libraries/CMSIS/Include ${arm_gcc_include_path} > ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
|
||||
DEPENDS ${RADIO_DIRECTORY}/src/datastructs.h ${RADIO_DIRECTORY}/util/generate_datacopy.py
|
||||
)
|
||||
|
||||
add_custom_target(datacopy
|
||||
DEPENDS ${PROJECT_BINARY_DIR}/radio/src/datacopy.cpp
|
||||
)
|
||||
|
||||
@@ -398,6 +398,12 @@ enum Analogs {
|
||||
#define DEFAULT_SLIDERS_CONFIG (SLIDER_WITH_DETENT << 1) + (SLIDER_WITH_DETENT << 0)
|
||||
#endif
|
||||
|
||||
#define HARDWARE_POT3
|
||||
#if !defined(PCBX12S) // ext are used by mouse on X12S
|
||||
#define HARDWARE_EXT1
|
||||
#define HARDWARE_EXT2
|
||||
#endif
|
||||
|
||||
enum CalibratedAnalogs {
|
||||
CALIBRATED_STICK1,
|
||||
CALIBRATED_STICK2,
|
||||
@@ -541,7 +547,8 @@ void backlightInit();
|
||||
#else
|
||||
void backlightEnable(uint8_t dutyCycle = 0);
|
||||
#endif
|
||||
#define BACKLIGHT_LEVEL_MAX 100
|
||||
#define BACKLIGHT_LEVEL_MAX 100
|
||||
#define BACKLIGHT_FORCED_ON BACKLIGHT_LEVEL_MAX + 1
|
||||
#if defined(PCBX12S)
|
||||
#define BACKLIGHT_LEVEL_MIN 5
|
||||
#elif defined(RADIO_FAMILY_T16)
|
||||
@@ -631,8 +638,8 @@ void sportUpdatePowerInit();
|
||||
#endif
|
||||
|
||||
// Aux serial port driver
|
||||
#if defined(AUX_SERIAL_GPIO)
|
||||
#define DEBUG_BAUDRATE 115200
|
||||
#if defined(AUX_SERIAL_GPIO)
|
||||
extern uint8_t auxSerialMode;
|
||||
void auxSerialInit(unsigned int mode, unsigned int protocol);
|
||||
void auxSerialPutc(char c);
|
||||
|
||||
@@ -404,7 +404,7 @@
|
||||
#endif
|
||||
|
||||
// Serial Port (DEBUG)
|
||||
#if defined(PCBX12S) || defined(RADIO_TX16S)
|
||||
#if (defined(PCBX12S) || (defined(RADIO_TX16S)) && !defined(HARDWARE_EXTERNAL_ACCESS_MOD))
|
||||
#define AUX_SERIAL_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
|
||||
#define AUX_SERIAL_RCC_APB1Periph RCC_APB1Periph_USART3
|
||||
#define AUX_SERIAL_RCC_APB2Periph 0
|
||||
@@ -447,6 +447,9 @@
|
||||
#define AUX2_SERIAL_DMA_Channel_RX DMA_Channel_5
|
||||
#define AUX2_SERIAL_PWR_GPIO GPIOB
|
||||
#define AUX2_SERIAL_PWR_GPIO_PIN GPIO_Pin_0 // PB.00
|
||||
#if defined(RADIO_TX16S)
|
||||
#define TRAINER_BATTERY_COMPARTMENT // allows serial port TTL trainer
|
||||
#endif
|
||||
#elif defined(RADIO_TX16S) && defined(INTERNAL_GPS)
|
||||
#define GPS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOG)
|
||||
#define GPS_RCC_APB1Periph 0
|
||||
@@ -768,7 +771,7 @@
|
||||
#define INTMODULE_BOOTCMD_GPIO_PIN GPIO_Pin_9 // PI.09
|
||||
#endif
|
||||
#define INIT_INTMODULE_BOOTCMD_PIN() GPIO_ResetBits(INTMODULE_BOOTCMD_GPIO, INTMODULE_BOOTCMD_GPIO_PIN);
|
||||
#if defined(PCBX10) || PCBREV >= 13
|
||||
#if (defined(PCBX10) || PCBREV >= 13) && !defined(HARDWARE_EXTERNAL_ACCESS_MOD) //TIM2 used by ext mod
|
||||
#define INTMODULE_RCC_APB1Periph RCC_APB1Periph_TIM2
|
||||
#define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1
|
||||
#define INTMODULE_TIMER TIM2
|
||||
@@ -788,7 +791,7 @@
|
||||
#define EXTMODULE_PWR_GPIO GPIOB
|
||||
#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_3 // PB.03
|
||||
#define EXTERNAL_MODULE_PWR_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
|
||||
#if defined(PCBX10) && defined(PCBREV_EXPRESS)
|
||||
#if (defined(PCBX10) && defined(PCBREV_EXPRESS)) || defined(HARDWARE_EXTERNAL_ACCESS_MOD)
|
||||
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
|
||||
#define EXTMODULE_RCC_APB1Periph (RCC_APB1Periph_TIM2 | RCC_APB1Periph_USART3)
|
||||
#define EXTMODULE_RCC_APB2Periph 0
|
||||
@@ -867,7 +870,7 @@
|
||||
#define INTMODULE_HEARTBEAT_EXTI_LINE EXTI_Line12
|
||||
#define INTMODULE_HEARTBEAT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define INTMODULE_HEARTBEAT_REUSE_INTERRUPT_ROTARY_ENCODER
|
||||
#if defined(PXX2)
|
||||
#if defined(INTERNAL_MODULE_PXX2)
|
||||
#define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Falling
|
||||
#else
|
||||
#define INTMODULE_HEARTBEAT_TRIGGER EXTI_Trigger_Rising
|
||||
|
||||
@@ -42,7 +42,11 @@ add_definitions(-DBATTERY_CHARGE) # -DSOFTWARE_VOLUME
|
||||
set(TARGET_SRC
|
||||
${TARGET_SRC}
|
||||
audio_spi_driver.cpp
|
||||
adc_driver.cpp
|
||||
)
|
||||
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
x12s_adc_driver.cpp
|
||||
)
|
||||
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
|
||||
@@ -413,6 +413,7 @@ bool isBacklightEnabled();
|
||||
#endif
|
||||
|
||||
#define BACKLIGHT_LEVEL_MAX 100
|
||||
#define BACKLIGHT_FORCED_ON BACKLIGHT_LEVEL_MAX + 1
|
||||
#define BACKLIGHT_LEVEL_MIN 15
|
||||
|
||||
#define BACKLIGHT_ENABLE() backlightEnable(globalData.unexpectedShutdown ? BACKLIGHT_LEVEL_MAX : BACKLIGHT_LEVEL_MAX-g_eeGeneral.backlightBright)
|
||||
|
||||
@@ -734,6 +734,11 @@ uint16_t getBatteryVoltage()
|
||||
return (g_eeGeneral.vBatWarn * 10) + 50; // 0.5 volt above alerm (value is PREC1)
|
||||
}
|
||||
|
||||
uint16_t getRTCBatteryVoltage()
|
||||
{
|
||||
return 300;
|
||||
}
|
||||
|
||||
void boardOff()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -278,6 +278,7 @@ extern "C" {
|
||||
#define isBacklightEnabled() (PWM->PWM_CH_NUM[0].PWM_CDTY != 100)
|
||||
#define BACKLIGHT_ENABLE() backlightEnable()
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
#define BACKLIGHT_FORCED_ON 101
|
||||
|
||||
// ADC driver
|
||||
#define NUM_POTS 3
|
||||
@@ -350,12 +351,12 @@ void coprocReadData(bool onlytemp=false);
|
||||
extern int8_t volumeRequired;
|
||||
|
||||
#if defined(COPROCESSOR)
|
||||
struct CoprocData {
|
||||
typedef struct {
|
||||
uint8_t read;
|
||||
int8_t valid;
|
||||
int8_t temp;
|
||||
int8_t maxtemp;
|
||||
};
|
||||
} CoprocData;
|
||||
|
||||
extern CoprocData coprocData;
|
||||
#endif
|
||||
|
||||
@@ -393,6 +393,10 @@ set(TARGET_SRC
|
||||
trainer_driver.cpp
|
||||
../common/arm/stm32/timers_driver.cpp
|
||||
../common/arm/stm32/audio_dac_driver.cpp
|
||||
)
|
||||
|
||||
set(FIRMWARE_TARGET_SRC
|
||||
${FIRMWARE_TARGET_SRC}
|
||||
../common/arm/stm32/adc_driver.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -659,6 +659,7 @@ void pwrResetHandler();
|
||||
void backlightInit();
|
||||
void backlightDisable();
|
||||
#define BACKLIGHT_DISABLE() backlightDisable()
|
||||
#define BACKLIGHT_FORCED_ON 101
|
||||
uint8_t isBacklightEnabled();
|
||||
#if !defined(__cplusplus)
|
||||
#define backlightEnable(...)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user