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
+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