Bsongis/x7d fixes (#4019)

* [X7D] Various fixes

[Others]
- Fixes the Mixer / Inputs MOVE / COPY problem on X9E
- Adds the copy/paste/rename feature in SDCARD menu on X7D/SKY9X
- Merges some duplicated code using the new directory structure
- Cosmetics
This commit is contained in:
Bertrand Songis
2016-11-13 19:06:21 +01:00
committed by GitHub
parent fd33cc9d2b
commit bfb5e9b8a6
42 changed files with 1285 additions and 2188 deletions
-1
View File
@@ -240,7 +240,6 @@ if(SDCARD)
add_definitions(-DSDCARD)
include_directories(${FATFS_DIR} ${FATFS_DIR}/option)
set(SRC ${SRC} sdcard.cpp rtc.cpp logs.cpp)
set(GUI_SRC ${GUI_SRC} radio_sdmanager.cpp)
set(FIRMWARE_SRC ${FIRMWARE_SRC} ${FATFS_SRC})
endif()
+17 -1
View File
@@ -213,7 +213,11 @@ int8_t checkIncDecGen(event_t event, int8_t i_val, int8_t i_min, int8_t i_max);
#define CHECK_INCDEC_GENVAR(event, var, min, max) \
var = checkIncDecGen(event, var, min, max)
#define CURSOR_ON_LINE() (0)
#if defined(CPUARM)
#define CURSOR_ON_LINE() (menuHorizontalPosition < 0)
#else
#define CURSOR_ON_LINE() (0)
#endif
void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow);
void check_simple(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuTabSize, vertpos_t maxrow);
@@ -308,13 +312,19 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, event_t event);
#endif
void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event);
#if defined(GVARS)
#define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0)
#else
#define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v)
#endif
#if defined(CPUARM)
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active, LcdFlags attr=ZCHAR);
#else
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active);
#endif
#if defined(CPUM64)
#define editSingleName(x, y, label, name, size, event, active) editName(x, y, name, size, event, active)
@@ -404,6 +414,12 @@ void drawStatusLine();
#define EDIT_MODE_INIT -1
#endif
#if defined(CPUM64)
#define editNameCursorPos menuHorizontalPosition
#else
extern uint8_t editNameCursorPos;
#endif
#if defined(VIRTUAL_INPUTS)
uint8_t getExposCount();
void insertExpo(uint8_t idx);
+3 -4
View File
@@ -109,10 +109,9 @@ void lcdPutPattern(coord_t x, coord_t y, const uint8_t * pattern, uint8_t width,
lcdDrawPoint(x, y+j, plot ? FORCE : ERASE);
}
}
x++;
lcdNextPos++;
}
x++;
lcdNextPos++;
}
}
@@ -338,7 +337,7 @@ void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, uint8_t len, LcdF
c = pgm_read_byte(s);
break;
}
if (setx) {
x = c;
setx = false;
+2 -93
View File
@@ -39,102 +39,11 @@ uint8_t s_maxLines = 8;
uint8_t s_copySrcIdx;
uint8_t s_copySrcCh;
#if defined(CPUM64)
#define editNameCursorPos menuHorizontalPosition
#else
#if !defined(CPUM64)
uint8_t editNameCursorPos = 0;
#endif
#if defined(PCBX7D)
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active/* TODO, uint8_t attr*/)
{
LcdFlags attr = ZCHAR; // TODO in args
uint8_t mode = 0;
if (active) {
if (s_editMode <= 0)
mode = INVERS + FIXEDWIDTH;
else
mode = FIXEDWIDTH;
}
lcdDrawSizedText(x, y, name, size, attr | mode);
coord_t backupNextPos = lcdNextPos;
if (active) {
uint8_t cur = editNameCursorPos;
if (s_editMode > 0) {
int8_t c = name[cur];
int8_t v = c;
if (event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) {
if (attr == ZCHAR) {
v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0);
if (c <= 0) v = -v;
}
else {
v = checkIncDec(event, abs(v), '0', 'z', 0);
}
}
switch (event) {
case EVT_ROTARY_BREAK:
if (s_editMode == EDIT_MODIFY_FIELD) {
s_editMode = EDIT_MODIFY_STRING;
cur = 0;
}
else if (cur<size-1)
cur++;
else
s_editMode = 0;
break;
case EVT_ROTARY_LONG:
if (attr & ZCHAR) {
if (v == 0) {
s_editMode = 0;
killEvents(event);
}
else if (v>=-26 && v<=26) {
v = -v; // toggle case
}
}
else {
if (v == ' ') {
s_editMode = 0;
killEvents(event);
break;
}
else if (v>='A' && v<='Z') {
v = 'a'+v-'A'; // toggle case
}
else if (v>='a' && v<='z') {
v = 'A'+v-'a'; // toggle case
}
}
break;
}
if (c != v) {
name[cur] = v;
storageDirty(menuVerticalPositions[0] == 0 ? EE_MODEL : EE_GENERAL);
}
if (attr == ZCHAR) {
lcdDrawChar(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH);
}
else {
lcdDrawChar(x+editNameCursorPos*FW, y, v, ERASEBG|INVERS|FIXEDWIDTH);
}
}
else {
cur = 0;
}
editNameCursorPos = cur;
lcdNextPos = backupNextPos;
}
}
#else
#if !defined(CPUARM)
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active)
{
#if defined(CPUM64)
+2 -1
View File
@@ -130,7 +130,9 @@ void menuModelSelect(event_t event);
void menuModelSetup(event_t event);
void menuModelHeli(event_t event);
void menuModelFlightModesAll(event_t event);
void menuModelExpoOne(event_t event);
void menuModelExposAll(event_t event);
void menuModelMixOne(event_t event);
void menuModelMixAll(event_t event);
void menuModelLimits(event_t event);
void menuModelCurvesAll(event_t event);
@@ -142,7 +144,6 @@ void menuModelTelemetryFrsky(event_t event);
void menuModelTelemetryMavlink(event_t event);
void menuModelDisplay(event_t event);
void menuModelTemplates(event_t event);
void menuModelExpoOne(event_t event);
static const MenuHandlerFunc menuTabModel[] PROGMEM = {
menuModelSelect,
+188
View File
@@ -0,0 +1,188 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
#define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2)
#define EXPO_ONE_FM_WIDTH (5*FW)
int expoFn(int x)
{
ExpoData * ed = expoAddress(s_currIdx);
int16_t anas[NUM_INPUTS] = {0};
applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x);
return anas[ed->chn];
}
void drawFunction(FnFuncP fn, uint8_t offset)
{
lcdDrawVerticalLine(CURVE_CENTER_X-offset, 0/*TODO CURVE_CENTER_Y-CURVE_SIDE_WIDTH*/, CURVE_SIDE_WIDTH*2, 0xee);
lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
coord_t prev_yv = (coord_t)-1;
for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
if (prev_yv != (coord_t)-1) {
if (abs((int8_t)yv-prev_yv) <= 1) {
lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
}
else {
uint8_t tmp = (prev_yv < yv ? 0 : 1);
lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
}
}
prev_yv = yv;
}
}
enum ExposFields {
EXPO_FIELD_INPUT_NAME,
EXPO_FIELD_LINE_NAME,
EXPO_FIELD_SOURCE,
EXPO_FIELD_SCALE,
EXPO_FIELD_WEIGHT,
EXPO_FIELD_OFFSET,
CASE_CURVES(EXPO_FIELD_CURVE_LABEL)
CASE_CURVES(EXPO_FIELD_CURVE)
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES_LABEL)
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
EXPO_FIELD_SWITCH,
EXPO_FIELD_SIDE,
EXPO_FIELD_TRIM,
EXPO_FIELD_MAX
};
void menuModelExpoOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
// TODO pushMenu(menuChannelsView);
killEvents(event);
}
ExpoData * ed = expoAddress(s_currIdx);
drawSource(PSIZE(TR_MENUINPUTS)*FW+FW, 0, MIXSRC_FIRST_INPUT+ed->chn, 0);
SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(LABEL(Curve)) CASE_CURVES(1) CASE_FLIGHT_MODES(LABEL(Flight Mode)) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/});
int8_t sub = menuVerticalPosition;
coord_t y = MENU_HEADER_HEIGHT + 1;
for (uint8_t k=0; k<NUM_BODY_LINES; k++) {
int i = k + menuVerticalOffset;
for (int j=0; j<=i; ++j) {
if (j<(int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) {
++i;
}
}
LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch (i) {
case EXPO_FIELD_INPUT_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN-LEN_INPUT_NAME*FW, y, STR_INPUTNAME, g_model.inputNames[ed->chn], LEN_INPUT_NAME, event, attr);
break;
case EXPO_FIELD_LINE_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN-LEN_EXPOMIX_NAME*FW, y, STR_EXPONAME, ed->name, LEN_EXPOMIX_NAME, event, attr);
break;
case EXPO_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr);
if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable);
break;
case EXPO_FIELD_SCALE:
lcdDrawTextAlignedLeft(y, STR_SCALE);
drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), attr);
if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
break;
case EXPO_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, RIGHT | attr, 0, event);
break;
case EXPO_FIELD_OFFSET:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, RIGHT | attr, 0, event);
break;
#if defined(CURVES)
case EXPO_FIELD_CURVE_LABEL:
lcdDrawTextAlignedLeft(y, STR_CURVE);
break;
case EXPO_FIELD_CURVE:
editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, RIGHT | attr);
break;
#endif
#if defined(FLIGHT_MODES)
case EXPO_FIELD_FLIGHT_MODES_LABEL:
lcdDrawTextAlignedLeft(y, STR_FLMODE);
break;
case EXPO_FIELD_FLIGHT_MODES:
ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-9*FW+1, y, event, ed->flightModes, attr);
break;
#endif
case EXPO_FIELD_SWITCH:
ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN, y, ed->swtch, RIGHT | attr, event);
break;
case EXPO_FIELD_SIDE:
ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, RIGHT | attr, event);
break;
case EXPO_FIELD_TRIM:
uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail);
int8_t carryTrim = -ed->carryTrim;
lcdDrawTextAlignedLeft(y, STR_TRIM);
lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, RIGHT | (menuHorizontalPosition==0 ? attr : 0));
if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST);
break;
}
y += FH;
}
drawFunction(expoFn);
int x512 = getValue(ed->srcRaw);
if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
drawSensorCustomValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
}
else {
lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
}
x512 = limit(-1024, x512, 1024);
int y512 = expoFn(x512);
y512 = limit(-1024, y512, 1024);
lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
}
@@ -339,14 +339,6 @@ enum MixFields {
MIX_FIELD_COUNT
};
void gvarWeightItem(coord_t x, coord_t y, MixData * md, uint8_t attr, event_t event)
{
u_int8int16_t weight;
MD_WEIGHT_TO_UNION(md, weight);
weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event);
MD_UNION_TO_WEIGHT(weight, md);
}
#if !defined(CPUM64) || !defined(TELEMETRY_FRSKY)
#define GAUGE_WIDTH 33
#define GAUGE_HEIGHT 6
+193
View File
@@ -0,0 +1,193 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
enum MixFields {
MIX_FIELD_NAME,
MIX_FIELD_SOURCE,
MIX_FIELD_WEIGHT,
MIX_FIELD_OFFSET,
MIX_FIELD_TRIM,
CASE_CURVES(MIX_FIELD_CURVE)
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_MODE)
MIX_FIELD_SWITCH,
MIX_FIELD_WARNING,
MIX_FIELD_MLTPX,
MIX_FIELD_DELAY_UP,
MIX_FIELD_DELAY_DOWN,
MIX_FIELD_SLOW_UP,
MIX_FIELD_SLOW_DOWN,
MIX_FIELD_COUNT
};
void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
{
const int gaugeWidth = 33;
const int gaugeHeight = 6;
int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int barMin = offset - weight;
int barMax = offset + weight;
if (y > 15) {
lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
lcdDrawNumber(x+gaugeWidth+1, y-6, barMax, TINSIZE|RIGHT);
}
if (weight < 0) {
barMin = -barMin;
barMax = -barMax;
}
if (barMin < -101)
barMin = -101;
if (barMax > 101)
barMax = 101;
lcdDrawHorizontalLine(x-2, y, gaugeWidth+2, DOTTED);
lcdDrawHorizontalLine(x-2, y+gaugeHeight, gaugeWidth+2, DOTTED);
lcdDrawSolidVerticalLine(x-2, y+1, gaugeHeight-1);
lcdDrawSolidVerticalLine(x+gaugeWidth-1, y+1, gaugeHeight-1);
if (barMin <= barMax) {
int8_t right = (barMax * gaugeWidth) / 200;
int8_t left = ((barMin * gaugeWidth) / 200)-1;
lcdDrawSolidFilledRect(x+gaugeWidth/2+left, y+2, right-left, gaugeHeight-3);
}
lcdDrawSolidVerticalLine(x+gaugeWidth/2-1, y, gaugeHeight+1);
if (barMin == -101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+i, y+4-i);
lcdDrawPoint(x+3+i, y+4-i);
}
}
if (barMax == 101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+gaugeWidth-8+i, y+4-i);
lcdDrawPoint(x+gaugeWidth-5+i, y+4-i);
}
}
}
void menuModelMixOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
// TODO pushMenu(menuChannelsView);
killEvents(event);
}
MixData * md2 = mixAddress(s_currIdx) ;
putsChn(PSIZE(TR_MIXER)*FW+FW, 0, md2->destCh+1,0);
SUBMENU(STR_MIXER, MIX_FIELD_COUNT, {0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
int8_t sub = menuVerticalPosition;
int8_t editMode = s_editMode;
for (int k=0; k<LCD_LINES-1; k++) {
coord_t y;
if (k >= LCD_LINES-1)
y = 1 + (k-LCD_LINES+2)*FH;
else
y = 1 + (k+1)*FH;
int8_t i = k;
i += menuVerticalOffset;
LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch(i) {
case MIX_FIELD_NAME:
editSingleName(MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
break;
case MIX_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
break;
case MIX_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
break;
case MIX_FIELD_OFFSET:
{
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
u_int8int16_t offset;
MD_OFFSET_TO_UNION(md2, offset);
offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event);
MD_UNION_TO_OFFSET(offset, md2);
drawOffsetBar(MIXES_2ND_COLUMN+22, y, md2);
break;
}
case MIX_FIELD_TRIM:
lcdDrawTextAlignedLeft(y, STR_TRIM);
drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr);
if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1);
break;
#if defined(CURVES)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr);
break;
#endif
#if defined(FLIGHT_MODES)
case MIX_FIELD_FLIGHT_MODE:
lcdDrawTextAlignedLeft(y, STR_FLMODE);
md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
break;
#endif
case MIX_FIELD_SWITCH:
md2->swtch = editSwitch(MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
break;
case MIX_FIELD_WARNING:
drawFieldLabel(MIXES_2ND_COLUMN, y, STR_MIXWARNING);
if (md2->mixWarn)
lcdDrawNumber(MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
else
lcdDrawText(MIXES_2ND_COLUMN, y, STR_OFF, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
break;
case MIX_FIELD_MLTPX:
md2->mltpx = editChoice(MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
break;
case MIX_FIELD_DELAY_UP:
md2->delayUp = EDIT_DELAY(0, y, event, attr, STR_DELAYUP, md2->delayUp);
break;
case MIX_FIELD_DELAY_DOWN:
md2->delayDown = EDIT_DELAY(0, y, event, attr, STR_DELAYDOWN, md2->delayDown);
break;
case MIX_FIELD_SLOW_UP:
md2->speedUp = EDIT_DELAY(0, y, event, attr, STR_SLOWUP, md2->speedUp);
break;
case MIX_FIELD_SLOW_DOWN:
md2->speedDown = EDIT_DELAY(0, y, event, attr, STR_SLOWDOWN, md2->speedDown);
break;
}
}
}
+12 -5
View File
@@ -66,6 +66,7 @@ void onModelSelectMenu(const char * result)
#if defined(SDCARD)
else {
// The user choosed a file on SD to restore
storageCheck(true);
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
if (!warningText && g_eeGeneral.currModel == sub) {
eeLoadModel(sub);
@@ -79,6 +80,9 @@ void menuModelSelect(event_t event)
{
if (warningResult) {
warningResult = 0;
#if defined(CPUARM)
storageCheck(true);
#endif
eeDeleteModel(menuVerticalPosition); // delete file
s_copyMode = 0;
event = EVT_ENTRY_UP;
@@ -92,7 +96,7 @@ void menuModelSelect(event_t event)
int8_t oldSub = menuVerticalPosition;
check_submenu_simple(_event_, MAX_MODELS-HEADER_LINE);
check_submenu_simple(_event_, MAX_MODELS - HEADER_LINE);
#if defined(NAVIGATION_POT2)
if (event==0 && p2valdiff<0) {
@@ -113,10 +117,13 @@ void menuModelSelect(event_t event)
switch (event) {
case EVT_ENTRY:
menuVerticalPosition = sub = g_eeGeneral.currModel;
if (sub >= LCD_LINES-1) menuVerticalOffset = sub-LCD_LINES+2;
if (sub >= NUM_BODY_LINES)
menuVerticalOffset = sub-(NUM_BODY_LINES-1);
s_copyMode = 0;
s_editMode = EDIT_MODE_INIT;
#if !defined(CPUARM)
storageCheck(true);
#endif
break;
case EVT_KEY_LONG(KEY_EXIT):
@@ -336,11 +343,11 @@ void menuModelSelect(event_t event)
TITLE(STR_MENUMODELSEL);
for (uint8_t i=0; i<LCD_LINES-1; i++) {
for (uint8_t i=0; i<NUM_BODY_LINES; i++) {
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
uint8_t k = i+menuVerticalOffset;
lcdDrawNumber(3*FW+2, y, k+1, RIGHT+LEADING0+((!s_copyMode && sub==k) ? INVERS : 0), 2);
lcdDrawNumber(3*FW+2, y, k+1, RIGHT|LEADING0|((!s_copyMode && sub==k) ? INVERS : 0), 2);
if (s_copyMode == MOVE_MODE || (s_copyMode == COPY_MODE && s_copySrcRow >= 0)) {
if (k == sub) {
@@ -361,7 +368,7 @@ void menuModelSelect(event_t event)
k %= MAX_MODELS;
if (eeModelExists(k)) {
#if defined(PCBSKY9X)
#if defined(CPUARM)
putsModelName(4*FW, y, modelHeaders[k].name, k, 0);
#else
char * name = reusableBuffer.modelsel.listnames[i];
+21 -17
View File
@@ -160,7 +160,7 @@ enum MenuModelTelemetryFrskyItems {
#if defined(PCBSTD)
#define VARIO_RANGE_ROWS 1
#else
#define VARIO_RANGE_ROWS 3
#define VARIO_RANGE_ROWS (NAVIGATION_LINE_BY_LINE | 3)
#endif
#if defined(REVX)
@@ -232,7 +232,7 @@ void menuModelSensor(event_t event)
k++;
}
uint8_t attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
LcdFlags attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch (k) {
@@ -422,9 +422,9 @@ void menuModelSensor(event_t event)
}
}
void onSensorMenu(const char *result)
void onSensorMenu(const char * result)
{
uint8_t index = menuVerticalPosition - 1 - ITEM_TELEMETRY_SENSOR1;
uint8_t index = menuVerticalPosition - HEADER_LINE - ITEM_TELEMETRY_SENSOR1;
if (index < MAX_TELEMETRY_SENSORS) {
if (result == STR_EDIT) {
@@ -436,11 +436,10 @@ void onSensorMenu(const char *result)
if (index<MAX_TELEMETRY_SENSORS && isTelemetryFieldAvailable(index))
menuVerticalPosition += 1;
else
menuVerticalPosition = 1+ITEM_TELEMETRY_NEW_SENSOR;
menuVerticalPosition = HEADER_LINE + ITEM_TELEMETRY_NEW_SENSOR;
}
else if (result == STR_COPY) {
int newIndex = availableTelemetryIndex();
if (newIndex >= 0) {
TelemetrySensor & sourceSensor = g_model.telemetrySensors[index];
TelemetrySensor & newSensor = g_model.telemetrySensors[newIndex];
@@ -495,8 +494,8 @@ void menuModelTelemetryFrsky(event_t event)
}
#endif
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
uint8_t attr = (sub == k ? blink : 0);
LcdFlags blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
LcdFlags attr = (sub == k ? blink : 0);
#if !defined(CPUARM)
uint8_t ch = TELEMETRY_CURRENT_CHANNEL(k);
@@ -506,7 +505,7 @@ void menuModelTelemetryFrsky(event_t event)
#if defined(CPUARM)
if (k>=ITEM_TELEMETRY_SENSOR1 && k<ITEM_TELEMETRY_SENSOR1+MAX_TELEMETRY_SENSORS) {
int index = k-ITEM_TELEMETRY_SENSOR1;
int index = k - ITEM_TELEMETRY_SENSOR1;
lcdDrawNumber(INDENT_WIDTH, y, index+1, LEFT|attr);
lcdDrawChar(lcdLastPos, y, ':', attr);
lcdDrawSizedText(3*FW, y, g_model.telemetrySensors[index].label, TELEM_LABEL_LEN, ZCHAR);
@@ -586,10 +585,12 @@ void menuModelTelemetryFrsky(event_t event)
case ITEM_TELEMETRY_DELETE_ALL_SENSORS:
lcdDrawText(0, y, STR_DELETE_ALL_SENSORS, attr);
s_editMode = 0;
if (attr && event==EVT_KEY_LONG(KEY_ENTER)) {
killEvents(KEY_ENTER);
POPUP_CONFIRMATION(STR_CONFIRMDELETE);
if (attr) {
s_editMode = 0;
if (event==EVT_KEY_LONG(KEY_ENTER)) {
killEvents(KEY_ENTER);
POPUP_CONFIRMATION(STR_CONFIRMDELETE);
}
}
break;
@@ -774,10 +775,13 @@ void menuModelTelemetryFrsky(event_t event)
}
}
#else
lcdDrawNumber(TELEM_COL2, y, -10+g_model.frsky.varioMin, (menuHorizontalPosition<=0 ? attr : 0)|LEFT);
lcdDrawNumber(TELEM_COL2+7*FW-2, y, -5+g_model.frsky.varioCenterMin, ((CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0)|PREC1);
lcdDrawNumber(TELEM_COL2+10*FW-1, y, 5+g_model.frsky.varioCenterMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0)|PREC1);
lcdDrawNumber(TELEM_COL2+13*FW, y, 10+g_model.frsky.varioMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==3) ? attr : 0));
if (attr && menuHorizontalPosition<0) {
lcdDrawSolidFilledRect(TELEM_COL2-1, y-1, LCD_W-TELEM_COL2+1, FH+1);
}
lcdDrawNumber(TELEM_COL2, y, -10+g_model.frsky.varioMin, ((CURSOR_ON_LINE() || menuHorizontalPosition==0) ? attr : 0)|LEFT);
lcdDrawNumber(TELEM_COL2+4*FW-2, y, -5+g_model.frsky.varioCenterMin, ((CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0)|PREC1|LEFT);
lcdDrawNumber(TELEM_COL2+8*FW-1, y, 5+g_model.frsky.varioCenterMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0)|PREC1|LEFT);
lcdDrawNumber(TELEM_COL2+12*FW-4, y, 10+g_model.frsky.varioMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==3) ? attr : 0)|LEFT);
if (attr && (s_editMode>0 || p1valdiff)) {
switch (menuHorizontalPosition) {
case 0:
+7 -3
View File
@@ -61,8 +61,11 @@ void menuRadioDiagAnalogs(event_t event)
lcdDrawText(64+5, MENU_HEADER_HEIGHT+1+3*FH, STR_BG);
lcdDrawNumber(64+5+6*FW-3, 1+4*FH, BandGap, RIGHT);
#endif
#if defined(PCBSKY9X)
#if defined(PCBX7D)
lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH, STR_BATT_CALIB);
putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH + 2, getBatteryVoltage(), (menuVerticalPosition==HEADER_LINE ? INVERS | (s_editMode > 0 ? BLINK : 0) : 0) | PREC2 | LEFT);
#elif defined(PCBSKY9X)
lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+1+4*FH, STR_BATT_CALIB);
static int32_t adcBatt;
// TODO board.cpp
@@ -104,6 +107,7 @@ void menuRadioDiagAnalogs(event_t event)
lcdDrawTextAlignedLeft(TEMP_CALIB_POS, STR_TEMP_CALIB);
drawValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, TEMP_CALIB_POS, getTemperature(), UNIT_TEMPERATURE, (menuVerticalPosition==TEMP_CALIB_MENU_POS ? INVERS : 0)) ;
if (menuVerticalPosition==TEMP_CALIB_MENU_POS) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureCalib, -100, 100);
if (menuVerticalPosition==TEMP_CALIB_MENU_POS)
CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureCalib, -100, 100);
#endif
}
-296
View File
@@ -1,296 +0,0 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
void menuRadioSdManagerInfo(event_t event)
{
SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1);
lcdDrawTextAlignedLeft(2*FH, STR_SD_TYPE);
lcdDrawText(10*FW, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD);
lcdDrawTextAlignedLeft(3*FH, STR_SD_SIZE);
lcdDrawNumber(10*FW, 3*FH, sdGetSize(), LEFT);
lcdDrawChar(lcdLastPos, 3*FH, 'M');
lcdDrawTextAlignedLeft(4*FH, STR_SD_SECTORS);
#if defined(SD_GET_FREE_BLOCKNR)
lcdDrawNumber(10*FW, 4*FH, SD_GET_FREE_BLOCKNR()/1000, LEFT);
lcdDrawChar(lcdLastPos, 4*FH, '/');
lcdDrawNumber(lcdLastPos+FW, 4*FH, sdGetNoSectors()/1000, LEFT);
#else
lcdDrawNumber(10*FW, 4*FH, sdGetNoSectors()/1000, LEFT);
#endif
lcdDrawChar(lcdLastPos, 4*FH, 'k');
lcdDrawTextAlignedLeft(5*FH, STR_SD_SPEED);
lcdDrawNumber(10*FW, 5*FH, SD_GET_SPEED()/1000, LEFT);
lcdDrawText(lcdLastPos, 5*FH, "kb/s");
}
inline bool isFilenameGreater(bool isfile, const char * fn, const char * line)
{
return (isfile && !line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) > 0);
}
inline bool isFilenameLower(bool isfile, const char * fn, const char * line)
{
return (!isfile && line[SD_SCREEN_FILE_LENGTH+1]) || (isfile==(bool)line[SD_SCREEN_FILE_LENGTH+1] && strcasecmp(fn, line) < 0);
}
void getSelectionFullPath(char * lfn)
{
f_getcwd(lfn, _MAX_LFN);
strcat(lfn, PSTR("/"));
strcat(lfn, reusableBuffer.sdmanager.lines[menuVerticalPosition - HEADER_LINE - menuVerticalOffset]);
}
void onSdManagerMenu(const char * result)
{
TCHAR lfn[_MAX_LFN+1];
uint8_t index = menuVerticalPosition-HEADER_LINE-menuVerticalOffset;
if (result == STR_SD_INFO) {
pushMenu(menuRadioSdManagerInfo);
}
else if (result == STR_SD_FORMAT) {
POPUP_CONFIRMATION(STR_CONFIRM_FORMAT);
}
else if (result == STR_DELETE_FILE) {
getSelectionFullPath(lfn);
f_unlink(lfn);
strncpy(statusLineMsg, reusableBuffer.sdmanager.lines[index], 13);
strcpy_P(statusLineMsg+min((uint8_t)strlen(statusLineMsg), (uint8_t)13), STR_REMOVED);
showStatusLine();
if ((uint16_t)menuVerticalPosition == reusableBuffer.sdmanager.count) menuVerticalPosition--;
reusableBuffer.sdmanager.offset = menuVerticalOffset-HEADER_LINE;
}
#if defined(CPUARM)
/* TODO else if (result == STR_LOAD_FILE) {
getSelectionFullPath(lfn);
POPUP_WARNING(eeLoadModelSD(lfn));
} */
else if (result == STR_PLAY_FILE) {
getSelectionFullPath(lfn);
audioQueue.stopAll();
audioQueue.playFile(lfn, 0, ID_PLAY_FROM_SD_MANAGER);
}
#endif
#if defined(LUA)
else if (result == STR_EXECUTE_FILE) {
getSelectionFullPath(lfn);
luaExec(lfn);
}
#endif
}
void menuRadioSdManager(event_t _event)
{
#if defined(SDCARD)
if (warningResult) {
warningResult = 0;
showMessageBox(STR_FORMATTING);
logsClose();
#if defined(PCBSKY9X)
Card_state = SD_ST_DATA;
#endif
#if defined(CPUARM)
audioQueue.stopSD();
#endif
BYTE work[_MAX_SS];
if (f_mkfs(0, FM_FAT32, 0, work, sizeof(work)) == FR_OK) {
f_chdir("/");
reusableBuffer.sdmanager.offset = -1;
}
else {
POPUP_WARNING(STR_SDCARD_ERROR);
}
}
#endif
event_t event = ((READ_ONLY() && EVT_KEY_MASK(_event) == KEY_ENTER) ? 0 : _event);
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, MENU_RADIO_SD_MANAGER, HEADER_LINE+reusableBuffer.sdmanager.count);
if (s_editMode > 0)
s_editMode = 0;
switch (_event) {
case EVT_ENTRY:
f_chdir(ROOT_PATH);
reusableBuffer.sdmanager.offset = 65535;
break;
#if !defined(PCBX7D)
CASE_EVT_ROTARY_BREAK
case EVT_KEY_FIRST(KEY_RIGHT):
#endif
case EVT_KEY_FIRST(KEY_ENTER):
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
if (menuVerticalPosition >= HEADER_LINE) {
#pragma GCC diagnostic pop
vertpos_t index = menuVerticalPosition-HEADER_LINE-menuVerticalOffset;
if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) {
f_chdir(reusableBuffer.sdmanager.lines[index]);
menuVerticalOffset = 0;
menuVerticalPosition = HEADER_LINE;
reusableBuffer.sdmanager.offset = 65535;
killEvents(_event);
break;
}
}
if (!IS_ROTARY_BREAK(_event) || menuVerticalPosition==0)
break;
// no break;
}
case EVT_KEY_LONG(KEY_ENTER):
killEvents(_event);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
if (menuVerticalPosition < HEADER_LINE) {
#pragma GCC diagnostic pop
POPUP_MENU_ADD_ITEM(STR_SD_INFO);
POPUP_MENU_ADD_ITEM(STR_SD_FORMAT);
}
else
{
#if defined(CPUARM)
uint8_t index = menuVerticalPosition-HEADER_LINE-menuVerticalOffset;
// TODO duplicated code for finding extension
char * ext = reusableBuffer.sdmanager.lines[index];
int len = strlen(ext) - 4;
ext += len;
/* TODO if (!strcasecmp(ext, MODELS_EXT)) {
popupMenuItems[popupMenuNoItems++] = STR_LOAD_FILE;
}
else */ if (!strcasecmp(ext, SOUNDS_EXT)) {
POPUP_MENU_ADD_ITEM(STR_PLAY_FILE);
}
#endif
#if defined(LUA)
else if (!strcasecmp(ext, SCRIPTS_EXT)) {
POPUP_MENU_ADD_ITEM(STR_EXECUTE_FILE);
}
#endif
if (!READ_ONLY()) {
POPUP_MENU_ADD_ITEM(STR_DELETE_FILE);
// POPUP_MENU_ADD_ITEM(STR_RENAME_FILE); TODO: Implement
// POPUP_MENU_ADD_ITEM(STR_COPY_FILE); TODO: Implement
}
}
POPUP_MENU_START(onSdManagerMenu);
break;
}
if (reusableBuffer.sdmanager.offset != menuVerticalOffset) {
FILINFO fno;
DIR dir;
if (menuVerticalOffset == 0) {
reusableBuffer.sdmanager.offset = 0;
memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines));
}
else if (menuVerticalOffset == reusableBuffer.sdmanager.count-7) {
reusableBuffer.sdmanager.offset = menuVerticalOffset;
memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines));
}
else if (menuVerticalOffset > reusableBuffer.sdmanager.offset) {
memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], 6*sizeof(reusableBuffer.sdmanager.lines[0]));
memset(reusableBuffer.sdmanager.lines[6], 0xff, SD_SCREEN_FILE_LENGTH);
reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = 1;
}
else {
memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], 6*sizeof(reusableBuffer.sdmanager.lines[0]));
memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
}
reusableBuffer.sdmanager.count = 0;
FRESULT res = f_opendir(&dir, "."); // Open the directory
if (res == FR_OK) {
bool firstTime = true;
for (;;) {
res = sdReadDir(&dir, &fno, firstTime);
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
if (strlen(fno.fname) > SD_SCREEN_FILE_LENGTH) continue;
reusableBuffer.sdmanager.count++;
bool isfile = !(fno.fattrib & AM_DIR);
if (menuVerticalOffset == 0) {
for (uint8_t i=0; i<LCD_LINES-1; i++) {
char * line = reusableBuffer.sdmanager.lines[i];
if (line[0] == '\0' || isFilenameLower(isfile, fno.fname, line)) {
if (i < 6) memmove(reusableBuffer.sdmanager.lines[i+1], line, sizeof(reusableBuffer.sdmanager.lines[i]) * (6-i));
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
strcpy(line, fno.fname);
line[SD_SCREEN_FILE_LENGTH+1] = isfile;
break;
}
}
}
else if (reusableBuffer.sdmanager.offset == menuVerticalOffset) {
for (int8_t i=6; i>=0; i--) {
char * line = reusableBuffer.sdmanager.lines[i];
if (line[0] == '\0' || isFilenameGreater(isfile, fno.fname, line)) {
if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i);
memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[i]));
strcpy(line, fno.fname);
line[SD_SCREEN_FILE_LENGTH+1] = isfile;
break;
}
}
}
else if (menuVerticalOffset > reusableBuffer.sdmanager.offset) {
if (isFilenameGreater(isfile, fno.fname, reusableBuffer.sdmanager.lines[5]) && isFilenameLower(isfile, fno.fname, reusableBuffer.sdmanager.lines[6])) {
memset(reusableBuffer.sdmanager.lines[6], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(reusableBuffer.sdmanager.lines[6], fno.fname);
reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = isfile;
}
}
else {
if (isFilenameLower(isfile, fno.fname, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fno.fname, reusableBuffer.sdmanager.lines[0])) {
memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
strcpy(reusableBuffer.sdmanager.lines[0], fno.fname);
reusableBuffer.sdmanager.lines[0][SD_SCREEN_FILE_LENGTH+1] = isfile;
}
}
}
}
}
reusableBuffer.sdmanager.offset = menuVerticalOffset;
for (uint8_t i=0; i<LCD_LINES-1; i++) {
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
lcdNextPos = 0;
uint8_t attr = (menuVerticalPosition-HEADER_LINE-menuVerticalOffset == i ? BSS|INVERS : BSS);
if (reusableBuffer.sdmanager.lines[i][0]) {
if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) { lcdDrawChar(0, y, '[', attr); }
lcdDrawText(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], attr);
if (!reusableBuffer.sdmanager.lines[i][SD_SCREEN_FILE_LENGTH+1]) { lcdDrawChar(lcdNextPos, y, ']', attr); }
}
}
}
+5 -5
View File
@@ -546,10 +546,10 @@ void menuRadioSetup(event_t event)
case ITEM_SETUP_STICK_MODE_LABELS:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_MODE));
for (uint8_t i=0; i<4; i++) {
lcd_img((6+4*i)*FW, y, sticks, i, 0);
lcd_img(5*FW+i*(4*FW+2), y, sticks, i, 0);
#if defined(FRSKY_STICKS)
if (g_eeGeneral.stickReverse & (1<<i)) {
lcdDrawFilledRect((6+4*i)*FW, y, 3*FW, FH-1);
lcdDrawFilledRect(5*FW+i*(4*FW+2), y, 3*FW, FH-1);
}
#endif
}
@@ -557,15 +557,15 @@ void menuRadioSetup(event_t event)
if (attr) {
s_editMode = 0;
CHECK_INCDEC_GENVAR(event, g_eeGeneral.stickReverse, 0, 15);
lcdDrawRect(6*FW-1, y-1, 15*FW+2, 9);
lcdDrawRect(5*FW-1, y-1, 16*FW+2, 9);
}
#endif
break;
case ITEM_SETUP_STICK_MODE:
lcdDrawChar(2*FW, y, '1'+reusableBuffer.generalSettings.stickMode, attr);
for (uint8_t i=0; i<4; i++) {
drawSource((6+4*i)*FW, y, MIXSRC_Rud + pgm_read_byte(modn12x3 + 4*reusableBuffer.generalSettings.stickMode + i), 0);
for (uint8_t i=0; i<NUM_STICKS; i++) {
drawSource(5*FW+i*(4*FW+2), y, MIXSRC_Rud + pgm_read_byte(modn12x3 + 4*reusableBuffer.generalSettings.stickMode + i), 0);
}
if (attr && s_editMode>0) {
CHECK_INCDEC_GENVAR(event, reusableBuffer.generalSettings.stickMode, 0, 3);
+40 -15
View File
@@ -33,9 +33,7 @@
#define VBATTUNIT_X (VBATT_X-1)
#define VBATTUNIT_Y (3*FH)
#define REBOOT_X (20*FW-3)
#define VSWITCH_X(i) (16 + 3*i)
#define VSWITCH_Y (LCD_H-8)
#define BAR_HEIGHT (BOX_WIDTH-1l)
#define BAR_HEIGHT (BOX_WIDTH-1)
#define TRIM_LH_X (LCD_W*1/4+2)
#define TRIM_LV_X 3
#define TRIM_RV_X (LCD_W-4)
@@ -222,6 +220,8 @@ void displayVoltageOrAlarm()
#if defined(PCBX7D)
#define EVT_KEY_CONTEXT_MENU EVT_KEY_LONG(KEY_ENTER)
#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_PAGE)
#define EVT_KEY_NEXT_PAGE EVT_ROTARY_RIGHT
#define EVT_KEY_PREVIOUS_PAGE EVT_ROTARY_LEFT
#define EVT_KEY_MODEL_MENU EVT_KEY_BREAK(KEY_MENU)
#define EVT_KEY_GENERAL_MENU EVT_KEY_LONG(KEY_MENU)
#define EVT_KEY_TELEMETRY EVT_KEY_LONG(KEY_PAGE)
@@ -229,6 +229,8 @@ void displayVoltageOrAlarm()
#define EVT_KEY_CONTEXT_MENU EVT_KEY_BREAK(KEY_MENU)
#define EVT_KEY_PREVIOUS_VIEW EVT_KEY_BREAK(KEY_UP)
#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_DOWN)
#define EVT_KEY_NEXT_PAGE EVT_KEY_BREAK(KEY_RIGHT)
#define EVT_KEY_PREVIOUS_PAGE EVT_KEY_BREAK(KEY_LEFT)
#define EVT_KEY_MODEL_MENU EVT_KEY_LONG(KEY_RIGHT)
#define EVT_KEY_GENERAL_MENU EVT_KEY_LONG(KEY_LEFT)
#define EVT_KEY_LAST_MENU EVT_KEY_LONG(KEY_MENU)
@@ -306,14 +308,14 @@ void menuMainView(event_t event)
break;
*/
case EVT_KEY_BREAK(KEY_RIGHT):
case EVT_KEY_BREAK(KEY_LEFT):
case EVT_KEY_NEXT_PAGE:
case EVT_KEY_PREVIOUS_PAGE:
if (view_base <= VIEW_INPUTS) {
#if defined(CPUARM)
if (view_base == VIEW_INPUTS)
g_eeGeneral.view ^= ALTERNATE_VIEW;
else
g_eeGeneral.view = (g_eeGeneral.view + (4*ALTERNATE_VIEW) + ((event==EVT_KEY_BREAK(KEY_LEFT)) ? -ALTERNATE_VIEW : ALTERNATE_VIEW)) % (4*ALTERNATE_VIEW);
g_eeGeneral.view = (g_eeGeneral.view + (4*ALTERNATE_VIEW) + ((event==EVT_KEY_PREVIOUS_PAGE) ? -ALTERNATE_VIEW : ALTERNATE_VIEW)) % (4*ALTERNATE_VIEW);
#else
g_eeGeneral.view ^= ALTERNATE_VIEW;
#endif
@@ -510,7 +512,21 @@ void menuMainView(event_t event)
doMainScreenGraphics();
// Switches
#if !defined(PCBX7D)
#if defined(PCBX7D)
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 = 17*FW-1;
y -= 3*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);
}
}
#else
// The ID0 3-POS switch is merged with the TRN switch
for (uint8_t i=SWSRC_THR; i<=SWSRC_TRN; i++) {
int8_t sw = (i == SWSRC_TRN ? (switchState(SW_ID0) ? SWSRC_ID0 : (switchState(SW_ID1) ? SWSRC_ID1 : SWSRC_ID2)) : i);
uint8_t x = 2*FW-2, y = i*FH+1;
@@ -539,21 +555,30 @@ void menuMainView(event_t event)
// Logical Switches
#if defined(CPUARM)
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++) {
int8_t len = getSwitch(SWSRC_SW1+i) ? BAR_HEIGHT : 1;
uint8_t x = VSWITCH_X(i);
lcdDrawSolidVerticalLine(x-1, VSWITCH_Y-len, len);
lcdDrawSolidVerticalLine(x, VSWITCH_Y-len, len);
uint8_t index = 0;
uint8_t y = LCD_H-20;
for (uint8_t line=0; line<2; line++) {
for (uint8_t column=0; column<MAX_LOGICAL_SWITCHES/2; column++) {
int8_t len = getSwitch(SWSRC_SW1+index) ? 10 : 1;
uint8_t x = (16 + 3*column);
lcdDrawSolidVerticalLine(x-1, y-len, len);
lcdDrawSolidVerticalLine(x, y-len, len);
index++;
}
y += 12;
}
#elif defined(CPUM2560)
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++)
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++) {
drawSwitch(2*FW-3 + (i/3)*(i/3>2 ? 3*FW+2 : (3*FW-1)) + (i/3>2 ? 2*FW : 0), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0);
}
#elif !defined(PCBSTD)
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++)
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++) {
drawSwitch(2*FW-2 + (i/3)*(4*FW-1), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0);
}
#else
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++)
for (uint8_t i=0; i<MAX_LOGICAL_SWITCHES; i++) {
drawSwitch(2*FW-3 + (i/3)*(4*FW), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0);
}
#endif
}
}
+10 -2
View File
@@ -248,12 +248,20 @@ void drawStatusLine()
void drawProgressBar(const char * label)
{
// TODO
lcdDrawTextAlignedLeft(4*FH, label);
lcdDrawRect(4, 6*FH+4, LCD_W-8, 7);
lcdRefresh();
}
void updateProgressBar(int num, int den)
{
// TODO
if (num > 0 && den > 0) {
int width = ((LCD_W-12)*num)/den;
lcdDrawSolidHorizontalLine(6, 6*FH+6, width, FORCE);
lcdDrawSolidHorizontalLine(6, 6*FH+7, width, FORCE);
lcdDrawSolidHorizontalLine(6, 6*FH+8, width, FORCE);
lcdRefresh();
}
}
#if defined(CPUARM) || defined(CPUM2560)
+3 -1
View File
@@ -245,11 +245,13 @@ int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int
#define displayGVar(x, y, v, min, max) lcdDrawNumber(x, y, v)
#endif
void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event);
extern uint8_t s_curveChan;
void editCurveRef(coord_t x, coord_t y, CurveRef & curve, event_t event, LcdFlags flags);
extern uint8_t editNameCursorPos;
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active, uint8_t attr=ZCHAR);
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active, LcdFlags attr=ZCHAR);
void editSingleName(coord_t x, coord_t y, const pm_char * label, char * name, uint8_t size, event_t event, uint8_t active);
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay);
-88
View File
@@ -61,94 +61,6 @@ uint8_t s_copySrcCh;
uint8_t editNameCursorPos = 0;
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active, uint8_t attr)
{
uint8_t mode = 0;
if (active) {
if (s_editMode <= 0)
mode = INVERS + FIXEDWIDTH;
else
mode = FIXEDWIDTH;
}
lcdDrawSizedText(x, y, name, size, attr | mode);
coord_t backupNextPos = lcdNextPos;
if (active) {
uint8_t cur = editNameCursorPos;
if (s_editMode > 0) {
int8_t c = name[cur];
int8_t v = c;
if (IS_NEXT_EVENT(event) || IS_PREVIOUS_EVENT(event)) {
if (attr == ZCHAR) {
v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0);
if (c <= 0) v = -v;
}
else {
v = checkIncDec(event, abs(v), '0', 'z', 0);
}
}
switch (event) {
case EVT_KEY_BREAK(KEY_ENTER):
if (s_editMode == EDIT_MODIFY_FIELD) {
s_editMode = EDIT_MODIFY_STRING;
cur = 0;
}
else if (cur<size-1)
cur++;
else
s_editMode = 0;
break;
case EVT_KEY_LONG(KEY_ENTER):
if (attr & ZCHAR) {
if (v == 0) {
s_editMode = 0;
killEvents(event);
}
else if (v>=-26 && v<=26) {
v = -v; // toggle case
}
}
else {
if (v == ' ') {
s_editMode = 0;
killEvents(event);
break;
}
else if (v>='A' && v<='Z') {
v = 'a'+v-'A'; // toggle case
}
else if (v>='a' && v<='z') {
v = 'A'+v-'a'; // toggle case
}
}
break;
}
if (c != v) {
name[cur] = v;
storageDirty(menuVerticalPositions[0] == 0 ? EE_MODEL : EE_GENERAL);
}
if (attr == ZCHAR) {
lcdDrawChar(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH);
}
else {
lcdDrawChar(x+editNameCursorPos*FW, y, v, ERASEBG|INVERS|FIXEDWIDTH);
}
}
else {
cur = 0;
}
editNameCursorPos = cur;
lcdNextPos = backupNextPos;
}
}
void editSingleName(coord_t x, coord_t y, const pm_char * label, char *name, uint8_t size, event_t event, uint8_t active)
{
lcdDrawTextAlignedLeft(y, label);
+2 -1
View File
@@ -110,7 +110,9 @@ void menuModelSetup(event_t event);
void menuModelFailsafe(event_t event);
void menuModelHeli(event_t event);
void menuModelFlightModesAll(event_t event);
void menuModelExpoOne(event_t event);
void menuModelExposAll(event_t event);
void menuModelMixOne(event_t event);
void menuModelMixAll(event_t event);
void menuModelLimits(event_t event);
void menuModelCurvesAll(event_t event);
@@ -121,7 +123,6 @@ void menuModelSpecialFunctions(event_t event);
void menuModelCustomScripts(event_t event);
void menuModelTelemetryFrsky(event_t event);
void menuModelDisplay(event_t event);
void menuModelExpoOne(event_t event);
extern const MenuHandlerFunc menuTabModel[MENU_MODEL_PAGES_COUNT];
+185
View File
@@ -0,0 +1,185 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
#define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90)
#define EXPO_ONE_FM_WIDTH (9*FW)
int expoFn(int x)
{
ExpoData * ed = expoAddress(s_currIdx);
int16_t anas[NUM_INPUTS] = {0};
applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x);
return anas[ed->chn];
}
void drawFunction(FnFuncP fn, uint8_t offset)
{
lcdDrawVerticalLine(CURVE_CENTER_X-offset, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, CURVE_SIDE_WIDTH*2, 0xee);
lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
coord_t prev_yv = (coord_t)-1;
for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
if (prev_yv != (coord_t)-1) {
if (abs((int8_t)yv-prev_yv) <= 1) {
lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
}
else {
uint8_t tmp = (prev_yv < yv ? 0 : 1);
lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
}
}
prev_yv = yv;
}
}
enum ExposFields {
EXPO_FIELD_INPUT_NAME,
EXPO_FIELD_LINE_NAME,
EXPO_FIELD_SOURCE,
EXPO_FIELD_SCALE,
EXPO_FIELD_WEIGHT,
EXPO_FIELD_OFFSET,
CASE_CURVES(EXPO_FIELD_CURVE)
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
EXPO_FIELD_SWITCH,
EXPO_FIELD_SIDE,
EXPO_FIELD_TRIM,
EXPO_FIELD_MAX
};
#define CURVE_ROWS 1
void menuModelExpoOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
pushMenu(menuChannelsView);
killEvents(event);
}
ExpoData * ed = expoAddress(s_currIdx);
drawSource(PSIZE(TR_MENUINPUTS)*FW+FW, 0, MIXSRC_FIRST_INPUT+ed->chn, 0);
lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/});
SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW);
int8_t sub = menuVerticalPosition;
coord_t y = MENU_HEADER_HEIGHT + 1;
for (uint8_t k=0; k<NUM_BODY_LINES; k++) {
int i = k + menuVerticalOffset;
for (int j=0; j<=i; ++j) {
if (j<(int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) {
++i;
}
}
LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch (i) {
case EXPO_FIELD_INPUT_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], LEN_INPUT_NAME, event, attr);
break;
case EXPO_FIELD_LINE_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, LEN_EXPOMIX_NAME, event, attr);
break;
case EXPO_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr);
if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable);
break;
case EXPO_FIELD_SCALE:
lcdDrawTextAlignedLeft(y, STR_SCALE);
drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr);
if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
break;
case EXPO_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, LEFT|attr, 0, event);
break;
case EXPO_FIELD_OFFSET:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event);
break;
#if defined(CURVES)
case EXPO_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr);
break;
#endif
#if defined(FLIGHT_MODES)
case EXPO_FIELD_FLIGHT_MODES:
drawFieldLabel(EXPO_ONE_2ND_COLUMN, y, STR_FLMODE);
ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr);
break;
#endif
case EXPO_FIELD_SWITCH:
ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event);
break;
case EXPO_FIELD_SIDE:
ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event);
break;
case EXPO_FIELD_TRIM:
uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail);
int8_t carryTrim = -ed->carryTrim;
lcdDrawTextAlignedLeft(y, STR_TRIM);
lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0);
if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST);
break;
}
y += FH;
}
drawFunction(expoFn);
int x512 = getValue(ed->srcRaw);
if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
drawSensorCustomValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
}
else {
lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
}
x512 = limit(-1024, x512, 1024);
int y512 = expoFn(x512);
y512 = limit(-1024, y512, 1024);
lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
}
-575
View File
@@ -1,575 +0,0 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
#define EXPO_ONE_2ND_COLUMN (LCD_W-8*FW-90)
#define EXPO_ONE_FM_WIDTH (9*FW)
int expoFn(int x)
{
ExpoData * ed = expoAddress(s_currIdx);
int16_t anas[NUM_INPUTS] = {0};
applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x);
return anas[ed->chn];
}
void drawFunction(FnFuncP fn, uint8_t offset)
{
lcdDrawVerticalLine(CURVE_CENTER_X-offset, CURVE_CENTER_Y-CURVE_SIDE_WIDTH, CURVE_SIDE_WIDTH*2, 0xee);
lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
coord_t prev_yv = (coord_t)-1;
for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
if (prev_yv != (coord_t)-1) {
if (abs((int8_t)yv-prev_yv) <= 1) {
lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
}
else {
uint8_t tmp = (prev_yv < yv ? 0 : 1);
lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
}
}
prev_yv = yv;
}
}
uint8_t getExposCount()
{
uint8_t count = 0;
uint8_t ch ;
for (int i=MAX_EXPOS-1 ; i>=0; i--) {
ch = EXPO_VALID(expoAddress(i));
if (ch != 0) {
count++;
}
}
return count;
}
bool reachExposLimit()
{
if (getExposCount() >= MAX_EXPOS) {
POPUP_WARNING(STR_NOFREEEXPO);
return true;
}
return false;
}
void deleteExpo(uint8_t idx)
{
pauseMixerCalculations();
ExpoData * expo = expoAddress(idx);
int input = expo->chn;
memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData));
if (!isInputAvailable(input)) {
memclear(&g_model.inputNames[input], LEN_INPUT_NAME);
}
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
// TODO avoid this global s_currCh on ARM boards ...
int8_t s_currCh;
void insertExpo(uint8_t idx)
{
pauseMixerCalculations();
ExpoData * expo = expoAddress(idx);
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memclear(expo, sizeof(ExpoData));
expo->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh));
expo->curve.type = CURVE_REF_EXPO;
expo->mode = 3; // pos+neg
expo->chn = s_currCh - 1;
expo->weight = 100;
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
void copyExpo(uint8_t idx)
{
pauseMixerCalculations();
ExpoData * expo = expoAddress(idx);
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
bool swapExpos(uint8_t & idx, uint8_t up)
{
ExpoData * x, * y;
int8_t tgt_idx = (up ? idx-1 : idx+1);
x = expoAddress(idx);
if (tgt_idx < 0) {
if (x->chn == 0)
return false;
x->chn--;
return true;
}
if (tgt_idx == MAX_EXPOS) {
if (x->chn == NUM_INPUTS-1)
return false;
x->chn++;
return true;
}
y = expoAddress(tgt_idx);
if (x->chn != y->chn || !EXPO_VALID(y)) {
if (up) {
if (x->chn>0) x->chn--;
else return false;
}
else {
if (x->chn<NUM_INPUTS-1) x->chn++;
else return false;
}
return true;
}
pauseMixerCalculations();
memswap(x, y, sizeof(ExpoData));
resumeMixerCalculations();
idx = tgt_idx;
return true;
}
enum ExposFields {
EXPO_FIELD_INPUT_NAME,
EXPO_FIELD_NAME,
EXPO_FIELD_SOURCE,
EXPO_FIELD_SCALE,
EXPO_FIELD_WEIGHT,
EXPO_FIELD_OFFSET,
CASE_CURVES(EXPO_FIELD_CURVE)
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
EXPO_FIELD_SWITCH,
EXPO_FIELD_SIDE,
EXPO_FIELD_TRIM,
EXPO_FIELD_MAX
};
#define CURVE_ROWS 1
void menuModelExpoOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
pushMenu(menuChannelsView);
killEvents(event);
}
ExpoData * ed = expoAddress(s_currIdx);
drawSource(PSIZE(TR_MENUINPUTS)*FW+FW, 0, MIXSRC_FIRST_INPUT+ed->chn, 0);
lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(CURVE_ROWS) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/});
SET_SCROLLBAR_X(EXPO_ONE_2ND_COLUMN+10*FW);
int8_t sub = menuVerticalPosition;
coord_t y = MENU_HEADER_HEIGHT + 1;
for (uint8_t k=0; k<NUM_BODY_LINES; k++) {
int i = k + menuVerticalOffset;
for (int j=0; j<=i; ++j) {
if (j<(int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) {
++i;
}
}
LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch(i) {
case EXPO_FIELD_INPUT_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_INPUTNAME, g_model.inputNames[ed->chn], sizeof(g_model.inputNames[ed->chn]), event, attr);
break;
case EXPO_FIELD_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr);
break;
case EXPO_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|attr);
if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable);
break;
case EXPO_FIELD_SCALE:
lcdDrawTextAlignedLeft(y, STR_SCALE);
drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|attr);
if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
break;
case EXPO_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, LEFT|attr, 0, event);
break;
case EXPO_FIELD_OFFSET:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, LEFT|attr, 0, event);
break;
#if defined(CURVES)
case EXPO_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, attr);
break;
#endif
#if defined(FLIGHT_MODES)
case EXPO_FIELD_FLIGHT_MODES:
drawFieldLabel(EXPO_ONE_2ND_COLUMN, y, STR_FLMODE);
ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN, y, event, ed->flightModes, attr);
break;
#endif
case EXPO_FIELD_SWITCH:
ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN, y, ed->swtch, attr, event);
break;
case EXPO_FIELD_SIDE:
ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event);
break;
case EXPO_FIELD_TRIM:
uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail);
int8_t carryTrim = -ed->carryTrim;
lcdDrawTextAlignedLeft(y, STR_TRIM);
lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0);
if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST);
break;
}
y += FH;
}
drawFunction(expoFn);
int x512 = getValue(ed->srcRaw);
if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
drawSensorCustomValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
}
else {
lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
}
x512 = limit(-1024, x512, 1024);
int y512 = expoFn(x512);
y512 = limit(-1024, y512, 1024);
lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
}
#define _STR_MAX(x) PSTR("/" #x)
#define STR_MAX(x) _STR_MAX(x)
#define EXPO_LINE_WEIGHT_POS 8*FW+8
#define EXPO_LINE_SRC_POS 9*FW+3
#define EXPO_LINE_CURVE_POS 12*FW+11
#define EXPO_LINE_TRIM_POS 19*FW-4
#define EXPO_LINE_SWITCH_POS 20*FW-1
#define EXPO_LINE_SIDE_POS 25*FW
#define EXPO_LINE_FM_POS 12*FW+11
#define EXPO_LINE_SELECT_POS 5*FW+2
#define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH
void onExposMenu(const char * result)
{
uint8_t chn = expoAddress(s_currIdx)->chn + 1;
if (result == STR_EDIT) {
pushMenu(menuModelExpoOne);
}
else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) {
if (!reachExposLimit()) {
s_currCh = chn;
if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; }
insertExpo(s_currIdx);
pushMenu(menuModelExpoOne);
}
}
else if (result == STR_COPY || result == STR_MOVE) {
s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE);
s_copySrcIdx = s_currIdx;
s_copySrcCh = chn;
s_copySrcRow = menuVerticalPosition;
}
else if (result == STR_DELETE) {
deleteExpo(s_currIdx);
}
}
void displayExpoInfos(coord_t y, ExpoData * ed)
{
drawCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0);
drawSwitch(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0);
}
void displayExpoLine(coord_t y, ExpoData * ed)
{
drawSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0);
if (ed->carryTrim != TRIM_ON) {
lcdDrawChar(EXPO_LINE_TRIM_POS, y, ed->carryTrim > 0 ? '-' : STR_RETA123[-ed->carryTrim]);
}
if (!ed->flightModes || ((ed->curve.value || ed->swtch) && ((get_tmr10ms() / 200) & 1)))
displayExpoInfos(y, ed);
else
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes);
if (ed->name[0]) {
lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
}
}
void menuModelExposAll(event_t event)
{
uint8_t sub = menuVerticalPosition;
if (s_editMode > 0) {
s_editMode = 0;
}
uint8_t chn = expoAddress(s_currIdx)->chn + 1;
switch (event) {
case EVT_ENTRY:
case EVT_ENTRY_UP:
s_copyMode = 0;
s_copyTgtOfs = 0;
break;
case EVT_KEY_LONG(KEY_EXIT):
if (s_copyMode && s_copyTgtOfs == 0) {
deleteExpo(s_currIdx);
killEvents(event);
event = 0;
}
// no break
case EVT_KEY_BREAK(KEY_EXIT):
if (s_copyMode) {
if (s_copyTgtOfs) {
// cancel the current copy / move operation
if (s_copyMode == COPY_MODE) {
deleteExpo(s_currIdx);
}
else {
do {
swapExpos(s_currIdx, s_copyTgtOfs > 0);
s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1);
} while (s_copyTgtOfs != 0);
storageDirty(EE_MODEL);
}
menuVerticalPosition = s_copySrcRow;
s_copyTgtOfs = 0;
}
s_copyMode = 0;
event = 0;
}
break;
case EVT_KEY_BREAK(KEY_ENTER):
if ((!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) {
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
s_copySrcIdx = s_currIdx;
s_copySrcCh = chn;
s_copySrcRow = sub;
break;
}
// no break
case EVT_KEY_LONG(KEY_ENTER):
killEvents(event);
if (s_copyTgtOfs) {
s_copyMode = 0;
s_copyTgtOfs = 0;
}
else {
if (READ_ONLY()) {
if (!s_currCh) {
pushMenu(menuModelExpoOne);
}
}
else {
if (s_copyMode) s_currCh = 0;
if (s_currCh) {
if (reachExposLimit()) break;
insertExpo(s_currIdx);
pushMenu(menuModelExpoOne);
s_copyMode = 0;
}
else {
event = 0;
s_copyMode = 0;
POPUP_MENU_ADD_ITEM(STR_EDIT);
POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE);
POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER);
POPUP_MENU_ADD_ITEM(STR_COPY);
POPUP_MENU_ADD_ITEM(STR_MOVE);
POPUP_MENU_ADD_ITEM(STR_DELETE);
POPUP_MENU_START(onExposMenu);
}
}
}
break;
case EVT_KEY_LONG(KEY_LEFT):
case EVT_KEY_LONG(KEY_RIGHT):
if (s_copyMode && !s_copyTgtOfs) {
if (reachExposLimit()) break;
s_currCh = chn;
if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; }
insertExpo(s_currIdx);
pushMenu(menuModelExpoOne);
s_copyMode = 0;
killEvents(event);
}
break;
case EVT_KEY_FIRST(KEY_UP):
case EVT_KEY_REPT(KEY_UP):
case EVT_KEY_FIRST(KEY_DOWN):
case EVT_KEY_REPT(KEY_DOWN):
if (s_copyMode) {
uint8_t key = (event & 0x1f);
uint8_t next_ofs = (key==KEY_UP ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) {
// insert a mix on the same channel (just above / just below)
if (reachExposLimit()) break;
copyExpo(s_currIdx);
if (key==KEY_DOWN) s_currIdx++;
else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++;
}
else if (next_ofs==0 && s_copyMode==COPY_MODE) {
// delete the mix
deleteExpo(s_currIdx);
if (key==KEY_UP) s_currIdx--;
}
else {
// only swap the mix with its neighbor
if (!swapExpos(s_currIdx, key==KEY_UP)) break;
storageDirty(EE_MODEL);
}
s_copyTgtOfs = next_ofs;
}
break;
}
lcdDrawNumber(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, getExposCount(), RIGHT);
lcdDrawText(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, STR_MAX(MAX_EXPOS));
// Value
uint8_t index = expoAddress(s_currIdx)->chn;
if (!s_currCh) {
lcdDrawNumber(127, 2, calcRESXto1000(anas[index]), PREC1|TINSIZE|RIGHT);
}
SIMPLE_MENU(STR_MENUINPUTS, menuTabModel, MENU_MODEL_INPUTS, s_maxLines);
// Gauge
if (!s_currCh) {
drawGauge(127, 1, 58, 6, anas[index], 1024);
}
sub = menuVerticalPosition;
s_currCh = 0;
int cur = 0;
int i = 0;
for (int ch=1; ch<=NUM_INPUTS; ch++) {
ExpoData * ed;
coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH;
if (i<MAX_EXPOS && (ed=expoAddress(i))->chn+1 == ch && EXPO_VALID(ed)) {
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
drawSource(0, y, ch, 0);
}
uint8_t mixCnt = 0;
do {
if (s_copyMode) {
if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
lcdDrawRect(18, y-1, LCD_W-18, 9, DOTTED);
cur++; y+=FH;
}
if (s_currIdx == i) {
sub = menuVerticalPosition = cur;
s_currCh = ch;
}
}
else if (sub == cur) {
s_currIdx = i;
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, RIGHT | attr | (isExpoActive(i) ? BOLD : 0), 0, 0);
displayExpoLine(y, ed);
if (ed->mode!=3) {
lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127);
}
if (s_copyMode) {
if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
/* draw a border around the raw on selection mode (copy/move) */
lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
}
if (cur == sub) {
/* invert the raw when it's the current one */
lcdDrawFilledRect(EXPO_LINE_SELECT_POS+1, y, LCD_W-EXPO_LINE_SELECT_POS-2, 7);
}
}
}
cur++; y+=FH; mixCnt++; i++; ed++;
} while (i<MAX_EXPOS && ed->chn+1 == ch && EXPO_VALID(ed));
if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, DOTTED);
cur++;
}
}
else {
uint8_t attr = 0;
if (sub == cur) {
s_currIdx = i;
s_currCh = ch;
if (!s_copyMode) {
attr = INVERS;
}
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
drawSource(0, y, ch, attr);
if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) {
lcdDrawRect(EXPO_LINE_SELECT_POS, y-1, LCD_W-EXPO_LINE_SELECT_POS, 9, DOTTED);
}
}
cur++;
}
}
s_maxLines = cur;
if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1;
}
+187
View File
@@ -0,0 +1,187 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
enum MixFields {
MIX_FIELD_NAME,
MIX_FIELD_SOURCE,
MIX_FIELD_WEIGHT,
MIX_FIELD_OFFSET,
MIX_FIELD_TRIM,
CASE_CURVES(MIX_FIELD_CURVE)
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_MODE)
MIX_FIELD_SWITCH,
MIX_FIELD_WARNING,
MIX_FIELD_MLTPX,
MIX_FIELD_DELAY_UP,
MIX_FIELD_DELAY_DOWN,
MIX_FIELD_SLOW_UP,
MIX_FIELD_SLOW_DOWN,
MIX_FIELD_COUNT
};
void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
{
const int gaugeWidth = 33;
const int gaugeHeight = 6;
int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int barMin = offset - weight;
int barMax = offset + weight;
if (y > 15) {
lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
lcdDrawNumber(x+gaugeWidth+1, y-6, barMax, TINSIZE|RIGHT);
}
if (weight < 0) {
barMin = -barMin;
barMax = -barMax;
}
if (barMin < -101)
barMin = -101;
if (barMax > 101)
barMax = 101;
lcdDrawHorizontalLine(x-2, y, gaugeWidth+2, DOTTED);
lcdDrawHorizontalLine(x-2, y+gaugeHeight, gaugeWidth+2, DOTTED);
lcdDrawSolidVerticalLine(x-2, y+1, gaugeHeight-1);
lcdDrawSolidVerticalLine(x+gaugeWidth-1, y+1, gaugeHeight-1);
if (barMin <= barMax) {
int8_t right = (barMax * gaugeWidth) / 200;
int8_t left = ((barMin * gaugeWidth) / 200)-1;
lcdDrawFilledRect(x+gaugeWidth/2+left, y+2, right-left, gaugeHeight-3);
}
lcdDrawSolidVerticalLine(x+gaugeWidth/2-1, y, gaugeHeight+1);
if (barMin == -101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+i, y+4-i);
lcdDrawPoint(x+3+i, y+4-i);
}
}
if (barMax == 101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+gaugeWidth-8+i, y+4-i);
lcdDrawPoint(x+gaugeWidth-5+i, y+4-i);
}
}
}
void menuModelMixOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
pushMenu(menuChannelsView);
killEvents(event);
}
MixData * md2 = mixAddress(s_currIdx) ;
putsChn(PSIZE(TR_MIXER)*FW+FW, 0, md2->destCh+1,0);
lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
SUBMENU(STR_MIXER, MIX_FIELD_COUNT, {0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
int8_t sub = menuVerticalPosition;
int8_t editMode = s_editMode;
for (uint8_t k=0; k<NUM_BODY_LINES; k++) {
coord_t y = MENU_HEADER_HEIGHT + 1 + k*FH;
int i = k + menuVerticalOffset;
LcdFlags attr = (sub==i ? INVERS | (editMode>0 ? BLINK : 0) : 0);
switch (i) {
case MIX_FIELD_NAME:
editSingleName(MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
break;
case MIX_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
break;
case MIX_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
break;
case MIX_FIELD_OFFSET:
{
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
u_int8int16_t offset;
MD_OFFSET_TO_UNION(md2, offset);
offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event);
MD_UNION_TO_OFFSET(offset, md2);
drawOffsetBar(MIXES_2ND_COLUMN+22, y, md2);
break;
}
case MIX_FIELD_TRIM:
lcdDrawTextAlignedLeft(y, STR_TRIM);
drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr);
if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1);
break;
#if defined(CURVES)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr);
break;
#endif
#if defined(FLIGHT_MODES)
case MIX_FIELD_FLIGHT_MODE:
drawFieldLabel(MIXES_2ND_COLUMN, y, STR_FLMODE);
md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
break;
#endif
case MIX_FIELD_SWITCH:
md2->swtch = editSwitch(MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
break;
case MIX_FIELD_WARNING:
drawFieldLabel(MIXES_2ND_COLUMN, y, STR_MIXWARNING);
if (md2->mixWarn)
lcdDrawNumber(MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
else
lcdDrawText(MIXES_2ND_COLUMN, y, STR_OFF, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
break;
case MIX_FIELD_MLTPX:
md2->mltpx = editChoice(MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
break;
case MIX_FIELD_DELAY_UP:
md2->delayUp = EDIT_DELAY(y, event, attr, STR_DELAYUP, md2->delayUp);
break;
case MIX_FIELD_DELAY_DOWN:
md2->delayDown = EDIT_DELAY(y, event, attr, STR_DELAYDOWN, md2->delayDown);
break;
case MIX_FIELD_SLOW_UP:
md2->speedUp = EDIT_DELAY(y, event, attr, STR_SLOWUP, md2->speedUp);
break;
case MIX_FIELD_SLOW_DOWN:
md2->speedDown = EDIT_DELAY(y, event, attr, STR_SLOWDOWN, md2->speedDown);
break;
}
}
}
-596
View File
@@ -1,596 +0,0 @@
/*
* Copyright (C) OpenTX
*
* Based on code named
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "opentx.h"
uint8_t getMixesCount()
{
uint8_t count = 0;
uint8_t ch ;
for (int i=MAX_MIXERS-1; i>=0; i--) {
ch = mixAddress(i)->srcRaw;
if (ch != 0) {
count++;
}
}
return count;
}
bool reachMixesLimit()
{
if (getMixesCount() >= MAX_MIXERS) {
POPUP_WARNING(STR_NOFREEMIXER);
return true;
}
return false;
}
void deleteMix(uint8_t idx)
{
pauseMixerCalculations();
MixData * mix = mixAddress(idx);
memmove(mix, mix+1, (MAX_MIXERS-(idx+1))*sizeof(MixData));
memclear(&g_model.mixData[MAX_MIXERS-1], sizeof(MixData));
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
void insertMix(uint8_t idx)
{
pauseMixerCalculations();
MixData * mix = mixAddress(idx);
memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
memclear(mix, sizeof(MixData));
mix->destCh = s_currCh-1;
mix->srcRaw = s_currCh;
if (!isSourceAvailable(mix->srcRaw)) {
mix->srcRaw = (s_currCh > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh));
while (!isSourceAvailable(mix->srcRaw)) {
mix->srcRaw += 1;
}
}
mix->weight = 100;
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
void copyMix(uint8_t idx)
{
pauseMixerCalculations();
MixData * mix = mixAddress(idx);
memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
bool swapMixes(uint8_t & idx, uint8_t up)
{
MixData * x, * y;
int8_t tgt_idx = (up ? idx-1 : idx+1);
x = mixAddress(idx);
if (tgt_idx < 0) {
if (x->destCh == 0)
return false;
x->destCh--;
return true;
}
if (tgt_idx == MAX_MIXERS) {
if (x->destCh == MAX_OUTPUT_CHANNELS-1)
return false;
x->destCh++;
return true;
}
y = mixAddress(tgt_idx);
uint8_t destCh = x->destCh;
if(!y->srcRaw || destCh != y->destCh) {
if (up) {
if (destCh>0) x->destCh--;
else return false;
}
else {
if (destCh<MAX_OUTPUT_CHANNELS-1) x->destCh++;
else return false;
}
return true;
}
pauseMixerCalculations();
memswap(x, y, sizeof(MixData));
resumeMixerCalculations();
idx = tgt_idx;
return true;
}
enum MixFields {
MIX_FIELD_NAME,
MIX_FIELD_SOURCE,
MIX_FIELD_WEIGHT,
MIX_FIELD_OFFSET,
MIX_FIELD_TRIM,
CASE_CURVES(MIX_FIELD_CURVE)
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_MODE)
MIX_FIELD_SWITCH,
MIX_FIELD_WARNING,
MIX_FIELD_MLTPX,
MIX_FIELD_DELAY_UP,
MIX_FIELD_DELAY_DOWN,
MIX_FIELD_SLOW_UP,
MIX_FIELD_SLOW_DOWN,
MIX_FIELD_COUNT
};
void gvarWeightItem(coord_t x, coord_t y, MixData *md, uint8_t attr, event_t event)
{
u_int8int16_t weight;
MD_WEIGHT_TO_UNION(md, weight);
weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event);
MD_UNION_TO_WEIGHT(weight, md);
}
void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
{
const int gaugeWidth = 33;
const int gaugeHeight = 6;
int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int barMin = offset - weight;
int barMax = offset + weight;
if (y > 15) {
lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
lcdDrawNumber(x+gaugeWidth+1, y-6, barMax, TINSIZE|RIGHT);
}
if (weight < 0) {
barMin = -barMin;
barMax = -barMax;
}
if (barMin < -101)
barMin = -101;
if (barMax > 101)
barMax = 101;
lcdDrawHorizontalLine(x-2, y, gaugeWidth+2, DOTTED);
lcdDrawHorizontalLine(x-2, y+gaugeHeight, gaugeWidth+2, DOTTED);
lcdDrawSolidVerticalLine(x-2, y+1, gaugeHeight-1);
lcdDrawSolidVerticalLine(x+gaugeWidth-1, y+1, gaugeHeight-1);
if (barMin <= barMax) {
int8_t right = (barMax * gaugeWidth) / 200;
int8_t left = ((barMin * gaugeWidth) / 200)-1;
lcdDrawFilledRect(x+gaugeWidth/2+left, y+2, right-left, gaugeHeight-3);
}
lcdDrawSolidVerticalLine(x+gaugeWidth/2-1, y, gaugeHeight+1);
if (barMin == -101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+i, y+4-i);
lcdDrawPoint(x+3+i, y+4-i);
}
}
if (barMax == 101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+gaugeWidth-8+i, y+4-i);
lcdDrawPoint(x+gaugeWidth-5+i, y+4-i);
}
}
}
void menuModelMixOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
pushMenu(menuChannelsView);
killEvents(event);
}
MixData * md2 = mixAddress(s_currIdx) ;
putsChn(PSIZE(TR_MIXER)*FW+FW, 0, md2->destCh+1,0);
lcdDrawFilledRect(0, 0, LCD_W, FH, SOLID, FILL_WHITE|GREY_DEFAULT);
SUBMENU(STR_MIXER, MIX_FIELD_COUNT, {0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
int8_t sub = menuVerticalPosition;
int8_t editMode = s_editMode;
for (uint8_t k=0; k<NUM_BODY_LINES; k++) {
coord_t y = MENU_HEADER_HEIGHT + 1 + k*FH;
int i = k + menuVerticalOffset;
LcdFlags attr = (sub==i ? INVERS | (editMode>0 ? BLINK : 0) : 0);
switch (i) {
case MIX_FIELD_NAME:
editSingleName(MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
break;
case MIX_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
break;
case MIX_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
break;
case MIX_FIELD_OFFSET:
{
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
u_int8int16_t offset;
MD_OFFSET_TO_UNION(md2, offset);
offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event);
MD_UNION_TO_OFFSET(offset, md2);
drawOffsetBar(MIXES_2ND_COLUMN+22, y, md2);
break;
}
case MIX_FIELD_TRIM:
lcdDrawTextAlignedLeft(y, STR_TRIM);
drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr);
if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1);
break;
#if defined(CURVES)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr);
break;
#endif
#if defined(FLIGHT_MODES)
case MIX_FIELD_FLIGHT_MODE:
drawFieldLabel(MIXES_2ND_COLUMN, y, STR_FLMODE);
md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
break;
#endif
case MIX_FIELD_SWITCH:
md2->swtch = editSwitch(MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
break;
case MIX_FIELD_WARNING:
drawFieldLabel(MIXES_2ND_COLUMN, y, STR_MIXWARNING);
if (md2->mixWarn)
lcdDrawNumber(MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
else
lcdDrawText(MIXES_2ND_COLUMN, y, STR_OFF, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
break;
case MIX_FIELD_MLTPX:
md2->mltpx = editChoice(MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
break;
case MIX_FIELD_DELAY_UP:
md2->delayUp = EDIT_DELAY(y, event, attr, STR_DELAYUP, md2->delayUp);
break;
case MIX_FIELD_DELAY_DOWN:
md2->delayDown = EDIT_DELAY(y, event, attr, STR_DELAYDOWN, md2->delayDown);
break;
case MIX_FIELD_SLOW_UP:
md2->speedUp = EDIT_DELAY(y, event, attr, STR_SLOWUP, md2->speedUp);
break;
case MIX_FIELD_SLOW_DOWN:
md2->speedDown = EDIT_DELAY(y, event, attr, STR_SLOWDOWN, md2->speedDown);
break;
}
}
}
#define _STR_MAX(x) PSTR("/" #x)
#define STR_MAX(x) _STR_MAX(x)
#define MIX_LINE_WEIGHT_POS 2*FW+12
#define MIX_LINE_SRC_POS 7*FW+5
#define MIX_LINE_CURVE_POS 13*FW+3
#define MIX_LINE_SWITCH_POS 19*FW+1
#define MIX_LINE_FM_POS 13*FW+3
#define MIX_LINE_DELAY_POS 24*FW+3
#define MIX_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH
void onMixesMenu(const char * result)
{
uint8_t chn = mixAddress(s_currIdx)->destCh + 1;
if (result == STR_EDIT) {
pushMenu(menuModelMixOne);
}
else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) {
if (!reachMixesLimit()) {
s_currCh = chn;
if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; }
insertMix(s_currIdx);
pushMenu(menuModelMixOne);
}
}
else if (result == STR_COPY || result == STR_MOVE) {
s_copyMode = (result == STR_COPY ? COPY_MODE : MOVE_MODE);
s_copySrcIdx = s_currIdx;
s_copySrcCh = chn;
s_copySrcRow = menuVerticalPosition;
}
else if (result == STR_DELETE) {
deleteMix(s_currIdx);
}
}
void displayHeaderChannelName(uint8_t ch)
{
uint8_t len = zlen(g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name));
if (len) {
lcdDrawSizedText(80, 1, g_model.limitData[ch].name, len, ZCHAR|SMLSIZE);
}
}
void displayMixInfos(coord_t y, MixData * md)
{
drawCurveRef(MIX_LINE_CURVE_POS, y, md->curve, 0);
if (md->swtch) {
drawSwitch(MIX_LINE_SWITCH_POS, y, md->swtch);
}
}
void displayMixLine(coord_t y, MixData * md)
{
if (md->name[0])
lcdDrawSizedText(MIX_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR);
if (!md->flightModes || ((md->curve.value || md->swtch) && ((get_tmr10ms() / 200) & 1)))
displayMixInfos(y, md);
else
displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes);
char cs = ' ';
if (md->speedDown || md->speedUp)
cs = 'S';
if (md->delayUp || md->delayDown)
cs = (cs == 'S' ? '*' : 'D');
lcdDrawChar(MIX_LINE_DELAY_POS, y, cs);
}
void menuModelMixAll(event_t event)
{
uint8_t sub = menuVerticalPosition;
if (s_editMode > 0) {
s_editMode = 0;
}
uint8_t chn = mixAddress(s_currIdx)->destCh + 1;
switch (event) {
case EVT_ENTRY:
case EVT_ENTRY_UP:
s_copyMode = 0;
s_copyTgtOfs = 0;
break;
case EVT_KEY_LONG(KEY_EXIT):
if (s_copyMode && s_copyTgtOfs == 0) {
deleteMix(s_currIdx);
killEvents(event);
event = 0;
}
// no break
case EVT_KEY_BREAK(KEY_EXIT):
if (s_copyMode) {
if (s_copyTgtOfs) {
// cancel the current copy / move operation
if (s_copyMode == COPY_MODE) {
deleteMix(s_currIdx);
}
else {
do {
swapMixes(s_currIdx, s_copyTgtOfs > 0);
s_copyTgtOfs += (s_copyTgtOfs < 0 ? +1 : -1);
} while (s_copyTgtOfs != 0);
storageDirty(EE_MODEL);
}
menuVerticalPosition = s_copySrcRow;
s_copyTgtOfs = 0;
}
s_copyMode = 0;
event = 0;
}
break;
case EVT_KEY_BREAK(KEY_ENTER):
if ((!s_currCh || (s_copyMode && !s_copyTgtOfs)) && !READ_ONLY()) {
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
s_copySrcIdx = s_currIdx;
s_copySrcCh = chn;
s_copySrcRow = sub;
break;
}
// no break
case EVT_KEY_LONG(KEY_ENTER):
killEvents(event);
if (s_copyTgtOfs) {
s_copyMode = 0;
s_copyTgtOfs = 0;
}
else {
if (READ_ONLY()) {
if (!s_currCh) {
pushMenu(menuModelMixOne);
}
}
else {
if (s_copyMode) s_currCh = 0;
if (s_currCh) {
if (reachMixesLimit()) break;
insertMix(s_currIdx);
pushMenu(menuModelMixOne);
s_copyMode = 0;
}
else {
event = 0;
s_copyMode = 0;
POPUP_MENU_ADD_ITEM(STR_EDIT);
POPUP_MENU_ADD_ITEM(STR_INSERT_BEFORE);
POPUP_MENU_ADD_ITEM(STR_INSERT_AFTER);
POPUP_MENU_ADD_ITEM(STR_COPY);
POPUP_MENU_ADD_ITEM(STR_MOVE);
POPUP_MENU_ADD_ITEM(STR_DELETE);
POPUP_MENU_START(onMixesMenu);
}
}
}
break;
case EVT_KEY_LONG(KEY_LEFT):
case EVT_KEY_LONG(KEY_RIGHT):
if (s_copyMode && !s_copyTgtOfs) {
if (reachMixesLimit()) break;
s_currCh = chn;
if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; }
insertMix(s_currIdx);
pushMenu(menuModelMixOne);
s_copyMode = 0;
killEvents(event);
}
break;
case EVT_KEY_FIRST(KEY_UP):
case EVT_KEY_REPT(KEY_UP):
case EVT_KEY_FIRST(KEY_DOWN):
case EVT_KEY_REPT(KEY_DOWN):
if (s_copyMode) {
uint8_t key = (event & 0x1f);
uint8_t next_ofs = (key==KEY_UP ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) {
// insert a mix on the same channel (just above / just below)
if (reachMixesLimit()) break;
copyMix(s_currIdx);
if (key==KEY_DOWN) s_currIdx++;
else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++;
}
else if (next_ofs==0 && s_copyMode==COPY_MODE) {
// delete the mix
deleteMix(s_currIdx);
if (key==KEY_UP) s_currIdx--;
}
else {
// only swap the mix with its neighbor
if (!swapMixes(s_currIdx, key==KEY_UP)) break;
storageDirty(EE_MODEL);
}
s_copyTgtOfs = next_ofs;
}
break;
}
lcdDrawNumber(FW*sizeof(TR_MIXER)+FW+FW/2, 0, getMixesCount(), RIGHT);
lcdDrawText(FW*sizeof(TR_MIXER)+FW+FW/2, 0, STR_MAX(MAX_MIXERS));
// Value
uint8_t index = mixAddress(s_currIdx)->destCh;
if (!s_currCh) {
displayHeaderChannelName(index);
lcdDrawNumber(127, 2, calcRESXto1000(ex_chans[index]), PREC1|TINSIZE|RIGHT);
}
SIMPLE_MENU(STR_MIXER, menuTabModel, MENU_MODEL_MIXES, s_maxLines);
// Gauge
if (!s_currCh) {
drawGauge(127, 1, 58, 6, ex_chans[index], 1024);
}
sub = menuVerticalPosition;
s_currCh = 0;
int cur = 0;
int i = 0;
for (int ch=1; ch<=MAX_OUTPUT_CHANNELS; ch++) {
MixData * md;
coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH;
if (i<MAX_MIXERS && (md=mixAddress(i))->srcRaw && md->destCh+1 == ch) {
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
putsChn(0, y, ch, 0); // show CHx
}
uint8_t mixCnt = 0;
do {
if (s_copyMode) {
if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
lcdDrawRect(22, y-1, LCD_W-22, 9, DOTTED);
cur++; y+=FH;
}
if (s_currIdx == i) {
sub = menuVerticalPosition = cur;
s_currCh = ch;
}
}
else if (sub == cur) {
s_currIdx = i;
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0);
drawSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0);
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, LEFT | attr | (isMixActive(i) ? BOLD : 0), 0);
displayMixLine(y, md);
if (s_copyMode) {
if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
/* draw a border around the raw on selection mode (copy/move) */
lcdDrawRect(22, y-1, LCD_W-22, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
}
if (cur == sub) {
/* invert the raw when it's the current one */
lcdDrawFilledRect(23, y, LCD_W-24, 7);
}
}
}
cur++; y+=FH; mixCnt++; i++; md++;
} while (i<MAX_MIXERS && md->srcRaw && md->destCh+1 == ch);
if (s_copyMode == MOVE_MODE && cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
lcdDrawRect(22, y-1, LCD_W-22, 9, DOTTED);
cur++;
}
}
else {
uint8_t attr = 0;
if (sub == cur) {
s_currIdx = i;
s_currCh = ch;
if (!s_copyMode) {
attr = INVERS;
}
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
putsChn(0, y, ch, attr); // show CHx
if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) {
lcdDrawRect(22, y-1, LCD_W-22, 9, DOTTED);
}
}
cur++;
}
}
s_maxLines = cur;
if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1;
}
+5 -3
View File
@@ -90,7 +90,8 @@ void menuModelSelect(event_t event)
switch (event) {
case EVT_ENTRY:
menuVerticalPosition = sub = g_eeGeneral.currModel;
if (sub >= NUM_BODY_LINES) menuVerticalOffset = sub-(NUM_BODY_LINES-1);
if (sub >= NUM_BODY_LINES)
menuVerticalOffset = sub-(NUM_BODY_LINES-1);
s_copyMode = 0;
s_editMode = EDIT_MODE_INIT;
break;
@@ -133,8 +134,9 @@ void menuModelSelect(event_t event)
uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS;
if (s_copyMode == COPY_MODE) {
if (!eeCopyModel(cur, s_copySrcRow))
if (!eeCopyModel(cur, s_copySrcRow)) {
cur = sub;
}
}
s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value
@@ -260,7 +262,7 @@ void menuModelSelect(event_t event)
}
if (s_copyMode && (vertpos_t)sub==i+menuVerticalOffset) {
lcdDrawFilledRect(9, y, MODELSEL_W-1-9, 7);
lcdDrawSolidFilledRect(9, y, MODELSEL_W-1-9, 7);
lcdDrawRect(8, y-1, MODELSEL_W-1-7, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
}
}
+5 -5
View File
@@ -98,17 +98,17 @@ void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uin
void drawProgressBar(const char *label)
{
lcdDrawTextAlignedLeft(4*FH, label);
lcdDrawRect(3, 6*FH+4, 204, 7);
lcdDrawRect(4, 6*FH+4, LCD_W-8, 7);
lcdRefresh();
}
void updateProgressBar(int num, int den)
{
if (num > 0 && den > 0) {
int width = (200*num)/den;
lcdDrawSolidHorizontalLine(5, 6*FH+6, width, FORCE);
lcdDrawSolidHorizontalLine(5, 6*FH+7, width, FORCE);
lcdDrawSolidHorizontalLine(5, 6*FH+8, width, FORCE);
int width = ((LCD_W-12)*num)/den;
lcdDrawSolidHorizontalLine(6, 6*FH+6, width, FORCE);
lcdDrawSolidHorizontalLine(6, 6*FH+7, width, FORCE);
lcdDrawSolidHorizontalLine(6, 6*FH+8, width, FORCE);
lcdRefresh();
}
}
-1
View File
@@ -162,4 +162,3 @@ void drawSourceValue(coord_t x, coord_t y, source_t source, LcdFlags flags)
getvalue_t value = getValue(source);
drawSourceCustomValue(x, y, source, value, flags);
}
@@ -9,6 +9,11 @@ endif()
if(ARCH STREQUAL ARM)
add_definitions(-DGRAPHICS)
set(GUI_SRC
${GUI_SRC}
../common/stdlcd/model_inputs.cpp
../common/stdlcd/model_mixes.cpp
)
set(CURVE_EDIT_SRC model_curve_edit.cpp)
else()
set(CURVE_EDIT_SRC model_curve_simple_edit.cpp)
@@ -21,3 +26,10 @@ if(CURVES)
${CURVE_EDIT_SRC}
)
endif()
if(SDCARD)
set(GUI_SRC
${GUI_SRC}
../common/stdlcd/radio_sdmanager.cpp
)
endif()
@@ -20,44 +20,14 @@
#include "opentx.h"
#define EXPO_ONE_2ND_COLUMN (7*FW+3*FW+2)
#define EXPO_ONE_FM_WIDTH (5*FW)
int expoFn(int x)
{
ExpoData * ed = expoAddress(s_currIdx);
int16_t anas[NUM_INPUTS] = {0};
applyExpos(anas, e_perout_mode_inactive_flight_mode, ed->srcRaw, x);
return anas[ed->chn];
}
void drawFunction(FnFuncP fn, uint8_t offset)
{
lcdDrawVerticalLine(CURVE_CENTER_X-offset, 0/*TODO CURVE_CENTER_Y-CURVE_SIDE_WIDTH*/, CURVE_SIDE_WIDTH*2, 0xee);
lcdDrawHorizontalLine(CURVE_CENTER_X-CURVE_SIDE_WIDTH-offset, CURVE_CENTER_Y, CURVE_SIDE_WIDTH*2, 0xee);
coord_t prev_yv = (coord_t)-1;
for (int xv=-CURVE_SIDE_WIDTH; xv<=CURVE_SIDE_WIDTH; xv++) {
coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/CURVE_SIDE_WIDTH))) / 2 * (LCD_H-1) / RESX);
if (prev_yv != (coord_t)-1) {
if (abs((int8_t)yv-prev_yv) <= 1) {
lcdDrawPoint(CURVE_CENTER_X+xv-offset-1, prev_yv, FORCE);
}
else {
uint8_t tmp = (prev_yv < yv ? 0 : 1);
lcdDrawSolidVerticalLine(CURVE_CENTER_X+xv-offset-1, yv+tmp, prev_yv-yv);
}
}
prev_yv = yv;
}
}
#define _STR_MAX(x) PSTR("/" #x)
#define STR_MAX(x) _STR_MAX(x)
uint8_t getExposCount()
{
uint8_t count = 0;
uint8_t ch ;
for (int i=MAX_EXPOS-1 ; i>=0; i--) {
ch = EXPO_VALID(expoAddress(i));
if (ch != 0) {
@@ -76,20 +46,6 @@ bool reachExposLimit()
return false;
}
void deleteExpo(uint8_t idx)
{
pauseMixerCalculations();
ExpoData * expo = expoAddress(idx);
int input = expo->chn;
memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData));
if (!isInputAvailable(input)) {
memclear(&g_model.inputNames[input], LEN_INPUT_NAME);
}
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
// TODO avoid this global s_currCh on ARM boards ...
int8_t s_currCh;
void insertExpo(uint8_t idx)
@@ -120,23 +76,23 @@ bool swapExpos(uint8_t & idx, uint8_t up)
{
ExpoData * x, * y;
int8_t tgt_idx = (up ? idx-1 : idx+1);
x = expoAddress(idx);
if (tgt_idx < 0) {
if (x->chn == 0)
return false;
x->chn--;
return true;
}
if (tgt_idx == MAX_EXPOS) {
if (x->chn == NUM_INPUTS-1)
return false;
x->chn++;
return true;
}
y = expoAddress(tgt_idx);
if (x->chn != y->chn || !EXPO_VALID(y)) {
if (up) {
@@ -149,164 +105,33 @@ bool swapExpos(uint8_t & idx, uint8_t up)
}
return true;
}
pauseMixerCalculations();
memswap(x, y, sizeof(ExpoData));
resumeMixerCalculations();
idx = tgt_idx;
return true;
}
enum ExposFields {
EXPO_FIELD_INPUT_NAME,
EXPO_FIELD_LINE_NAME,
EXPO_FIELD_SOURCE,
EXPO_FIELD_SCALE,
EXPO_FIELD_WEIGHT,
EXPO_FIELD_OFFSET,
CASE_CURVES(EXPO_FIELD_CURVE_LABEL)
CASE_CURVES(EXPO_FIELD_CURVE)
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES_LABEL)
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
EXPO_FIELD_SWITCH,
EXPO_FIELD_SIDE,
EXPO_FIELD_TRIM,
EXPO_FIELD_MAX
};
void menuModelExpoOne(event_t event)
void deleteExpo(uint8_t idx)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
// TODO pushMenu(menuChannelsView);
killEvents(event);
pauseMixerCalculations();
ExpoData * expo = expoAddress(idx);
int input = expo->chn;
memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData));
if (!isInputAvailable(input)) {
memclear(&g_model.inputNames[input], LEN_INPUT_NAME);
}
ExpoData * ed = expoAddress(s_currIdx);
drawSource(PSIZE(TR_MENUINPUTS)*FW+FW, 0, MIXSRC_FIRST_INPUT+ed->chn, 0);
SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {0, 0, 0, ed->srcRaw >= MIXSRC_FIRST_TELEM ? (uint8_t)0 : (uint8_t)HIDDEN_ROW, 0, 0, CASE_CURVES(LABEL(Curve)) CASE_CURVES(1) CASE_FLIGHT_MODES(LABEL(Flight Mode)) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0 /*, ...*/});
int8_t sub = menuVerticalPosition;
coord_t y = MENU_HEADER_HEIGHT + 1;
for (uint8_t k=0; k<NUM_BODY_LINES; k++) {
int i = k + menuVerticalOffset;
for (int j=0; j<=i; ++j) {
if (j<(int)DIM(mstate_tab) && mstate_tab[j] == HIDDEN_ROW) {
++i;
}
}
LcdFlags attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch (i) {
case EXPO_FIELD_INPUT_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN-LEN_INPUT_NAME*FW, y, STR_INPUTNAME, g_model.inputNames[ed->chn], LEN_INPUT_NAME, event, attr);
break;
case EXPO_FIELD_LINE_NAME:
editSingleName(EXPO_ONE_2ND_COLUMN-LEN_EXPOMIX_NAME*FW, y, STR_EXPONAME, ed->name, LEN_EXPOMIX_NAME, event, attr);
break;
case EXPO_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, RIGHT|STREXPANDED|attr);
if (attr) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable);
break;
case EXPO_FIELD_SCALE:
lcdDrawTextAlignedLeft(y, STR_SCALE);
drawSensorCustomValue(EXPO_ONE_2ND_COLUMN, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), attr);
if (attr) ed->scale = checkIncDec(event, ed->scale, 0, maxTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1), EE_MODEL);
break;
case EXPO_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, RIGHT | attr, 0, event);
break;
case EXPO_FIELD_OFFSET:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
ed->offset = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->offset, -100, 100, RIGHT | attr, 0, event);
break;
#if defined(CURVES)
case EXPO_FIELD_CURVE_LABEL:
lcdDrawTextAlignedLeft(y, STR_CURVE);
break;
case EXPO_FIELD_CURVE:
editCurveRef(EXPO_ONE_2ND_COLUMN, y, ed->curve, event, RIGHT | attr);
break;
#endif
#if defined(FLIGHT_MODES)
case EXPO_FIELD_FLIGHT_MODES_LABEL:
lcdDrawTextAlignedLeft(y, STR_FLMODE);
break;
case EXPO_FIELD_FLIGHT_MODES:
ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-9*FW+1, y, event, ed->flightModes, attr);
break;
#endif
case EXPO_FIELD_SWITCH:
ed->swtch = editSwitch(EXPO_ONE_2ND_COLUMN, y, ed->swtch, RIGHT | attr, event);
break;
case EXPO_FIELD_SIDE:
ed->mode = 4 - editChoice(EXPO_ONE_2ND_COLUMN, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, RIGHT | attr, event);
break;
case EXPO_FIELD_TRIM:
uint8_t not_stick = (ed->srcRaw > MIXSRC_Ail);
int8_t carryTrim = -ed->carryTrim;
lcdDrawTextAlignedLeft(y, STR_TRIM);
lcdDrawTextAtIndex(EXPO_ONE_2ND_COLUMN, y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, RIGHT | (menuHorizontalPosition==0 ? attr : 0));
if (attr) ed->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_LAST);
break;
}
y += FH;
}
drawFunction(expoFn);
int x512 = getValue(ed->srcRaw);
if (ed->srcRaw >= MIXSRC_FIRST_TELEM) {
drawSensorCustomValue(LCD_W-8, 6*FH, (ed->srcRaw - MIXSRC_FIRST_TELEM) / 3, x512, 0);
if (ed->scale > 0) x512 = (x512 * 1024) / convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale);
}
else {
lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto1000(x512), RIGHT | PREC1);
}
x512 = limit(-1024, x512, 1024);
int y512 = expoFn(x512);
y512 = limit(-1024, y512, 1024);
lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto1000(y512), RIGHT | PREC1);
x512 = CURVE_CENTER_X+x512/(RESX/CURVE_SIDE_WIDTH);
y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
resumeMixerCalculations();
storageDirty(EE_MODEL);
}
#define _STR_MAX(x) PSTR("/" #x)
#define STR_MAX(x) _STR_MAX(x)
#define EXPO_LINE_WEIGHT_POS 7*FW+8
#define EXPO_LINE_SRC_POS 8*FW+3
#define EXPO_LINE_INFOS_POS 11*FW+11
#define EXPO_LINE_CURVE_POS 11*FW+11
#define EXPO_LINE_SWITCH_POS 17*FW
#define EXPO_LINE_SIDE_POS 20*FW+2
#define EXPO_LINE_SELECT_POS 4*FW+2
void onExposMenu(const char * result)
{
uint8_t chn = expoAddress(s_currIdx)->chn + 1;
if (result == STR_EDIT) {
pushMenu(menuModelExpoOne);
}
@@ -329,6 +154,55 @@ void onExposMenu(const char * result)
}
}
#if LCD_W >= 212
#define EXPO_LINE_WEIGHT_POS 8*FW+8
#define EXPO_LINE_SRC_POS 9*FW+3
#define EXPO_LINE_CURVE_POS 12*FW+11
#define EXPO_LINE_TRIM_POS 19*FW-4
#define EXPO_LINE_SWITCH_POS 20*FW-1
#define EXPO_LINE_SIDE_POS 25*FW
#define EXPO_LINE_FM_POS 12*FW+11
#define EXPO_LINE_SELECT_POS 5*FW+2
#define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH
void displayExpoInfos(coord_t y, ExpoData * ed)
{
drawCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0);
drawSwitch(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0);
}
void displayExpoLine(coord_t y, ExpoData * ed)
{
drawSource(EXPO_LINE_SRC_POS, y, ed->srcRaw, 0);
if (ed->carryTrim != TRIM_ON) {
lcdDrawChar(EXPO_LINE_TRIM_POS, y, ed->carryTrim > 0 ? '-' : STR_RETA123[-ed->carryTrim]);
}
if (!ed->flightModes || ((ed->curve.value || ed->swtch) && ((get_tmr10ms() / 200) & 1)))
displayExpoInfos(y, ed);
else
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes);
if (ed->name[0]) {
lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
}
#if LCD_DEPTH > 1
if (ed->mode!=3) {
lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127);
}
#endif
}
#else
#define EXPO_LINE_WEIGHT_POS 7*FW+8
#define EXPO_LINE_SRC_POS 8*FW+3
#define EXPO_LINE_INFOS_POS 11*FW+11
#define EXPO_LINE_CURVE_POS 11*FW+11
#define EXPO_LINE_SWITCH_POS 17*FW
#define EXPO_LINE_SIDE_POS 20*FW+2
#define EXPO_LINE_SELECT_POS 4*FW+2
void displayExpoInfos(coord_t y, ExpoData * ed)
{
drawCurveRef(EXPO_LINE_CURVE_POS, y, ed->curve, 0);
@@ -349,17 +223,18 @@ void displayExpoLine(coord_t y, ExpoData * ed)
else
displayFlightModes(EXPO_LINE_INFOS_POS, y, ed->flightModes);
}
#endif
void menuModelExposAll(event_t event)
{
int8_t sub = menuVerticalPosition - HEADER_LINE;
if (s_editMode > 0) {
s_editMode = 0;
}
uint8_t chn = expoAddress(s_currIdx)->chn + 1;
switch (event) {
case EVT_ENTRY:
case EVT_ENTRY_UP:
@@ -453,38 +328,44 @@ void menuModelExposAll(event_t event)
case EVT_KEY_REPT(KEY_UP):
case EVT_KEY_FIRST(KEY_DOWN):
case EVT_KEY_REPT(KEY_DOWN):
#if defined(ROTARY_ENCODER_NAVIGATION)
case EVT_ROTARY_RIGHT:
case EVT_ROTARY_LEFT:
#endif
if (s_copyMode) {
uint8_t key = (event & 0x1f);
uint8_t next_ofs = (key==KEY_UP ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
uint8_t next_ofs = (IS_PREVIOUS_EVENT(event) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) {
// insert a mix on the same channel (just above / just below)
if (reachExposLimit()) break;
copyExpo(s_currIdx);
if (key==KEY_DOWN) s_currIdx++;
else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++;
if (IS_NEXT_EVENT(event))
s_currIdx++;
else if (sub-menuVerticalOffset >= 6)
menuVerticalOffset++;
}
else if (next_ofs==0 && s_copyMode==COPY_MODE) {
// delete the mix
deleteExpo(s_currIdx);
if (key==KEY_UP) s_currIdx--;
if (IS_PREVIOUS_EVENT(event))
s_currIdx--;
}
else {
// only swap the mix with its neighbor
if (!swapExpos(s_currIdx, key==KEY_UP)) break;
if (!swapExpos(s_currIdx, IS_PREVIOUS_EVENT(event)))
break;
storageDirty(EE_MODEL);
}
s_copyTgtOfs = next_ofs;
}
break;
}
lcdDrawNumber(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, getExposCount(), RIGHT);
lcdDrawText(FW*sizeof(TR_MENUINPUTS)+FW+FW/2, 0, STR_MAX(MAX_EXPOS));
#if 0
// NOT ENOUGH SPACE ?
#if LCD_DEPTH > 1
// Value
uint8_t index = expoAddress(s_currIdx)->chn;
if (!s_currCh) {
@@ -494,16 +375,18 @@ void menuModelExposAll(event_t event)
SIMPLE_MENU(STR_MENUINPUTS, menuTabModel, MENU_MODEL_INPUTS, HEADER_LINE + s_maxLines);
#if LCD_DEPTH > 1
// Gauge
if (!s_currCh) {
// NOT ENOUGH SPACE ? drawGauge(127, 1, 58, 6, anas[index], 1024);
drawGauge(127, 1, 58, 6, anas[index], 1024);
}
#endif
sub = menuVerticalPosition - HEADER_LINE;
s_currCh = 0;
int cur = 0;
int i = 0;
for (int ch=1; ch<=NUM_INPUTS; ch++) {
ExpoData * ed;
coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH;
@@ -529,10 +412,10 @@ void menuModelExposAll(event_t event)
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
LcdFlags attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, RIGHT | attr | (isExpoActive(i) ? BOLD : 0), 0, 0);
displayExpoLine(y, ed);
if (s_copyMode) {
if ((s_copyMode==COPY_MODE || s_copyTgtOfs == 0) && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
/* draw a border around the raw on selection mode (copy/move) */
@@ -570,5 +453,7 @@ void menuModelExposAll(event_t event)
}
}
s_maxLines = cur;
if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines - 1 + HEADER_LINE;
if (sub >= s_maxLines-1) {
menuVerticalPosition = s_maxLines - 1 + HEADER_LINE;
}
}
@@ -20,11 +20,14 @@
#include "opentx.h"
#define _STR_MAX(x) PSTR("/" #x)
#define STR_MAX(x) _STR_MAX(x)
uint8_t getMixesCount()
{
uint8_t count = 0;
uint8_t ch ;
for (int i=MAX_MIXERS-1; i>=0; i--) {
ch = mixAddress(i)->srcRaw;
if (ch != 0) {
@@ -85,23 +88,23 @@ bool swapMixes(uint8_t & idx, uint8_t up)
{
MixData * x, * y;
int8_t tgt_idx = (up ? idx-1 : idx+1);
x = mixAddress(idx);
if (tgt_idx < 0) {
if (x->destCh == 0)
return false;
x->destCh--;
return true;
}
if (tgt_idx == MAX_MIXERS) {
if (x->destCh == MAX_OUTPUT_CHANNELS-1)
return false;
x->destCh++;
return true;
}
y = mixAddress(tgt_idx);
uint8_t destCh = x->destCh;
if(!y->srcRaw || destCh != y->destCh) {
@@ -115,210 +118,19 @@ bool swapMixes(uint8_t & idx, uint8_t up)
}
return true;
}
pauseMixerCalculations();
memswap(x, y, sizeof(MixData));
resumeMixerCalculations();
idx = tgt_idx;
return true;
}
enum MixFields {
MIX_FIELD_NAME,
MIX_FIELD_SOURCE,
MIX_FIELD_WEIGHT,
MIX_FIELD_OFFSET,
MIX_FIELD_TRIM,
CASE_CURVES(MIX_FIELD_CURVE)
CASE_FLIGHT_MODES(MIX_FIELD_FLIGHT_MODE)
MIX_FIELD_SWITCH,
MIX_FIELD_WARNING,
MIX_FIELD_MLTPX,
MIX_FIELD_DELAY_UP,
MIX_FIELD_DELAY_DOWN,
MIX_FIELD_SLOW_UP,
MIX_FIELD_SLOW_DOWN,
MIX_FIELD_COUNT
};
void gvarWeightItem(coord_t x, coord_t y, MixData *md, uint8_t attr, event_t event)
{
u_int8int16_t weight;
MD_WEIGHT_TO_UNION(md, weight);
weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event);
MD_UNION_TO_WEIGHT(weight, md);
}
void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
{
const int gaugeWidth = 33;
const int gaugeHeight = 6;
int offset = GET_GVAR(MD_OFFSET(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int weight = GET_GVAR(MD_WEIGHT(md), GV_RANGELARGE_NEG, GV_RANGELARGE, mixerCurrentFlightMode);
int barMin = offset - weight;
int barMax = offset + weight;
if (y > 15) {
lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
lcdDrawNumber(x+gaugeWidth+1, y-6, barMax, TINSIZE|RIGHT);
}
if (weight < 0) {
barMin = -barMin;
barMax = -barMax;
}
if (barMin < -101)
barMin = -101;
if (barMax > 101)
barMax = 101;
lcdDrawHorizontalLine(x-2, y, gaugeWidth+2, DOTTED);
lcdDrawHorizontalLine(x-2, y+gaugeHeight, gaugeWidth+2, DOTTED);
lcdDrawSolidVerticalLine(x-2, y+1, gaugeHeight-1);
lcdDrawSolidVerticalLine(x+gaugeWidth-1, y+1, gaugeHeight-1);
if (barMin <= barMax) {
int8_t right = (barMax * gaugeWidth) / 200;
int8_t left = ((barMin * gaugeWidth) / 200)-1;
lcdDrawSolidFilledRect(x+gaugeWidth/2+left, y+2, right-left, gaugeHeight-3);
}
lcdDrawSolidVerticalLine(x+gaugeWidth/2-1, y, gaugeHeight+1);
if (barMin == -101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+i, y+4-i);
lcdDrawPoint(x+3+i, y+4-i);
}
}
if (barMax == 101) {
for (uint8_t i=0; i<3; ++i) {
lcdDrawPoint(x+gaugeWidth-8+i, y+4-i);
lcdDrawPoint(x+gaugeWidth-5+i, y+4-i);
}
}
}
void menuModelMixOne(event_t event)
{
if (event == EVT_KEY_LONG(KEY_MENU)) {
// TODO pushMenu(menuChannelsView);
killEvents(event);
}
MixData * md2 = mixAddress(s_currIdx) ;
putsChn(PSIZE(TR_MIXER)*FW+FW, 0, md2->destCh+1,0);
SUBMENU(STR_MIXER, MIX_FIELD_COUNT, {0, 0, 0, 0, 0, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
int8_t sub = menuVerticalPosition;
int8_t editMode = s_editMode;
for (int k=0; k<LCD_LINES-1; k++) {
coord_t y;
if (k >= LCD_LINES-1)
y = 1 + (k-LCD_LINES+2)*FH;
else
y = 1 + (k+1)*FH;
int8_t i = k;
i += menuVerticalOffset;
LcdFlags attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0);
switch(i) {
case MIX_FIELD_NAME:
editSingleName(MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
break;
case MIX_FIELD_SOURCE:
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_SOURCE));
drawSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
break;
case MIX_FIELD_WEIGHT:
lcdDrawTextAlignedLeft(y, STR_WEIGHT);
gvarWeightItem(MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
break;
case MIX_FIELD_OFFSET:
{
lcdDrawTextAlignedLeft(y, NO_INDENT(STR_OFFSET));
u_int8int16_t offset;
MD_OFFSET_TO_UNION(md2, offset);
offset.word = GVAR_MENU_ITEM(MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event);
MD_UNION_TO_OFFSET(offset, md2);
drawOffsetBar(MIXES_2ND_COLUMN+22, y, md2);
break;
}
case MIX_FIELD_TRIM:
lcdDrawTextAlignedLeft(y, STR_TRIM);
drawCheckBox(MIXES_2ND_COLUMN, y, !md2->carryTrim, attr);
if (attr) md2->carryTrim = !checkIncDecModel(event, !md2->carryTrim, 0, 1);
break;
#if defined(CURVES)
case MIX_FIELD_CURVE:
lcdDrawTextAlignedLeft(y, STR_CURVE);
editCurveRef(MIXES_2ND_COLUMN, y, md2->curve, event, attr);
break;
#endif
#if defined(FLIGHT_MODES)
case MIX_FIELD_FLIGHT_MODE:
lcdDrawTextAlignedLeft(y, STR_FLMODE);
md2->flightModes = editFlightModes(MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
break;
#endif
case MIX_FIELD_SWITCH:
md2->swtch = editSwitch(MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
break;
case MIX_FIELD_WARNING:
drawFieldLabel(MIXES_2ND_COLUMN, y, STR_MIXWARNING);
if (md2->mixWarn)
lcdDrawNumber(MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
else
lcdDrawText(MIXES_2ND_COLUMN, y, STR_OFF, attr);
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
break;
case MIX_FIELD_MLTPX:
md2->mltpx = editChoice(MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
break;
case MIX_FIELD_DELAY_UP:
md2->delayUp = EDIT_DELAY(0, y, event, attr, STR_DELAYUP, md2->delayUp);
break;
case MIX_FIELD_DELAY_DOWN:
md2->delayDown = EDIT_DELAY(0, y, event, attr, STR_DELAYDOWN, md2->delayDown);
break;
case MIX_FIELD_SLOW_UP:
md2->speedUp = EDIT_DELAY(0, y, event, attr, STR_SLOWUP, md2->speedUp);
break;
case MIX_FIELD_SLOW_DOWN:
md2->speedDown = EDIT_DELAY(0, y, event, attr, STR_SLOWDOWN, md2->speedDown);
break;
}
}
}
#define _STR_MAX(x) PSTR("/" #x)
#define STR_MAX(x) _STR_MAX(x)
#define MIX_LINE_WEIGHT_POS 6*FW+8
#define MIX_LINE_SRC_POS 7*FW+3
#define MIX_LINE_CURVE_POS 12*FW
#define MIX_LINE_SWITCH_POS 16*FW+4
#define MIX_LINE_FM_POS 13*FW+3
#define MIX_LINE_DELAY_POS 20*FW+2
#define MIX_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW
void onMixesMenu(const char * result)
{
uint8_t chn = mixAddress(s_currIdx)->destCh + 1;
if (result == STR_EDIT) {
pushMenu(menuModelMixOne);
}
@@ -341,6 +153,15 @@ void onMixesMenu(const char * result)
}
}
#if LCD_W >= 212
#define MIX_LINE_WEIGHT_POS 2*FW+12
#define MIX_LINE_SRC_POS 7*FW+5
#define MIX_LINE_CURVE_POS 13*FW+3
#define MIX_LINE_SWITCH_POS 19*FW+1
#define MIX_LINE_FM_POS 13*FW+3
#define MIX_LINE_DELAY_POS 24*FW+3
#define MIX_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH
void displayHeaderChannelName(uint8_t ch)
{
uint8_t len = zlen(g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name));
@@ -356,6 +177,48 @@ void displayMixInfos(coord_t y, MixData * md)
if (md->swtch) {
drawSwitch(MIX_LINE_SWITCH_POS, y, md->swtch);
}
}
void displayMixLine(coord_t y, MixData * md)
{
if (md->name[0])
lcdDrawSizedText(MIX_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR);
if (!md->flightModes || ((md->curve.value || md->swtch) && ((get_tmr10ms() / 200) & 1)))
displayMixInfos(y, md);
else
displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes);
char cs = ' ';
if (md->speedDown || md->speedUp)
cs = 'S';
if (md->delayUp || md->delayDown)
cs = (cs == 'S' ? '*' : 'D');
lcdDrawChar(MIX_LINE_DELAY_POS, y, cs);
}
#else
#define MIX_LINE_WEIGHT_POS 6*FW+8
#define MIX_LINE_SRC_POS 7*FW+3
#define MIX_LINE_CURVE_POS 12*FW
#define MIX_LINE_SWITCH_POS 16*FW+4
#define MIX_LINE_FM_POS 13*FW+3
#define MIX_LINE_DELAY_POS 20*FW+2
#define MIX_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW
void displayHeaderChannelName(uint8_t ch)
{
uint8_t len = zlen(g_model.limitData[ch].name, sizeof(g_model.limitData[ch].name));
if (len) {
lcdDrawSizedText(80, 1, g_model.limitData[ch].name, len, ZCHAR|SMLSIZE);
}
}
void displayMixInfos(coord_t y, MixData * md)
{
drawCurveRef(MIX_LINE_CURVE_POS, y, md->curve, 0);
if (md->swtch) {
drawSwitch(MIX_LINE_SWITCH_POS, y, md->swtch);
}
char cs = ' ';
if (md->speedDown || md->speedUp)
@@ -374,17 +237,18 @@ void displayMixLine(coord_t y, MixData * md)
else
displayFlightModes(MIX_LINE_FM_POS, y, md->flightModes);
}
#endif
void menuModelMixAll(event_t event)
{
int8_t sub = menuVerticalPosition - HEADER_LINE;
if (s_editMode > 0) {
s_editMode = 0;
}
uint8_t chn = mixAddress(s_currIdx)->destCh + 1;
switch (event) {
case EVT_ENTRY:
case EVT_ENTRY_UP:
@@ -428,7 +292,7 @@ void menuModelMixAll(event_t event)
break;
}
// no break
case EVT_KEY_LONG(KEY_ENTER):
killEvents(event);
if (s_copyTgtOfs) {
@@ -479,55 +343,65 @@ void menuModelMixAll(event_t event)
case EVT_KEY_REPT(KEY_UP):
case EVT_KEY_FIRST(KEY_DOWN):
case EVT_KEY_REPT(KEY_DOWN):
#if defined(ROTARY_ENCODER_NAVIGATION)
case EVT_ROTARY_RIGHT:
case EVT_ROTARY_LEFT:
#endif
if (s_copyMode) {
uint8_t key = (event & 0x1f);
uint8_t next_ofs = (key==KEY_UP ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
uint8_t next_ofs = (IS_PREVIOUS_EVENT(event) ? s_copyTgtOfs - 1 : s_copyTgtOfs + 1);
if (s_copyTgtOfs==0 && s_copyMode==COPY_MODE) {
// insert a mix on the same channel (just above / just below)
if (reachMixesLimit()) break;
copyMix(s_currIdx);
if (key==KEY_DOWN) s_currIdx++;
else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++;
if (IS_NEXT_EVENT(event))
s_currIdx++;
else if (sub - menuVerticalOffset >= 6)
menuVerticalOffset++;
}
else if (next_ofs==0 && s_copyMode==COPY_MODE) {
// delete the mix
deleteMix(s_currIdx);
if (key==KEY_UP) s_currIdx--;
if (IS_PREVIOUS_EVENT(event))
s_currIdx--;
}
else {
// only swap the mix with its neighbor
if (!swapMixes(s_currIdx, key==KEY_UP)) break;
if (!swapMixes(s_currIdx, IS_PREVIOUS_EVENT(event))) break;
storageDirty(EE_MODEL);
}
s_copyTgtOfs = next_ofs;
}
break;
}
lcdDrawNumber(FW*sizeof(TR_MIXER)+FW+FW/2, 0, getMixesCount(), RIGHT);
lcdDrawText(FW*sizeof(TR_MIXER)+FW+FW/2, 0, STR_MAX(MAX_MIXERS));
// Value
uint8_t index = mixAddress(s_currIdx)->destCh;
if (!s_currCh) {
displayHeaderChannelName(index);
/// NOT ENOUGH SPACE ? lcdDrawNumber(127, 2, calcRESXto1000(ex_chans[index]), PREC1|TINSIZE|RIGHT);
#if LCD_W >= 212
lcdDrawNumber(127, 2, calcRESXto1000(ex_chans[index]), PREC1|TINSIZE|RIGHT);
#endif
}
SIMPLE_MENU(STR_MIXER, menuTabModel, MENU_MODEL_MIXES, HEADER_LINE + s_maxLines);
#if LCD_W >= 212
// Gauge
if (!s_currCh) {
// TODO ? drawGauge(127, 1, 58, 6, ex_chans[index], 1024);
drawGauge(127, 1, 58, 6, ex_chans[index], 1024);
}
#endif
sub = menuVerticalPosition - HEADER_LINE;
s_currCh = 0;
int cur = 0;
int i = 0;
for (int ch=1; ch<=MAX_OUTPUT_CHANNELS; ch++) {
MixData * md;
coord_t y = MENU_HEADER_HEIGHT+1+(cur-menuVerticalOffset)*FH;
@@ -553,13 +427,13 @@ void menuModelMixAll(event_t event)
}
if (cur-menuVerticalOffset >= 0 && cur-menuVerticalOffset < NUM_BODY_LINES) {
uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0);
drawSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0);
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, RIGHT | attr | (isMixActive(i) ? BOLD : 0), 0);
displayMixLine(y, md);
if (s_copyMode) {
@@ -599,5 +473,7 @@ void menuModelMixAll(event_t event)
}
}
s_maxLines = cur;
if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines - 1 + HEADER_LINE;
if (sub >= s_maxLines-1) {
menuVerticalPosition = s_maxLines - 1 + HEADER_LINE;
}
}
@@ -65,7 +65,7 @@ void getSelectionFullPath(char * lfn)
{
f_getcwd(lfn, _MAX_LFN);
strcat(lfn, PSTR("/"));
strcat(lfn, reusableBuffer.sdmanager.lines[menuVerticalPosition - menuVerticalOffset]);
strcat(lfn, reusableBuffer.sdmanager.lines[menuVerticalPosition - HEADER_LINE - menuVerticalOffset]);
}
void onSdManagerMenu(const char * result)
@@ -74,8 +74,8 @@ void onSdManagerMenu(const char * result)
// TODO possible buffer overflows here!
uint8_t index = menuVerticalPosition-menuVerticalOffset;
char *line = reusableBuffer.sdmanager.lines[index];
uint8_t index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset;
char * line = reusableBuffer.sdmanager.lines[index];
if (result == STR_SD_INFO) {
pushMenu(menuRadioSdManagerInfo);
@@ -83,6 +83,7 @@ void onSdManagerMenu(const char * result)
else if (result == STR_SD_FORMAT) {
POPUP_CONFIRMATION(STR_CONFIRM_FORMAT);
}
#if defined(CPUARM)
else if (result == STR_COPY_FILE) {
clipboard.type = CLIPBOARD_TYPE_SD_FILE;
f_getcwd(clipboard.data.sd.directory, CLIPBOARD_PATH_LEN);
@@ -116,6 +117,7 @@ void onSdManagerMenu(const char * result)
s_editMode = EDIT_MODIFY_STRING;
editNameCursorPos = 0;
}
#endif
else if (result == STR_DELETE_FILE) {
getSelectionFullPath(lfn);
f_unlink(lfn);
@@ -124,20 +126,27 @@ void onSdManagerMenu(const char * result)
showStatusLine();
REFRESH_FILES();
}
#if defined(CPUARM)
else if (result == STR_PLAY_FILE) {
getSelectionFullPath(lfn);
audioQueue.stopAll();
audioQueue.playFile(lfn, 0, ID_PLAY_FROM_SD_MANAGER);
}
#endif
#if LCD_DEPTH > 1
else if (result == STR_ASSIGN_BITMAP) {
strAppendFilename(g_model.header.bitmap, line, sizeof(g_model.header.bitmap));
memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap));
storageDirty(EE_MODEL);
}
#endif
#if defined(CPUARM)
else if (result == STR_VIEW_TEXT) {
getSelectionFullPath(lfn);
pushMenuTextView(lfn);
}
#endif
#if defined(PCBTARANIS)
else if (result == STR_FLASH_BOOTLOADER) {
getSelectionFullPath(lfn);
bootloaderFlash(lfn);
@@ -150,6 +159,7 @@ void onSdManagerMenu(const char * result)
getSelectionFullPath(lfn);
sportFlashDevice(EXTERNAL_MODULE, lfn);
}
#endif
#if defined(LUA)
else if (result == STR_EXECUTE_FILE) {
getSelectionFullPath(lfn);
@@ -164,7 +174,12 @@ void menuRadioSdManager(event_t _event)
warningResult = 0;
showMessageBox(STR_FORMATTING);
logsClose();
#if defined(PCBSKY9X)
Card_state = SD_ST_DATA;
#endif
#if defined(CPUARM)
audioQueue.stopSD();
#endif
BYTE work[_MAX_SS];
if (f_mkfs(0, FM_FAT32, 0, work, sizeof(work)) == FR_OK) {
f_chdir("/");
@@ -175,20 +190,25 @@ void menuRadioSdManager(event_t _event)
}
}
#if LCD_DEPTH > 1
int lastPos = menuVerticalPosition;
#endif
event_t event = (EVT_KEY_MASK(_event) == KEY_ENTER ? 0 : _event);
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, MENU_RADIO_SD_MANAGER, reusableBuffer.sdmanager.count);
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, MENU_RADIO_SD_MANAGER, HEADER_LINE + reusableBuffer.sdmanager.count);
int index = menuVerticalPosition-menuVerticalOffset;
int index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset;
switch (_event) {
case EVT_ENTRY:
f_chdir(ROOT_PATH);
REFRESH_FILES();
#if LCD_DEPTH > 1
lastPos = -1;
#endif
break;
#if defined(PCBTARANIS)
case EVT_KEY_LONG(KEY_MENU):
if (!READ_ONLY() && s_editMode == 0) {
killEvents(_event);
@@ -197,11 +217,16 @@ void menuRadioSdManager(event_t _event)
POPUP_MENU_START(onSdManagerMenu);
}
break;
#endif
case EVT_KEY_BREAK(KEY_EXIT):
REFRESH_FILES();
break;
#if !defined(PCBTARANIS)
CASE_EVT_ROTARY_BREAK
case EVT_KEY_FIRST(KEY_RIGHT):
#endif
case EVT_KEY_BREAK(KEY_ENTER):
if (s_editMode > 0) {
break;
@@ -210,7 +235,7 @@ void menuRadioSdManager(event_t _event)
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[index])) {
f_chdir(reusableBuffer.sdmanager.lines[index]);
menuVerticalOffset = 0;
menuVerticalPosition = 1;
menuVerticalPosition = HEADER_LINE;
index = 1;
REFRESH_FILES();
killEvents(_event);
@@ -220,22 +245,34 @@ void menuRadioSdManager(event_t _event)
// no break
case EVT_KEY_LONG(KEY_ENTER):
#if !defined(PCBTARANIS)
if (menuVerticalPosition < HEADER_LINE) {
killEvents(_event);
POPUP_MENU_ADD_ITEM(STR_SD_INFO);
POPUP_MENU_ADD_ITEM(STR_SD_FORMAT);
POPUP_MENU_START(onSdManagerMenu);
break;
}
#endif
if (s_editMode == 0) {
killEvents(_event);
char * line = reusableBuffer.sdmanager.lines[index];
char * ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1);
if (!strcmp(line, "..")) {
break; // no menu for parent dir
break; // no menu for parent dir
}
#if defined(CPUARM)
char * ext = getFileExtension(line, SD_SCREEN_FILE_LENGTH+1);
if (ext) {
if (!strcasecmp(ext, SOUNDS_EXT)) {
POPUP_MENU_ADD_ITEM(STR_PLAY_FILE);
}
#if LCD_DEPTH > 1
else if (!strcasecmp(ext, BITMAPS_EXT)) {
if (!READ_ONLY() && (ext-line) <= (int)sizeof(g_model.header.bitmap)) {
POPUP_MENU_ADD_ITEM(STR_ASSIGN_BITMAP);
}
}
#endif
else if (!strcasecmp(ext, TEXT_EXT)) {
POPUP_MENU_ADD_ITEM(STR_VIEW_TEXT);
}
@@ -244,6 +281,7 @@ void menuRadioSdManager(event_t _event)
POPUP_MENU_ADD_ITEM(STR_EXECUTE_FILE);
}
#endif
#if defined(PCBTARANIS)
else if (!READ_ONLY() && !strcasecmp(ext, FIRMWARE_EXT)) {
TCHAR lfn[_MAX_LFN + 1];
getSelectionFullPath(lfn);
@@ -255,13 +293,17 @@ void menuRadioSdManager(event_t _event)
POPUP_MENU_ADD_ITEM(STR_FLASH_EXTERNAL_DEVICE);
POPUP_MENU_ADD_ITEM(STR_FLASH_INTERNAL_MODULE);
}
#endif
}
#endif
if (!READ_ONLY()) {
#if defined(CPUARM)
if (IS_FILE(line))
POPUP_MENU_ADD_ITEM(STR_COPY_FILE);
if (clipboard.type == CLIPBOARD_TYPE_SD_FILE)
POPUP_MENU_ADD_ITEM(STR_PASTE);
POPUP_MENU_ADD_ITEM(STR_RENAME_FILE);
#endif
if (IS_FILE(line))
POPUP_MENU_ADD_ITEM(STR_DELETE_FILE);
}
@@ -355,7 +397,10 @@ void menuRadioSdManager(event_t _event)
lcdNextPos = 0;
LcdFlags attr = (index == i ? INVERS : 0);
if (reusableBuffer.sdmanager.lines[i][0]) {
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) { lcdDrawChar(0, y, '[', s_editMode == EDIT_MODIFY_STRING ? 0 : attr); }
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) {
lcdDrawChar(0, y, '[', s_editMode == EDIT_MODIFY_STRING ? 0 : attr);
}
#if defined(CPUARM)
if (s_editMode == EDIT_MODIFY_STRING && attr) {
editName(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], SD_SCREEN_FILE_LENGTH-4, _event, attr, 0);
if (s_editMode == 0) {
@@ -374,10 +419,16 @@ void menuRadioSdManager(event_t _event)
else {
lcdDrawText(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], attr);
}
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) { lcdDrawChar(lcdNextPos, y, ']', s_editMode == EDIT_MODIFY_STRING ? 0 : attr); }
#else
lcdDrawText(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], attr);
#endif
if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) {
lcdDrawChar(lcdNextPos, y, ']', s_editMode == EDIT_MODIFY_STRING ? 0 : attr);
}
}
}
#if LCD_DEPTH > 1
char * ext = getFileExtension(reusableBuffer.sdmanager.lines[index], SD_SCREEN_FILE_LENGTH+1);
if (ext && !strcasecmp(ext, BITMAPS_EXT)) {
if (lastPos != menuVerticalPosition) {
@@ -387,4 +438,5 @@ void menuRadioSdManager(event_t _event)
}
lcdDrawBitmap(22*FW+2, 2*FH+FH/2, modelBitmap);
}
#endif
}
+97
View File
@@ -55,3 +55,100 @@ FlightModesType editFlightModes(coord_t x, coord_t y, event_t event, FlightModes
return value;
}
#endif
#if defined(CPUARM)
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active, LcdFlags attr)
{
uint8_t mode = 0;
if (active) {
if (s_editMode <= 0)
mode = INVERS + FIXEDWIDTH;
else
mode = FIXEDWIDTH;
}
lcdDrawSizedText(x, y, name, size, attr | mode);
coord_t backupNextPos = lcdNextPos;
if (active) {
uint8_t cur = editNameCursorPos;
if (s_editMode > 0) {
int8_t c = name[cur];
int8_t v = c;
if (IS_NEXT_EVENT(event) || IS_PREVIOUS_EVENT(event)) {
if (attr == ZCHAR) {
v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0);
if (c <= 0) v = -v;
}
else {
v = checkIncDec(event, abs(v), '0', 'z', 0);
}
}
switch (event) {
case EVT_KEY_BREAK(KEY_ENTER):
if (s_editMode == EDIT_MODIFY_FIELD) {
s_editMode = EDIT_MODIFY_STRING;
cur = 0;
}
else if (cur<size-1)
cur++;
else
s_editMode = 0;
break;
case EVT_KEY_LONG(KEY_ENTER):
if (attr & ZCHAR) {
if (v == 0) {
s_editMode = 0;
killEvents(event);
}
else if (v>=-26 && v<=26) {
v = -v; // toggle case
}
}
else {
if (v == ' ') {
s_editMode = 0;
killEvents(event);
break;
}
else if (v>='A' && v<='Z') {
v = 'a'+v-'A'; // toggle case
}
else if (v>='a' && v<='z') {
v = 'A'+v-'a'; // toggle case
}
}
break;
}
if (c != v) {
name[cur] = v;
storageDirty(menuVerticalPositions[0] == 0 ? EE_MODEL : EE_GENERAL);
}
if (attr == ZCHAR) {
lcdDrawChar(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH);
}
else {
lcdDrawChar(x+editNameCursorPos*FW, y, v, ERASEBG|INVERS|FIXEDWIDTH);
}
}
else {
cur = 0;
}
editNameCursorPos = cur;
lcdNextPos = backupNextPos;
}
}
#endif
void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event)
{
u_int8int16_t weight;
MD_WEIGHT_TO_UNION(md, weight);
weight.word = GVAR_MENU_ITEM(x, y, weight.word, GV_RANGELARGE_WEIGHT_NEG, GV_RANGELARGE_WEIGHT, attr, 0, event);
MD_UNION_TO_WEIGHT(weight, md);
}
+2
View File
@@ -766,6 +766,8 @@ const luaL_Reg lcdLib[] = {
{ "drawPixmap", luaLcdDrawPixmap },
{ "drawScreenTitle", luaLcdDrawScreenTitle },
{ "drawCombobox", luaLcdDrawCombobox },
#else
{ "getLastPos", luaLcdGetLastPos },
#endif
{ NULL, NULL } /* sentinel */
};
+9
View File
@@ -237,7 +237,16 @@ char * getSwitchString(char * dest, swsrc_t idx)
}
else {
*s++ = 'S';
#if defined(PCBX7D)
if (swinfo.quot == 5)
*s++ = 'H';
else if (swinfo.quot == 4)
*s++ = 'F';
else
*s++ = 'A'+swinfo.quot;
#else
*s++ = 'A'+swinfo.quot;
#endif
}
*s++ = "\300-\301"[swinfo.rem];
*s = '\0';
+1
View File
@@ -38,6 +38,7 @@ set(GUI_SRC
bitmapbuffer.cpp
curves.cpp
bitmaps.cpp
radio_sdmanager.cpp
radio_hardware.cpp
model_inputs.cpp
model_mixes.cpp
+2 -2
View File
@@ -45,8 +45,8 @@ add_definitions(-DEEPROM_VARIANT=0)
set(GUI_SRC
${GUI_SRC}
model_inputs.cpp
model_mixes.cpp
model_input_edit.cpp
model_mix_edit.cpp
model_display.cpp
radio_diagkeys.cpp
radio_diaganas.cpp
+2 -2
View File
@@ -77,8 +77,8 @@ add_definitions(-DPCBTARANIS -DPPM_PIN_TIMER)
add_definitions(-DAUDIO -DVOICE -DRTCLOCK)
set(GUI_SRC ${GUI_SRC}
model_inputs.cpp
model_mixes.cpp
model_input_edit.cpp
model_mix_edit.cpp
model_display.cpp
radio_diagkeys.cpp
radio_diaganas.cpp
+1 -1
View File
@@ -80,7 +80,7 @@ void adcInit()
ADC1->SQR2 = (ADC_CHANNEL_POT4<<0) + (ADC_CHANNEL_SLIDER3<<5) + (ADC_CHANNEL_SLIDER4<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
ADC1->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT2<<20) + (ADC_CHANNEL_POT3<<25); // conversions 1 to 6
#elif defined(PCBX7D)
ADC1->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
ADC1->SQR2 = (ADC_CHANNEL_BATT<<0); // conversions 7 and more
ADC1->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<25) + (ADC_CHANNEL_POT2<<20); // conversions 1 to 6
#else
ADC1->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
@@ -112,7 +112,7 @@ void backlightInit()
BACKLIGHT_TIMER->PSC = BACKLIGHT_TIMER_FREQ / 50000 - 1; // 20us * 100 = 2ms => 500Hz
BACKLIGHT_TIMER->CCMR1 = TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2; // PWM
BACKLIGHT_TIMER->CCER = TIM_CCER_CC2E;
BACKLIGHT_TIMER->CCR2 = 0;
BACKLIGHT_TIMER->CCR2 = 100;
BACKLIGHT_TIMER->EGR = 0;
BACKLIGHT_TIMER->CR1 = TIM_CR1_CEN; // Counter enable
}
+2 -2
View File
@@ -320,8 +320,8 @@ void checkTrainerSettings()
uint16_t getBatteryVoltage()
{
int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose
int32_t instant_vbat = anaIn(TX_VOLTAGE); // using filtered ADC value on purpose
instant_vbat = (instant_vbat * BATT_SCALE * (128 + g_eeGeneral.txVoltageCalibration) ) / 26214;
instant_vbat += 20; // add 0.2V because of the diode TODO check if this is needed, but removal will beak existing calibrations!!!
instant_vbat += 20; // add 0.2V because of the diode TODO check if this is needed, but removal will beak existing calibrations!!!
return (uint16_t)instant_vbat;
}
-3
View File
@@ -394,9 +394,6 @@
#define ADC_GPIOC_PINS ADC_GPIO_PIN_BATT
#define ADC_CHANNEL_POT1 ADC_Channel_6
#define ADC_CHANNEL_POT2 ADC_Channel_8
#define ADC_CHANNEL_POT3 ADC_Channel_9
#define ADC_CHANNEL_SLIDER1 ADC_Channel_14
#define ADC_CHANNEL_SLIDER2 ADC_Channel_15
#define ADC_CHANNEL_BATT ADC_Channel_10
#else
#define ADC_GPIO_PIN_POT1 GPIO_Pin_6 // PA.06
+1 -1
View File
@@ -1022,7 +1022,7 @@
#define TR_FAILSAFESET "Failsafe setzen"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSORS"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Landescode"
#define TR_VOICELANG "Sprach-Ansage"
+5 -5
View File
@@ -632,7 +632,7 @@
#if defined(PCBFLAMENCO)
#define TR_POPUPS TR_EXIT "\010" TR_ENTER
#elif defined(PCBTARANIS)
#define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
#define TR_POPUPS TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
#else
#define TR_POPUPS TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
@@ -978,9 +978,9 @@
#define TR_PATH_TOO_LONG "Path too long"
#define TR_VIEW_TEXT "View text"
#define TR_FLASH_BOOTLOADER "Flash bootLoader"
#define TR_FLASH_EXTERNAL_DEVICE "Flash external device"
#define TR_FLASH_INTERNAL_MODULE "Flash internal module"
#define TR_WRITING "\032Writing..."
#define TR_FLASH_EXTERNAL_DEVICE TR("Flash ext. device", "Flash external device")
#define TR_FLASH_INTERNAL_MODULE TR("Flash int. module", "Flash internal module")
#define TR_WRITING TR("\14Writing...", "\032Writing...")
#define TR_CONFIRM_FORMAT "Confirm Format?"
#define TR_INTERNALRF "Internal RF"
#define TR_EXTERNALRF "External RF"
@@ -988,7 +988,7 @@
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSORS"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Country code"
#define TR_VOICELANG "Voice language"
+1 -1
View File
@@ -996,7 +996,7 @@
#define TR_FAILSAFESET "Failsafe instellen"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSORS"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Landcode"
#define TR_VOICELANG "Taal"