2.4 continued (#8092)

Quite a bit of work on 2.4

Co-authored-by: 3djc <Th1sisfmyofmyo>
This commit is contained in:
3djc
2020-11-14 14:55:37 +04:00
committed by GitHub
co-authored by 3djc <Th1sisfmyofmyo>
parent cd6aa7af00
commit 87cd9047b1
238 changed files with 5164 additions and 2755 deletions
+6 -1
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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
+18 -11
View File
@@ -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);
+12 -11
View File
@@ -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);
+6 -7
View File
@@ -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()
+218
View File
@@ -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;
};
+3 -3
View File
@@ -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)
+63 -1
View File
@@ -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);
}),
+18
View File
@@ -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);
+6 -123
View File
@@ -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);
+1 -1
View File
@@ -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);
+10 -10
View File
@@ -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);
}
}
+5 -4
View File
@@ -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
};
-1
View File
@@ -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);
+96 -3
View File
@@ -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);
}
}
+7 -3
View File
@@ -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();
+39 -25
View File
@@ -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);
+41 -40
View File
@@ -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;
+41 -14
View File
@@ -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);
+39 -13
View File
@@ -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);
+30 -53
View File
@@ -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

+81 -5
View File
@@ -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);
}
};
+131
View File
@@ -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);
}
}
}
};
+2 -1
View File
@@ -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;
+6 -3
View File
@@ -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)
+5 -1
View File
@@ -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);
+11 -9
View File
@@ -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
+2 -3
View File
@@ -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++) {
+1 -1
View File
@@ -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);
+2 -3
View File
@@ -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,
+5 -4
View File
@@ -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);
+4 -1
View File
@@ -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) {
+4 -4
View File
@@ -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)
+1 -1
View File
@@ -78,7 +78,7 @@ class Page: public Window {
}
#endif
void deleteLater();
void deleteLater(bool detach=true) override;
void paint(BitmapBuffer * dc) override;
+66 -73
View File
@@ -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);
+51 -1
View File
@@ -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));
+4 -47
View File
@@ -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);
+166 -23
View File
@@ -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();
}
+3 -3
View File
@@ -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;
+1 -1
View File
@@ -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();
};
+20 -7
View File
@@ -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;
+6 -4
View File
@@ -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);
}
};
+7 -2
View File
@@ -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 -22
View File
@@ -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
+14 -7
View File
@@ -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_
@@ -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
+13 -4
View File
@@ -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
+41 -26
View File
@@ -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
}
+9 -5
View File
@@ -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_
+46 -157
View File
@@ -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);
}
+43
View File
@@ -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;
};
+22 -108
View File
@@ -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;
+1 -3
View File
@@ -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_
+192 -234
View File
@@ -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)
+82
View File
@@ -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();
};
+40 -32
View File
@@ -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);
+16 -16
View File
@@ -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 -25
View File
@@ -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);
-5
View File
@@ -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);
+69 -61
View File
@@ -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);
-4
View File
@@ -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));
+18 -29
View File
@@ -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;
}
}
}
+14 -15
View File
@@ -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
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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
+783
View File
@@ -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 */
};
+26 -25
View File
@@ -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
View File
@@ -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;
}
}
}
+644
View File
@@ -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 */
};
+5
View File
@@ -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)))
+4 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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();
+1
View File
@@ -828,6 +828,7 @@ enum FunctionsActive {
#endif
FUNCTION_BACKGND_MUSIC,
FUNCTION_BACKGND_MUSIC_PAUSE,
FUNCTION_BACKLIGHT,
};
#define VARIO_FREQUENCY_ZERO 700/*Hz*/
+12
View File
@@ -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>
+6
View File
@@ -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
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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
-4
View File
@@ -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);
+16 -2
View File
@@ -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
)
+9 -2
View File
@@ -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);
+7 -4
View File
@@ -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
+5 -1
View File
@@ -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
+1
View File
@@ -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)
+5
View File
@@ -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()
{
}
+3 -2
View File
@@ -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
+4
View File
@@ -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
)
+1
View File
@@ -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