Bsongis/move everything (#3669)
* Directories moved * Directories moved * Directories moved * Directories moved * Directories moved * rename horus directories in gui to 480x272 * Directories moved * Rename taranis to 212x64 * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Fix x9e compile * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Directories moved - TARANIS target removed, it's now X9E / X9D+ / X9D * Minor improvement of path handling * Another bunch of files renamed :) * Another bunch of files renamed :) * Another bunch of files renamed :) * Another bunch of files renamed :) * Another bunch of files renamed :) * Rename 9x to 128x64 * Compilation fixes * Compilation fixes * Compilation fixes * Compilation fixes * Compilation fixes * Compilation fixes
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
const pm_uchar font_5x7[] PROGMEM = {
|
||||
#if defined (CPUARM)
|
||||
#include "font_05x07.lbm"
|
||||
#else
|
||||
#include "font_05x07_avr.lbm"
|
||||
#endif
|
||||
#if defined(TRANSLATIONS_DE)
|
||||
#include "font_de_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_CZ)
|
||||
#include "font_cz_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_ES)
|
||||
#include "font_es_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_FI)
|
||||
#include "font_fi_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_FR)
|
||||
#include "font_fr_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_IT)
|
||||
#include "font_it_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_PL)
|
||||
#include "font_pl_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_PT)
|
||||
#include "font_pt_05x07.lbm"
|
||||
#elif defined(TRANSLATIONS_SE)
|
||||
#include "font_se_05x07.lbm"
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(BOLD_SPECIFIC_FONT)
|
||||
const pm_uchar font_5x7_B[] PROGMEM = {
|
||||
#include "font_05x07_B_compressed.lbm"
|
||||
};
|
||||
#endif
|
||||
|
||||
#if !defined(BOOT)
|
||||
const pm_uchar font_10x14[] PROGMEM = {
|
||||
#include "font_10x14_compressed.lbm"
|
||||
#if defined(CPUARM)
|
||||
#if defined(TRANSLATIONS_DE)
|
||||
#include "font_de_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_CZ)
|
||||
#include "font_cz_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_ES)
|
||||
#include "font_es_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_FI)
|
||||
#include "font_fi_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_FR)
|
||||
#include "font_fr_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_IT)
|
||||
#include "font_it_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_PL)
|
||||
#include "font_pl_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_PT)
|
||||
#include "font_pt_10x14.lbm"
|
||||
#elif defined(TRANSLATIONS_SE)
|
||||
#include "font_se_10x14.lbm"
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM) && !defined(BOOT)
|
||||
const pm_uchar font_3x5[] PROGMEM = {
|
||||
#include "font_03x05.lbm"
|
||||
};
|
||||
const pm_uchar font_4x6[] PROGMEM = {
|
||||
#include "font_04x06.lbm"
|
||||
#if defined(TRANSLATIONS_DE)
|
||||
#include "font_de_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_CZ)
|
||||
#include "font_cz_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_ES)
|
||||
#include "font_es_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_FI)
|
||||
#include "font_fi_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_FR)
|
||||
#include "font_fr_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_IT)
|
||||
#include "font_it_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_PL)
|
||||
#include "font_pl_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_PT)
|
||||
#include "font_pt_04x06.lbm"
|
||||
#elif defined(TRANSLATIONS_SE)
|
||||
#include "font_se_04x06.lbm"
|
||||
#endif
|
||||
};
|
||||
|
||||
const pm_uchar font_8x10[] PROGMEM = {
|
||||
#include "font_08x10.lbm"
|
||||
#if defined(TRANSLATIONS_DE)
|
||||
#include "font_de_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_CZ)
|
||||
#include "font_cz_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_ES)
|
||||
#include "font_es_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_FI)
|
||||
#include "font_fi_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_FR)
|
||||
#include "font_fr_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_IT)
|
||||
#include "font_it_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_PL)
|
||||
#include "font_pl_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_PT)
|
||||
#include "font_pt_08x10.lbm"
|
||||
#elif defined(TRANSLATIONS_SE)
|
||||
#include "font_se_08x10.lbm"
|
||||
#endif
|
||||
};
|
||||
|
||||
const pm_uchar font_22x38_num[] PROGMEM = {
|
||||
#include "font_22x38_num.lbm"
|
||||
};
|
||||
|
||||
const pm_uchar font_4x6_extra[] PROGMEM = {
|
||||
#include "font_04x06_extra.lbm"
|
||||
};
|
||||
|
||||
const pm_uchar font_5x7_extra[] PROGMEM = {
|
||||
#include "font_05x07_extra.lbm"
|
||||
};
|
||||
|
||||
const pm_uchar font_10x14_extra[] PROGMEM = {
|
||||
#include "font_10x14_extra.lbm"
|
||||
};
|
||||
|
||||
#endif // defined(CPUARM) && !defined(BOOT)
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _GUI_H_
|
||||
#define _GUI_H_
|
||||
|
||||
#if defined(CPUARM)
|
||||
#include "gui_helpers.h"
|
||||
#endif
|
||||
|
||||
#include "lcd.h"
|
||||
#include "menus.h"
|
||||
|
||||
extern const pm_uchar sticks[] PROGMEM;
|
||||
|
||||
#define NUM_BODY_LINES (LCD_LINES-1)
|
||||
#define MENU_HEADER_HEIGHT FH
|
||||
#define MENU_INIT_VPOS 0
|
||||
#define DEFAULT_SCROLLBAR_X (LCD_W-1)
|
||||
|
||||
#define WCHART (LCD_H/2)
|
||||
#define X0 (LCD_W-WCHART-2)
|
||||
#define Y0 (LCD_H/2)
|
||||
|
||||
#if LCD_W >= 212
|
||||
#define MIXES_2ND_COLUMN (18*FW)
|
||||
#else
|
||||
#define MIXES_2ND_COLUMN (12*FW)
|
||||
#endif
|
||||
|
||||
void drawSplash();
|
||||
void drawScreenIndex(uint8_t index, uint8_t count, uint8_t attr);
|
||||
void drawStick(coord_t centrex, int16_t xval, int16_t yval);
|
||||
|
||||
#if !defined(CPUM64)
|
||||
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
|
||||
#endif
|
||||
|
||||
#define SET_SCROLLBAR_X(x)
|
||||
#define LOAD_MODEL_BITMAP()
|
||||
|
||||
#endif // _GUI_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LCD_H_
|
||||
#define _LCD_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define LCD_W 128
|
||||
#define LCD_H 64
|
||||
#define BOX_WIDTH 23
|
||||
#define coord_t uint8_t
|
||||
#define scoord_t int8_t
|
||||
#define CENTER
|
||||
#define CENTER_OFS 0
|
||||
#define CONTRAST_MIN 10
|
||||
#define CONTRAST_MAX 45
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define lcdint_t int32_t
|
||||
#define lcduint_t uint32_t
|
||||
#else
|
||||
#define lcdint_t int16_t
|
||||
#define lcduint_t uint16_t
|
||||
#endif
|
||||
|
||||
#define FW 6
|
||||
#define FWNUM 5
|
||||
#define FH 8
|
||||
|
||||
#define LCD_LINES (LCD_H/FH)
|
||||
#define LCD_COLS (LCD_W/FW)
|
||||
|
||||
/* lcd common flags */
|
||||
#define BLINK 0x01
|
||||
|
||||
/* lcd text flags */
|
||||
#define INVERS 0x02
|
||||
#if defined(BOLD_FONT)
|
||||
#define BOLD 0x40
|
||||
#else
|
||||
#define BOLD 0x00
|
||||
#endif
|
||||
|
||||
/* lcd putc flags */
|
||||
#define CONDENSED 0x08
|
||||
#define FIXEDWIDTH 0x10
|
||||
/* lcd puts flags */
|
||||
/* no 0x80 here because of "GV"1 which is aligned LEFT */
|
||||
/* no 0x10 here because of "MODEL"01 which uses LEADING0 */
|
||||
#if defined(CPUARM)
|
||||
#define BSS 0x00
|
||||
#else
|
||||
#define BSS 0x20
|
||||
#endif
|
||||
#define ZCHAR 0x80
|
||||
|
||||
/* lcd outdez flags */
|
||||
#define UNSIGN 0x08
|
||||
#define LEADING0 0x10
|
||||
#define PREC1 0x20
|
||||
#define PREC2 0x30
|
||||
#define MODE(flags) ((((int8_t)(flags) & 0x30) - 0x10) >> 4)
|
||||
#define LEFT 0x80 /* align left */
|
||||
#define RIGHT 0x00 /* fake */
|
||||
|
||||
/* line, rect, square flags */
|
||||
#define FORCE 0x02
|
||||
#define ERASE 0x04
|
||||
#define ROUND 0x08
|
||||
|
||||
/* telemetry flags */
|
||||
#define NO_UNIT 0x40
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define FONTSIZE(x) ((x) & 0x0700)
|
||||
#define TINSIZE 0x0100
|
||||
#define SMLSIZE 0x0200
|
||||
#define MIDSIZE 0x0300
|
||||
#define DBLSIZE 0x0400
|
||||
#define XXLSIZE 0x0500
|
||||
#define ERASEBG 0x8000
|
||||
#define VERTICAL 0x0800
|
||||
#else
|
||||
#define DBLSIZE 0x04
|
||||
#define MIDSIZE DBLSIZE
|
||||
#define SMLSIZE 0x00
|
||||
#define TINSIZE 0x00
|
||||
#define XXLSIZE 0x00
|
||||
#define ERASEBG 0x00
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define TIMEBLINK 0x1000
|
||||
#define TIMEHOUR 0x2000
|
||||
#define STREXPANDED 0x4000
|
||||
#else
|
||||
#define STREXPANDED 0x00
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define LcdFlags uint32_t
|
||||
#else
|
||||
#define LcdFlags uint8_t
|
||||
#endif
|
||||
|
||||
#define display_t uint8_t
|
||||
#define DISPLAY_BUFFER_SIZE (LCD_W*((LCD_H+7)/8))
|
||||
|
||||
extern display_t displayBuf[DISPLAY_BUFFER_SIZE];
|
||||
|
||||
#define lcdRefreshWait()
|
||||
|
||||
extern coord_t lcdLastPos;
|
||||
extern coord_t lcdNextPos;
|
||||
|
||||
#define DISPLAY_END (displayBuf + DISPLAY_BUFFER_SIZE)
|
||||
#define ASSERT_IN_DISPLAY(p) assert((p) >= displayBuf && (p) < DISPLAY_END)
|
||||
|
||||
#if defined(PCBSTD) && defined(VOICE)
|
||||
extern volatile uint8_t LcdLock ;
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
extern volatile uint8_t lcdLock ;
|
||||
extern volatile uint32_t lcdInputs ;
|
||||
#endif
|
||||
|
||||
#if defined(BOOT)
|
||||
// TODO quick & dirty :(
|
||||
typedef const unsigned char pm_uchar;
|
||||
typedef const char pm_char;
|
||||
#endif
|
||||
|
||||
void lcdDrawChar(coord_t x, coord_t y, const unsigned char c);
|
||||
void lcdDrawChar(coord_t x, coord_t y, const unsigned char c, LcdFlags flags);
|
||||
void lcdDrawText(coord_t x, coord_t y, const pm_char * s, LcdFlags flags);
|
||||
void lcdDrawTextAtIndex(coord_t x, coord_t y, const pm_char * s, uint8_t idx, LcdFlags flags);
|
||||
void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, unsigned char len, LcdFlags flags);
|
||||
void lcdDrawText(coord_t x, coord_t y, const pm_char * s);
|
||||
void lcdDrawSizedText(coord_t x, coord_t y, const pm_char * s, unsigned char len);
|
||||
void lcd_putsLeft(coord_t y, const pm_char * s);
|
||||
|
||||
#define lcd_putsCenter(y, s) lcdDrawText((LCD_W-sizeof(TR_##s)*FW+FW+1)/2, y, STR_##s)
|
||||
|
||||
#if defined(CPUARM)
|
||||
void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0);
|
||||
#else
|
||||
void lcdDrawHexNumber(coord_t x, coord_t y, uint16_t val);
|
||||
#endif
|
||||
|
||||
void lcdDrawNumber(coord_t x, coord_t y, lcdint_t val, LcdFlags mode, uint8_t len);
|
||||
void lcdDrawNumber(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0);
|
||||
void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val);
|
||||
|
||||
void drawStringWithIndex(coord_t x, coord_t y, const pm_char *str, uint8_t idx, LcdFlags att=0);
|
||||
void putsModelName(coord_t x, coord_t y, char *name, uint8_t id, LcdFlags att);
|
||||
void putsSwitches(coord_t x, coord_t y, int8_t swtch, LcdFlags att=0);
|
||||
void putsMixerSource(coord_t x, coord_t y, uint8_t idx, LcdFlags att=0);
|
||||
void putsFlightMode(coord_t x, coord_t y, int8_t idx, LcdFlags att=0);
|
||||
void drawCurveName(coord_t x, coord_t y, int8_t idx, LcdFlags att=0);
|
||||
void putsTimerMode(coord_t x, coord_t y, int8_t mode, LcdFlags att=0);
|
||||
void putsTrimMode(coord_t x, coord_t y, uint8_t phase, uint8_t idx, LcdFlags att);
|
||||
#if defined(ROTARY_ENCODERS)
|
||||
void putsRotaryEncoderMode(coord_t x, coord_t y, uint8_t phase, uint8_t idx, LcdFlags att);
|
||||
#endif
|
||||
|
||||
#define putsChn(x, y, idx, att) putsMixerSource(x, y, MIXSRC_CH1+idx-1, att)
|
||||
void putsChnLetter(coord_t x, coord_t y, uint8_t idx, LcdFlags attr);
|
||||
|
||||
void putsVolts(coord_t x, coord_t y, uint16_t volts, LcdFlags att);
|
||||
void putsVBat(coord_t x, coord_t y, LcdFlags att);
|
||||
|
||||
#if !defined(BOOT)
|
||||
void putsChannelValue(coord_t x, coord_t y, source_t channel, lcdint_t val, LcdFlags att=0);
|
||||
void putsChannel(coord_t x, coord_t y, source_t channel, LcdFlags att=0);
|
||||
void putsTelemetryChannelValue(coord_t x, coord_t y, uint8_t channel, lcdint_t val, LcdFlags att=0);
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define putstime_t int32_t
|
||||
#define FlightModesType uint16_t
|
||||
#else
|
||||
#define putstime_t int16_t
|
||||
#define FlightModesType uint8_t
|
||||
#endif
|
||||
|
||||
void putsRtcTime(coord_t x, coord_t y, LcdFlags att);
|
||||
void putsTimer(coord_t x, coord_t y, putstime_t tme, LcdFlags att, LcdFlags att2);
|
||||
|
||||
#define SOLID 0xff
|
||||
#define DOTTED 0x55
|
||||
|
||||
void lcdDrawPoint(coord_t x, coord_t y, LcdFlags att=0);
|
||||
void lcdMaskPoint(uint8_t *p, uint8_t mask, LcdFlags att=0);
|
||||
void lcdDrawSolidHorizontalLine(coord_t x, coord_t y, coord_t w, LcdFlags att=0);
|
||||
void lcdDrawHorizontalLine(coord_t x, coord_t y, coord_t w, uint8_t pat, LcdFlags att=0);
|
||||
void lcdDrawSolidVerticalLine(coord_t x, scoord_t y, scoord_t h);
|
||||
#if defined(CPUM64)
|
||||
void lcdDrawVerticalLine(coord_t x, scoord_t y, int8_t h, uint8_t pat);
|
||||
#else
|
||||
void lcdDrawVerticalLine(coord_t x, scoord_t y, scoord_t h, uint8_t pat, LcdFlags att=0);
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
void lcdDrawLine(coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
#endif
|
||||
|
||||
void lcdDrawFilledRect(coord_t x, scoord_t y, coord_t w, coord_t h, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
void lcdDrawRect(coord_t x, coord_t y, coord_t w, coord_t h, uint8_t pat=SOLID, LcdFlags att=0);
|
||||
|
||||
void lcdInvertLine(int8_t line);
|
||||
#define lcdInvertLastLine() lcdInvertLine(LCD_LINES-1)
|
||||
inline void lcdDrawSquare(coord_t x, coord_t y, coord_t w, LcdFlags att=0) { lcdDrawRect(x, y, w, w, SOLID, att); }
|
||||
|
||||
void lcdDrawTelemetryTopBar();
|
||||
|
||||
#define V_BAR(xx, yy, ll) \
|
||||
lcdDrawSolidVerticalLine(xx-1,yy-ll,ll); \
|
||||
lcdDrawSolidVerticalLine(xx ,yy-ll,ll); \
|
||||
lcdDrawSolidVerticalLine(xx+1,yy-ll,ll)
|
||||
|
||||
#if defined(PCBMEGA2560) && !defined(SIMU)
|
||||
void lcd_imgfar(coord_t x, coord_t y, const uint_farptr_t img, uint8_t idx, LcdFlags att); // progmem "far"
|
||||
#endif
|
||||
|
||||
void lcd_img(coord_t x, coord_t y, const pm_uchar * img, uint8_t idx, LcdFlags att=0);
|
||||
|
||||
void lcdSetRefVolt(unsigned char val);
|
||||
void lcdClear();
|
||||
void lcdSetContrast();
|
||||
void lcdInit();
|
||||
#define lcdOff()
|
||||
|
||||
void lcdRefresh();
|
||||
|
||||
#if defined(LCD_KS108)
|
||||
void lcdRefreshSide();
|
||||
#endif
|
||||
|
||||
#if defined(LCD_ST7920)
|
||||
uint8_t lcdRefresh_ST7920(uint8_t full);
|
||||
#define IS_LCD_REFRESH_ALLOWED() (0==lcdstate)
|
||||
#else
|
||||
#define IS_LCD_REFRESH_ALLOWED() (1)
|
||||
#endif
|
||||
|
||||
#if defined(BOOT)
|
||||
#define BLINK_ON_PHASE (0)
|
||||
#else
|
||||
#define BLINK_ON_PHASE (g_blinkTmr10ms & (1<<6))
|
||||
#endif
|
||||
|
||||
#endif // _LCD_H_
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#if defined(MAVLINK)
|
||||
#include "view_mavlink.h"
|
||||
#endif
|
||||
|
||||
uint8_t editDelay(const coord_t y, const uint8_t event, const uint8_t attr, const pm_char *str, uint8_t delay)
|
||||
{
|
||||
lcd_putsLeft(y, str);
|
||||
lcdDrawNumber(MIXES_2ND_COLUMN, y, (10/DELAY_STEP)*delay, attr|PREC1|LEFT);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, delay, DELAY_MAX);
|
||||
return delay;
|
||||
}
|
||||
|
||||
uint8_t s_copyMode = 0;
|
||||
int8_t s_copySrcRow;
|
||||
int8_t s_copyTgtOfs;
|
||||
|
||||
#if defined(CPUM64)
|
||||
#define editNameCursorPos menuHorizontalPosition
|
||||
#else
|
||||
static uint8_t editNameCursorPos = 0;
|
||||
#endif
|
||||
|
||||
void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uint8_t active)
|
||||
{
|
||||
#if defined(CPUM64)
|
||||
// in order to save flash
|
||||
lcd_putsLeft(y, STR_NAME);
|
||||
#endif
|
||||
|
||||
uint8_t mode = 0;
|
||||
if (active) {
|
||||
if (s_editMode <= 0)
|
||||
mode = INVERS + FIXEDWIDTH;
|
||||
else
|
||||
mode = FIXEDWIDTH;
|
||||
}
|
||||
|
||||
lcdDrawSizedText(x, y, name, size, ZCHAR | mode);
|
||||
|
||||
if (active) {
|
||||
uint8_t cur = editNameCursorPos;
|
||||
if (s_editMode > 0) {
|
||||
int8_t c = name[cur];
|
||||
int8_t v = c;
|
||||
|
||||
if (p1valdiff || IS_ROTARY_RIGHT(event) || IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP)
|
||||
|| event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP)) {
|
||||
v = checkIncDec(event, abs(v), 0, ZCHAR_MAX, 0);
|
||||
if (c <= 0) v = -v;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
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;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_BREAK(KEY_LEFT):
|
||||
if (cur>0) cur--;
|
||||
break;
|
||||
case EVT_KEY_BREAK(KEY_RIGHT):
|
||||
if (cur<size-1) cur++;
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LONG:
|
||||
if (v==0) {
|
||||
s_editMode = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
#endif
|
||||
|
||||
case EVT_KEY_LONG(KEY_LEFT):
|
||||
case EVT_KEY_LONG(KEY_RIGHT):
|
||||
if (v>=-26 && v<=26) {
|
||||
v = -v; // toggle case
|
||||
if (event==EVT_KEY_LONG(KEY_LEFT))
|
||||
killEvents(KEY_LEFT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (c != v) {
|
||||
name[cur] = v;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
lcdDrawChar(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH);
|
||||
}
|
||||
else {
|
||||
cur = 0;
|
||||
}
|
||||
editNameCursorPos = cur;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(CPUM64)
|
||||
void editSingleName(coord_t x, coord_t y, const pm_char *label, char *name, uint8_t size, uint8_t event, uint8_t active)
|
||||
{
|
||||
lcd_putsLeft(y, label);
|
||||
editName(x, y, name, size, event, active);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t s_currIdx;
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#if defined(CPUARM)
|
||||
void menuGeneralCustomFunctions(uint8_t event)
|
||||
{
|
||||
MENU(STR_MENUGLOBALFUNCS, menuTabGeneral, e_GeneralCustomFunctions, NUM_CFN+1, {0, NAVIGATION_LINE_BY_LINE|4/*repeated*/});
|
||||
return menuCustomFunctions(event, g_eeGeneral.customFn, &globalFunctionsContext);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
MenuHandlerFunc menuHandlers[5];
|
||||
uint8_t menuEvent = 0;
|
||||
uint8_t menuVerticalPositions[4];
|
||||
uint8_t menuLevel = 0;
|
||||
|
||||
void popMenu()
|
||||
{
|
||||
assert(menuLevel>0);
|
||||
menuLevel = menuLevel-1;
|
||||
menuEvent = EVT_ENTRY_UP;
|
||||
}
|
||||
|
||||
void chainMenu(MenuHandlerFunc newMenu)
|
||||
{
|
||||
menuHandlers[menuLevel] = newMenu;
|
||||
menuEvent = EVT_ENTRY;
|
||||
}
|
||||
|
||||
void pushMenu(MenuHandlerFunc newMenu)
|
||||
{
|
||||
killEvents(KEY_ENTER);
|
||||
|
||||
if (menuLevel == 0) {
|
||||
if (newMenu == menuGeneralSetup)
|
||||
menuVerticalPositions[0] = 1;
|
||||
if (newMenu == menuModelSelect)
|
||||
menuVerticalPositions[0] = 0;
|
||||
}
|
||||
else {
|
||||
menuVerticalPositions[menuLevel] = menuVerticalPosition;
|
||||
}
|
||||
|
||||
menuLevel++;
|
||||
|
||||
assert(menuLevel < DIM(menuHandlers));
|
||||
|
||||
menuHandlers[menuLevel] = newMenu;
|
||||
menuEvent = EVT_ENTRY;
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
void menuModelNotes(uint8_t event)
|
||||
{
|
||||
if (event == EVT_ENTRY) {
|
||||
strcpy(s_text_file, MODELS_PATH "/");
|
||||
char *buf = strcat_modelname(&s_text_file[sizeof(MODELS_PATH)], g_eeGeneral.currModel);
|
||||
strcpy(buf, TEXT_EXT);
|
||||
}
|
||||
|
||||
menuTextView(event);
|
||||
}
|
||||
|
||||
void pushModelNotes()
|
||||
{
|
||||
pushMenu(menuModelNotes);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,565 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _MENUS_H_
|
||||
#define _MENUS_H_
|
||||
|
||||
#define MENUS_SCROLLBAR_WIDTH 0
|
||||
#define MENU_COLUMNS 1
|
||||
#define COLUMN_X 0
|
||||
#define lcd_putsColumnLeft(x, y, str) lcd_putsLeft(y, str)
|
||||
|
||||
// Menus related stuff ...
|
||||
#if defined(SDCARD)
|
||||
typedef uint16_t vertpos_t;
|
||||
#else
|
||||
typedef uint8_t vertpos_t;
|
||||
#endif
|
||||
|
||||
typedef uint8_t check_event_t;
|
||||
#define horzpos_t uint8_t
|
||||
|
||||
#if defined(CPUARM)
|
||||
extern tmr10ms_t menuEntryTime;
|
||||
#endif
|
||||
|
||||
extern vertpos_t menuVerticalPosition;
|
||||
extern horzpos_t menuHorizontalPosition;
|
||||
extern vertpos_t menuVerticalOffset;
|
||||
extern uint8_t calibrationState;
|
||||
|
||||
// Temporary no highlight
|
||||
extern uint8_t noHighlightCounter;
|
||||
#define NO_HIGHLIGHT() (noHighlightCounter > 0)
|
||||
#define START_NO_HIGHLIGHT() do { noHighlightCounter = 25; } while(0)
|
||||
|
||||
void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr);
|
||||
|
||||
typedef void (* MenuHandlerFunc)(uint8_t event);
|
||||
|
||||
extern MenuHandlerFunc menuHandlers[5];
|
||||
extern uint8_t menuVerticalPositions[4];
|
||||
extern uint8_t menuLevel;
|
||||
extern uint8_t menuEvent;
|
||||
|
||||
/// goto given Menu, but substitute current menu in menuStack
|
||||
void chainMenu(MenuHandlerFunc newMenu);
|
||||
/// goto given Menu, store current menu in menuStack
|
||||
void pushMenu(MenuHandlerFunc newMenu);
|
||||
/// return to last menu in menustack
|
||||
void popMenu();
|
||||
///deliver address of last menu which was popped from
|
||||
inline MenuHandlerFunc lastPopMenu()
|
||||
{
|
||||
return menuHandlers[menuLevel+1];
|
||||
}
|
||||
|
||||
void drawPotsBars();
|
||||
void doMainScreenGraphics();
|
||||
void menuFirstCalib(uint8_t event);
|
||||
|
||||
void onMainViewMenu(const char * result);
|
||||
void menuMainView(uint8_t event);
|
||||
void menuTelemetryFrsky(uint8_t event);
|
||||
void menuTelemetryMavlinkSetup(uint8_t event);
|
||||
|
||||
void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFunctionsContext * functionsContext);
|
||||
|
||||
enum EnumTabDiag
|
||||
{
|
||||
e_Setup,
|
||||
CASE_SDCARD(e_Sd)
|
||||
CASE_CPUARM(e_GeneralCustomFunctions)
|
||||
e_Trainer,
|
||||
e_Vers,
|
||||
e_Keys,
|
||||
e_Ana,
|
||||
CASE_CPUARM(e_Hardware)
|
||||
e_Calib
|
||||
};
|
||||
|
||||
void menuGeneralSetup(uint8_t event);
|
||||
void menuGeneralSdManager(uint8_t event);
|
||||
void menuGeneralCustomFunctions(uint8_t event);
|
||||
void menuGeneralTrainer(uint8_t event);
|
||||
void menuGeneralVersion(uint8_t event);
|
||||
void menuGeneralDiagKeys(uint8_t event);
|
||||
void menuGeneralDiagAna(uint8_t event);
|
||||
void menuGeneralHardware(uint8_t event);
|
||||
void menuGeneralCalib(uint8_t event);
|
||||
|
||||
static const MenuHandlerFunc menuTabGeneral[] PROGMEM = {
|
||||
menuGeneralSetup,
|
||||
CASE_SDCARD(menuGeneralSdManager)
|
||||
CASE_CPUARM(menuGeneralCustomFunctions)
|
||||
menuGeneralTrainer,
|
||||
menuGeneralVersion,
|
||||
menuGeneralDiagKeys,
|
||||
menuGeneralDiagAna,
|
||||
CASE_CPUARM(menuGeneralHardware)
|
||||
menuGeneralCalib
|
||||
};
|
||||
|
||||
enum EnumTabModel {
|
||||
e_ModelSelect,
|
||||
e_ModelSetup,
|
||||
CASE_HELI(e_Heli)
|
||||
CASE_FLIGHT_MODES(e_FlightModesAll)
|
||||
e_InputsAll,
|
||||
e_MixAll,
|
||||
e_Limits,
|
||||
CASE_CURVES(e_CurvesAll)
|
||||
e_LogicalSwitches,
|
||||
e_CustomFunctions,
|
||||
CASE_FRSKY(e_Telemetry)
|
||||
CASE_MAVLINK(e_MavSetup)
|
||||
CASE_TEMPLATES(e_Templates)
|
||||
};
|
||||
|
||||
void menuModelSelect(uint8_t event);
|
||||
void menuModelSetup(uint8_t event);
|
||||
void menuModelHeli(uint8_t event);
|
||||
void menuModelFlightModesAll(uint8_t event);
|
||||
void menuModelExposAll(uint8_t event);
|
||||
void menuModelMixAll(uint8_t event);
|
||||
void menuModelLimits(uint8_t event);
|
||||
void menuModelCurvesAll(uint8_t event);
|
||||
void menuModelCurveOne(uint8_t event);
|
||||
void menuModelGVars(uint8_t event);
|
||||
void menuModelLogicalSwitches(uint8_t event);
|
||||
void menuModelCustomFunctions(uint8_t event);
|
||||
void menuModelTelemetry(uint8_t event);
|
||||
void menuModelTemplates(uint8_t event);
|
||||
void menuModelExpoOne(uint8_t event);
|
||||
|
||||
static const MenuHandlerFunc menuTabModel[] PROGMEM = {
|
||||
menuModelSelect,
|
||||
menuModelSetup,
|
||||
CASE_HELI(menuModelHeli)
|
||||
CASE_FLIGHT_MODES(menuModelFlightModesAll)
|
||||
menuModelExposAll,
|
||||
menuModelMixAll,
|
||||
menuModelLimits,
|
||||
CASE_CURVES(menuModelCurvesAll)
|
||||
menuModelLogicalSwitches,
|
||||
menuModelCustomFunctions,
|
||||
CASE_FRSKY(menuModelTelemetry)
|
||||
CASE_MAVLINK(menuTelemetryMavlinkSetup)
|
||||
CASE_TEMPLATES(menuModelTemplates)
|
||||
};
|
||||
|
||||
void menuStatisticsView(uint8_t event);
|
||||
void menuStatisticsDebug(uint8_t event);
|
||||
void menuAboutView(uint8_t event);
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
void menuTraceBuffer(uint8_t event);
|
||||
#endif
|
||||
|
||||
#if !defined(CPUM64)
|
||||
void drawSlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr);
|
||||
#elif defined(GRAPHICS)
|
||||
void display5posSlider(coord_t x, coord_t y, uint8_t value, uint8_t attr);
|
||||
#define drawSlider(x, y, value, max, attr) lcdDrawNumber(x, y, value, attr|LEFT)
|
||||
#else
|
||||
#define drawSlider(x, y, value, max, attr) lcdDrawNumber(x, y, value, attr|LEFT)
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_POT1)
|
||||
extern int16_t p1valdiff;
|
||||
#else
|
||||
#define p1valdiff 0
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_POT2)
|
||||
extern int8_t p2valdiff;
|
||||
#else
|
||||
#define p2valdiff 0
|
||||
#endif
|
||||
|
||||
extern int8_t checkIncDec_Ret; // global helper vars
|
||||
|
||||
#define EDIT_SELECT_MENU -1
|
||||
#define EDIT_SELECT_FIELD 0
|
||||
#define EDIT_MODIFY_FIELD 1
|
||||
#define EDIT_MODIFY_STRING 2
|
||||
extern int8_t s_editMode; // global editmode
|
||||
|
||||
// checkIncDec flags
|
||||
#define EE_GENERAL 0x01
|
||||
#define EE_MODEL 0x02
|
||||
#define NO_INCDEC_MARKS 0x04
|
||||
#define INCDEC_SWITCH 0x08
|
||||
#define INCDEC_SOURCE 0x10
|
||||
#define INCDEC_REP10 0x40
|
||||
#define NO_DBLKEYS 0x80
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define INCDEC_DECLARE_VARS(f) uint8_t incdecFlag = (f); IsValueAvailable isValueAvailable = NULL
|
||||
#define INCDEC_SET_FLAG(f) incdecFlag = (f)
|
||||
#define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn
|
||||
#define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable)
|
||||
#elif defined(CPUM64)
|
||||
#define INCDEC_DECLARE_VARS(f)
|
||||
#define INCDEC_SET_FLAG(f)
|
||||
#define INCDEC_ENABLE_CHECK(fn)
|
||||
#define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, EE_MODEL)
|
||||
#else
|
||||
#define INCDEC_DECLARE_VARS(f) uint8_t incdecFlag = (f)
|
||||
#define INCDEC_SET_FLAG(f) incdecFlag = (f)
|
||||
#define INCDEC_ENABLE_CHECK(fn)
|
||||
#define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag)
|
||||
#endif
|
||||
|
||||
// mawrow special values
|
||||
#define TITLE_ROW ((uint8_t)-1)
|
||||
#define HIDDEN_ROW ((uint8_t)-2)
|
||||
|
||||
#if defined(CPUARM)
|
||||
struct CheckIncDecStops {
|
||||
const int count;
|
||||
const int stops[];
|
||||
int min() const
|
||||
{
|
||||
return stops[0];
|
||||
}
|
||||
int max() const
|
||||
{
|
||||
return stops[count-1];
|
||||
}
|
||||
bool contains(int value) const
|
||||
{
|
||||
for (int i=0; i<count; ++i) {
|
||||
int stop = stops[i];
|
||||
if (value == stop)
|
||||
return true;
|
||||
else if (value < stop)
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
extern const CheckIncDecStops &stops100;
|
||||
extern const CheckIncDecStops &stops1000;
|
||||
extern const CheckIncDecStops &stopsSwitch;
|
||||
#define INIT_STOPS(var, ...) \
|
||||
const int _ ## var[] = { __VA_ARGS__ }; \
|
||||
const CheckIncDecStops &var = (const CheckIncDecStops&)_ ## var;
|
||||
#define CATEGORY_END(val) \
|
||||
(val), (val+1)
|
||||
int checkIncDec(unsigned int event, int val, int i_min, int i_max, unsigned int i_flags=0, IsValueAvailable isValueAvailable=NULL, const CheckIncDecStops &stops=stops100);
|
||||
#else
|
||||
int16_t checkIncDec(uint8_t event, int16_t i_pval, int16_t i_min, int16_t i_max, uint8_t i_flags=0);
|
||||
#endif
|
||||
|
||||
int8_t checkIncDecMovedSwitch(int8_t val);
|
||||
|
||||
#if defined(CPUM64)
|
||||
int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max);
|
||||
int8_t checkIncDecModelZero(uint8_t event, int8_t i_val, int8_t i_max);
|
||||
int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max);
|
||||
#else
|
||||
#define checkIncDecModel(event, i_val, i_min, i_max) checkIncDec(event, i_val, i_min, i_max, EE_MODEL)
|
||||
#define checkIncDecModelZero(event, i_val, i_max) checkIncDec(event, i_val, 0, i_max, EE_MODEL)
|
||||
#define checkIncDecGen(event, i_val, i_min, i_max) checkIncDec(event, i_val, i_min, i_max, EE_GENERAL)
|
||||
#endif
|
||||
|
||||
#define CHECK_INCDEC_MODELVAR(event, var, min, max) \
|
||||
var = checkIncDecModel(event,var,min,max)
|
||||
|
||||
#define CHECK_INCDEC_MODELVAR_ZERO(event, var, max) \
|
||||
var = checkIncDecModelZero(event,var,max)
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define CHECK_INCDEC_MODELVAR_CHECK(event, var, min, max, check) \
|
||||
var = checkIncDec(event, var, min, max, EE_MODEL, check)
|
||||
#define CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, var, max, check) \
|
||||
var = checkIncDec(event, var, 0, max, EE_MODEL, check)
|
||||
#else
|
||||
#define CHECK_INCDEC_MODELVAR_CHECK(event, var, min, max, check) \
|
||||
var = checkIncDec(event, var, min, max, EE_MODEL)
|
||||
#define CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, var, max, check) \
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, var, max)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER))
|
||||
#define CHECK_INCDEC_SWITCH(event, var, min, max, flags, available) \
|
||||
var = checkIncDec(event, var, min, max, (flags)|INCDEC_SWITCH, available)
|
||||
#define CHECK_INCDEC_MODELSWITCH(event, var, min, max, available) \
|
||||
CHECK_INCDEC_SWITCH(event, var, min, max, EE_MODEL, available)
|
||||
#elif defined(AUTOSWITCH)
|
||||
#define AUTOSWITCH_ENTER_LONG() (attr && event==EVT_KEY_LONG(KEY_ENTER))
|
||||
#define CHECK_INCDEC_SWITCH(event, var, min, max, flags, available) \
|
||||
var = checkIncDec(event, var, min, max, (flags)|INCDEC_SWITCH)
|
||||
#define CHECK_INCDEC_MODELSWITCH(event, var, min, max, available) \
|
||||
CHECK_INCDEC_SWITCH(event, var, min, max, EE_MODEL, available)
|
||||
#else
|
||||
#define AUTOSWITCH_ENTER_LONG() (0)
|
||||
#define CHECK_INCDEC_SWITCH(event, var, min, max, flags, available) \
|
||||
CHECK_INCDEC_MODELVAR(event, var, min, max)
|
||||
#define CHECK_INCDEC_MODELSWITCH(event, var, min, max, available) \
|
||||
CHECK_INCDEC_MODELVAR(event, var, min, max)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \
|
||||
var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isSourceAvailable)
|
||||
#elif defined(AUTOSOURCE)
|
||||
#define CHECK_INCDEC_MODELSOURCE(event, var, min, max) \
|
||||
var = checkIncDec(event,var,min,max,EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS)
|
||||
#else
|
||||
#define CHECK_INCDEC_MODELSOURCE CHECK_INCDEC_MODELVAR
|
||||
#endif
|
||||
|
||||
#define CHECK_INCDEC_GENVAR(event, var, min, max) \
|
||||
var = checkIncDecGen(event, var, min, max)
|
||||
|
||||
#define NAVIGATION_LINE_BY_LINE 0
|
||||
#define CURSOR_ON_LINE() (0)
|
||||
|
||||
void check(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(check_event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuTabSize, vertpos_t maxrow);
|
||||
void check_submenu_simple(check_event_t event, uint8_t maxrow);
|
||||
|
||||
void title(const pm_char * s);
|
||||
#define TITLE(str) title(str)
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define MENU_TAB(...) const uint8_t mstate_tab[] = __VA_ARGS__
|
||||
#else
|
||||
#define MENU_TAB(...) static const pm_uint8_t mstate_tab[] PROGMEM = __VA_ARGS__
|
||||
#endif
|
||||
|
||||
#define MENU_CHECK(tab, menu, lines_count) \
|
||||
check(event, menu, tab, DIM(tab), mstate_tab, DIM(mstate_tab)-1, (lines_count)-1)
|
||||
|
||||
#define MENU(title, tab, menu, lines_count, ...) \
|
||||
MENU_TAB(__VA_ARGS__); \
|
||||
MENU_CHECK(tab, menu, lines_count); \
|
||||
TITLE(title)
|
||||
|
||||
#define SIMPLE_MENU_NOTITLE(tab, menu, lines_count) \
|
||||
check_simple(event, menu, tab, DIM(tab), (lines_count)-1);
|
||||
|
||||
#define SIMPLE_MENU(title, tab, menu, lines_count) \
|
||||
SIMPLE_MENU_NOTITLE(tab, menu, lines_count); \
|
||||
TITLE(title)
|
||||
|
||||
#define SUBMENU_NOTITLE(lines_count, ...) { \
|
||||
MENU_TAB(__VA_ARGS__); \
|
||||
check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, (lines_count)-1); \
|
||||
}
|
||||
|
||||
#define SUBMENU(title, lines_count, ...) \
|
||||
MENU_TAB(__VA_ARGS__); \
|
||||
check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, (lines_count)-1); \
|
||||
TITLE(title)
|
||||
|
||||
#define SIMPLE_SUBMENU_NOTITLE(lines_count) \
|
||||
check_submenu_simple(event, (lines_count)-1);
|
||||
|
||||
#define SIMPLE_SUBMENU(title, lines_count) \
|
||||
SIMPLE_SUBMENU_NOTITLE(lines_count); \
|
||||
TITLE(title)
|
||||
|
||||
#if defined(CPUARM)
|
||||
typedef int select_menu_value_t;
|
||||
#else
|
||||
typedef int8_t select_menu_value_t;
|
||||
#endif
|
||||
|
||||
select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event);
|
||||
uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event);
|
||||
int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event);
|
||||
|
||||
#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = editCheckBox(value, x, y, label, attr, event)
|
||||
|
||||
#if defined(CPUARM) && defined(GVARS)
|
||||
#define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, editflags, event)
|
||||
#else
|
||||
#define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, event)
|
||||
#endif
|
||||
|
||||
#if defined(GVARS)
|
||||
#if defined(CPUARM)
|
||||
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event);
|
||||
#else
|
||||
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event); // @@@ open.20.fsguruh
|
||||
#endif
|
||||
#define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0)
|
||||
#else
|
||||
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event);
|
||||
#define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v)
|
||||
#endif
|
||||
|
||||
void editName(coord_t x, coord_t y, char *name, uint8_t size, uint8_t event, uint8_t active);
|
||||
|
||||
#if defined(CPUM64)
|
||||
#define editSingleName(x, y, label, name, size, event, active) editName(x, y, name, size, event, active)
|
||||
#else
|
||||
void editSingleName(coord_t x, coord_t y, const pm_char *label, char *name, uint8_t size, uint8_t event, uint8_t active);
|
||||
#endif
|
||||
|
||||
uint8_t editDelay(const coord_t y, const uint8_t event, const uint8_t attr, const pm_char * str, uint8_t delay);
|
||||
#define EDIT_DELAY(x, y, event, attr, str, delay) editDelay(y, event, attr, str, delay)
|
||||
|
||||
#define WARNING_TYPE_ASTERISK 0
|
||||
#define WARNING_TYPE_CONFIRM 1
|
||||
#define WARNING_TYPE_INPUT 2
|
||||
|
||||
extern const pm_char * warningText;
|
||||
extern const pm_char * warningInfoText;
|
||||
extern uint8_t warningInfoLength;
|
||||
extern uint8_t warningResult;
|
||||
extern uint8_t warningType;
|
||||
|
||||
#define COPY_MODE 1
|
||||
#define MOVE_MODE 2
|
||||
extern uint8_t s_copyMode;
|
||||
extern int8_t s_copySrcRow;
|
||||
extern int8_t s_copyTgtOfs;
|
||||
extern uint8_t s_currIdx;
|
||||
extern uint8_t s_curveChan;
|
||||
|
||||
#define MENU_X 10
|
||||
#define MENU_Y 16
|
||||
#define MENU_W LCD_W-(2*MENU_X)
|
||||
#define WARNING_LINE_LEN 20
|
||||
#define WARNING_LINE_X 16
|
||||
#define WARNING_LINE_Y 3*FH
|
||||
|
||||
void displayBox();
|
||||
void displayPopup(const pm_char * pstr);
|
||||
void displayWarning(uint8_t event);
|
||||
|
||||
#if defined(CPUARM)
|
||||
extern void (*popupFunc)(uint8_t event);
|
||||
extern int16_t warningInputValue;
|
||||
extern int16_t warningInputValueMin;
|
||||
extern int16_t warningInputValueMax;
|
||||
extern uint8_t warningInfoFlags;
|
||||
#endif
|
||||
|
||||
#if !defined(GUI)
|
||||
#define DISPLAY_WARNING(...)
|
||||
#define POPUP_WARNING(...)
|
||||
#define POPUP_CONFIRMATION(...)
|
||||
#define POPUP_INPUT(...)
|
||||
#define WARNING_INFO_FLAGS 0
|
||||
#define SET_WARNING_INFO(...)
|
||||
#elif defined(CPUARM)
|
||||
#define DISPLAY_WARNING (*popupFunc)
|
||||
#define POPUP_WARNING(s) (warningText = s, warningInfoText = 0, popupFunc = displayWarning)
|
||||
#define POPUP_CONFIRMATION(s) (warningText = s, warningType = WARNING_TYPE_CONFIRM, warningInfoText = 0, popupFunc = displayWarning)
|
||||
#define POPUP_INPUT(s, func, start, min, max) (warningText = s, warningType = WARNING_TYPE_INPUT, popupFunc = func, warningInputValue = start, warningInputValueMin = min, warningInputValueMax = max)
|
||||
#define WARNING_INFO_FLAGS warningInfoFlags
|
||||
#define SET_WARNING_INFO(info, len, flags) (warningInfoText = info, warningInfoLength = len, warningInfoFlags = flags)
|
||||
#else
|
||||
#define DISPLAY_WARNING displayWarning
|
||||
#define POPUP_WARNING(s) warningText = s
|
||||
#define POPUP_CONFIRMATION(s) (warningText = s, warningType = WARNING_TYPE_CONFIRM)
|
||||
#define WARNING_INFO_FLAGS ZCHAR
|
||||
#define SET_WARNING_INFO(info, len, flags) (warningInfoText = info, warningInfoLength = len)
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD) || (defined(ROTARY_ENCODER_NAVIGATION) && !defined(CPUM64))
|
||||
#define NAVIGATION_MENUS
|
||||
#define POPUP_MENU_ADD_ITEM(s) popupMenuItems[popupMenuNoItems++] = s
|
||||
#define POPUP_MENU_START(func) do { popupMenuHandler = (func); AUDIO_KEY_PRESS(); } while(0)
|
||||
#define POPUP_MENU_MAX_LINES 6
|
||||
#define MENU_MAX_DISPLAY_LINES POPUP_MENU_MAX_LINES
|
||||
#if defined(SDCARD)
|
||||
#define POPUP_MENU_ADD_SD_ITEM(s) POPUP_MENU_ADD_ITEM(s)
|
||||
#else
|
||||
#define POPUP_MENU_ADD_SD_ITEM(s)
|
||||
#endif
|
||||
#define MENU_LINE_LENGTH (LEN_MODEL_NAME+1)
|
||||
#define POPUP_MENU_ITEMS_FROM_BSS() (popupMenuFlags = BSS)
|
||||
extern const char *popupMenuItems[POPUP_MENU_MAX_LINES];
|
||||
extern uint16_t popupMenuNoItems;
|
||||
extern uint8_t popupMenuFlags;
|
||||
extern uint16_t popupMenuOffset;
|
||||
const char * displayPopupMenu(uint8_t event);
|
||||
extern void (*popupMenuHandler)(const char *result);
|
||||
#else
|
||||
#define popupMenuNoItems 0
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD)
|
||||
#define STATUS_LINE_LENGTH 32
|
||||
extern char statusLineMsg[STATUS_LINE_LENGTH];
|
||||
void showStatusLine();
|
||||
void drawStatusLine();
|
||||
#else
|
||||
#define drawStatusLine()
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define TEXT_FILENAME_MAXLEN 40
|
||||
extern char s_text_file[TEXT_FILENAME_MAXLEN];
|
||||
void menuTextView(uint8_t event);
|
||||
void pushMenuTextView(const char *filename);
|
||||
void pushModelNotes();
|
||||
#endif
|
||||
|
||||
#define LABEL(...) (uint8_t)-1
|
||||
|
||||
#define CURSOR_MOVED_LEFT(event) (IS_ROTARY_LEFT(event) || EVT_KEY_MASK(event) == KEY_LEFT)
|
||||
#define CURSOR_MOVED_RIGHT(event) (IS_ROTARY_RIGHT(event) || EVT_KEY_MASK(event) == KEY_RIGHT)
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
#define IS_ROTARY_LEFT(evt) (evt == EVT_ROTARY_LEFT)
|
||||
#define IS_ROTARY_RIGHT(evt) (evt == EVT_ROTARY_RIGHT)
|
||||
#define IS_ROTARY_BREAK(evt) (evt == EVT_ROTARY_BREAK)
|
||||
#define IS_ROTARY_LONG(evt) (evt == EVT_ROTARY_LONG)
|
||||
#define IS_ROTARY_EVENT(evt) (EVT_KEY_MASK(evt) >= 0x0e)
|
||||
#define CASE_EVT_ROTARY_BREAK case EVT_ROTARY_BREAK:
|
||||
#define CASE_EVT_ROTARY_LONG case EVT_ROTARY_LONG:
|
||||
#define CASE_EVT_ROTARY_LEFT case EVT_ROTARY_LEFT:
|
||||
#define CASE_EVT_ROTARY_RIGHT case EVT_ROTARY_RIGHT:
|
||||
void repeatLastCursorMove(uint8_t event);
|
||||
#define REPEAT_LAST_CURSOR_MOVE() { if (EVT_KEY_MASK(event) >= 0x0e) putEvent(event); else repeatLastCursorMove(event); }
|
||||
#define MOVE_CURSOR_FROM_HERE() if (menuHorizontalPosition > 0) REPEAT_LAST_CURSOR_MOVE()
|
||||
#else
|
||||
#define IS_ROTARY_LEFT(evt) (0)
|
||||
#define IS_ROTARY_RIGHT(evt) (0)
|
||||
#define IS_ROTARY_BREAK(evt) (0)
|
||||
#define IS_ROTARY_LONG(evt) (0)
|
||||
#define IS_ROTARY_EVENT(evt) (0)
|
||||
#define CASE_EVT_ROTARY_BREAK
|
||||
#define CASE_EVT_ROTARY_LONG
|
||||
#define CASE_EVT_ROTARY_LEFT
|
||||
#define CASE_EVT_ROTARY_RIGHT
|
||||
void repeatLastCursorMove(uint8_t event);
|
||||
#define REPEAT_LAST_CURSOR_MOVE() repeatLastCursorMove(event)
|
||||
#define MOVE_CURSOR_FROM_HERE() REPEAT_LAST_CURSOR_MOVE()
|
||||
#endif
|
||||
|
||||
#define POS_HORZ_INIT(posVert) 0
|
||||
#define EDIT_MODE_INIT -1
|
||||
|
||||
typedef int16_t (*FnFuncP) (int16_t x);
|
||||
void drawFunction(FnFuncP fn, uint8_t offset=0);
|
||||
|
||||
uint8_t switchToMix(uint8_t source);
|
||||
|
||||
void deleteExpoMix(uint8_t expo, uint8_t idx);
|
||||
|
||||
#endif // _MENUS_H_
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* 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 s_curveChan;
|
||||
|
||||
int16_t curveFn(int16_t x)
|
||||
{
|
||||
return applyCustomCurve(x, s_curveChan);
|
||||
}
|
||||
|
||||
struct point_t {
|
||||
coord_t x;
|
||||
coord_t y;
|
||||
};
|
||||
|
||||
point_t getPoint(uint8_t i)
|
||||
{
|
||||
point_t result = {0, 0};
|
||||
CurveInfo crv = curveInfo(s_curveChan);
|
||||
int8_t *points = crv.crv;
|
||||
bool custom = crv.custom;
|
||||
uint8_t count = crv.points;
|
||||
if (i < count) {
|
||||
result.x = X0-1-WCHART+i*WCHART/(count/2);
|
||||
result.y = (LCD_H-1) - (100 + points[i]) * (LCD_H-1) / 200;
|
||||
if (custom && i>0 && i<count-1)
|
||||
result.x = X0-1-WCHART + (100 + (100 + points[count+i-1]) * (2*WCHART)) / 200;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DrawCurve(uint8_t offset=0)
|
||||
{
|
||||
drawFunction(curveFn, offset);
|
||||
|
||||
uint8_t i = 0;
|
||||
do {
|
||||
point_t point = getPoint(i);
|
||||
i++;
|
||||
if (point.x == 0) break;
|
||||
lcdDrawFilledRect(point.x-offset, point.y-1, 3, 3, SOLID, FORCE); // do markup square
|
||||
} while(1);
|
||||
}
|
||||
|
||||
bool moveCurve(uint8_t index, int8_t shift, int8_t custom=0)
|
||||
{
|
||||
if (g_model.curves[MAX_CURVES-1] + shift > NUM_POINTS-5*MAX_CURVES) {
|
||||
AUDIO_WARNING2();
|
||||
return false;
|
||||
}
|
||||
|
||||
int8_t *crv = curveAddress(index);
|
||||
if (shift < 0) {
|
||||
for (uint8_t i=0; i<custom; i++)
|
||||
crv[i] = crv[2*i];
|
||||
}
|
||||
|
||||
int8_t *nextCrv = curveAddress(index+1);
|
||||
memmove(nextCrv+shift, nextCrv, 5*(MAX_CURVES-index-1)+g_model.curves[MAX_CURVES-1]-g_model.curves[index]);
|
||||
if (shift < 0) memclear(&g_model.points[NUM_POINTS-1] + shift, -shift);
|
||||
while (index<MAX_CURVES)
|
||||
g_model.curves[index++] += shift;
|
||||
|
||||
for (uint8_t i=0; i<custom-2; i++)
|
||||
crv[custom+i] = -100 + ((200 * (i+1) + custom/2) / (custom-1)) ;
|
||||
|
||||
storageDirty(EE_MODEL);
|
||||
return true;
|
||||
}
|
||||
|
||||
void menuModelCurveOne(uint8_t event)
|
||||
{
|
||||
TITLE(STR_MENUCURVE);
|
||||
lcdDrawNumber(PSIZE(TR_MENUCURVE)*FW+1, 0, s_curveChan+1, INVERS|LEFT);
|
||||
DISPLAY_PROGRESS_BAR(20*FW+1);
|
||||
|
||||
CurveInfo crv = curveInfo(s_curveChan);
|
||||
|
||||
switch(event) {
|
||||
case EVT_ENTRY:
|
||||
s_editMode = 1;
|
||||
break;
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
if (s_editMode <= 0)
|
||||
menuHorizontalPosition = 0;
|
||||
if (s_editMode == 1 && crv.custom)
|
||||
s_editMode = 2;
|
||||
else
|
||||
s_editMode = 1;
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
if (s_editMode <= 0) {
|
||||
if (int8_t(++menuHorizontalPosition) > 4)
|
||||
menuHorizontalPosition = -4;
|
||||
for (uint8_t i=0; i<crv.points; i++)
|
||||
crv.crv[i] = (i-(crv.points/2)) * int8_t(menuHorizontalPosition) * 50 / (crv.points-1);
|
||||
storageDirty(EE_MODEL);
|
||||
killEvents(event);
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
if (s_editMode > 0) {
|
||||
if (--s_editMode == 0)
|
||||
menuHorizontalPosition = 0;
|
||||
}
|
||||
else {
|
||||
popMenu();
|
||||
}
|
||||
break;
|
||||
|
||||
/* CASE_EVT_ROTARY_LEFT */
|
||||
case EVT_KEY_REPT(KEY_LEFT):
|
||||
case EVT_KEY_FIRST(KEY_LEFT):
|
||||
if (s_editMode==1 && menuHorizontalPosition>0) menuHorizontalPosition--;
|
||||
if (s_editMode <= 0) {
|
||||
if (crv.custom) {
|
||||
moveCurve(s_curveChan, -crv.points+2);
|
||||
}
|
||||
else if (crv.points > MIN_POINTS) {
|
||||
moveCurve(s_curveChan, -1, (crv.points+1)/2);
|
||||
}
|
||||
else {
|
||||
AUDIO_WARNING2();
|
||||
}
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
/* CASE_EVT_ROTARY_RIGHT */
|
||||
case EVT_KEY_REPT(KEY_RIGHT):
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
if (s_editMode==1 && menuHorizontalPosition<(crv.points-1)) menuHorizontalPosition++;
|
||||
if (s_editMode <= 0) {
|
||||
if (!crv.custom) {
|
||||
moveCurve(s_curveChan, crv.points-2, crv.points);
|
||||
}
|
||||
else if (crv.points < MAX_POINTS) {
|
||||
if (moveCurve(s_curveChan, 1)) {
|
||||
for (int8_t i=crv.points+crv.points-2; i>=0; i--) {
|
||||
if (i%2)
|
||||
crv.crv[i] = (crv.crv[i/2] + crv.crv[1+i/2]) / 2;
|
||||
else
|
||||
crv.crv[i] = crv.crv[i/2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
AUDIO_WARNING2();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
lcd_putsLeft(7*FH, STR_TYPE);
|
||||
uint8_t attr = (s_editMode <= 0 ? INVERS : 0);
|
||||
lcdDrawNumber(5*FW-2, 7*FH, crv.points, LEFT|attr);
|
||||
lcdDrawText(lcdLastPos, 7*FH, crv.custom ? PSTR("pt'") : PSTR("pt"), attr);
|
||||
|
||||
DrawCurve();
|
||||
|
||||
if (s_editMode>0) {
|
||||
uint8_t i = menuHorizontalPosition;
|
||||
point_t point = getPoint(i);
|
||||
|
||||
if (s_editMode==1 || !BLINK_ON_PHASE) {
|
||||
// do selection square
|
||||
lcdDrawFilledRect(point.x-1, point.y-2, 5, 5, SOLID, FORCE);
|
||||
lcdDrawFilledRect(point.x, point.y-1, 3, 3, SOLID);
|
||||
}
|
||||
|
||||
int8_t x = -100 + 200*i/(crv.points-1);
|
||||
if (crv.custom && i>0 && i<crv.points-1) x = crv.crv[crv.points+i-1];
|
||||
lcdDrawText(7, 2*FH, PSTR("x=")); lcdDrawNumber(7+2*FW, 2*FH, x, LEFT);
|
||||
lcdDrawText(7, 3*FH, PSTR("y=")); lcdDrawNumber(7+2*FW, 3*FH, crv.crv[i], LEFT);
|
||||
lcdDrawRect(3, 1*FH+4, 7*FW-2, 3*FH-2);
|
||||
|
||||
if (p1valdiff || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_DOWN) || event==EVT_KEY_REPT(KEY_UP))
|
||||
CHECK_INCDEC_MODELVAR(event, crv.crv[i], -100, 100); // edit Y on up/down
|
||||
|
||||
if (i>0 && i<crv.points-1 && s_editMode==2 && (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_LEFT) || event==EVT_KEY_REPT(KEY_RIGHT)))
|
||||
CHECK_INCDEC_MODELVAR(event, crv.crv[crv.points+i-1], i==1 ? -99 : crv.crv[crv.points+i-2]+1, i==crv.points-2 ? 99 : crv.crv[crv.points+i]-1); // edit X on left/right
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(GVARS)
|
||||
#define CURVE_SELECTED() (sub >= 0 && sub < MAX_CURVES)
|
||||
#define GVAR_SELECTED() (sub >= MAX_CURVES)
|
||||
#else
|
||||
#define CURVE_SELECTED() (sub >= 0)
|
||||
#endif
|
||||
|
||||
void menuModelCurvesAll(uint8_t event)
|
||||
{
|
||||
#if defined(GVARS) && defined(PCBSTD)
|
||||
SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES+MAX_GVARS);
|
||||
#else
|
||||
SIMPLE_MENU(STR_MENUCURVES, menuTabModel, e_CurvesAll, 1+MAX_CURVES);
|
||||
#endif
|
||||
|
||||
int8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
switch (event) {
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_BREAK:
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
if (CURVE_SELECTED() && !READ_ONLY()) {
|
||||
s_curveChan = sub;
|
||||
pushMenu(menuModelCurveOne);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i + menuVerticalOffset;
|
||||
uint8_t attr = (sub == k ? INVERS : 0);
|
||||
#if defined(GVARS) && defined(PCBSTD)
|
||||
if (k >= MAX_CURVES) {
|
||||
drawStringWithIndex(0, y, STR_GV, k-MAX_CURVES+1);
|
||||
if (GVAR_SELECTED()) {
|
||||
if (attr && s_editMode>0) attr |= BLINK;
|
||||
lcdDrawNumber(10*FW, y, GVAR_VALUE(k-MAX_CURVES, -1), attr);
|
||||
if (attr) g_model.gvars[k-MAX_CURVES] = checkIncDec(event, g_model.gvars[k-MAX_CURVES], -1000, 1000, EE_MODEL);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
drawStringWithIndex(0, y, STR_CV, k+1, attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (CURVE_SELECTED()) {
|
||||
s_curveChan = sub;
|
||||
DrawCurve(23);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* 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 displayFlightModes(coord_t x, coord_t y, FlightModesType value)
|
||||
{
|
||||
uint8_t p = MAX_FLIGHT_MODES;
|
||||
do {
|
||||
--p;
|
||||
if (!(value & (1<<p)))
|
||||
lcdDrawChar(x, y, '0'+p);
|
||||
x -= FWNUM;
|
||||
} while (p!=0);
|
||||
}
|
||||
|
||||
enum menuModelPhaseItems {
|
||||
ITEM_MODEL_PHASE_NAME,
|
||||
ITEM_MODEL_PHASE_SWITCH,
|
||||
ITEM_MODEL_PHASE_TRIMS,
|
||||
IF_ROTARY_ENCODERS(ITEM_MODEL_PHASE_ROTARY_ENCODERS)
|
||||
ITEM_MODEL_PHASE_FADE_IN,
|
||||
ITEM_MODEL_PHASE_FADE_OUT,
|
||||
#if defined(GVARS) && !defined(PCBSTD)
|
||||
ITEM_MODEL_PHASE_GVARS_LABEL,
|
||||
ITEM_MODEL_PHASE_GV1,
|
||||
ITEM_MODEL_PHASE_GV2,
|
||||
ITEM_MODEL_PHASE_GV3,
|
||||
ITEM_MODEL_PHASE_GV4,
|
||||
ITEM_MODEL_PHASE_GV5,
|
||||
#if defined(CPUARM)
|
||||
ITEM_MODEL_PHASE_GV6,
|
||||
ITEM_MODEL_PHASE_GV7,
|
||||
ITEM_MODEL_PHASE_GV8,
|
||||
ITEM_MODEL_PHASE_GV9,
|
||||
#endif
|
||||
#endif
|
||||
ITEM_MODEL_PHASE_MAX
|
||||
};
|
||||
|
||||
void menuModelPhaseOne(uint8_t event)
|
||||
{
|
||||
FlightModeData *fm = flightModeAddress(s_currIdx);
|
||||
putsFlightMode(13*FW, 0, s_currIdx+1, (getFlightMode()==s_currIdx ? BOLD : 0));
|
||||
|
||||
#if defined(GVARS) && !defined(PCBSTD)
|
||||
static const pm_uint8_t mstate_tab_fm1[] PROGMEM = {0, 0, 0, (uint8_t)-1, 1, 1, 1, 1, 1};
|
||||
static const pm_uint8_t mstate_tab_others[] PROGMEM = {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0, 0, (uint8_t)-1, 2, 2, 2, 2, 2};
|
||||
|
||||
check(event, 0, NULL, 0, (s_currIdx == 0) ? mstate_tab_fm1 : mstate_tab_others, DIM(mstate_tab_others)-1, ITEM_MODEL_PHASE_MAX - 1 - (s_currIdx==0 ? (ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH) : 0));
|
||||
|
||||
TITLE(STR_MENUFLIGHTPHASE);
|
||||
|
||||
#define PHASE_ONE_FIRST_LINE (1+1*FH)
|
||||
#else
|
||||
SUBMENU(STR_MENUFLIGHTPHASE, 3 + (s_currIdx==0 ? 0 : 2 + (bool)NUM_ROTARY_ENCODERS), {0, 0, 3, IF_ROTARY_ENCODERS(NUM_ROTARY_ENCODERS-1) 0/*, 0*/});
|
||||
#define PHASE_ONE_FIRST_LINE (1+1*FH)
|
||||
#endif
|
||||
|
||||
int8_t sub = menuVerticalPosition;
|
||||
int8_t editMode = s_editMode;
|
||||
|
||||
#if defined(GVARS) && !defined(PCBSTD)
|
||||
if (s_currIdx == 0 && sub>=ITEM_MODEL_PHASE_SWITCH) sub += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH;
|
||||
|
||||
for (uint8_t k=0; k<LCD_LINES-1; k++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + k*FH;
|
||||
int8_t i = k + menuVerticalOffset;
|
||||
if (s_currIdx == 0 && i>=ITEM_MODEL_PHASE_SWITCH) i += ITEM_MODEL_PHASE_FADE_IN-ITEM_MODEL_PHASE_SWITCH;
|
||||
uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
#else
|
||||
for (uint8_t i=0, k=0, y=PHASE_ONE_FIRST_LINE; i<ITEM_MODEL_PHASE_MAX; i++, k++, y+=FH) {
|
||||
if (s_currIdx == 0 && i==ITEM_MODEL_PHASE_SWITCH) i = ITEM_MODEL_PHASE_FADE_IN;
|
||||
uint8_t attr = (sub==k ? (editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
#endif
|
||||
switch(i) {
|
||||
case ITEM_MODEL_PHASE_NAME:
|
||||
editSingleName(MIXES_2ND_COLUMN, y, STR_PHASENAME, fm->name, sizeof(fm->name), event, attr);
|
||||
break;
|
||||
case ITEM_MODEL_PHASE_SWITCH:
|
||||
fm->swtch = switchMenuItem(MIXES_2ND_COLUMN, y, fm->swtch, attr, event);
|
||||
break;
|
||||
case ITEM_MODEL_PHASE_TRIMS:
|
||||
lcd_putsLeft(y, STR_TRIMS);
|
||||
for (uint8_t t=0; t<NUM_STICKS; t++) {
|
||||
putsTrimMode(MIXES_2ND_COLUMN+(t*FW), y, s_currIdx, t, menuHorizontalPosition==t ? attr : 0);
|
||||
if (attr && menuHorizontalPosition==t && ((editMode>0) || p1valdiff)) {
|
||||
int16_t v = getRawTrimValue(s_currIdx, t);
|
||||
if (v < TRIM_EXTENDED_MAX) v = TRIM_EXTENDED_MAX;
|
||||
v = checkIncDec(event, v, TRIM_EXTENDED_MAX, TRIM_EXTENDED_MAX+MAX_FLIGHT_MODES-1, EE_MODEL);
|
||||
if (checkIncDec_Ret) {
|
||||
if (v == TRIM_EXTENDED_MAX) v = 0;
|
||||
setTrimValue(s_currIdx, t, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#if ROTARY_ENCODERS > 0
|
||||
case ITEM_MODEL_PHASE_ROTARY_ENCODERS:
|
||||
lcd_putsLeft(y, STR_ROTARY_ENCODER);
|
||||
for (uint8_t t=0; t<NUM_ROTARY_ENCODERS; t++) {
|
||||
putsRotaryEncoderMode(MIXES_2ND_COLUMN+(t*FW), y, s_currIdx, t, menuHorizontalPosition==t ? attr : 0);
|
||||
if (attr && menuHorizontalPosition==t && ((editMode>0) || p1valdiff)) {
|
||||
int16_t v = flightModeAddress(s_currIdx)->rotaryEncoders[t];
|
||||
if (v < ROTARY_ENCODER_MAX) v = ROTARY_ENCODER_MAX;
|
||||
v = checkIncDec(event, v, ROTARY_ENCODER_MAX, ROTARY_ENCODER_MAX+MAX_FLIGHT_MODES-1, EE_MODEL);
|
||||
if (checkIncDec_Ret) {
|
||||
if (v == ROTARY_ENCODER_MAX) v = 0;
|
||||
flightModeAddress(s_currIdx)->rotaryEncoders[t] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_MODEL_PHASE_FADE_IN:
|
||||
fm->fadeIn = EDIT_DELAY(0, y, event, attr, STR_FADEIN, fm->fadeIn);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_PHASE_FADE_OUT:
|
||||
fm->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, fm->fadeOut);
|
||||
break;
|
||||
|
||||
#if defined(GVARS) && !defined(PCBSTD)
|
||||
case ITEM_MODEL_PHASE_GVARS_LABEL:
|
||||
lcd_putsLeft(y, STR_GLOBAL_VARS);
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
uint8_t idx = i-ITEM_MODEL_PHASE_GV1;
|
||||
uint8_t posHorz = menuHorizontalPosition;
|
||||
if (attr && posHorz > 0 && s_currIdx==0) posHorz++;
|
||||
|
||||
drawStringWithIndex(INDENT_WIDTH, y, STR_GV, idx+1);
|
||||
|
||||
editName(4*FW, y, g_model.gvars[idx].name, LEN_GVAR_NAME, event, posHorz==0 ? attr : 0);
|
||||
|
||||
int16_t v = fm->gvars[idx];
|
||||
if (v > GVAR_MAX) {
|
||||
uint8_t p = v - GVAR_MAX - 1;
|
||||
if (p >= s_currIdx) p++;
|
||||
putsFlightMode(11*FW, y, p+1, posHorz==1 ? attr : 0);
|
||||
}
|
||||
else {
|
||||
lcdDrawText(11*FW, y, STR_OWN, posHorz==1 ? attr : 0);
|
||||
}
|
||||
if (attr && s_currIdx>0 && posHorz==1 && (editMode>0 || p1valdiff)) {
|
||||
if (v < GVAR_MAX) v = GVAR_MAX;
|
||||
v = checkIncDec(event, v, GVAR_MAX, GVAR_MAX+MAX_FLIGHT_MODES-1, EE_MODEL);
|
||||
if (checkIncDec_Ret) {
|
||||
if (v == GVAR_MAX) v = 0;
|
||||
fm->gvars[idx] = v;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t p = getGVarFlightMode(s_currIdx, idx);
|
||||
lcdDrawNumber(21*FW, y, GVAR_VALUE(idx, p), posHorz==2 ? attr : 0);
|
||||
if (attr && posHorz==2 && ((editMode>0) || p1valdiff)) {
|
||||
GVAR_VALUE(idx, p) = checkIncDec(event, GVAR_VALUE(idx, p), -500, 500, EE_MODEL);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ROTARY_ENCODERS)
|
||||
#if ROTARY_ENCODERS > 2
|
||||
#define NAME_OFS (-4-12)
|
||||
#define SWITCH_OFS (-FW/2-2-13)
|
||||
#define TRIMS_OFS (-FW/2-4-15)
|
||||
#define ROTARY_ENC_OFS (0)
|
||||
#else
|
||||
#define NAME_OFS (-4)
|
||||
#define SWITCH_OFS (-FW/2-2)
|
||||
#define TRIMS_OFS (-FW/2-4)
|
||||
#define ROTARY_ENC_OFS (2)
|
||||
#endif
|
||||
#else
|
||||
#define NAME_OFS 0
|
||||
#define SWITCH_OFS (FW/2)
|
||||
#define TRIMS_OFS (FW/2)
|
||||
#endif
|
||||
|
||||
void menuModelFlightModesAll(uint8_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUFLIGHTPHASES, menuTabModel, e_FlightModesAll, 1+MAX_FLIGHT_MODES+1);
|
||||
|
||||
int8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
switch (event) {
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
if (sub == MAX_FLIGHT_MODES) {
|
||||
s_editMode = 0;
|
||||
trimsCheckTimer = 200; // 2 seconds
|
||||
}
|
||||
// no break
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
if (sub >= 0 && sub < MAX_FLIGHT_MODES) {
|
||||
s_currIdx = sub;
|
||||
pushMenu(menuModelPhaseOne);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t att;
|
||||
for (uint8_t i=0; i<MAX_FLIGHT_MODES; i++) {
|
||||
#if defined(CPUARM)
|
||||
int8_t y = 1 + (1+i-menuVerticalOffset)*FH;
|
||||
if (y<1*FH+1 || y>(LCD_LINES-1)*FH+1) continue;
|
||||
#else
|
||||
uint8_t y = 1 + (i+1)*FH;
|
||||
#endif
|
||||
att = (i==sub ? INVERS : 0);
|
||||
FlightModeData *p = flightModeAddress(i);
|
||||
putsFlightMode(0, y, i+1, att|(getFlightMode()==i ? BOLD : 0));
|
||||
|
||||
lcdDrawSizedText(4*FW+NAME_OFS, y, p->name, sizeof(p->name), ZCHAR);
|
||||
if (i == 0) {
|
||||
lcdDrawText((5+LEN_FLIGHT_MODE_NAME)*FW+SWITCH_OFS, y, STR_DEFAULT);
|
||||
}
|
||||
else {
|
||||
putsSwitches((5+LEN_FLIGHT_MODE_NAME)*FW+SWITCH_OFS, y, p->swtch, 0);
|
||||
for (uint8_t t=0; t<NUM_STICKS; t++) {
|
||||
putsTrimMode((9+LEN_FLIGHT_MODE_NAME+t)*FW+TRIMS_OFS, y, i, t, 0);
|
||||
}
|
||||
#if defined(CPUM2560)
|
||||
for (uint8_t t=0; t<NUM_ROTARY_ENCODERS; t++) {
|
||||
putsRotaryEncoderMode((13+LEN_FLIGHT_MODE_NAME+t)*FW+TRIMS_OFS+ROTARY_ENC_OFS, y, i, t, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (p->fadeIn || p->fadeOut) {
|
||||
lcdDrawChar(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, (p->fadeIn && p->fadeOut) ? '*' : (p->fadeIn ? 'I' : 'O'));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
if (menuVerticalOffset != MAX_FLIGHT_MODES-(LCD_LINES-2)) return;
|
||||
#endif
|
||||
|
||||
lcd_putsLeft((LCD_LINES-1)*FH+1, STR_CHECKTRIMS);
|
||||
putsFlightMode(OFS_CHECKTRIMS, (LCD_LINES-1)*FH+1, mixerCurrentFlightMode+1);
|
||||
if (sub==MAX_FLIGHT_MODES && !trimsCheckTimer) {
|
||||
lcdInvertLastLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 menuModelHeliItems {
|
||||
ITEM_HELI_SWASHTYPE,
|
||||
ITEM_HELI_COLLECTIVE,
|
||||
ITEM_HELI_SWASHRING,
|
||||
ITEM_HELI_ELEDIRECTION,
|
||||
ITEM_HELI_AILDIRECTION,
|
||||
ITEM_HELI_COLDIRECTION
|
||||
};
|
||||
|
||||
#define HELI_PARAM_OFS (14*FW)
|
||||
|
||||
void menuModelHeli(uint8_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUHELISETUP, menuTabModel, e_Heli, 7);
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
for (uint8_t i=0; i<6; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t attr = (sub == i ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
switch(i) {
|
||||
case ITEM_HELI_SWASHTYPE:
|
||||
g_model.swashR.type = selectMenuItem(HELI_PARAM_OFS, y, STR_SWASHTYPE, STR_VSWASHTYPE, g_model.swashR.type, 0, SWASH_TYPE_MAX, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_COLLECTIVE:
|
||||
g_model.swashR.collectiveSource = selectMenuItem(HELI_PARAM_OFS, y, STR_COLLECTIVE, NULL, g_model.swashR.collectiveSource, 0, MIXSRC_LAST_CH, attr, event);
|
||||
putsMixerSource(HELI_PARAM_OFS, y, g_model.swashR.collectiveSource, attr);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_SWASHRING:
|
||||
lcd_putsLeft(y, STR_SWASHRING);
|
||||
lcdDrawNumber(HELI_PARAM_OFS, y, g_model.swashR.value, LEFT|attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.swashR.value, 100);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_ELEDIRECTION:
|
||||
g_model.swashR.invertELE = selectMenuItem(HELI_PARAM_OFS, y, STR_ELEDIRECTION, STR_MMMINV, g_model.swashR.invertELE, 0, 1, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_AILDIRECTION:
|
||||
g_model.swashR.invertAIL = selectMenuItem(HELI_PARAM_OFS, y, STR_AILDIRECTION, STR_MMMINV, g_model.swashR.invertAIL, 0, 1, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_HELI_COLDIRECTION:
|
||||
g_model.swashR.invertCOL = selectMenuItem(HELI_PARAM_OFS, y, STR_COLDIRECTION, STR_MMMINV, g_model.swashR.invertCOL, 0, 1, attr, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,992 @@
|
||||
/*
|
||||
* 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)
|
||||
|
||||
#if defined(FLIGHT_MODES)
|
||||
void displayFlightModes(coord_t x, coord_t y, FlightModesType value);
|
||||
FlightModesType editFlightModes(coord_t x, coord_t y, uint8_t event, FlightModesType value, uint8_t attr)
|
||||
{
|
||||
lcd_putsColumnLeft(x, y, STR_FLMODE);
|
||||
|
||||
uint8_t posHorz = menuHorizontalPosition;
|
||||
|
||||
#if defined(CPUARM)
|
||||
bool expoMenu = (x==EXPO_ONE_2ND_COLUMN-5*FW);
|
||||
#endif
|
||||
|
||||
for (uint8_t p=0; p<MAX_FLIGHT_MODES; p++) {
|
||||
#if defined(CPUARM)
|
||||
if (expoMenu && ((attr && p < posHorz-4) || (x > EXPO_ONE_2ND_COLUMN-FW)))
|
||||
continue;
|
||||
#endif
|
||||
lcdDrawChar(x, y, '0'+p, ((posHorz==p) && attr) ? BLINK|INVERS : ((value & (1<<p)) ? 0 : INVERS));
|
||||
x += FW;
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
if (s_editMode && ((event==EVT_KEY_BREAK(KEY_ENTER) || p1valdiff))) {
|
||||
s_editMode = 0;
|
||||
value ^= (1<<posHorz);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
#define displayFlightModes(...)
|
||||
#endif
|
||||
|
||||
int16_t expoFn(int16_t x)
|
||||
{
|
||||
ExpoData *ed = expoAddress(s_currIdx);
|
||||
int16_t anas[NUM_INPUTS] = {0};
|
||||
anas[ed->chn] = x;
|
||||
applyExpos(anas, e_perout_mode_inactive_flight_mode);
|
||||
return anas[ed->chn];
|
||||
}
|
||||
|
||||
void drawFunction(FnFuncP fn, uint8_t offset)
|
||||
{
|
||||
lcdDrawVerticalLine(X0-offset, 0, LCD_H, 0xee);
|
||||
lcdDrawHorizontalLine(X0-WCHART-offset, Y0, WCHART*2, 0xee);
|
||||
|
||||
coord_t prev_yv = (coord_t)-1;
|
||||
|
||||
for (int8_t xv=-WCHART; xv<=WCHART; xv++) {
|
||||
coord_t yv = (LCD_H-1) - (((uint16_t)RESX + fn(xv * (RESX/WCHART))) / 2 * (LCD_H-1) / RESX);
|
||||
if (prev_yv != (coord_t)-1) {
|
||||
if (abs((int8_t)yv-prev_yv) <= 1) {
|
||||
lcdDrawPoint(X0+xv-offset-1, prev_yv, FORCE);
|
||||
}
|
||||
else {
|
||||
uint8_t tmp = (prev_yv < yv ? 0 : 1);
|
||||
lcdDrawSolidVerticalLine(X0+xv-offset-1, yv+tmp, prev_yv-yv);
|
||||
}
|
||||
}
|
||||
prev_yv = yv;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t getExpoMixCount(uint8_t expo)
|
||||
{
|
||||
uint8_t count = 0;
|
||||
uint8_t ch ;
|
||||
|
||||
for(int8_t i=(expo ? MAX_EXPOS-1 : MAX_MIXERS-1); i>=0; i--) {
|
||||
ch = (expo ? EXPO_VALID(expoAddress(i)) : mixAddress(i)->srcRaw);
|
||||
if (ch != 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool reachExpoMixCountLimit(uint8_t expo)
|
||||
{
|
||||
// check mixers count limit
|
||||
if (getExpoMixCount(expo) >= (expo ? MAX_EXPOS : MAX_MIXERS)) {
|
||||
POPUP_WARNING(expo ? STR_NOFREEEXPO : STR_NOFREEMIXER);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void deleteExpoMix(uint8_t expo, uint8_t idx)
|
||||
{
|
||||
pauseMixerCalculations();
|
||||
if (expo) {
|
||||
ExpoData *expo = expoAddress(idx);
|
||||
memmove(expo, expo+1, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
memclear(&g_model.expoData[MAX_EXPOS-1], sizeof(ExpoData));
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
|
||||
// TODO avoid this global s_currCh on ARM boards ...
|
||||
int8_t s_currCh;
|
||||
void insertExpoMix(uint8_t expo, uint8_t idx)
|
||||
{
|
||||
pauseMixerCalculations();
|
||||
if (expo) {
|
||||
ExpoData *expo = expoAddress(idx);
|
||||
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
memclear(expo, sizeof(ExpoData));
|
||||
expo->mode = 3; // pos&neg
|
||||
expo->chn = s_currCh - 1;
|
||||
expo->weight = 100;
|
||||
}
|
||||
else {
|
||||
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 > 4 ? MIXSRC_Rud - 1 + s_currCh : MIXSRC_Rud - 1 + channel_order(s_currCh));
|
||||
mix->weight = 100;
|
||||
}
|
||||
resumeMixerCalculations();
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
void copyExpoMix(uint8_t expo, uint8_t idx)
|
||||
{
|
||||
pauseMixerCalculations();
|
||||
if (expo) {
|
||||
ExpoData *expo = expoAddress(idx);
|
||||
memmove(expo+1, expo, (MAX_EXPOS-(idx+1))*sizeof(ExpoData));
|
||||
}
|
||||
else {
|
||||
MixData *mix = mixAddress(idx);
|
||||
memmove(mix+1, mix, (MAX_MIXERS-(idx+1))*sizeof(MixData));
|
||||
}
|
||||
resumeMixerCalculations();
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
bool swapExpoMix(uint8_t expo, uint8_t &idx, uint8_t up)
|
||||
{
|
||||
void *x, *y;
|
||||
uint8_t size;
|
||||
int8_t tgt_idx = (up ? idx-1 : idx+1);
|
||||
|
||||
if (expo) {
|
||||
x = (ExpoData *)expoAddress(idx);
|
||||
|
||||
if (tgt_idx < 0) {
|
||||
if (((ExpoData *)x)->chn == 0)
|
||||
return false;
|
||||
((ExpoData *)x)->chn--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tgt_idx == MAX_EXPOS) {
|
||||
if (((ExpoData *)x)->chn == NUM_INPUTS-1)
|
||||
return false;
|
||||
((ExpoData *)x)->chn++;
|
||||
return true;
|
||||
}
|
||||
|
||||
y = (ExpoData *)expoAddress(tgt_idx);
|
||||
if(((ExpoData *)x)->chn != ((ExpoData *)y)->chn || !EXPO_VALID((ExpoData *)y)) {
|
||||
if (up) {
|
||||
if (((ExpoData *)x)->chn>0) ((ExpoData *)x)->chn--;
|
||||
else return false;
|
||||
}
|
||||
else {
|
||||
if (((ExpoData *)x)->chn<NUM_INPUTS-1) ((ExpoData *)x)->chn++;
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size = sizeof(ExpoData);
|
||||
}
|
||||
else {
|
||||
x = (MixData *)mixAddress(idx);
|
||||
|
||||
if (tgt_idx < 0) {
|
||||
if (((MixData *)x)->destCh == 0)
|
||||
return false;
|
||||
((MixData *)x)->destCh--;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tgt_idx == MAX_MIXERS) {
|
||||
if (((MixData *)x)->destCh == NUM_CHNOUT-1)
|
||||
return false;
|
||||
((MixData *)x)->destCh++;
|
||||
return true;
|
||||
}
|
||||
|
||||
y = (MixData *)mixAddress(tgt_idx);
|
||||
uint8_t destCh = ((MixData *)x)->destCh;
|
||||
if(!((MixData *)y)->srcRaw || destCh != ((MixData *)y)->destCh) {
|
||||
if (up) {
|
||||
if (destCh>0) ((MixData *)x)->destCh--;
|
||||
else return false;
|
||||
}
|
||||
else {
|
||||
if (destCh<NUM_CHNOUT-1) ((MixData *)x)->destCh++;
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
size = sizeof(MixData);
|
||||
}
|
||||
|
||||
pauseMixerCalculations();
|
||||
memswap(x, y, size);
|
||||
resumeMixerCalculations();
|
||||
|
||||
idx = tgt_idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
enum ExposFields {
|
||||
CASE_CPUARM(EXPO_FIELD_NAME)
|
||||
EXPO_FIELD_WEIGHT,
|
||||
EXPO_FIELD_EXPO,
|
||||
CASE_CURVES(EXPO_FIELD_CURVE)
|
||||
CASE_FLIGHT_MODES(EXPO_FIELD_FLIGHT_MODES)
|
||||
EXPO_FIELD_SWITCH,
|
||||
EXPO_FIELD_SIDE,
|
||||
EXPO_FIELD_MAX
|
||||
};
|
||||
|
||||
#define CURVE_ROWS 0
|
||||
|
||||
void menuModelExpoOne(uint8_t event)
|
||||
{
|
||||
ExpoData *ed = expoAddress(s_currIdx);
|
||||
putsMixerSource(7*FW+FW/2, 0, MIXSRC_Rud+ed->chn, 0);
|
||||
|
||||
SUBMENU(STR_MENUINPUTS, EXPO_FIELD_MAX, {CASE_CPUARM(0) 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 i=0; i<EXPO_FIELD_MAX+1; i++) {
|
||||
uint8_t attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
switch(i)
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
case EXPO_FIELD_NAME:
|
||||
editSingleName(EXPO_ONE_2ND_COLUMN-sizeof(ed->name)*FW, y, STR_EXPONAME, ed->name, sizeof(ed->name), event, attr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EXPO_FIELD_WEIGHT:
|
||||
lcd_putsLeft(y, STR_WEIGHT);
|
||||
ed->weight = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr, 0, event);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_EXPO:
|
||||
lcd_putsLeft(y, STR_EXPO);
|
||||
if (ed->curveMode==MODE_EXPO || ed->curveParam==0) {
|
||||
ed->curveMode = MODE_EXPO;
|
||||
ed->curveParam = GVAR_MENU_ITEM(EXPO_ONE_2ND_COLUMN, y, ed->curveParam, -100, 100, attr, 0, event);
|
||||
}
|
||||
else {
|
||||
lcdDrawText(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr);
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(CURVES)
|
||||
case EXPO_FIELD_CURVE:
|
||||
lcd_putsLeft(y, STR_CURVE);
|
||||
if (ed->curveMode!=MODE_EXPO || ed->curveParam==0) {
|
||||
drawCurveName(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->curveParam, attr);
|
||||
if (attr) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, ed->curveParam, CURVE_BASE+MAX_CURVES-1);
|
||||
if (ed->curveParam) ed->curveMode = MODE_CURVE;
|
||||
if (ed->curveParam>=CURVE_BASE && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
s_curveChan = ed->curveParam - CURVE_BASE;
|
||||
pushMenu(menuModelCurveOne);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawText(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_NA, attr);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(FLIGHT_MODES)
|
||||
case EXPO_FIELD_FLIGHT_MODES:
|
||||
ed->flightModes = editFlightModes(EXPO_ONE_2ND_COLUMN-EXPO_ONE_FM_WIDTH, y, event, ed->flightModes, attr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EXPO_FIELD_SWITCH:
|
||||
ed->swtch = switchMenuItem(EXPO_ONE_2ND_COLUMN-3*FW, y, ed->swtch, attr, event);
|
||||
break;
|
||||
|
||||
case EXPO_FIELD_SIDE:
|
||||
ed->mode = 4 - selectMenuItem(EXPO_ONE_2ND_COLUMN-3*FW, y, STR_SIDE, STR_VSIDE, 4-ed->mode, 1, 3, attr, event);
|
||||
break;
|
||||
}
|
||||
y += FH;
|
||||
}
|
||||
|
||||
drawFunction(expoFn);
|
||||
|
||||
int16_t x512 = calibratedStick[ed->chn];
|
||||
lcdDrawNumber(LCD_W-8, 6*FH, calcRESXto100(x512), 0);
|
||||
int16_t y512 = expoFn(x512);
|
||||
lcdDrawNumber(LCD_W-8-6*FW, 1*FH, calcRESXto100(y512), 0);
|
||||
|
||||
#if defined(CPUARM)
|
||||
x512 = X0+x512/(RESX/WCHART);
|
||||
y512 = (LCD_H-1) - ((y512+RESX)/2) * (LCD_H-1) / RESX;
|
||||
#else
|
||||
x512 = X0+x512/(RESXu/WCHART);
|
||||
y512 = (LCD_H-1) - (uint16_t)((y512+RESX)/2) * (LCD_H-1) / RESX;
|
||||
#endif
|
||||
|
||||
lcdDrawSolidVerticalLine(x512, y512-3, 3*2+1);
|
||||
lcdDrawSolidHorizontalLine(x512-3, y512, 3*2+1);
|
||||
}
|
||||
|
||||
enum MixFields {
|
||||
CASE_CPUARM(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_PHASE)
|
||||
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, uint8_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(FRSKY)
|
||||
#define GAUGE_WIDTH 33
|
||||
#define GAUGE_HEIGHT 6
|
||||
void drawOffsetBar(uint8_t x, uint8_t y, MixData * md)
|
||||
{
|
||||
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) {
|
||||
#if defined(CPUARM)
|
||||
lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-6, barMin, TINSIZE|LEFT);
|
||||
lcdDrawNumber(x+GAUGE_WIDTH+1, y-6, barMax, TINSIZE);
|
||||
#else
|
||||
lcdDrawNumber(x-((barMin >= 0) ? 2 : 3), y-8, barMin, LEFT);
|
||||
lcdDrawNumber(x+GAUGE_WIDTH+1, y-8, barMax);
|
||||
#endif
|
||||
}
|
||||
if (weight < 0) {
|
||||
barMin = -barMin;
|
||||
barMax = -barMax;
|
||||
}
|
||||
if (barMin < -101)
|
||||
barMin = -101;
|
||||
if (barMax > 101)
|
||||
barMax = 101;
|
||||
lcdDrawHorizontalLine(x-2, y, GAUGE_WIDTH+2, DOTTED);
|
||||
lcdDrawHorizontalLine(x-2, y+GAUGE_HEIGHT, GAUGE_WIDTH+2, DOTTED);
|
||||
lcdDrawSolidVerticalLine(x-2, y+1, GAUGE_HEIGHT-1);
|
||||
lcdDrawSolidVerticalLine(x+GAUGE_WIDTH-1, y+1, GAUGE_HEIGHT-1);
|
||||
if (barMin <= barMax) {
|
||||
int8_t right = (barMax * GAUGE_WIDTH) / 200;
|
||||
int8_t left = ((barMin * GAUGE_WIDTH) / 200)-1;
|
||||
lcdDrawFilledRect(x+GAUGE_WIDTH/2+left, y+2, right-left, GAUGE_HEIGHT-3);
|
||||
}
|
||||
lcdDrawSolidVerticalLine(x+GAUGE_WIDTH/2-1, y, GAUGE_HEIGHT+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+GAUGE_WIDTH-8+i, y+4-i);
|
||||
lcdDrawPoint(x+GAUGE_WIDTH-5+i, y+4-i);
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef GAUGE_WIDTH
|
||||
#undef GAUGE_HEIGHT
|
||||
#endif
|
||||
|
||||
void menuModelMixOne(uint8_t event)
|
||||
{
|
||||
TITLE(STR_MIXER);
|
||||
MixData * md2 = mixAddress(s_currIdx) ;
|
||||
putsChn(lcdLastPos+1*FW, 0, md2->destCh+1,0);
|
||||
|
||||
#if defined(ROTARY_ENCODERS)
|
||||
#if defined(CURVES)
|
||||
if ((menuVerticalPosition == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS) || (menuVerticalPosition == MIX_FIELD_CURVE && md2->curveMode == MODE_CURVE))
|
||||
#else
|
||||
if (menuVerticalPosition == MIX_FIELD_TRIM && md2->srcRaw > NUM_STICKS)
|
||||
#endif
|
||||
SUBMENU_NOTITLE(MIX_FIELD_COUNT, {CASE_CPUARM(0) 0, 0, 0, 0, CASE_CURVES(0) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/})
|
||||
else
|
||||
SUBMENU_NOTITLE(MIX_FIELD_COUNT, {CASE_CPUARM(0) 0, 0, 0, 1, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
|
||||
#else
|
||||
SUBMENU_NOTITLE(MIX_FIELD_COUNT, {CASE_CPUARM(0) 0, 0, 0, 1, CASE_CURVES(1) CASE_FLIGHT_MODES((MAX_FLIGHT_MODES-1) | NAVIGATION_LINE_BY_LINE) 0, 0 /*, ...*/});
|
||||
#endif
|
||||
|
||||
#if MENU_COLUMNS > 1
|
||||
lcdDrawSolidVerticalLine(MENU_COLUMN2_X-4, FH+1, LCD_H-FH-1);
|
||||
#endif
|
||||
|
||||
int8_t sub = menuVerticalPosition;
|
||||
int8_t editMode = s_editMode;
|
||||
|
||||
for (uint8_t k=0; k<MENU_COLUMNS*(LCD_LINES-1); k++) {
|
||||
|
||||
#if MENU_COLUMNS > 1
|
||||
coord_t y;
|
||||
coord_t COLUMN_X;
|
||||
if (k >= LCD_LINES-1) {
|
||||
y = 1 + (k-LCD_LINES+2)*FH;
|
||||
COLUMN_X = MENU_COLUMN2_X;
|
||||
}
|
||||
else {
|
||||
y = 1 + (k+1)*FH;
|
||||
COLUMN_X = 0;
|
||||
}
|
||||
int8_t i = k;
|
||||
#else
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + k*FH;
|
||||
int8_t i = k + menuVerticalOffset;
|
||||
#endif
|
||||
|
||||
uint8_t attr = (sub==i ? (editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
switch(i) {
|
||||
#if defined(CPUARM)
|
||||
case MIX_FIELD_NAME:
|
||||
editSingleName(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXNAME, md2->name, sizeof(md2->name), event, attr);
|
||||
break;
|
||||
#endif
|
||||
case MIX_FIELD_SOURCE:
|
||||
lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_SOURCE));
|
||||
putsMixerSource(COLUMN_X+MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr);
|
||||
if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST);
|
||||
break;
|
||||
case MIX_FIELD_WEIGHT:
|
||||
lcd_putsColumnLeft(COLUMN_X, y, STR_WEIGHT);
|
||||
gvarWeightItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2, attr|LEFT, event);
|
||||
break;
|
||||
case MIX_FIELD_OFFSET:
|
||||
{
|
||||
lcd_putsColumnLeft(COLUMN_X, y, NO_INDENT(STR_OFFSET));
|
||||
u_int8int16_t offset;
|
||||
MD_OFFSET_TO_UNION(md2, offset);
|
||||
offset.word = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN, y, offset.word, GV_RANGELARGE_OFFSET_NEG, GV_RANGELARGE_OFFSET, attr|LEFT, 0, event);
|
||||
MD_UNION_TO_OFFSET(offset, md2);
|
||||
#if !defined(CPUM64) || !defined(FRSKY)
|
||||
drawOffsetBar(COLUMN_X+MIXES_2ND_COLUMN+22, y, md2);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case MIX_FIELD_TRIM:
|
||||
{
|
||||
uint8_t not_stick = (md2->srcRaw > NUM_STICKS);
|
||||
int8_t carryTrim = -md2->carryTrim;
|
||||
lcd_putsColumnLeft(COLUMN_X, y, STR_TRIM);
|
||||
lcdDrawTextAtIndex((not_stick ? COLUMN_X+MIXES_2ND_COLUMN : COLUMN_X+6*FW-3), y, STR_VMIXTRIMS, (not_stick && carryTrim == 0) ? 0 : carryTrim+1, menuHorizontalPosition==0 ? attr : 0);
|
||||
if (attr && menuHorizontalPosition==0 && (not_stick || editMode>0)) md2->carryTrim = -checkIncDecModel(event, carryTrim, not_stick ? TRIM_ON : -TRIM_OFF, -TRIM_AIL);
|
||||
if (!not_stick) {
|
||||
lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_DREX);
|
||||
drawCheckBox(COLUMN_X+MIXES_2ND_COLUMN+DREX_CHBOX_OFFSET, y, !md2->noExpo, menuHorizontalPosition==1 ? attr : 0);
|
||||
if (attr && menuHorizontalPosition==1 && editMode>0) md2->noExpo = !checkIncDecModel(event, !md2->noExpo, 0, 1);
|
||||
}
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(CURVES)
|
||||
case MIX_FIELD_CURVE:
|
||||
{
|
||||
lcd_putsColumnLeft(COLUMN_X, y, STR_CURVE);
|
||||
int8_t curveParam = md2->curveParam;
|
||||
if (md2->curveMode == MODE_CURVE) {
|
||||
drawCurveName(COLUMN_X+MIXES_2ND_COLUMN, y, curveParam, attr);
|
||||
if (attr) {
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER) && (curveParam<0 || curveParam>=CURVE_BASE)){
|
||||
s_curveChan = (curveParam<0 ? -curveParam-1 : curveParam-CURVE_BASE);
|
||||
pushMenu(menuModelCurveOne);
|
||||
}
|
||||
else {
|
||||
CHECK_INCDEC_MODELVAR(event, md2->curveParam, -MAX_CURVES, CURVE_BASE+MAX_CURVES-1);
|
||||
if (md2->curveParam == 0)
|
||||
md2->curveMode = MODE_DIFFERENTIAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, PSTR("Diff"), menuHorizontalPosition==0 ? attr : 0);
|
||||
md2->curveParam = GVAR_MENU_ITEM(COLUMN_X+MIXES_2ND_COLUMN+5*FW, y, curveParam, -100, 100, LEFT|(menuHorizontalPosition==1 ? attr : 0), 0, editMode>0 ? event : 0);
|
||||
if (attr && editMode>0 && menuHorizontalPosition==0) {
|
||||
int8_t tmp = 0;
|
||||
CHECK_INCDEC_MODELVAR(event, tmp, -1, 1);
|
||||
if (tmp != 0) {
|
||||
md2->curveMode = MODE_CURVE;
|
||||
md2->curveParam = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(FLIGHT_MODES)
|
||||
case MIX_FIELD_FLIGHT_PHASE:
|
||||
md2->flightModes = editFlightModes(COLUMN_X+MIXES_2ND_COLUMN, y, event, md2->flightModes, attr);
|
||||
break;
|
||||
#endif
|
||||
case MIX_FIELD_SWITCH:
|
||||
md2->swtch = switchMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, md2->swtch, attr, event);
|
||||
break;
|
||||
case MIX_FIELD_WARNING:
|
||||
lcd_putsColumnLeft(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MIXWARNING);
|
||||
if (md2->mixWarn)
|
||||
lcdDrawNumber(COLUMN_X+MIXES_2ND_COLUMN, y, md2->mixWarn, attr|LEFT);
|
||||
else
|
||||
lcdDrawText(COLUMN_X+MIXES_2ND_COLUMN, y, STR_OFF, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, md2->mixWarn, 3);
|
||||
break;
|
||||
case MIX_FIELD_MLTPX:
|
||||
md2->mltpx = selectMenuItem(COLUMN_X+MIXES_2ND_COLUMN, y, STR_MULTPX, STR_VMLTPX, md2->mltpx, 0, 2, attr, event);
|
||||
break;
|
||||
case MIX_FIELD_DELAY_UP:
|
||||
md2->delayUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYUP, md2->delayUp);
|
||||
break;
|
||||
case MIX_FIELD_DELAY_DOWN:
|
||||
md2->delayDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_DELAYDOWN, md2->delayDown);
|
||||
break;
|
||||
case MIX_FIELD_SLOW_UP:
|
||||
md2->speedUp = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWUP, md2->speedUp);
|
||||
break;
|
||||
case MIX_FIELD_SLOW_DOWN:
|
||||
md2->speedDown = EDIT_DELAY(COLUMN_X, y, event, attr, STR_SLOWDOWN, md2->speedDown);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t s_maxLines = 8;
|
||||
static uint8_t s_copySrcIdx;
|
||||
static uint8_t s_copySrcCh;
|
||||
|
||||
#define _STR_MAX(x) PSTR("/" #x)
|
||||
#define STR_MAX(x) _STR_MAX(x)
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define EXPO_LINE_WEIGHT_POS 7*FW+1
|
||||
#define EXPO_LINE_EXPO_POS 10*FW+5
|
||||
#define EXPO_LINE_SWITCH_POS 11*FW+2
|
||||
#define EXPO_LINE_SIDE_POS 14*FW+2
|
||||
#define EXPO_LINE_SELECT_POS 24
|
||||
#define EXPO_LINE_FM_POS
|
||||
#define EXPO_LINE_NAME_POS LCD_W-LEN_EXPOMIX_NAME*FW-MENUS_SCROLLBAR_WIDTH
|
||||
#define MIX_LINE_SRC_POS 4*FW-1
|
||||
#define MIX_LINE_WEIGHT_POS 11*FW+3
|
||||
#define MIX_LINE_CURVE_POS 12*FW+2
|
||||
#define MIX_LINE_SWITCH_POS 16*FW
|
||||
#define MIX_LINE_DELAY_POS 19*FW+7
|
||||
#else
|
||||
#define EXPO_LINE_WEIGHT_POS 7*FW+1
|
||||
#define EXPO_LINE_EXPO_POS 11*FW
|
||||
#define EXPO_LINE_SWITCH_POS 11*FW+4
|
||||
#if MAX_FLIGHT_MODES == 6
|
||||
#define EXPO_LINE_SIDE_POS 15*FW
|
||||
#else
|
||||
#define EXPO_LINE_SIDE_POS 15*FW+2
|
||||
#endif
|
||||
#define EXPO_LINE_FM_POS LCD_W-FW-MENUS_SCROLLBAR_WIDTH
|
||||
#define EXPO_LINE_SELECT_POS 24
|
||||
#define MIX_LINE_SRC_POS 4*FW-1
|
||||
#define MIX_LINE_WEIGHT_POS 11*FW+3
|
||||
#define MIX_LINE_CURVE_POS 12*FW+2
|
||||
#define MIX_LINE_SWITCH_POS 16*FW
|
||||
#define MIX_LINE_DELAY_POS 19*FW+7
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
void onExpoMixMenu(const char *result)
|
||||
{
|
||||
bool expo = (menuHandlers[menuLevel] == menuModelExposAll);
|
||||
uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : mixAddress(s_currIdx)->destCh+1);
|
||||
|
||||
if (result == STR_EDIT) {
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
}
|
||||
else if (result == STR_INSERT_BEFORE || result == STR_INSERT_AFTER) {
|
||||
if (!reachExpoMixCountLimit(expo)) {
|
||||
s_currCh = chn;
|
||||
if (result == STR_INSERT_AFTER) { s_currIdx++; menuVerticalPosition++; }
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
pushMenu(expo ? menuModelExpoOne : 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) {
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void displayMixInfos(coord_t y, MixData *md)
|
||||
{
|
||||
if (md->curveParam) {
|
||||
if (md->curveMode == MODE_CURVE)
|
||||
drawCurveName(MIX_LINE_CURVE_POS, y, md->curveParam);
|
||||
else
|
||||
displayGVar(MIX_LINE_CURVE_POS+3*FW, y, md->curveParam, -100, 100);
|
||||
}
|
||||
|
||||
if (md->swtch) {
|
||||
putsSwitches(MIX_LINE_SWITCH_POS, y, md->swtch);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
void displayMixLine(coord_t y, MixData *md)
|
||||
{
|
||||
if (md->name[0]) {
|
||||
lcdDrawSizedText(EXPO_LINE_NAME_POS, y, md->name, sizeof(md->name), ZCHAR);
|
||||
}
|
||||
else {
|
||||
displayMixInfos(y, md);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define displayMixLine(y, md) displayMixInfos(y, md)
|
||||
#endif
|
||||
|
||||
void displayExpoInfos(coord_t y, ExpoData *ed)
|
||||
{
|
||||
if (ed->curveMode == MODE_CURVE)
|
||||
drawCurveName(EXPO_LINE_EXPO_POS-3*FW, y, ed->curveParam);
|
||||
else
|
||||
displayGVar(EXPO_LINE_EXPO_POS, y, ed->curveParam, -100, 100);
|
||||
|
||||
putsSwitches(EXPO_LINE_SWITCH_POS, y, ed->swtch, 0);
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
void displayExpoLine(coord_t y, ExpoData *ed)
|
||||
{
|
||||
displayExpoInfos(y, ed);
|
||||
|
||||
if (ed->name[0]) {
|
||||
lcdDrawSizedText(EXPO_LINE_NAME_POS, y, ed->name, sizeof(ed->name), ZCHAR);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define displayExpoLine(y, ed) \
|
||||
displayExpoInfos(y, ed); \
|
||||
displayFlightModes(EXPO_LINE_FM_POS, y, ed->flightModes)
|
||||
#endif
|
||||
|
||||
void menuModelExpoMix(uint8_t expo, uint8_t event)
|
||||
{
|
||||
uint8_t sub = menuVerticalPosition;
|
||||
|
||||
if (s_editMode > 0)
|
||||
s_editMode = 0;
|
||||
|
||||
uint8_t chn = (expo ? expoAddress(s_currIdx)->chn+1 : 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) {
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
killEvents(event);
|
||||
event = 0;
|
||||
}
|
||||
// no break
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LONG:
|
||||
if (s_copyMode) {
|
||||
killEvents(event);
|
||||
}
|
||||
#endif
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
if (s_copyMode) {
|
||||
if (s_copyTgtOfs) {
|
||||
// cancel the current copy / move operation
|
||||
if (s_copyMode == COPY_MODE) {
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
}
|
||||
else {
|
||||
do {
|
||||
swapExpoMix(expo, 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 (sub != 0 && (!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_ROTARY_BREAK
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
killEvents(event);
|
||||
if (s_copyTgtOfs) {
|
||||
s_copyMode = 0;
|
||||
s_copyTgtOfs = 0;
|
||||
}
|
||||
else if (sub != 0) {
|
||||
if (READ_ONLY()) {
|
||||
if (!s_currCh) {
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (s_copyMode) s_currCh = 0;
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
if (s_currCh) {
|
||||
if (reachExpoMixCountLimit(expo)) break;
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
s_copyMode = 0;
|
||||
return;
|
||||
}
|
||||
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(onExpoMixMenu);
|
||||
}
|
||||
#else
|
||||
if (s_currCh) {
|
||||
if (reachExpoMixCountLimit(expo)) break;
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
}
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
s_copyMode = 0;
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVT_KEY_LONG(KEY_LEFT):
|
||||
case EVT_KEY_LONG(KEY_RIGHT):
|
||||
if (s_copyMode && !s_copyTgtOfs) {
|
||||
if (reachExpoMixCountLimit(expo)) break;
|
||||
s_currCh = chn;
|
||||
if (event == EVT_KEY_LONG(KEY_RIGHT)) { s_currIdx++; menuVerticalPosition++; }
|
||||
insertExpoMix(expo, s_currIdx);
|
||||
pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
|
||||
s_copyMode = 0;
|
||||
killEvents(event);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LEFT:
|
||||
case EVT_ROTARY_RIGHT:
|
||||
#endif
|
||||
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 = ((IS_ROTARY_LEFT(event) || 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 (reachExpoMixCountLimit(expo)) break;
|
||||
copyExpoMix(expo, s_currIdx);
|
||||
if (IS_ROTARY_RIGHT(event) || key==KEY_DOWN) s_currIdx++;
|
||||
else if (sub-menuVerticalOffset >= 6) menuVerticalOffset++;
|
||||
}
|
||||
else if (next_ofs==0 && s_copyMode==COPY_MODE) {
|
||||
// delete the mix
|
||||
deleteExpoMix(expo, s_currIdx);
|
||||
if (IS_ROTARY_LEFT(event) || key==KEY_UP) s_currIdx--;
|
||||
}
|
||||
else {
|
||||
// only swap the mix with its neighbor
|
||||
if (!swapExpoMix(expo, s_currIdx, IS_ROTARY_LEFT(event) || key==KEY_UP)) break;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
s_copyTgtOfs = next_ofs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
lcdDrawNumber(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, getExpoMixCount(expo));
|
||||
lcdDrawText(FW*max(sizeof(TR_MENUINPUTS), sizeof(TR_MIXER))+FW+FW/2, 0, expo ? STR_MAX(MAX_EXPOS) : STR_MAX(MAX_MIXERS));
|
||||
|
||||
SIMPLE_MENU(expo ? STR_MENUINPUTS : STR_MIXER, menuTabModel, expo ? e_InputsAll : e_MixAll, s_maxLines);
|
||||
|
||||
sub = menuVerticalPosition;
|
||||
s_currCh = 0;
|
||||
uint8_t cur = 1;
|
||||
uint8_t i = 0;
|
||||
|
||||
for (uint8_t ch=1; ch<=(expo ? NUM_INPUTS : NUM_CHNOUT); ch++) {
|
||||
void *pointer = NULL; MixData * &md = (MixData * &)pointer; ExpoData * &ed = (ExpoData * &)pointer;
|
||||
coord_t y = MENU_HEADER_HEIGHT-FH+1+(cur-menuVerticalOffset)*FH;
|
||||
if (expo ? (i<MAX_EXPOS && (ed=expoAddress(i))->chn+1 == ch && EXPO_VALID(ed)) : (i<MAX_MIXERS && (md=mixAddress(i))->srcRaw && md->destCh+1 == ch)) {
|
||||
if (menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES) {
|
||||
if (expo) {
|
||||
putsMixerSource(0, y, MIXSRC_Rud+ch-1, 0);
|
||||
}
|
||||
else {
|
||||
putsChn(0, y, ch, 0); // show CHx
|
||||
}
|
||||
}
|
||||
uint8_t mixCnt = 0;
|
||||
do {
|
||||
if (s_copyMode) {
|
||||
if (s_copyMode == MOVE_MODE && menuVerticalOffset < cur && cur-menuVerticalOffset < 8 && s_copySrcCh == ch && s_copyTgtOfs != 0 && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
|
||||
lcdDrawRect(expo ? 18 : 22, y-1, expo ? LCD_W-18 : 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 (menuVerticalOffset < cur && cur-menuVerticalOffset < 8) {
|
||||
uint8_t attr = ((s_copyMode || sub != cur) ? 0 : INVERS);
|
||||
if (expo) {
|
||||
ed->weight = GVAR_MENU_ITEM(EXPO_LINE_WEIGHT_POS, y, ed->weight, MIN_EXPO_WEIGHT, 100, attr | (isExpoActive(i) ? BOLD : 0), 0, event);
|
||||
displayExpoLine(y, ed);
|
||||
if (ed->mode!=3) {
|
||||
lcdDrawChar(EXPO_LINE_SIDE_POS, y, ed->mode == 2 ? 126 : 127);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (mixCnt > 0) lcdDrawTextAtIndex(FW, y, STR_VMLTPX2, md->mltpx, 0);
|
||||
|
||||
putsMixerSource(MIX_LINE_SRC_POS, y, md->srcRaw, 0);
|
||||
|
||||
gvarWeightItem(MIX_LINE_WEIGHT_POS, y, md, attr | (isMixActive(i) ? BOLD : 0), event);
|
||||
|
||||
displayMixLine(y, md);
|
||||
|
||||
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);
|
||||
}
|
||||
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 ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
|
||||
}
|
||||
if (cur == sub) {
|
||||
/* invert the raw when it's the current one */
|
||||
lcdDrawFilledRect(expo ? EXPO_LINE_SELECT_POS+1 : 23, y, expo ? (LCD_W-EXPO_LINE_SELECT_POS-2) : (LCD_W-24), 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
cur++; y+=FH; mixCnt++; i++; if (expo) ed++; else md++;
|
||||
} while (expo ? (i<MAX_EXPOS && ed->chn+1 == ch && EXPO_VALID(ed)) : (i<MAX_MIXERS && md->srcRaw && md->destCh+1 == ch));
|
||||
if (s_copyMode == MOVE_MODE && menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES && s_copySrcCh == ch && i == (s_copySrcIdx + (s_copyTgtOfs<0))) {
|
||||
lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? LCD_W-EXPO_LINE_SELECT_POS : LCD_W-22, 9, DOTTED);
|
||||
cur++; y+=FH;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint8_t attr = 0;
|
||||
if (sub == cur) {
|
||||
s_currIdx = i;
|
||||
s_currCh = ch;
|
||||
if (!s_copyMode) {
|
||||
attr = INVERS;
|
||||
}
|
||||
}
|
||||
if (menuVerticalOffset < cur && cur-menuVerticalOffset < LCD_LINES) {
|
||||
if (expo) {
|
||||
putsMixerSource(0, y, MIXSRC_Rud+ch-1, attr);
|
||||
}
|
||||
else {
|
||||
putsChn(0, y, ch, attr); // show CHx
|
||||
}
|
||||
if (s_copyMode == MOVE_MODE && s_copySrcCh == ch) {
|
||||
lcdDrawRect(expo ? EXPO_LINE_SELECT_POS : 22, y-1, expo ? (LCD_W-EXPO_LINE_SELECT_POS) : (LCD_W-22), 9, DOTTED);
|
||||
}
|
||||
}
|
||||
cur++; y+=FH;
|
||||
}
|
||||
}
|
||||
s_maxLines = cur;
|
||||
if (sub >= s_maxLines-1) menuVerticalPosition = s_maxLines-1;
|
||||
}
|
||||
|
||||
void menuModelExposAll(uint8_t event)
|
||||
{
|
||||
return menuModelExpoMix(1, event);
|
||||
}
|
||||
|
||||
void menuModelMixAll(uint8_t event)
|
||||
{
|
||||
return menuModelExpoMix(0, event);
|
||||
}
|
||||
@@ -0,0 +1,536 @@
|
||||
/*
|
||||
* 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 LogicalSwitchFields {
|
||||
LS_FIELD_FUNCTION,
|
||||
LS_FIELD_V1,
|
||||
LS_FIELD_V2,
|
||||
LS_FIELD_ANDSW,
|
||||
#if defined(CPUARM)
|
||||
LS_FIELD_DURATION,
|
||||
LS_FIELD_DELAY,
|
||||
#endif
|
||||
LS_FIELD_COUNT,
|
||||
LS_FIELD_LAST = LS_FIELD_COUNT-1
|
||||
};
|
||||
|
||||
#define CSW_1ST_COLUMN (4*FW-3)
|
||||
#define CSW_2ND_COLUMN (8*FW-3)
|
||||
#define CSW_3RD_COLUMN (13*FW-6)
|
||||
#define CSW_4TH_COLUMN (18*FW+2)
|
||||
|
||||
#if defined(CPUARM)
|
||||
void putsEdgeDelayParam(coord_t x, coord_t y, LogicalSwitchData *cs, uint8_t lattr, uint8_t rattr)
|
||||
{
|
||||
lcdDrawChar(x-4, y, '[');
|
||||
lcdDrawNumber(x, y, lswTimerValue(cs->v2), LEFT|PREC1|lattr);
|
||||
lcdDrawChar(lcdLastPos, y, ':');
|
||||
if (cs->v3 < 0)
|
||||
lcdDrawText(lcdLastPos+3, y, "<<", rattr);
|
||||
else if (cs->v3 == 0)
|
||||
lcdDrawText(lcdLastPos+3, y, "--", rattr);
|
||||
else
|
||||
lcdDrawNumber(lcdLastPos+3, y, lswTimerValue(cs->v2+cs->v3), LEFT|PREC1|rattr);
|
||||
lcdDrawChar(lcdLastPos, y, ']');
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
|
||||
#define CSWONE_2ND_COLUMN (11*FW)
|
||||
|
||||
void menuModelLogicalSwitchOne(uint8_t event)
|
||||
{
|
||||
TITLE(STR_MENULOGICALSWITCH);
|
||||
|
||||
LogicalSwitchData * cs = lswAddress(s_currIdx);
|
||||
uint8_t sw = SWSRC_SW1+s_currIdx;
|
||||
putsSwitches(14*FW, 0, sw, (getSwitch(sw) ? BOLD : 0));
|
||||
|
||||
SUBMENU_NOTITLE(LS_FIELD_COUNT, {0, 0, 1, 0 /*, 0...*/});
|
||||
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
INCDEC_DECLARE_VARS(EE_MODEL);
|
||||
|
||||
int v1_val = cs->v1;
|
||||
|
||||
for (uint8_t k=0; k<LCD_LINES-1; k++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + k*FH;
|
||||
uint8_t i = k + menuVerticalOffset;
|
||||
uint8_t attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
uint8_t cstate = lswFamily(cs->func);
|
||||
switch(i) {
|
||||
case LS_FIELD_FUNCTION:
|
||||
lcd_putsLeft(y, STR_FUNC);
|
||||
lcdDrawTextAtIndex(CSWONE_2ND_COLUMN, y, STR_VCSWFUNC, cs->func, attr);
|
||||
if (attr) {
|
||||
cs->func = checkIncDec(event, cs->func, 0, LS_FUNC_MAX, EE_MODEL, isLogicalSwitchFunctionAvailable);
|
||||
uint8_t new_cstate = lswFamily(cs->func);
|
||||
if (cstate != new_cstate) {
|
||||
if (new_cstate == LS_FAMILY_TIMER) {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
else if (new_cstate == LS_FAMILY_EDGE) {
|
||||
cs->v1 = 0; cs->v2 = -129; cs->v3 = 0;
|
||||
}
|
||||
else {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LS_FIELD_V1:
|
||||
{
|
||||
lcd_putsLeft(y, STR_V1);
|
||||
int v1_min=0, v1_max=MIXSRC_LAST_TELEM;
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY || cstate == LS_FAMILY_EDGE) {
|
||||
putsSwitches(CSWONE_2ND_COLUMN, y, v1_val, attr);
|
||||
v1_min = SWSRC_OFF+1; v1_max = SWSRC_ON-1;
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
lcdDrawNumber(CSWONE_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT|PREC1|attr);
|
||||
v1_min = -128;
|
||||
v1_max = 122;
|
||||
}
|
||||
else {
|
||||
v1_val = (uint8_t)cs->v1;
|
||||
putsMixerSource(CSWONE_2ND_COLUMN, y, v1_val, attr);
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
if (attr) {
|
||||
cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LS_FIELD_V2:
|
||||
{
|
||||
lcd_putsLeft(y, STR_V2);
|
||||
int v2_min=0, v2_max=MIXSRC_LAST_TELEM;
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
putsSwitches(CSWONE_2ND_COLUMN, y, cs->v2, attr);
|
||||
v2_min = SWSRC_OFF+1; v2_max = SWSRC_ON-1;
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
lcdDrawNumber(CSWONE_2ND_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1|attr);
|
||||
v2_min = -128;
|
||||
v2_max = 122;
|
||||
}
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
putsEdgeDelayParam(CSWONE_2ND_COLUMN, y, cs, menuHorizontalPosition==0 ? attr : 0, menuHorizontalPosition==1 ? attr : 0);
|
||||
if (s_editMode <= 0) continue;
|
||||
if (attr && menuHorizontalPosition==1) {
|
||||
CHECK_INCDEC_MODELVAR(event, cs->v3, -1, 222 - cs->v2);
|
||||
break;
|
||||
}
|
||||
v2_min = -129; v2_max = 122;
|
||||
}
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
putsMixerSource(CSWONE_2ND_COLUMN, y, cs->v2, attr);
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
else {
|
||||
#if defined(FRSKY)
|
||||
if (v1_val >= MIXSRC_FIRST_TELEM) {
|
||||
#if defined(CPUARM)
|
||||
putsChannelValue(CSWONE_2ND_COLUMN, y, v1_val, convertLswTelemValue(cs), attr|LEFT);
|
||||
#else
|
||||
putsTelemetryChannelValue(CSWONE_2ND_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), attr|LEFT);
|
||||
#endif
|
||||
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
|
||||
if (cs->func == LS_FUNC_DIFFEGREATER)
|
||||
v2_min = -v2_max;
|
||||
else if (cs->func == LS_FUNC_ADIFFEGREATER)
|
||||
v2_min = 0;
|
||||
else
|
||||
v2_min = minTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_REP10 | NO_INCDEC_MARKS);
|
||||
if (cs->v2 < v2_min || cs->v2 > v2_max) {
|
||||
cs->v2 = 0;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT;
|
||||
lcdDrawNumber(CSWONE_2ND_COLUMN, y, cs->v2, LEFT|attr);
|
||||
}
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
CHECK_INCDEC_MODELVAR(event, cs->v2, v2_min, v2_max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LS_FIELD_ANDSW:
|
||||
lcd_putsLeft(y, STR_AND_SWITCH);
|
||||
putsSwitches(CSWONE_2ND_COLUMN, y, cs->andsw, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, cs->andsw, -MAX_LS_ANDSW, MAX_LS_ANDSW);
|
||||
break;
|
||||
case LS_FIELD_DURATION:
|
||||
lcd_putsLeft(y, STR_DURATION);
|
||||
if (cs->duration > 0)
|
||||
lcdDrawNumber(CSWONE_2ND_COLUMN, y, cs->duration, attr|PREC1|LEFT);
|
||||
else
|
||||
lcdDrawTextAtIndex(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_LS_DURATION);
|
||||
break;
|
||||
case LS_FIELD_DELAY:
|
||||
lcd_putsLeft(y, STR_DELAY);
|
||||
if (cs->delay > 0)
|
||||
lcdDrawNumber(CSWONE_2ND_COLUMN, y, cs->delay, attr|PREC1|LEFT);
|
||||
else
|
||||
lcdDrawTextAtIndex(CSWONE_2ND_COLUMN, y, STR_MMMINV, 0, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_LS_DELAY);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelLogicalSwitches(uint8_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENULOGICALSWITCHES, menuTabModel, e_LogicalSwitches, NUM_LOGICAL_SWITCH+1);
|
||||
|
||||
coord_t y = 0;
|
||||
uint8_t k = 0;
|
||||
int8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
switch (event) {
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_BREAK:
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
if (sub >= 0) {
|
||||
s_currIdx = sub;
|
||||
pushMenu(menuModelLogicalSwitchOne);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
y = 1 + (i+1)*FH;
|
||||
k = i+menuVerticalOffset;
|
||||
LogicalSwitchData * cs = lswAddress(k);
|
||||
|
||||
// CSW name
|
||||
uint8_t sw = SWSRC_SW1+k;
|
||||
|
||||
putsSwitches(0, y, sw, (sub==k ? INVERS : 0) | (getSwitch(sw) ? BOLD : 0));
|
||||
|
||||
if (cs->func > 0) {
|
||||
// CSW func
|
||||
lcdDrawTextAtIndex(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, 0);
|
||||
|
||||
// CSW params
|
||||
uint8_t cstate = lswFamily(cs->func);
|
||||
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
putsSwitches(CSW_3RD_COLUMN, y, cs->v2, 0);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
putsMixerSource(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, 0);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
putsSwitches(CSW_2ND_COLUMN, y, cs->v1, 0);
|
||||
putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, 0, 0);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
lcdDrawNumber(CSW_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT|PREC1);
|
||||
lcdDrawNumber(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1);
|
||||
}
|
||||
else {
|
||||
uint8_t v1 = cs->v1;
|
||||
putsMixerSource(CSW_2ND_COLUMN, y, v1, 0);
|
||||
if (v1 >= MIXSRC_FIRST_TELEM) {
|
||||
#if defined(CPUARM)
|
||||
putsChannelValue(CSW_3RD_COLUMN, y, v1, convertLswTelemValue(cs), LEFT);
|
||||
#else
|
||||
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1 - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(CSW_3RD_COLUMN, y, cs->v2, LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
// CSW and switch
|
||||
putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void menuModelLogicalSwitches(uint8_t event)
|
||||
{
|
||||
INCDEC_DECLARE_VARS(EE_MODEL);
|
||||
|
||||
MENU(STR_MENULOGICALSWITCHES, menuTabModel, e_LogicalSwitches, NUM_LOGICAL_SWITCH+1, {0, NAVIGATION_LINE_BY_LINE|LS_FIELD_LAST/*repeated...*/});
|
||||
|
||||
uint8_t k = 0;
|
||||
int8_t sub = menuVerticalPosition - 1;
|
||||
horzpos_t horz = menuHorizontalPosition;
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
k = i+menuVerticalOffset;
|
||||
uint8_t attr = (sub==k ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
uint8_t attr1 = (horz==1 ? attr : 0);
|
||||
uint8_t attr2 = (horz==2 ? attr : 0);
|
||||
LogicalSwitchData * cs = lswAddress(k);
|
||||
|
||||
// CSW name
|
||||
uint8_t sw = SWSRC_SW1+k;
|
||||
putsSwitches(0, y, sw, (getSwitch(sw) ? BOLD : 0) | ((sub==k && CURSOR_ON_LINE()) ? INVERS : 0));
|
||||
|
||||
// CSW func
|
||||
lcdDrawTextAtIndex(CSW_1ST_COLUMN, y, STR_VCSWFUNC, cs->func, horz==0 ? attr : 0);
|
||||
|
||||
// CSW params
|
||||
uint8_t cstate = lswFamily(cs->func);
|
||||
#if defined(CPUARM)
|
||||
int16_t v1_val=cs->v1, v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM;
|
||||
int16_t v3_min=-1, v3_max=100;
|
||||
#else
|
||||
int8_t v1_min=0, v1_max=MIXSRC_LAST_TELEM, v2_min=0, v2_max=MIXSRC_LAST_TELEM;
|
||||
#define v1_val cs->v1
|
||||
#endif
|
||||
|
||||
if (cstate == LS_FAMILY_BOOL || cstate == LS_FAMILY_STICKY) {
|
||||
putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1);
|
||||
putsSwitches(CSW_3RD_COLUMN, y, cs->v2, attr2);
|
||||
v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES;
|
||||
v2_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v2_max = SWSRC_LAST_IN_LOGICAL_SWITCHES;
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH);
|
||||
INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
else if (cstate == LS_FAMILY_EDGE) {
|
||||
putsSwitches(CSW_2ND_COLUMN, y, cs->v1, attr1);
|
||||
putsEdgeDelayParam(CSW_3RD_COLUMN, y, cs, attr2, horz==LS_FIELD_V3 ? attr : 0);
|
||||
v1_min = SWSRC_FIRST_IN_LOGICAL_SWITCHES; v1_max = SWSRC_LAST_IN_LOGICAL_SWITCHES;
|
||||
v2_min=-129; v2_max = 122;
|
||||
v3_max = 222 - cs->v2;
|
||||
if (horz == 1) {
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH);
|
||||
INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches);
|
||||
}
|
||||
else {
|
||||
INCDEC_SET_FLAG(EE_MODEL);
|
||||
INCDEC_ENABLE_CHECK(NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (cstate == LS_FAMILY_COMP) {
|
||||
#if defined(CPUARM)
|
||||
v1_val = (uint8_t)cs->v1;
|
||||
#endif
|
||||
putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1);
|
||||
putsMixerSource(CSW_3RD_COLUMN, y, cs->v2, attr2);
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
else if (cstate == LS_FAMILY_TIMER) {
|
||||
lcdDrawNumber(CSW_2ND_COLUMN, y, lswTimerValue(cs->v1), LEFT|PREC1|attr1);
|
||||
lcdDrawNumber(CSW_3RD_COLUMN, y, lswTimerValue(cs->v2), LEFT|PREC1|attr2);
|
||||
v1_min = v2_min = -128;
|
||||
v1_max = v2_max = 122;
|
||||
INCDEC_SET_FLAG(EE_MODEL);
|
||||
INCDEC_ENABLE_CHECK(NULL);
|
||||
}
|
||||
else {
|
||||
#if defined(CPUARM)
|
||||
v1_val = (uint8_t)cs->v1;
|
||||
#endif
|
||||
putsMixerSource(CSW_2ND_COLUMN, y, v1_val, attr1);
|
||||
if (horz == 1) {
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailableInCustomSwitches);
|
||||
}
|
||||
else {
|
||||
INCDEC_SET_FLAG(EE_MODEL);
|
||||
INCDEC_ENABLE_CHECK(NULL);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
putsChannelValue(CSW_3RD_COLUMN, y, v1_val, calc100toRESX(cs->v2), LEFT|attr2);
|
||||
v2_min = -30000;
|
||||
v2_max = 30000;
|
||||
#elif defined(FRSKY)
|
||||
if (v1_val >= MIXSRC_FIRST_TELEM) {
|
||||
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2);
|
||||
v2_max = maxTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
|
||||
#if defined(CPUARM)
|
||||
if (cs->func == LS_FUNC_DIFFEGREATER)
|
||||
v2_min = -v2_max;
|
||||
else if (cs->func == LS_FUNC_ADIFFEGREATER)
|
||||
v2_min = 0;
|
||||
else
|
||||
v2_min = minTelemValue(v1_val - MIXSRC_FIRST_TELEM + 1);
|
||||
if (horz == 2 && v2_max-v2_min > 1000)
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_REP10 | NO_INCDEC_MARKS);
|
||||
if (cs->v2 < v2_min || cs->v2 > v2_max) {
|
||||
cs->v2 = 0;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
#else
|
||||
if (cstate == LS_FAMILY_OFS) {
|
||||
v2_min = -128;
|
||||
v2_max -= 128;
|
||||
}
|
||||
else {
|
||||
v2_max = min((uint8_t)127, (uint8_t)v2_max);
|
||||
v2_min = -v2_max;
|
||||
}
|
||||
if (cs->v2 > v2_max) {
|
||||
cs->v2 = v2_max;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2);
|
||||
#if defined(CPUARM) && defined(GVARS)
|
||||
if (v1_val >= MIXSRC_GVAR1) {
|
||||
v2_min = -1024; v2_max = +1024;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (v1_val >= MIXSRC_FIRST_TELEM) {
|
||||
putsTelemetryChannelValue(CSW_3RD_COLUMN, y, v1_val - MIXSRC_FIRST_TELEM, convertLswTelemValue(cs), LEFT|attr2);
|
||||
v2_min = -128; v2_max = 127;
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(CSW_3RD_COLUMN, y, cs->v2, LEFT|attr2);
|
||||
v2_min = -LIMIT_EXT_PERCENT; v2_max = +LIMIT_EXT_PERCENT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// CSW AND switch
|
||||
#if defined(CPUARM)
|
||||
putsSwitches(CSW_4TH_COLUMN, y, cs->andsw, horz==LS_FIELD_ANDSW ? attr : 0);
|
||||
#else
|
||||
uint8_t andsw = cs->andsw;
|
||||
if (andsw > SWSRC_LAST_SWITCH) {
|
||||
andsw += SWSRC_SW1-SWSRC_LAST_SWITCH-1;
|
||||
}
|
||||
putsSwitches(CSW_4TH_COLUMN, y, andsw, horz==LS_FIELD_ANDSW ? attr : 0);
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
// CSW duration
|
||||
if (cs->duration > 0)
|
||||
lcdDrawNumber(CSW_5TH_COLUMN, y, cs->duration, (horz==LS_FIELD_DURATION ? attr : 0)|PREC1|LEFT);
|
||||
else
|
||||
lcdDrawTextAtIndex(CSW_5TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DURATION ? attr : 0);
|
||||
|
||||
// CSW delay
|
||||
if (cstate == LS_FAMILY_EDGE) {
|
||||
lcdDrawText(CSW_6TH_COLUMN, y, STR_NA);
|
||||
if (attr && horz == LS_FIELD_DELAY) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
}
|
||||
else if (cs->delay > 0) {
|
||||
lcdDrawNumber(CSW_6TH_COLUMN, y, cs->delay, (horz==LS_FIELD_DELAY ? attr : 0)|PREC1|LEFT);
|
||||
}
|
||||
else {
|
||||
lcdDrawTextAtIndex(CSW_6TH_COLUMN, y, STR_MMMINV, 0, horz==LS_FIELD_DELAY ? attr : 0);
|
||||
}
|
||||
|
||||
if (attr && horz == LS_FIELD_V3 && cstate != LS_FAMILY_EDGE) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((s_editMode>0 || p1valdiff) && attr) {
|
||||
switch (horz) {
|
||||
case LS_FIELD_FUNCTION:
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
cs->func = checkIncDec(event, cs->func, 0, LS_FUNC_MAX, EE_MODEL, isLogicalSwitchFunctionAvailable);
|
||||
#else
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, cs->func, LS_FUNC_MAX);
|
||||
#endif
|
||||
uint8_t new_cstate = lswFamily(cs->func);
|
||||
if (cstate != new_cstate) {
|
||||
#if defined(CPUARM)
|
||||
if (new_cstate == LS_FAMILY_TIMER) {
|
||||
cs->v1 = cs->v2 = -119;
|
||||
}
|
||||
else if (new_cstate == LS_FAMILY_EDGE) {
|
||||
cs->v1 = 0; cs->v2 = -129; cs->v3 = 0;
|
||||
}
|
||||
else {
|
||||
cs->v1 = cs->v2 = 0;
|
||||
}
|
||||
#else
|
||||
cs->v1 = cs->v2 = (new_cstate==LS_FAMILY_TIMER ? -119/*1.0*/ : 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LS_FIELD_V1:
|
||||
cs->v1 = CHECK_INCDEC_PARAM(event, v1_val, v1_min, v1_max);
|
||||
break;
|
||||
case LS_FIELD_V2:
|
||||
cs->v2 = CHECK_INCDEC_PARAM(event, cs->v2, v2_min, v2_max);
|
||||
if (checkIncDec_Ret) TRACE("v2=%d", cs->v2);
|
||||
break;
|
||||
#if defined(CPUARM)
|
||||
case LS_FIELD_V3:
|
||||
cs->v3 = CHECK_INCDEC_PARAM(event, cs->v3, v3_min, v3_max);
|
||||
break;
|
||||
#endif
|
||||
case LS_FIELD_ANDSW:
|
||||
#if defined(CPUARM)
|
||||
INCDEC_SET_FLAG(EE_MODEL | INCDEC_SWITCH);
|
||||
INCDEC_ENABLE_CHECK(isSwitchAvailableInLogicalSwitches);
|
||||
cs->andsw = CHECK_INCDEC_PARAM(event, cs->andsw, -MAX_LS_ANDSW, MAX_LS_ANDSW);
|
||||
#else
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, cs->andsw, MAX_LS_ANDSW);
|
||||
#endif
|
||||
break;
|
||||
#if defined(CPUARM)
|
||||
case LS_FIELD_DURATION:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, cs->duration, MAX_LS_DURATION);
|
||||
break;
|
||||
case LS_FIELD_DELAY:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, cs->delay, MAX_LS_DELAY);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
bool isThrottleOutput(uint8_t ch)
|
||||
{
|
||||
for (uint8_t i=0; i<MAX_MIXERS; i++) {
|
||||
MixData *mix = mixAddress(i);
|
||||
if (mix->destCh==ch && mix->srcRaw==MIXSRC_Thr)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum LimitsItems {
|
||||
ITEM_LIMITS_OFFSET,
|
||||
ITEM_LIMITS_MIN,
|
||||
ITEM_LIMITS_MAX,
|
||||
ITEM_LIMITS_DIRECTION,
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
ITEM_LIMITS_PPM_CENTER,
|
||||
#endif
|
||||
#if defined(PPM_LIMITS_SYMETRICAL)
|
||||
ITEM_LIMITS_SYMETRICAL,
|
||||
#endif
|
||||
ITEM_LIMITS_COUNT,
|
||||
ITEM_LIMITS_MAXROW = ITEM_LIMITS_COUNT-1
|
||||
};
|
||||
|
||||
#if defined(PPM_UNIT_US)
|
||||
#define LIMITS_MIN_POS 12*FW+1
|
||||
#else
|
||||
#define LIMITS_MIN_POS 12*FW
|
||||
#endif
|
||||
#define LIMITS_OFFSET_POS 8*FW
|
||||
#if defined(PPM_LIMITS_SYMETRICAL)
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
#define LIMITS_MAX_POS 15*FW
|
||||
#define LIMITS_REVERT_POS 16*FW-3
|
||||
#define LIMITS_PPM_CENTER_POS 20*FW+1
|
||||
#else
|
||||
#define LIMITS_DIRECTION_POS 12*FW+4
|
||||
#define LIMITS_MAX_POS 16*FW+4
|
||||
#define LIMITS_REVERT_POS 17*FW
|
||||
#endif
|
||||
#else
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
#define LIMITS_MAX_POS 16*FW
|
||||
#define LIMITS_REVERT_POS 17*FW-2
|
||||
#define LIMITS_PPM_CENTER_POS 21*FW+2
|
||||
#else
|
||||
#define LIMITS_MAX_POS 17*FW
|
||||
#define LIMITS_REVERT_POS 18*FW
|
||||
#define LIMITS_DIRECTION_POS 12*FW+5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define LIMITS_MIN_MAX_OFFSET 100
|
||||
#define CONVERT_US_MIN_MAX(x) ((int16_t(x)*128)/25)
|
||||
#define MIN_MAX_ATTR attr
|
||||
|
||||
#if defined(PPM_UNIT_US)
|
||||
#define SET_MIN_MAX(x, val) x = ((val)*250)/128
|
||||
#define MIN_MAX_DISPLAY(x) CONVERT_US_MIN_MAX(x)
|
||||
#elif defined(CPUARM)
|
||||
#define MIN_MAX_DISPLAY(x) (x)
|
||||
#define SET_MIN_MAX(x, val) x = (val)
|
||||
#else
|
||||
#define MIN_MAX_DISPLAY(x) ((int8_t)(x))
|
||||
#endif
|
||||
|
||||
void menuModelLimits(uint8_t event)
|
||||
{
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
if (sub < NUM_CHNOUT) {
|
||||
#if defined(PPM_CENTER_ADJUSTABLE) || defined(PPM_UNIT_US)
|
||||
lcdDrawNumber(13*FW, 0, PPM_CH_CENTER(sub)+channelOutputs[sub]/2, 0);
|
||||
lcdDrawText(13*FW, 0, STR_US);
|
||||
#else
|
||||
lcdDrawNumber(13*FW, 0, calcRESXto1000(channelOutputs[sub]), PREC1);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, NAVIGATION_LINE_BY_LINE|ITEM_LIMITS_MAXROW, 0});
|
||||
#else
|
||||
MENU(STR_MENULIMITS, menuTabModel, e_Limits, 1+NUM_CHNOUT+1, {0, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, ITEM_LIMITS_MAXROW, 0});
|
||||
#endif
|
||||
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
LimitData *ld = limitAddress(sub);
|
||||
ld->revert = !ld->revert;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
|
||||
if (k==NUM_CHNOUT) {
|
||||
// last line available - add the "copy trim menu" line
|
||||
uint8_t attr = (sub==NUM_CHNOUT) ? INVERS : 0;
|
||||
lcdDrawText(CENTER_OFS, y, STR_TRIMS2OFFSETS, NO_HIGHLIGHT() ? 0 : attr);
|
||||
if (attr) {
|
||||
s_editMode = 0;
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
START_NO_HIGHLIGHT();
|
||||
killEvents(event);
|
||||
moveTrimsToOffsets(); // if highlighted and menu pressed - move trims to offsets
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
LimitData *ld = limitAddress(k);
|
||||
|
||||
#if !defined(PPM_CENTER_ADJUSTABLE)
|
||||
int16_t v = (ld->revert) ? -LIMIT_OFS(ld) : LIMIT_OFS(ld);
|
||||
char swVal = '-'; // '-', '<', '>'
|
||||
if ((channelOutputs[k] - v) > 50) swVal = (ld->revert ? 127 : 126); // Switch to raw inputs? - remove trim!
|
||||
if ((channelOutputs[k] - v) < -50) swVal = (ld->revert ? 126 : 127);
|
||||
putsChn(0, y, k+1, 0);
|
||||
lcdDrawChar(LIMITS_DIRECTION_POS, y, swVal);
|
||||
#endif
|
||||
|
||||
int8_t limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : 100);
|
||||
|
||||
putsChn(0, y, k+1, 0);
|
||||
|
||||
for (uint8_t j=0; j<ITEM_LIMITS_COUNT; j++) {
|
||||
uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ;
|
||||
if (active) STICK_SCROLL_DISABLE();
|
||||
switch(j)
|
||||
{
|
||||
case ITEM_LIMITS_OFFSET:
|
||||
#if defined(PPM_UNIT_US)
|
||||
lcdDrawNumber(LIMITS_OFFSET_POS, y, ((int32_t)ld->offset*128) / 25, attr|PREC1);
|
||||
#else
|
||||
lcdDrawNumber(LIMITS_OFFSET_POS, y, ld->offset, attr|PREC1);
|
||||
#endif
|
||||
if (active) {
|
||||
#if defined(CPUARM)
|
||||
ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL, NULL, stops1000);
|
||||
#else
|
||||
ld->offset = checkIncDec(event, ld->offset, -1000, 1000, EE_MODEL|NO_INCDEC_MARKS);
|
||||
#endif
|
||||
}
|
||||
else if (attr && event==EVT_KEY_LONG(KEY_MENU)) {
|
||||
copySticksToOffset(k);
|
||||
s_editMode = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_MIN:
|
||||
lcdDrawNumber(LIMITS_MIN_POS, y, MIN_MAX_DISPLAY(ld->min-LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR);
|
||||
#if defined(CPUARM)
|
||||
if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL, NULL, stops1000);
|
||||
#else
|
||||
if (active) ld->min = LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->min-LIMITS_MIN_MAX_OFFSET, -limit, 0, EE_MODEL);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_MAX:
|
||||
lcdDrawNumber(LIMITS_MAX_POS, y, MIN_MAX_DISPLAY(ld->max+LIMITS_MIN_MAX_OFFSET), MIN_MAX_ATTR);
|
||||
#if defined(CPUARM)
|
||||
if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL, NULL, stops1000);
|
||||
#else
|
||||
if (active) ld->max = -LIMITS_MIN_MAX_OFFSET + checkIncDec(event, ld->max+LIMITS_MIN_MAX_OFFSET, 0, +limit, EE_MODEL);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ITEM_LIMITS_DIRECTION:
|
||||
{
|
||||
uint8_t revert = ld->revert;
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
lcdDrawChar(LIMITS_REVERT_POS, y, revert ? 127 : 126, attr);
|
||||
#else
|
||||
lcdDrawTextAtIndex(LIMITS_REVERT_POS, y, STR_MMMINV, revert, attr);
|
||||
#endif
|
||||
if (active) {
|
||||
uint8_t revert_new = checkIncDecModel(event, revert, 0, 1);
|
||||
if (checkIncDec_Ret && isThrottleOutput(k)) {
|
||||
POPUP_CONFIRMATION(STR_INVERT_THR);
|
||||
}
|
||||
else {
|
||||
ld->revert = revert_new;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(PPM_CENTER_ADJUSTABLE)
|
||||
case ITEM_LIMITS_PPM_CENTER:
|
||||
lcdDrawNumber(LIMITS_PPM_CENTER_POS, y, PPM_CENTER+ld->ppmCenter, attr);
|
||||
if (active) {
|
||||
CHECK_INCDEC_MODELVAR(event, ld->ppmCenter, -PPM_CENTER_MAX, +PPM_CENTER_MAX);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PPM_LIMITS_SYMETRICAL)
|
||||
case ITEM_LIMITS_SYMETRICAL:
|
||||
#if defined(CPUARM)
|
||||
lcdDrawChar(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '\306', attr);
|
||||
#else
|
||||
lcdDrawChar(LCD_W-FW-MENUS_SCROLLBAR_WIDTH, y, ld->symetrical ? '=' : '^', attr);
|
||||
#endif
|
||||
if (active) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, ld->symetrical, 1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* 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 MODELSIZE_POS_X 170
|
||||
#define MODELSEL_W LCD_W
|
||||
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
void onModelSelectMenu(const char *result)
|
||||
{
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
if (result == STR_SELECT_MODEL || result == STR_CREATE_MODEL) {
|
||||
selectModel(sub);
|
||||
}
|
||||
else if (result == STR_COPY_MODEL) {
|
||||
s_copyMode = COPY_MODE;
|
||||
s_copyTgtOfs = 0;
|
||||
s_copySrcRow = -1;
|
||||
}
|
||||
else if (result == STR_MOVE_MODEL) {
|
||||
s_copyMode = MOVE_MODE;
|
||||
s_copyTgtOfs = 0;
|
||||
s_copySrcRow = -1;
|
||||
}
|
||||
#if defined(SDCARD)
|
||||
else if (result == STR_BACKUP_MODEL) {
|
||||
storageCheck(true); // force writing of current model data before this is changed
|
||||
POPUP_WARNING(eeBackupModel(sub));
|
||||
}
|
||||
else if (result == STR_RESTORE_MODEL || result == STR_UPDATE_LIST) {
|
||||
if (!sdListFiles(MODELS_PATH, MODELS_EXT, MENU_LINE_LENGTH-1, NULL)) {
|
||||
POPUP_WARNING(STR_NO_MODELS_ON_SD);
|
||||
popupMenuFlags = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (result == STR_DELETE_MODEL) {
|
||||
POPUP_CONFIRMATION(STR_DELETEMODEL);
|
||||
#if defined(CPUARM)
|
||||
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
|
||||
#else
|
||||
char * name = reusableBuffer.modelsel.mainname;
|
||||
eeLoadModelName(sub, name);
|
||||
SET_WARNING_INFO(name, sizeof(g_model.header.name), ZCHAR);
|
||||
#endif
|
||||
}
|
||||
#if defined(SDCARD)
|
||||
else {
|
||||
// The user choosed a file on SD to restore
|
||||
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
|
||||
if (!warningText && g_eeGeneral.currModel == sub) {
|
||||
eeLoadModel(sub);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void menuModelSelect(uint8_t event)
|
||||
{
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
eeDeleteModel(menuVerticalPosition); // delete file
|
||||
s_copyMode = 0;
|
||||
event = EVT_ENTRY_UP;
|
||||
}
|
||||
|
||||
uint8_t _event_ = (IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event) ? 0 : event);
|
||||
|
||||
if ((s_copyMode && EVT_KEY_MASK(event) == KEY_EXIT) || event == EVT_KEY_BREAK(KEY_EXIT)) {
|
||||
_event_ -= KEY_EXIT;
|
||||
}
|
||||
|
||||
int8_t oldSub = menuVerticalPosition;
|
||||
|
||||
check_submenu_simple(_event_, MAX_MODELS-1);
|
||||
|
||||
#if defined(NAVIGATION_POT2)
|
||||
if (event==0 && p2valdiff<0) {
|
||||
event = EVT_KEY_FIRST(KEY_RIGHT);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s_editMode > 0) s_editMode = 0;
|
||||
|
||||
#if !defined(CPUARM)
|
||||
if (event) {
|
||||
eeFlush(); // flush eeprom write
|
||||
}
|
||||
#endif
|
||||
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
menuVerticalPosition = sub = g_eeGeneral.currModel;
|
||||
if (sub >= LCD_LINES-1) menuVerticalOffset = sub-LCD_LINES+2;
|
||||
s_copyMode = 0;
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
storageCheck(true);
|
||||
break;
|
||||
|
||||
case EVT_KEY_LONG(KEY_EXIT):
|
||||
killEvents(event);
|
||||
if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) {
|
||||
POPUP_CONFIRMATION(STR_DELETEMODEL);
|
||||
#if defined(CPUARM)
|
||||
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
|
||||
#else
|
||||
char * name = reusableBuffer.modelsel.mainname;
|
||||
eeLoadModelName(sub, name);
|
||||
SET_WARNING_INFO(name, sizeof(g_model.header.name), ZCHAR);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
s_copyMode = 0;
|
||||
menuVerticalPosition = g_eeGeneral.currModel;
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LONG:
|
||||
killEvents(event);
|
||||
if (s_editMode < 0) {
|
||||
popMenu();
|
||||
break;
|
||||
}
|
||||
else if (!s_copyMode) {
|
||||
menuVerticalPosition = sub = g_eeGeneral.currModel;
|
||||
s_copyMode = 0;
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
}
|
||||
// no break
|
||||
#endif
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
if (s_copyMode) {
|
||||
sub = menuVerticalPosition = (s_copyMode == MOVE_MODE || s_copySrcRow<0) ? (MAX_MODELS+sub+s_copyTgtOfs) % MAX_MODELS : s_copySrcRow;
|
||||
s_copyMode = 0;
|
||||
}
|
||||
else if (uint8_t(menuVerticalPosition) != g_eeGeneral.currModel) {
|
||||
menuVerticalPosition = g_eeGeneral.currModel;
|
||||
}
|
||||
else {
|
||||
popMenu();
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_BREAK:
|
||||
if (s_editMode == -1) {
|
||||
s_editMode = 0;
|
||||
break;
|
||||
}
|
||||
// no break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
s_editMode = 0;
|
||||
if (READ_ONLY()) {
|
||||
if (g_eeGeneral.currModel != sub && eeModelExists(sub)) {
|
||||
selectModel(sub);
|
||||
}
|
||||
}
|
||||
else if (s_copyMode && (s_copyTgtOfs || s_copySrcRow>=0)) {
|
||||
displayPopup(s_copyMode==COPY_MODE ? STR_COPYINGMODEL : STR_MOVINGMODEL);
|
||||
storageCheck(true); // force writing of current model data before this is changed
|
||||
|
||||
uint8_t cur = (MAX_MODELS + sub + s_copyTgtOfs) % MAX_MODELS;
|
||||
|
||||
if (s_copyMode == COPY_MODE) {
|
||||
if (!eeCopyModel(cur, s_copySrcRow)) {
|
||||
cur = sub;
|
||||
}
|
||||
}
|
||||
|
||||
s_copySrcRow = g_eeGeneral.currModel; // to update the currModel value
|
||||
while (sub != cur) {
|
||||
uint8_t src = cur;
|
||||
cur = (s_copyTgtOfs > 0 ? cur+MAX_MODELS-1 : cur+1) % MAX_MODELS;
|
||||
eeSwapModels(src, cur);
|
||||
if (src == s_copySrcRow)
|
||||
s_copySrcRow = cur;
|
||||
else if (cur == s_copySrcRow)
|
||||
s_copySrcRow = src;
|
||||
}
|
||||
|
||||
if (s_copySrcRow != g_eeGeneral.currModel) {
|
||||
g_eeGeneral.currModel = s_copySrcRow;
|
||||
storageDirty(EE_GENERAL);
|
||||
}
|
||||
|
||||
s_copyMode = 0;
|
||||
event = EVT_ENTRY_UP;
|
||||
}
|
||||
else if (event == EVT_KEY_LONG(KEY_ENTER) || IS_ROTARY_BREAK(event)) {
|
||||
s_copyMode = 0;
|
||||
killEvents(event);
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
if (g_eeGeneral.currModel != sub) {
|
||||
if (eeModelExists(sub)) {
|
||||
POPUP_MENU_ADD_ITEM(STR_SELECT_MODEL);
|
||||
POPUP_MENU_ADD_SD_ITEM(STR_BACKUP_MODEL);
|
||||
POPUP_MENU_ADD_ITEM(STR_COPY_MODEL);
|
||||
POPUP_MENU_ADD_ITEM(STR_MOVE_MODEL);
|
||||
POPUP_MENU_ADD_ITEM(STR_DELETE_MODEL);
|
||||
}
|
||||
else {
|
||||
#if defined(SDCARD)
|
||||
POPUP_MENU_ADD_ITEM(STR_CREATE_MODEL);
|
||||
POPUP_MENU_ADD_ITEM(STR_RESTORE_MODEL);
|
||||
#else
|
||||
selectModel(sub);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
POPUP_MENU_ADD_SD_ITEM(STR_BACKUP_MODEL);
|
||||
POPUP_MENU_ADD_ITEM(STR_COPY_MODEL);
|
||||
POPUP_MENU_ADD_ITEM(STR_MOVE_MODEL);
|
||||
}
|
||||
POPUP_MENU_START(onModelSelectMenu);
|
||||
#else
|
||||
if (g_eeGeneral.currModel != sub) {
|
||||
selectModel(sub);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (eeModelExists(sub)) {
|
||||
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
|
||||
s_copyTgtOfs = 0;
|
||||
s_copySrcRow = -1;
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LEFT:
|
||||
case EVT_ROTARY_RIGHT:
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_LEFT):
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
if ((!IS_ROTARY_RIGHT(event) && !IS_ROTARY_LEFT(event)) || s_editMode < 0) {
|
||||
#endif
|
||||
if (sub == g_eeGeneral.currModel) {
|
||||
chainMenu((IS_ROTARY_RIGHT(event) || event == EVT_KEY_FIRST(KEY_RIGHT)) ? menuModelSetup : menuTabModel[DIM(menuTabModel)-1]);
|
||||
}
|
||||
else {
|
||||
AUDIO_WARNING2();
|
||||
}
|
||||
break;
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
}
|
||||
// no break
|
||||
#endif
|
||||
|
||||
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) {
|
||||
int8_t next_ofs = s_copyTgtOfs + oldSub - menuVerticalPosition;
|
||||
if (next_ofs == MAX_MODELS || next_ofs == -MAX_MODELS)
|
||||
next_ofs = 0;
|
||||
|
||||
if (s_copySrcRow < 0 && s_copyMode==COPY_MODE) {
|
||||
s_copySrcRow = oldSub;
|
||||
// find a hole (in the first empty slot above / below)
|
||||
sub = eeFindEmptyModel(s_copySrcRow, IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_DOWN));
|
||||
if (sub < 0) {
|
||||
// no free room for duplicating the model
|
||||
AUDIO_ERROR();
|
||||
sub = oldSub;
|
||||
s_copyMode = 0;
|
||||
}
|
||||
next_ofs = 0;
|
||||
menuVerticalPosition = sub;
|
||||
}
|
||||
s_copyTgtOfs = next_ofs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(PCBSKY9X)
|
||||
lcdDrawText(9*FW-(LEN_FREE-4)*FW, 0, STR_FREE);
|
||||
if (event) reusableBuffer.modelsel.eepromfree = EeFsGetFree();
|
||||
lcdDrawNumber(17*FW, 0, reusableBuffer.modelsel.eepromfree, 0);
|
||||
#endif
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
drawScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? ((IS_RE_NAVIGATION_ENABLE() && s_editMode < 0) ? INVERS|BLINK : INVERS) : 0);
|
||||
#else
|
||||
drawScreenIndex(e_ModelSelect, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? INVERS : 0);
|
||||
#endif
|
||||
|
||||
TITLE(STR_MENUMODELSEL);
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
|
||||
lcdDrawNumber(3*FW+2, y, k+1, LEADING0+((!s_copyMode && sub==k) ? INVERS : 0), 2);
|
||||
|
||||
if (s_copyMode == MOVE_MODE || (s_copyMode == COPY_MODE && s_copySrcRow >= 0)) {
|
||||
if (k == sub) {
|
||||
if (s_copyMode == COPY_MODE) {
|
||||
k = s_copySrcRow;
|
||||
lcdDrawChar(MODELSEL_W-FW, y, '+');
|
||||
}
|
||||
else {
|
||||
k = sub + s_copyTgtOfs;
|
||||
}
|
||||
}
|
||||
else if (s_copyTgtOfs < 0 && ((k < sub && k >= sub+s_copyTgtOfs) || (k-MAX_MODELS < sub && k-MAX_MODELS >= sub+s_copyTgtOfs)))
|
||||
k += 1;
|
||||
else if (s_copyTgtOfs > 0 && ((k > sub && k <= sub+s_copyTgtOfs) || (k+MAX_MODELS > sub && k+MAX_MODELS <= sub+s_copyTgtOfs)))
|
||||
k += MAX_MODELS-1;
|
||||
}
|
||||
|
||||
k %= MAX_MODELS;
|
||||
|
||||
if (eeModelExists(k)) {
|
||||
#if defined(PCBSKY9X)
|
||||
putsModelName(4*FW, y, modelHeaders[k].name, k, 0);
|
||||
#else
|
||||
char * name = reusableBuffer.modelsel.listnames[i];
|
||||
if (event) eeLoadModelName(k, name);
|
||||
putsModelName(4*FW, y, name, k, 0);
|
||||
lcdDrawNumber(20*FW, y, eeModelSize(k), 0);
|
||||
#endif
|
||||
if (k==g_eeGeneral.currModel && (s_copyMode!=COPY_MODE || s_copySrcRow<0 || i+menuVerticalOffset!=(vertpos_t)sub))
|
||||
lcdDrawChar(1, y, '*');
|
||||
}
|
||||
|
||||
if (s_copyMode && (vertpos_t)sub==i+menuVerticalOffset) {
|
||||
lcdDrawFilledRect(9, y, MODELSEL_W-1-9, 7);
|
||||
lcdDrawRect(8, y-1, MODELSEL_W-1-7, 9, s_copyMode == COPY_MODE ? SOLID : DOTTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,893 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#if defined(CPUARM)
|
||||
uint8_t g_moduleIdx;
|
||||
void menuModelFailsafe(uint8_t event);
|
||||
#endif
|
||||
|
||||
enum menuModelSetupItems {
|
||||
ITEM_MODEL_NAME,
|
||||
ITEM_MODEL_TIMER1,
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER1_NAME)
|
||||
CASE_PERSISTENT_TIMERS(ITEM_MODEL_TIMER1_PERSISTENT)
|
||||
ITEM_MODEL_TIMER1_MINUTE_BEEP,
|
||||
ITEM_MODEL_TIMER1_COUNTDOWN_BEEP,
|
||||
ITEM_MODEL_TIMER2,
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER2_NAME)
|
||||
CASE_PERSISTENT_TIMERS(ITEM_MODEL_TIMER2_PERSISTENT)
|
||||
ITEM_MODEL_TIMER2_MINUTE_BEEP,
|
||||
ITEM_MODEL_TIMER2_COUNTDOWN_BEEP,
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER3)
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER3_NAME)
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER3_PERSISTENT)
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER3_MINUTE_BEEP)
|
||||
CASE_CPUARM(ITEM_MODEL_TIMER3_COUNTDOWN_BEEP)
|
||||
ITEM_MODEL_EXTENDED_LIMITS,
|
||||
ITEM_MODEL_EXTENDED_TRIMS,
|
||||
CASE_CPUARM(ITEM_MODEL_DISPLAY_TRIMS)
|
||||
ITEM_MODEL_TRIM_INC,
|
||||
ITEM_MODEL_THROTTLE_REVERSED,
|
||||
ITEM_MODEL_THROTTLE_TRACE,
|
||||
ITEM_MODEL_THROTTLE_TRIM,
|
||||
CASE_CPUARM(ITEM_MODEL_PREFLIGHT_LABEL)
|
||||
CASE_CPUARM(ITEM_MODEL_CHECKLIST_DISPLAY)
|
||||
ITEM_MODEL_THROTTLE_WARNING,
|
||||
ITEM_MODEL_SWITCHES_WARNING,
|
||||
ITEM_MODEL_BEEP_CENTER,
|
||||
CASE_CPUARM(ITEM_MODEL_USE_GLOBAL_FUNCTIONS)
|
||||
#if defined(CPUARM)
|
||||
ITEM_MODEL_EXTERNAL_MODULE_LABEL,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_MODE,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_CHANNELS,
|
||||
ITEM_MODEL_EXTERNAL_MODULE_BIND,
|
||||
#if defined(PCBSKY9X) && defined(REVX)
|
||||
ITEM_MODEL_EXTERNAL_MODULE_OUTPUT_TYPE,
|
||||
#endif
|
||||
ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE,
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
ITEM_MODEL_EXTRA_MODULE_LABEL,
|
||||
ITEM_MODEL_EXTRA_MODULE_CHANNELS,
|
||||
ITEM_MODEL_EXTRA_MODULE_BIND,
|
||||
#endif
|
||||
#else
|
||||
ITEM_MODEL_PPM1_PROTOCOL,
|
||||
ITEM_MODEL_PPM1_PARAMS,
|
||||
#endif
|
||||
ITEM_MODEL_SETUP_MAX
|
||||
};
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
#define FIELD_PROTOCOL_MAX 2
|
||||
#else
|
||||
#define FIELD_PROTOCOL_MAX 1
|
||||
#endif
|
||||
|
||||
#define MODEL_SETUP_2ND_COLUMN (LCD_W-11*FW-MENUS_SCROLLBAR_WIDTH)
|
||||
#define MODEL_SETUP_BIND_OFS 2*FW+1
|
||||
#define MODEL_SETUP_RANGE_OFS 4*FW+3
|
||||
#define MODEL_SETUP_SET_FAILSAFE_OFS 7*FW-2
|
||||
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
#define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_EXTRA_MODULE_LABEL ? EXTRA_MODULE : EXTERNAL_MODULE)
|
||||
#else
|
||||
#define CURRENT_MODULE_EDITED(k) (EXTERNAL_MODULE)
|
||||
#endif
|
||||
|
||||
void menuModelSetup(uint8_t event)
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
#define IF_EXTERNAL_MODULE_XJT(x) (IS_MODULE_XJT(EXTERNAL_MODULE) ? (uint8_t)(x) : HIDDEN_ROW)
|
||||
#define IF_EXTERNAL_MODULE_ON(x) (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_NONE ? HIDDEN_ROW : (uint8_t)(x))
|
||||
#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8)
|
||||
#define EXTERNAL_MODULE_CHANNELS_ROWS() IF_EXTERNAL_MODULE_ON(IS_MODULE_DSM2(EXTERNAL_MODULE) ? (uint8_t)0 : (uint8_t)1)
|
||||
#define EXTERNAL_MODULE_SETTINGS_ROWS() (IS_MODULE_XJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) ? (uint8_t)1 : (IS_MODULE_PPM(EXTERNAL_MODULE) || IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW
|
||||
#if defined(PCBSKY9X) && defined(REVX)
|
||||
#define OUTPUT_TYPE_ROWS() (IS_MODULE_PPM(EXTERNAL_MODULE) ? (uint8_t)0 : HIDDEN_ROW) ,
|
||||
#else
|
||||
#define OUTPUT_TYPE_ROWS()
|
||||
#endif
|
||||
#define TRAINER_CHANNELS_ROWS() (HIDDEN_ROW)
|
||||
#define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS() : 0)
|
||||
#define FAILSAFE_ROWS(x) (IS_MODULE_XJT(x) && HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW)
|
||||
#define CURSOR_ON_CELL (true)
|
||||
#define MODEL_SETUP_MAX_LINES (1+ITEM_MODEL_SETUP_MAX)
|
||||
#define POT_WARN_ITEMS() ((g_model.nPotsToWarn >> 6) ? (uint8_t)NUM_POTS : (uint8_t)0)
|
||||
#define TIMER_ROWS 2, 0, CASE_PERSISTENT_TIMERS(0) 0, 0
|
||||
#if defined(PCBSKY9X) && !defined(REVA)
|
||||
#define EXTRA_MODULE_ROWS LABEL(ExtraModule), 1, 2,
|
||||
#else
|
||||
#define EXTRA_MODULE_ROWS
|
||||
#endif
|
||||
#define TRAINER_MODULE_ROWS
|
||||
MENU_TAB({ 0, 0, TIMER_ROWS, TIMER_ROWS, TIMER_ROWS, 0, 1, 0, 0, 0, 0, 0, CASE_CPUARM(LABEL(PreflightCheck)) CASE_CPUARM(0) 0, 6, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, 0,
|
||||
LABEL(ExternalModule),
|
||||
(IS_MODULE_XJT(EXTERNAL_MODULE) || IS_MODULE_DSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0,
|
||||
EXTERNAL_MODULE_CHANNELS_ROWS(),
|
||||
EXTERNAL_MODULE_SETTINGS_ROWS(),
|
||||
OUTPUT_TYPE_ROWS()
|
||||
FAILSAFE_ROWS(EXTERNAL_MODULE),
|
||||
EXTRA_MODULE_ROWS
|
||||
TRAINER_MODULE_ROWS });
|
||||
#elif defined(CPUM64)
|
||||
#define CURSOR_ON_CELL (true)
|
||||
#define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX)
|
||||
uint8_t protocol = g_model.protocol;
|
||||
MENU_TAB({ 0, 0, 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2 });
|
||||
#else
|
||||
#define CURSOR_ON_CELL (true)
|
||||
#define MODEL_SETUP_MAX_LINES ((IS_PPM_PROTOCOL(protocol)||IS_DSM2_PROTOCOL(protocol)||IS_PXX_PROTOCOL(protocol)) ? 1+ITEM_MODEL_SETUP_MAX : ITEM_MODEL_SETUP_MAX)
|
||||
uint8_t protocol = g_model.protocol;
|
||||
MENU_TAB({ 0, 0, 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 2, CASE_PERSISTENT_TIMERS(0) 0, 0, 0, 1, 0, 0, 0, 0, 0, NUM_SWITCHES, NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS-1, FIELD_PROTOCOL_MAX, 2, CASE_PCBSKY9X(1) CASE_PCBSKY9X(2) });
|
||||
#endif
|
||||
|
||||
MENU_CHECK(menuTabModel, e_ModelSetup, MODEL_SETUP_MAX_LINES);
|
||||
|
||||
#if defined(CPUARM) && (defined(DSM2) || defined(PXX))
|
||||
if (menuEvent) {
|
||||
moduleFlag[0] = 0;
|
||||
#if NUM_MODULES > 1
|
||||
moduleFlag[1] = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
TITLE(STR_MENUSETUP);
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
int8_t editMode = s_editMode;
|
||||
|
||||
for (uint8_t i=0; i<NUM_BODY_LINES; ++i) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
#if defined(CPUARM)
|
||||
for (int j=0; j<=k; j++) {
|
||||
if (mstate_tab[j+1] == HIDDEN_ROW) {
|
||||
if (++k >= (int)DIM(mstate_tab)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LcdFlags blink = ((editMode>0) ? BLINK|INVERS : INVERS);
|
||||
LcdFlags attr = (sub == k ? blink : 0);
|
||||
|
||||
switch(k) {
|
||||
case ITEM_MODEL_NAME:
|
||||
editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_MODELNAME, g_model.header.name, sizeof(g_model.header.name), event, attr);
|
||||
#if defined(CPUARM)
|
||||
memcpy(modelHeaders[g_eeGeneral.currModel].name, g_model.header.name, sizeof(g_model.header.name));
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_TIMER1:
|
||||
case ITEM_MODEL_TIMER2:
|
||||
case ITEM_MODEL_TIMER3:
|
||||
{
|
||||
unsigned int timerIdx = (k>=ITEM_MODEL_TIMER3 ? 2 : (k>=ITEM_MODEL_TIMER2 ? 1 : 0));
|
||||
TimerData * timer = &g_model.timers[timerIdx];
|
||||
drawStringWithIndex(0*FW, y, STR_TIMER, timerIdx+1);
|
||||
putsTimerMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, menuHorizontalPosition==0 ? attr : 0);
|
||||
putsTimer(MODEL_SETUP_2ND_COLUMN+5*FW-2+5*FWNUM+1, y, timer->start, menuHorizontalPosition==1 ? attr : 0, menuHorizontalPosition==2 ? attr : 0);
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
div_t qr = div(timer->start, 60);
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
{
|
||||
int8_t timerMode = timer->mode;
|
||||
if (timerMode < 0) timerMode -= TMRMODE_COUNT-1;
|
||||
CHECK_INCDEC_MODELVAR_CHECK(event, timerMode, -TMRMODE_COUNT-SWSRC_LAST+1, TMRMODE_COUNT+SWSRC_LAST-1, isSwitchAvailableInTimers);
|
||||
if (timerMode < 0) timerMode += TMRMODE_COUNT-1;
|
||||
timer->mode = timerMode;
|
||||
#if defined(AUTOSWITCH)
|
||||
if (s_editMode>0) {
|
||||
int8_t val = timer->mode - (TMRMODE_COUNT-1);
|
||||
int8_t switchVal = checkIncDecMovedSwitch(val);
|
||||
if (val != switchVal) {
|
||||
timer->mode = switchVal + (TMRMODE_COUNT-1);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 539); // 8:59
|
||||
timer->start = qr.rem + qr.quot*60;
|
||||
break;
|
||||
case 2:
|
||||
qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62)-2;
|
||||
timer->start -= qr.rem ;
|
||||
if ((int16_t)timer->start < 0) timer->start=0;
|
||||
if ((int16_t)timer->start > 5999) timer->start=32399; // 8:59:59
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_TIMER1_NAME:
|
||||
case ITEM_MODEL_TIMER2_NAME:
|
||||
case ITEM_MODEL_TIMER3_NAME:
|
||||
{
|
||||
TimerData * timer = &g_model.timers[k>=ITEM_MODEL_TIMER3 ? 2 : (k>=ITEM_MODEL_TIMER2 ? 1 : 0)];
|
||||
editSingleName(MODEL_SETUP_2ND_COLUMN, y, STR_TIMER_NAME, timer->name, sizeof(timer->name), event, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_TIMER1_MINUTE_BEEP:
|
||||
case ITEM_MODEL_TIMER2_MINUTE_BEEP:
|
||||
case ITEM_MODEL_TIMER3_MINUTE_BEEP:
|
||||
{
|
||||
TimerData * timer = &g_model.timers[k>=ITEM_MODEL_TIMER3 ? 2 : (k>=ITEM_MODEL_TIMER2 ? 1 : 0)];
|
||||
timer->minuteBeep = editCheckBox(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP:
|
||||
case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP:
|
||||
case ITEM_MODEL_TIMER3_COUNTDOWN_BEEP:
|
||||
{
|
||||
TimerData * timer = &g_model.timers[k>=ITEM_MODEL_TIMER3 ? 2 : (k>=ITEM_MODEL_TIMER2 ? 1 : 0)];
|
||||
timer->countdownBeep = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, STR_VBEEPCOUNTDOWN, timer->countdownBeep, COUNTDOWN_SILENT, COUNTDOWN_COUNT-1, attr, event);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_TIMER1_PERSISTENT:
|
||||
case ITEM_MODEL_TIMER2_PERSISTENT:
|
||||
case ITEM_MODEL_TIMER3_PERSISTENT:
|
||||
{
|
||||
TimerData * timer = &g_model.timers[k>=ITEM_MODEL_TIMER3 ? 2 : (k>=ITEM_MODEL_TIMER2 ? 1 : 0)];
|
||||
timer->persistent = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, timer->persistent, 0, 2, attr, event);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
case ITEM_MODEL_TIMER1:
|
||||
case ITEM_MODEL_TIMER2:
|
||||
case ITEM_MODEL_TIMER1_MINUTE_BEEP:
|
||||
case ITEM_MODEL_TIMER2_MINUTE_BEEP:
|
||||
case ITEM_MODEL_TIMER1_COUNTDOWN_BEEP:
|
||||
case ITEM_MODEL_TIMER2_COUNTDOWN_BEEP:
|
||||
{
|
||||
TimerData *timer = &g_model.timers[k>=ITEM_MODEL_TIMER2 ? 1 : 0];
|
||||
if (k==ITEM_MODEL_TIMER1_MINUTE_BEEP || k==ITEM_MODEL_TIMER2_MINUTE_BEEP) {
|
||||
timer->minuteBeep = editCheckBox(timer->minuteBeep, MODEL_SETUP_2ND_COLUMN, y, STR_MINUTEBEEP, attr, event);
|
||||
}
|
||||
else if (k==ITEM_MODEL_TIMER1_COUNTDOWN_BEEP || k==ITEM_MODEL_TIMER2_COUNTDOWN_BEEP) {
|
||||
timer->countdownBeep = editCheckBox(timer->countdownBeep, MODEL_SETUP_2ND_COLUMN, y, STR_BEEPCOUNTDOWN, attr, event);
|
||||
}
|
||||
else {
|
||||
drawStringWithIndex(0*FW, y, STR_TIMER, k>=ITEM_MODEL_TIMER2 ? 2 : 1);
|
||||
putsTimerMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, menuHorizontalPosition==0 ? attr : 0);
|
||||
putsTimer(MODEL_SETUP_2ND_COLUMN+5*FW-2+5*FWNUM+1, y, timer->start, menuHorizontalPosition==1 ? attr : 0, menuHorizontalPosition==2 ? attr : 0);
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
div_t qr = div(timer->start, 60);
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_CHECK(event, timer->mode, SWSRC_FIRST, TMRMODE_COUNT+SWSRC_LAST-1/*SWSRC_None removed*/, isSwitchAvailableInTimers);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, qr.quot, 59);
|
||||
timer->start = qr.rem + qr.quot*60;
|
||||
break;
|
||||
case 2:
|
||||
qr.rem -= checkIncDecModel(event, qr.rem+2, 1, 62) - 2;
|
||||
if ((int16_t)timer->start >= qr.rem) {
|
||||
timer->start -= qr.rem ;
|
||||
}
|
||||
if ((int16_t)timer->start > 3599) {
|
||||
timer->start = 3599; // 59:59
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(CPUM2560)
|
||||
case ITEM_MODEL_TIMER1_PERSISTENT:
|
||||
case ITEM_MODEL_TIMER2_PERSISTENT:
|
||||
{
|
||||
TimerData &timer = g_model.timers[k==ITEM_MODEL_TIMER2_PERSISTENT];
|
||||
timer.persistent = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_PERSISTENT, STR_VPERSISTENT, timer.persistent, 0, 2, attr, event);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
case ITEM_MODEL_EXTENDED_LIMITS:
|
||||
ON_OFF_MENU_ITEM(g_model.extendedLimits, MODEL_SETUP_2ND_COLUMN, y, STR_ELIMITS, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_EXTENDED_TRIMS:
|
||||
#if defined(CPUM64)
|
||||
ON_OFF_MENU_ITEM(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, attr, event);
|
||||
#else
|
||||
ON_OFF_MENU_ITEM(g_model.extendedTrims, MODEL_SETUP_2ND_COLUMN, y, STR_ETRIMS, menuHorizontalPosition<=0 ? attr : 0, event==EVT_KEY_BREAK(KEY_ENTER) ? event : 0);
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_RESET_BTN, (menuHorizontalPosition>0 && !NO_HIGHLIGHT()) ? attr : 0);
|
||||
if (attr && menuHorizontalPosition>0) {
|
||||
s_editMode = 0;
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
START_NO_HIGHLIGHT();
|
||||
for (uint8_t i=0; i<MAX_FLIGHT_MODES; i++) {
|
||||
memclear(&g_model.flightModeData[i], TRIMS_ARRAY_SIZE);
|
||||
}
|
||||
storageDirty(EE_MODEL);
|
||||
AUDIO_WARNING1();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_DISPLAY_TRIMS:
|
||||
g_model.displayTrims = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_DISPLAY_TRIMS, STR_VDISPLAYTRIMS, g_model.displayTrims, 0, 2, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_MODEL_TRIM_INC:
|
||||
g_model.trimInc = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_TRIMINC, STR_VTRIMINC, g_model.trimInc, -2, 2, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_THROTTLE_REVERSED:
|
||||
ON_OFF_MENU_ITEM(g_model.throttleReversed, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEREVERSE, attr, event ) ;
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_THROTTLE_TRACE:
|
||||
{
|
||||
lcd_putsLeft(y, STR_TTRACE);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.thrTraceSrc, NUM_POTS+NUM_CHNOUT);
|
||||
uint8_t idx = g_model.thrTraceSrc + MIXSRC_Thr;
|
||||
if (idx > MIXSRC_Thr)
|
||||
idx += 1;
|
||||
if (idx >= MIXSRC_FIRST_POT+NUM_POTS)
|
||||
idx += MIXSRC_CH1 - MIXSRC_FIRST_POT - NUM_POTS;
|
||||
putsMixerSource(MODEL_SETUP_2ND_COLUMN, y, idx, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_THROTTLE_TRIM:
|
||||
ON_OFF_MENU_ITEM(g_model.thrTrim, MODEL_SETUP_2ND_COLUMN, y, STR_TTRIM, attr, event);
|
||||
break;
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_PREFLIGHT_LABEL:
|
||||
lcd_putsLeft(y, STR_PREFLIGHT);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_CHECKLIST_DISPLAY:
|
||||
ON_OFF_MENU_ITEM(g_model.displayChecklist, MODEL_SETUP_2ND_COLUMN, y, STR_CHECKLIST, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_MODEL_THROTTLE_WARNING:
|
||||
g_model.disableThrottleWarning = !editCheckBox(!g_model.disableThrottleWarning, MODEL_SETUP_2ND_COLUMN, y, STR_THROTTLEWARNING, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_SWITCHES_WARNING:
|
||||
{
|
||||
lcd_putsLeft(y, STR_SWITCHWARNING);
|
||||
swarnstate_t states = g_model.switchWarningState;
|
||||
char c;
|
||||
if (attr) {
|
||||
s_editMode = 0;
|
||||
if (!READ_ONLY()) {
|
||||
switch (event) {
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
#if defined(CPUM64)
|
||||
g_model.switchWarningEnable ^= (1 << menuHorizontalPosition);
|
||||
storageDirty(EE_MODEL);
|
||||
#else
|
||||
if (menuHorizontalPosition < NUM_SWITCHES-1) {
|
||||
g_model.switchWarningEnable ^= (1 << menuHorizontalPosition);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
#if defined(CPUM64)
|
||||
getMovedSwitch();
|
||||
g_model.switchWarningState = switches_states;
|
||||
AUDIO_WARNING1();
|
||||
storageDirty(EE_MODEL);
|
||||
#else
|
||||
if (menuHorizontalPosition == NUM_SWITCHES-1) {
|
||||
START_NO_HIGHLIGHT();
|
||||
getMovedSwitch();
|
||||
g_model.switchWarningState = switches_states;
|
||||
AUDIO_WARNING1();
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
#endif
|
||||
killEvents(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LcdFlags line = attr;
|
||||
|
||||
for (uint8_t i=0; i<NUM_SWITCHES-1/*not on TRN switch*/; i++) {
|
||||
uint8_t swactive = !(g_model.switchWarningEnable & 1 << i);
|
||||
attr = 0;
|
||||
|
||||
if (IS_3POS(i)) {
|
||||
c = '0'+(states & 0x03);
|
||||
states >>= 2;
|
||||
}
|
||||
else {
|
||||
if ((states & 0x01) && swactive)
|
||||
attr = INVERS;
|
||||
c = pgm_read_byte(STR_VSWITCHES - 2 + 9 + (3*(i+1)));
|
||||
states >>= 1;
|
||||
}
|
||||
if (line && (menuHorizontalPosition == i)) {
|
||||
attr = BLINK;
|
||||
if (swactive)
|
||||
attr |= INVERS;
|
||||
}
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+i*FW, y, (swactive || (attr & BLINK)) ? c : '-', attr);
|
||||
#if !defined(CPUM64)
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+(NUM_SWITCHES*FW), y, PSTR("<]"), (menuHorizontalPosition == NUM_SWITCHES-1 && !NO_HIGHLIGHT()) ? line : 0);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_MODEL_BEEP_CENTER:
|
||||
lcd_putsLeft(y, STR_BEEPCTR);
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS+NUM_ROTARY_ENCODERS; i++) {
|
||||
// TODO flash saving, \001 not needed in STR_RETA123
|
||||
coord_t x = MODEL_SETUP_2ND_COLUMN+i*FW;
|
||||
lcdDrawTextAtIndex(x, y, STR_RETA123, i, ((menuHorizontalPosition==i) && attr) ? BLINK|INVERS : (((g_model.beepANACenter & ((BeepANACenter)1<<i)) || (attr && CURSOR_ON_LINE())) ? INVERS : 0 ) );
|
||||
}
|
||||
if (attr && CURSOR_ON_CELL) {
|
||||
if (event==EVT_KEY_BREAK(KEY_ENTER) || p1valdiff) {
|
||||
if (READ_ONLY_UNLOCKED()) {
|
||||
s_editMode = 0;
|
||||
g_model.beepANACenter ^= ((BeepANACenter)1<<menuHorizontalPosition);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_USE_GLOBAL_FUNCTIONS:
|
||||
lcd_putsLeft(y, STR_USE_GLOBAL_FUNCS);
|
||||
drawCheckBox(MODEL_SETUP_2ND_COLUMN, y, !g_model.noGlobalFunctions, attr);
|
||||
if (attr) g_model.noGlobalFunctions = !checkIncDecModel(event, !g_model.noGlobalFunctions, 0, 1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
case ITEM_MODEL_EXTRA_MODULE_LABEL:
|
||||
lcd_putsLeft(y, "RF Port 2 (PPM)");
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_LABEL:
|
||||
lcd_putsLeft(y, TR_EXTERNALRF);
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_MODE:
|
||||
lcd_putsLeft(y, STR_MODE);
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_TARANIS_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].type, menuHorizontalPosition==0 ? attr : 0);
|
||||
if (IS_MODULE_XJT(EXTERNAL_MODULE))
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
|
||||
else if (IS_MODULE_DSM2(EXTERNAL_MODULE))
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+5*FW, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable);
|
||||
if (checkIncDec_Ret) {
|
||||
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
|
||||
if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM)
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = 0;
|
||||
else
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (IS_MODULE_DSM2(EXTERNAL_MODULE))
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
|
||||
else
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, RF_PROTO_X16, RF_PROTO_LAST);
|
||||
if (checkIncDec_Ret) {
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
|
||||
g_model.moduleData[EXTERNAL_MODULE].channelsCount = MAX_EXTERNAL_MODULE_CHANNELS();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
case ITEM_MODEL_EXTRA_MODULE_CHANNELS:
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
lcd_putsLeft(y, STR_CHANNELRANGE);
|
||||
if ((int8_t)PORT_CHANNELS_ROWS(moduleIdx) >= 0) {
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_CH, menuHorizontalPosition==0 ? attr : 0);
|
||||
lcdDrawNumber(lcdLastPos, y, moduleData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0));
|
||||
lcdDrawChar(lcdLastPos, y, '-');
|
||||
lcdDrawNumber(lcdLastPos + FW+1, y, moduleData.channelsStart+NUM_CHANNELS(moduleIdx), LEFT | (menuHorizontalPosition==1 ? attr : 0));
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min<int8_t>(MAX_CHANNELS(moduleIdx), 32-8-moduleData.channelsStart));
|
||||
if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM)) {
|
||||
SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
case ITEM_MODEL_EXTRA_MODULE_BIND:
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_BIND:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
if (IS_MODULE_PPM(moduleIdx)) {
|
||||
lcd_putsLeft(y, STR_PPMFRAME);
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS);
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)moduleData.ppm.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT);
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u');
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (moduleData.ppm.delay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+10*FW, y, moduleData.ppm.pulsePol ? '+' : '-', (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0);
|
||||
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, moduleData.ppm.frameLength, -20, 35);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, moduleData.ppm.delay, -4, 10);
|
||||
break;
|
||||
case 2:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.ppm.pulsePol, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
horzpos_t l_posHorz = menuHorizontalPosition;
|
||||
coord_t xOffsetBind = MODEL_SETUP_BIND_OFS;
|
||||
if (IS_MODULE_XJT(moduleIdx) && IS_D8_RX(moduleIdx)) {
|
||||
xOffsetBind = 0;
|
||||
lcd_putsLeft(y, STR_RECEIVER);
|
||||
if (attr) l_posHorz += 1;
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(y, STR_RECEIVER_NUM);
|
||||
}
|
||||
if (IS_MODULE_XJT(moduleIdx) || IS_MODULE_DSM2(moduleIdx)) {
|
||||
if (xOffsetBind) lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
|
||||
if (attr && l_posHorz==0) {
|
||||
if (editMode>0 || p1valdiff) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], IS_MODULE_DSM2(moduleIdx) ? 20 : 63);
|
||||
if (checkIncDec_Ret) {
|
||||
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
|
||||
}
|
||||
}
|
||||
if (editMode==0 && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
checkModelIdUnique(g_eeGeneral.currModel, moduleIdx);
|
||||
}
|
||||
}
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, l_posHorz==1 ? attr : 0);
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, l_posHorz==2 ? attr : 0);
|
||||
uint8_t newFlag = 0;
|
||||
if (attr && l_posHorz>0 && s_editMode>0) {
|
||||
if (l_posHorz == 1)
|
||||
newFlag = MODULE_BIND;
|
||||
else if (l_posHorz == 2) {
|
||||
newFlag = MODULE_RANGECHECK;
|
||||
}
|
||||
}
|
||||
moduleFlag[moduleIdx] = newFlag;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X) && defined(REVX)
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_OUTPUT_TYPE:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
moduleData.ppm.outputType = selectMenuItem(MODEL_SETUP_2ND_COLUMN, y, STR_OUTPUT_TYPE, STR_VOUTPUT_TYPE, moduleData.ppm.outputType, 0, 1, attr, event);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE:
|
||||
{
|
||||
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
|
||||
ModuleData & moduleData = g_model.moduleData[moduleIdx];
|
||||
lcd_putsLeft(y, TR_FAILSAFE);
|
||||
if (IS_MODULE_XJT(moduleIdx)) {
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VFAILSAFE, moduleData.failsafeMode, menuHorizontalPosition==0 ? attr : 0);
|
||||
if (moduleData.failsafeMode == FAILSAFE_CUSTOM) lcdDrawText(MODEL_SETUP_2ND_COLUMN + MODEL_SETUP_SET_FAILSAFE_OFS, y, STR_SET, menuHorizontalPosition==1 ? attr : 0);
|
||||
if (attr) {
|
||||
if (moduleData.failsafeMode != FAILSAFE_CUSTOM)
|
||||
menuHorizontalPosition = 0;
|
||||
if (menuHorizontalPosition==0) {
|
||||
if (editMode>0 || p1valdiff) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.failsafeMode, FAILSAFE_LAST);
|
||||
if (checkIncDec_Ret) SEND_FAILSAFE_NOW(moduleIdx);
|
||||
}
|
||||
}
|
||||
else if (menuHorizontalPosition==1) {
|
||||
s_editMode = 0;
|
||||
if (moduleData.failsafeMode==FAILSAFE_CUSTOM && event==EVT_KEY_FIRST(KEY_ENTER)) {
|
||||
g_moduleIdx = moduleIdx;
|
||||
pushMenu(menuModelFailsafe);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcdDrawFilledRect(MODEL_SETUP_2ND_COLUMN, y, LCD_W-MODEL_SETUP_2ND_COLUMN-MENUS_SCROLLBAR_WIDTH, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM)
|
||||
case ITEM_MODEL_PPM1_PROTOCOL:
|
||||
lcd_putsLeft(y, NO_INDENT(STR_PROTO));
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, protocol, menuHorizontalPosition<=0 ? attr : 0);
|
||||
if (IS_PPM_PROTOCOL(protocol)) {
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN+7*FW, y, STR_NCHANNELS, g_model.ppmNCH+2, menuHorizontalPosition!=0 ? attr : 0);
|
||||
}
|
||||
else if (menuHorizontalPosition>0 && attr) {
|
||||
MOVE_CURSOR_FROM_HERE();
|
||||
}
|
||||
if (attr && (editMode>0 || p1valdiff || (!IS_PPM_PROTOCOL(protocol) && !IS_DSM2_PROTOCOL(protocol)))) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.protocol, PROTO_MAX-1);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.ppmNCH, -2, 4);
|
||||
g_model.ppmFrameLength = g_model.ppmNCH * 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
case ITEM_MODEL_PPM2_PROTOCOL:
|
||||
lcd_putsLeft(y, PSTR("Port2"));
|
||||
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VPROTOS, 0, 0);
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+4*FW+3, y, STR_CH, menuHorizontalPosition<=0 ? attr : 0);
|
||||
lcdDrawNumber(lcdLastPos, y, g_model.moduleData[1].channelsStart+1, LEFT | (menuHorizontalPosition<=0 ? attr : 0));
|
||||
lcdDrawChar(lcdLastPos, y, '-');
|
||||
lcdDrawNumber(lcdLastPos + FW+1, y, g_model.moduleData[1].channelsStart+8+g_model.moduleData[1].channelsCount, LEFT | (menuHorizontalPosition!=0 ? attr : 0));
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].channelsStart, 32-8-g_model.moduleData[1].channelsCount);
|
||||
SET_DEFAULT_PPM_FRAME_LENGTH(1);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].channelsCount, -4, min<int8_t>(8, 32-8-g_model.moduleData[1].channelsStart));
|
||||
SET_DEFAULT_PPM_FRAME_LENGTH(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_MODEL_PPM2_PARAMS:
|
||||
lcd_putsLeft(y, STR_PPMFRAME);
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS);
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.moduleData[1].ppmFrameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT);
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u');
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[1].ppmDelay*50)+300, (menuHorizontalPosition < 0 || menuHorizontalPosition==1) ? attr : 0);
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[1].ppmPulsePol ? '+' : '-', (menuHorizontalPosition < 0 || menuHorizontalPosition==2) ? attr : 0);
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmFrameLength, -20, 35);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmDelay, -4, 10);
|
||||
break;
|
||||
case 2:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].ppmPulsePol, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM)
|
||||
case ITEM_MODEL_PPM1_PARAMS:
|
||||
if (IS_PPM_PROTOCOL(protocol)) {
|
||||
lcd_putsLeft(y, STR_PPMFRAME);
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS);
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.ppmFrameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT);
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u');
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.ppmDelay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
|
||||
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.pulsePol ? '+' : '-', (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0);
|
||||
if (attr && (editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.ppmFrameLength, -20, 35);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.ppmDelay, -4, 10);
|
||||
break;
|
||||
case 2:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.pulsePol, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(DSM2) || defined(PXX)
|
||||
else if (IS_DSM2_PROTOCOL(protocol) || IS_PXX_PROTOCOL(protocol)) {
|
||||
if (attr && menuHorizontalPosition > 1) {
|
||||
REPEAT_LAST_CURSOR_MOVE(); // limit 3 column row to 2 colums (Rx_Num and RANGE fields)
|
||||
}
|
||||
lcd_putsLeft(y, STR_RECEIVER_NUM);
|
||||
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[0], (menuHorizontalPosition<=0 ? attr : 0) | LEADING0|LEFT, 2);
|
||||
if (attr && (menuHorizontalPosition==0 && (editMode>0 || p1valdiff))) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[0], 99);
|
||||
}
|
||||
#if defined(PXX)
|
||||
if (protocol == PROTO_PXX) {
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_SYNCMENU, menuHorizontalPosition!=0 ? attr : 0);
|
||||
uint8_t newFlag = 0;
|
||||
if (attr && menuHorizontalPosition>0 && editMode>0) {
|
||||
// send reset code
|
||||
newFlag = MODULE_BIND;
|
||||
}
|
||||
moduleFlag[0] = newFlag;
|
||||
}
|
||||
#endif
|
||||
#if defined(DSM2)
|
||||
if (IS_DSM2_PROTOCOL(protocol)) {
|
||||
lcdDrawText(MODEL_SETUP_2ND_COLUMN+4*FW, y, STR_MODULE_RANGE, menuHorizontalPosition!=0 ? attr : 0);
|
||||
moduleFlag[0] = (attr && menuHorizontalPosition>0 && editMode>0) ? MODULE_RANGECHECK : 0; // [MENU] key toggles range check mode
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CPUARM) && defined(PXX)
|
||||
if (IS_RANGECHECK_ENABLE()) {
|
||||
displayPopup("RSSI: ");
|
||||
lcdDrawNumber(16+4*FW, 5*FH, TELEMETRY_RSSI(), BOLD);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
void menuModelFailsafe(uint8_t event)
|
||||
{
|
||||
static bool longNames = false;
|
||||
bool newLongNames = false;
|
||||
uint8_t ch = 0;
|
||||
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER) && s_editMode) {
|
||||
START_NO_HIGHLIGHT();
|
||||
g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition];
|
||||
storageDirty(EE_MODEL);
|
||||
AUDIO_WARNING1();
|
||||
SEND_FAILSAFE_NOW(g_moduleIdx);
|
||||
}
|
||||
|
||||
SIMPLE_SUBMENU_NOTITLE(NUM_CHNOUT);
|
||||
|
||||
SET_SCROLLBAR_X(0);
|
||||
|
||||
#define COL_W (LCD_W)
|
||||
const uint8_t SLIDER_W = 90;
|
||||
ch = 8 * (menuVerticalPosition / 8);
|
||||
|
||||
lcd_putsCenter(0*FH, FAILSAFESET);
|
||||
lcdInvertLine(0);
|
||||
|
||||
uint8_t col = 0;
|
||||
|
||||
{
|
||||
coord_t x = col*COL_W+1;
|
||||
|
||||
// Channels
|
||||
for (uint8_t line=0; line<8; line++) {
|
||||
coord_t y = 9+line*7;
|
||||
int32_t val;
|
||||
uint8_t ofs = (col ? 0 : 1);
|
||||
|
||||
if (ch < g_model.moduleData[g_moduleIdx].channelsStart || ch >= NUM_CHANNELS(g_moduleIdx) + g_model.moduleData[g_moduleIdx].channelsStart)
|
||||
val = 0;
|
||||
else if (s_editMode && menuVerticalPosition == ch)
|
||||
val = channelOutputs[ch];
|
||||
else
|
||||
val = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
|
||||
|
||||
putsChn(x+1-ofs, y, ch+1, SMLSIZE);
|
||||
|
||||
// Value
|
||||
LcdFlags flags = TINSIZE;
|
||||
if (menuVerticalPosition == ch && !NO_HIGHLIGHT()) {
|
||||
flags |= INVERS;
|
||||
if (s_editMode)
|
||||
flags |= BLINK;
|
||||
}
|
||||
#if defined(PPM_UNIT_US)
|
||||
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, PPM_CH_CENTER(ch)+val/2, flags);
|
||||
#elif defined(PPM_UNIT_PERCENT_PREC1)
|
||||
uint8_t wbar = (longNames ? SLIDER_W-16 : SLIDER_W-6);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val), PREC1|flags);
|
||||
#else
|
||||
uint8_t wbar = (longNames ? SLIDER_W-10 : SLIDER_W);
|
||||
lcdDrawNumber(x+COL_W-4-wbar-ofs, y, calcRESXto1000(val)/10, flags);
|
||||
#endif
|
||||
|
||||
// Gauge
|
||||
lcdDrawRect(x+COL_W-3-wbar-ofs, y, wbar+1, 6);
|
||||
uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2;
|
||||
uint8_t len = limit((uint8_t)1, uint8_t((abs(val) * wbar/2 + lim/2) / lim), uint8_t(wbar/2));
|
||||
coord_t x0 = (val>0) ? x+COL_W-ofs-3-wbar/2 : x+COL_W-ofs-2-wbar/2-len;
|
||||
lcdDrawSolidHorizontalLine(x0, y+1, len);
|
||||
lcdDrawSolidHorizontalLine(x0, y+2, len);
|
||||
lcdDrawSolidHorizontalLine(x0, y+3, len);
|
||||
lcdDrawSolidHorizontalLine(x0, y+4, len);
|
||||
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
longNames = newLongNames;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* 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 MODEL_SPECIAL_FUNC_1ST_COLUMN (3)
|
||||
#define MODEL_SPECIAL_FUNC_2ND_COLUMN (5*FW-2)
|
||||
#define MODEL_SPECIAL_FUNC_3RD_COLUMN (15*FW+2)
|
||||
#define MODEL_SPECIAL_FUNC_4TH_COLUMN (20*FW)
|
||||
#if defined(GRAPHICS)
|
||||
#define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (20*FW)
|
||||
#else
|
||||
#define MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF (18*FW+2)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM) && defined(SDCARD)
|
||||
void onCustomFunctionsFileSelectionMenu(const char *result)
|
||||
{
|
||||
int sub = menuVerticalPosition - 1;
|
||||
CustomFunctionData * cfn;
|
||||
uint8_t eeFlags;
|
||||
|
||||
if (menuHandlers[menuLevel] == menuModelCustomFunctions) {
|
||||
cfn = &g_model.customFn[sub];
|
||||
eeFlags = EE_MODEL;
|
||||
}
|
||||
else {
|
||||
cfn = &g_eeGeneral.customFn[sub];
|
||||
eeFlags = EE_GENERAL;
|
||||
}
|
||||
|
||||
uint8_t func = CFN_FUNC(cfn);
|
||||
|
||||
if (result == STR_UPDATE_LIST) {
|
||||
char directory[256];
|
||||
if (func == FUNC_PLAY_SCRIPT) {
|
||||
strcpy(directory, SCRIPTS_FUNCS_PATH);
|
||||
}
|
||||
else {
|
||||
strcpy(directory, SOUNDS_PATH);
|
||||
strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
}
|
||||
if (!sdListFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), NULL)) {
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
popupMenuFlags = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The user choosed a file in the list
|
||||
memcpy(cfn->play.name, result, sizeof(cfn->play.name));
|
||||
storageDirty(eeFlags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void menuCustomFunctions(uint8_t event, CustomFunctionData * functions, CustomFunctionsContext * functionsContext)
|
||||
{
|
||||
int8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
#if defined(CPUARM)
|
||||
uint8_t eeFlags = (functions == g_model.customFn) ? EE_MODEL : EE_GENERAL;
|
||||
#elif !defined(CPUM64) || defined(AUTOSWITCH)
|
||||
uint8_t eeFlags = EE_MODEL;
|
||||
#endif
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
|
||||
CustomFunctionData *cfn = &functions[k];
|
||||
uint8_t func = CFN_FUNC(cfn);
|
||||
for (uint8_t j=0; j<5; j++) {
|
||||
uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
|
||||
uint8_t active = (attr && (s_editMode>0 || p1valdiff));
|
||||
switch (j) {
|
||||
case 0:
|
||||
putsSwitches(MODEL_SPECIAL_FUNC_1ST_COLUMN, y, CFN_SWITCH(cfn), attr | ((functionsContext->activeSwitches & ((MASK_CFN_TYPE)1 << k)) ? BOLD : 0));
|
||||
if (active || AUTOSWITCH_ENTER_LONG()) CHECK_INCDEC_SWITCH(event, CFN_SWITCH(cfn), SWSRC_FIRST, SWSRC_LAST, eeFlags, isSwitchAvailableInCustomFunctions);
|
||||
#if defined(CPUARM)
|
||||
if (func == FUNC_OVERRIDE_CHANNEL && functions != g_model.customFn) {
|
||||
func = CFN_FUNC(cfn) = func+1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (CFN_SWITCH(cfn)) {
|
||||
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_2ND_COLUMN, y, STR_VFSWFUNC, func, attr);
|
||||
if (active) {
|
||||
#if defined(CPUARM)
|
||||
CFN_FUNC(cfn) = checkIncDec(event, CFN_FUNC(cfn), 0, FUNC_MAX-1, eeFlags, isAssignableFunctionAvailable);
|
||||
#else
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, CFN_FUNC(cfn), FUNC_MAX-1);
|
||||
#endif
|
||||
if (checkIncDec_Ret) CFN_RESET(cfn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
j = 4; // skip other fields
|
||||
if (sub==k && menuHorizontalPosition > 0) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
int8_t maxParam = NUM_CHNOUT-1;
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
if (func == FUNC_OVERRIDE_CHANNEL) {
|
||||
putsChn(lcdNextPos, y, CFN_CH_INDEX(cfn)+1, attr);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (func == FUNC_TRAINER) {
|
||||
maxParam = 4;
|
||||
#if defined(CPUARM)
|
||||
putsMixerSource(lcdNextPos, y, CFN_CH_INDEX(cfn)==0 ? 0 : MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr);
|
||||
#else
|
||||
putsMixerSource(lcdNextPos, y, MIXSRC_Rud+CFN_CH_INDEX(cfn)-1, attr);
|
||||
#endif
|
||||
}
|
||||
#if defined(GVARS)
|
||||
else if (func == FUNC_ADJUST_GVAR) {
|
||||
maxParam = MAX_GVARS-1;
|
||||
drawStringWithIndex(lcdNextPos, y, STR_GV, CFN_GVAR_INDEX(cfn)+1, attr);
|
||||
#if defined(CPUARM)
|
||||
if (active) CFN_GVAR_INDEX(cfn) = checkIncDec(event, CFN_GVAR_INDEX(cfn), 0, maxParam, eeFlags);
|
||||
#else
|
||||
if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_GVAR_INDEX(cfn), maxParam);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
else if (func == FUNC_SET_TIMER) {
|
||||
maxParam = MAX_TIMERS-1;
|
||||
lcdDrawTextAtIndex(lcdNextPos, y, STR_VFSWRESET, CFN_TIMER_INDEX(cfn), attr);
|
||||
if (active) CFN_TIMER_INDEX(cfn) = checkIncDec(event, CFN_TIMER_INDEX(cfn), 0, maxParam, eeFlags);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_CH_INDEX(cfn), maxParam);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
INCDEC_DECLARE_VARS(eeFlags);
|
||||
int16_t val_displayed = CFN_PARAM(cfn);
|
||||
#if defined(CPUARM)
|
||||
int16_t val_min = 0;
|
||||
int16_t val_max = 255;
|
||||
#else
|
||||
int8_t val_min = 0;
|
||||
uint8_t val_max = 255;
|
||||
#endif
|
||||
if (func == FUNC_RESET) {
|
||||
val_max = FUNC_RESET_PARAM_LAST;
|
||||
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, STR_VFSWRESET, CFN_PARAM(cfn), attr);
|
||||
}
|
||||
#if defined(OVERRIDE_CHANNEL_FUNCTION)
|
||||
else if (func == FUNC_OVERRIDE_CHANNEL) {
|
||||
#if !defined(CPUARM)
|
||||
val_displayed = (int8_t)CFN_PARAM(cfn);
|
||||
#endif
|
||||
val_min = -LIMIT_EXT_PERCENT; val_max = +LIMIT_EXT_PERCENT;
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
else if (func >= FUNC_SET_FAILSAFE && func <= FUNC_BIND) {
|
||||
val_max = NUM_MODULES-1;
|
||||
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, "\004Int.Ext.", CFN_PARAM(cfn), attr);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
else if (func == FUNC_SET_TIMER) {
|
||||
val_max = 539*60+59;
|
||||
putsTimer(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT, attr);
|
||||
}
|
||||
#endif
|
||||
#if defined(AUDIO)
|
||||
else if (func == FUNC_PLAY_SOUND) {
|
||||
val_max = AU_SPECIAL_SOUND_LAST-AU_SPECIAL_SOUND_FIRST-1;
|
||||
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, STR_FUNCSOUNDS, val_displayed, attr);
|
||||
}
|
||||
#endif
|
||||
#if defined(HAPTIC)
|
||||
else if (func == FUNC_HAPTIC) {
|
||||
val_max = 3;
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM) && defined(SDCARD)
|
||||
else if (func == FUNC_PLAY_TRACK || func == FUNC_BACKGND_MUSIC || func == FUNC_PLAY_SCRIPT) {
|
||||
coord_t x = (func == FUNC_PLAY_TRACK ? MODEL_SPECIAL_FUNC_2ND_COLUMN + FW + FW*strlen(TR_PLAY_TRACK) : MODEL_SPECIAL_FUNC_3RD_COLUMN);
|
||||
if (ZEXIST(cfn->play.name))
|
||||
lcdDrawSizedText(x, y, cfn->play.name, sizeof(cfn->play.name), attr);
|
||||
else
|
||||
lcdDrawTextAtIndex(x, y, STR_VCSWFUNC, 0, attr);
|
||||
if (active && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
char directory[256];
|
||||
if (func==FUNC_PLAY_SCRIPT) {
|
||||
strcpy(directory, SCRIPTS_FUNCS_PATH);
|
||||
}
|
||||
else {
|
||||
strcpy(directory, SOUNDS_PATH);
|
||||
strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
|
||||
}
|
||||
if (sdListFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), cfn->play.name)) {
|
||||
POPUP_MENU_START(onCustomFunctionsFileSelectionMenu);
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
|
||||
popupMenuFlags = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (func == FUNC_PLAY_VALUE) {
|
||||
val_max = MIXSRC_LAST_TELEM;
|
||||
putsMixerSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
else if (func == FUNC_VOLUME) {
|
||||
val_max = MIXSRC_LAST_CH;
|
||||
putsMixerSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
}
|
||||
#elif defined(VOICE)
|
||||
else if (func == FUNC_PLAY_TRACK) {
|
||||
#if defined(GVARS)
|
||||
if (attr && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
s_editMode = !s_editMode;
|
||||
active = true;
|
||||
val_displayed = (val_displayed > 250 ? 0 : 251);
|
||||
}
|
||||
if (val_displayed > 250) {
|
||||
drawStringWithIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, STR_GV, val_displayed-250, attr);
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT);
|
||||
}
|
||||
#else
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed+PROMPT_CUSTOM_BASE, attr|LEFT);
|
||||
#endif
|
||||
}
|
||||
else if (func == FUNC_PLAY_BOTH) {
|
||||
lcdDrawChar(MODEL_SPECIAL_FUNC_3RD_COLUMN+3*FWNUM, y, '|', attr);
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN+3*FWNUM, y, val_displayed+PROMPT_CUSTOM_BASE, attr);
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN+2+3*FWNUM, y, (val_displayed+PROMPT_CUSTOM_BASE+1)%10, attr|LEFT);
|
||||
}
|
||||
else if (func == FUNC_PLAY_VALUE) {
|
||||
val_max = MIXSRC_FIRST_TELEM + TELEM_DISPLAY_MAX - 1;
|
||||
putsMixerSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_ENABLE_CHECK(functionsContext == &globalFunctionsContext ? isSourceAvailableInGlobalFunctions : isSourceAvailable);
|
||||
}
|
||||
#endif
|
||||
#if defined(SDCARD)
|
||||
else if (func == FUNC_LOGS) {
|
||||
if (val_displayed) {
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|PREC1|LEFT);
|
||||
lcdDrawChar(lcdLastPos, y, 's');
|
||||
}
|
||||
else {
|
||||
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, STR_MMMINV, 0, attr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(GVARS)
|
||||
else if (func == FUNC_ADJUST_GVAR) {
|
||||
switch (CFN_GVAR_MODE(cfn)) {
|
||||
case FUNC_ADJUST_GVAR_CONSTANT:
|
||||
val_displayed = (int16_t)CFN_PARAM(cfn);
|
||||
val_min = -CFN_GVAR_CST_MAX; val_max = +CFN_GVAR_CST_MAX;
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr|LEFT);
|
||||
break;
|
||||
case FUNC_ADJUST_GVAR_SOURCE:
|
||||
val_max = MIXSRC_LAST_CH;
|
||||
putsMixerSource(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, val_displayed, attr);
|
||||
INCDEC_SET_FLAG(eeFlags | INCDEC_SOURCE);
|
||||
INCDEC_ENABLE_CHECK(isSourceAvailable);
|
||||
break;
|
||||
case FUNC_ADJUST_GVAR_GVAR:
|
||||
val_max = MAX_GVARS-1;
|
||||
drawStringWithIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, STR_GV, val_displayed+1, attr);
|
||||
break;
|
||||
default: // FUNC_ADJUST_GVAR_INC
|
||||
val_max = 1;
|
||||
lcdDrawTextAtIndex(MODEL_SPECIAL_FUNC_3RD_COLUMN, y, PSTR("\003-=1+=1"), val_displayed, attr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (attr && event==EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
s_editMode = !s_editMode;
|
||||
active = true;
|
||||
CFN_GVAR_MODE(cfn) += 1;
|
||||
#if defined(CPUARM)
|
||||
CFN_GVAR_MODE(cfn) &= 0x03;
|
||||
#endif
|
||||
val_displayed = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
|
||||
if (active) {
|
||||
CFN_PARAM(cfn) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
if (HAS_ENABLE_PARAM(func)) {
|
||||
drawCheckBox(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF, y, CFN_ACTIVE(cfn), attr);
|
||||
#if defined(CPUARM)
|
||||
if (active) CFN_ACTIVE(cfn) = checkIncDec(event, CFN_ACTIVE(cfn), 0, 1, eeFlags);
|
||||
#else
|
||||
if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_ACTIVE(cfn), 1);
|
||||
#endif
|
||||
}
|
||||
else if (HAS_REPEAT_PARAM(func)) {
|
||||
if (CFN_PLAY_REPEAT(cfn) == 0) {
|
||||
lcdDrawChar(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF+3, y, '-', attr);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
else if (CFN_PLAY_REPEAT(cfn) == CFN_PLAY_REPEAT_NOSTART) {
|
||||
lcdDrawText(MODEL_SPECIAL_FUNC_4TH_COLUMN_ONOFF, y, "!-", attr);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
lcdDrawNumber(MODEL_SPECIAL_FUNC_4TH_COLUMN+2+FW, y, CFN_PLAY_REPEAT(cfn)*CFN_PLAY_REPEAT_MUL, attr);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
if (active) CFN_PLAY_REPEAT(cfn) = checkIncDec(event, CFN_PLAY_REPEAT(cfn)==CFN_PLAY_REPEAT_NOSTART?-1:CFN_PLAY_REPEAT(cfn), -1, 60/CFN_PLAY_REPEAT_MUL, eeFlags);
|
||||
#else
|
||||
if (active) CHECK_INCDEC_MODELVAR_ZERO(event, CFN_PLAY_REPEAT(cfn), 60/CFN_PLAY_REPEAT_MUL);
|
||||
#endif
|
||||
}
|
||||
else if (attr) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menuModelCustomFunctions(uint8_t event)
|
||||
{
|
||||
MENU(STR_MENUCUSTOMFUNC, menuTabModel, e_CustomFunctions, NUM_CFN+1, {0, NAVIGATION_LINE_BY_LINE|4/*repeated*/});
|
||||
return menuCustomFunctions(event, g_model.customFn, &modelFunctionsContext);
|
||||
}
|
||||
@@ -0,0 +1,964 @@
|
||||
/*
|
||||
* 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 menuModelTelemetryItems {
|
||||
CASE_CPUARM(ITEM_TELEMETRY_PROTOCOL_TYPE)
|
||||
#if defined(REVX)
|
||||
ITEM_TELEMETRY_INVERTED_SERIAL,
|
||||
#endif
|
||||
#if !defined(CPUARM)
|
||||
ITEM_TELEMETRY_A1_LABEL,
|
||||
ITEM_TELEMETRY_A1_RANGE,
|
||||
ITEM_TELEMETRY_A1_OFFSET,
|
||||
ITEM_TELEMETRY_A1_ALARM1,
|
||||
ITEM_TELEMETRY_A1_ALARM2,
|
||||
ITEM_TELEMETRY_A2_LABEL,
|
||||
ITEM_TELEMETRY_A2_RANGE,
|
||||
ITEM_TELEMETRY_A2_OFFSET,
|
||||
ITEM_TELEMETRY_A2_ALARM1,
|
||||
ITEM_TELEMETRY_A2_ALARM2,
|
||||
#endif
|
||||
ITEM_TELEMETRY_RSSI_LABEL,
|
||||
ITEM_TELEMETRY_RSSI_ALARM1,
|
||||
ITEM_TELEMETRY_RSSI_ALARM2,
|
||||
#if defined(CPUARM)
|
||||
ITEM_TELEMETRY_SENSORS_LABEL,
|
||||
ITEM_TELEMETRY_SENSOR1,
|
||||
ITEM_TELEMETRY_SENSOR2,
|
||||
ITEM_TELEMETRY_SENSOR3,
|
||||
ITEM_TELEMETRY_SENSOR4,
|
||||
ITEM_TELEMETRY_SENSOR5,
|
||||
ITEM_TELEMETRY_SENSOR6,
|
||||
ITEM_TELEMETRY_SENSOR7,
|
||||
ITEM_TELEMETRY_SENSOR8,
|
||||
ITEM_TELEMETRY_SENSOR9,
|
||||
ITEM_TELEMETRY_SENSOR10,
|
||||
ITEM_TELEMETRY_SENSOR11,
|
||||
ITEM_TELEMETRY_SENSOR12,
|
||||
ITEM_TELEMETRY_SENSOR13,
|
||||
ITEM_TELEMETRY_SENSOR14,
|
||||
ITEM_TELEMETRY_SENSOR15,
|
||||
ITEM_TELEMETRY_SENSOR16,
|
||||
ITEM_TELEMETRY_SENSOR17,
|
||||
ITEM_TELEMETRY_SENSOR18,
|
||||
ITEM_TELEMETRY_SENSOR19,
|
||||
ITEM_TELEMETRY_SENSOR20,
|
||||
ITEM_TELEMETRY_SENSOR21,
|
||||
ITEM_TELEMETRY_SENSOR22,
|
||||
ITEM_TELEMETRY_SENSOR23,
|
||||
ITEM_TELEMETRY_SENSOR24,
|
||||
ITEM_TELEMETRY_SENSOR25,
|
||||
ITEM_TELEMETRY_SENSOR26,
|
||||
ITEM_TELEMETRY_SENSOR27,
|
||||
ITEM_TELEMETRY_SENSOR28,
|
||||
ITEM_TELEMETRY_SENSOR29,
|
||||
ITEM_TELEMETRY_SENSOR30,
|
||||
ITEM_TELEMETRY_SENSOR31,
|
||||
ITEM_TELEMETRY_SENSOR32,
|
||||
ITEM_TELEMETRY_DISCOVER_SENSORS,
|
||||
ITEM_TELEMETRY_NEW_SENSOR,
|
||||
ITEM_TELEMETRY_DELETE_ALL_SENSORS,
|
||||
ITEM_TELEMETRY_IGNORE_SENSOR_INSTANCE,
|
||||
#endif
|
||||
#if !defined(CPUARM)
|
||||
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
|
||||
ITEM_TELEMETRY_USR_LABEL,
|
||||
ITEM_TELEMETRY_USR_PROTO,
|
||||
ITEM_TELEMETRY_USR_BLADES,
|
||||
#endif
|
||||
ITEM_TELEMETRY_USR_VOLTAGE_SOURCE,
|
||||
ITEM_TELEMETRY_USR_CURRENT_SOURCE,
|
||||
#if defined(FAS_OFFSET) || !defined(CPUM64)
|
||||
ITEM_TELEMETRY_FAS_OFFSET,
|
||||
#endif
|
||||
#endif
|
||||
CASE_VARIO(ITEM_TELEMETRY_VARIO_LABEL)
|
||||
#if defined(VARIO)
|
||||
ITEM_TELEMETRY_VARIO_SOURCE,
|
||||
#endif
|
||||
CASE_VARIO(ITEM_TELEMETRY_VARIO_RANGE)
|
||||
ITEM_TELEMETRY_SCREEN_LABEL1,
|
||||
ITEM_TELEMETRY_SCREEN_LINE1,
|
||||
ITEM_TELEMETRY_SCREEN_LINE2,
|
||||
ITEM_TELEMETRY_SCREEN_LINE3,
|
||||
ITEM_TELEMETRY_SCREEN_LINE4,
|
||||
ITEM_TELEMETRY_SCREEN_LABEL2,
|
||||
ITEM_TELEMETRY_SCREEN_LINE5,
|
||||
ITEM_TELEMETRY_SCREEN_LINE6,
|
||||
ITEM_TELEMETRY_SCREEN_LINE7,
|
||||
ITEM_TELEMETRY_SCREEN_LINE8,
|
||||
#if defined(CPUARM)
|
||||
ITEM_TELEMETRY_SCREEN_LABEL3,
|
||||
ITEM_TELEMETRY_SCREEN_LINE9,
|
||||
ITEM_TELEMETRY_SCREEN_LINE10,
|
||||
ITEM_TELEMETRY_SCREEN_LINE11,
|
||||
ITEM_TELEMETRY_SCREEN_LINE12,
|
||||
ITEM_TELEMETRY_SCREEN_LABEL4,
|
||||
ITEM_TELEMETRY_SCREEN_LINE13,
|
||||
ITEM_TELEMETRY_SCREEN_LINE14,
|
||||
ITEM_TELEMETRY_SCREEN_LINE15,
|
||||
ITEM_TELEMETRY_SCREEN_LINE16,
|
||||
#endif
|
||||
ITEM_TELEMETRY_MAX
|
||||
};
|
||||
|
||||
#if defined(FRSKY)
|
||||
#define TELEM_COL1 INDENT_WIDTH
|
||||
#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_CZ)
|
||||
#define TELEM_COL2 (9*FW)
|
||||
#else
|
||||
#define TELEM_COL2 (8*FW)
|
||||
#endif
|
||||
#define TELEM_BARS_COLMIN (56-3*FW)
|
||||
#define TELEM_BARS_COLMAX (14*FW-3)
|
||||
#define TELEM_SCRTYPE_COL TELEM_COL2
|
||||
|
||||
#define IS_RANGE_DEFINED(k) (g_model.frsky.channels[k].ratio > 0)
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define CHANNELS_ROWS
|
||||
#define SENSOR_ROWS(x) (isTelemetryFieldAvailable(x) ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSORS_ROWS LABEL(Sensors), SENSOR_ROWS(0), SENSOR_ROWS(1), SENSOR_ROWS(2), SENSOR_ROWS(3), SENSOR_ROWS(4), SENSOR_ROWS(5), SENSOR_ROWS(6), SENSOR_ROWS(7), SENSOR_ROWS(8), SENSOR_ROWS(9), SENSOR_ROWS(10), SENSOR_ROWS(11), SENSOR_ROWS(12), SENSOR_ROWS(13), SENSOR_ROWS(14), SENSOR_ROWS(15), SENSOR_ROWS(16), SENSOR_ROWS(17), SENSOR_ROWS(18), SENSOR_ROWS(19), SENSOR_ROWS(20), SENSOR_ROWS(21), SENSOR_ROWS(22), SENSOR_ROWS(23), SENSOR_ROWS(24), SENSOR_ROWS(25), SENSOR_ROWS(26), SENSOR_ROWS(27), SENSOR_ROWS(28), SENSOR_ROWS(29), SENSOR_ROWS(30), SENSOR_ROWS(31), 0, 0, 0, 0,
|
||||
#else
|
||||
#define CHANNEL_ROWS(x) LABEL(CHANNEL), 1, 0, 2, 2
|
||||
#define CHANNELS_ROWS CHANNEL_ROWS(0), CHANNEL_ROWS(1),
|
||||
#define SENSORS_ROWS
|
||||
#endif
|
||||
|
||||
#if defined(FAS_OFFSET) || !defined(CPUM64)
|
||||
#define IF_FAS_OFFSET(x) x,
|
||||
#else
|
||||
#define IF_FAS_OFFSET(x)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define USRDATA_ROWS
|
||||
#elif defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
|
||||
#define USRDATA_ROWS LABEL(UsrData), 0, 0, 0, 0, IF_FAS_OFFSET(0)
|
||||
#else
|
||||
#define USRDATA_ROWS 0, 0, IF_FAS_OFFSET(0)
|
||||
#endif
|
||||
|
||||
#define RSSI_ROWS LABEL(RSSI), 1, 1,
|
||||
|
||||
#if defined(CPUARM) || defined(GAUGES)
|
||||
#define SCREEN_TYPE_ROWS 0
|
||||
#else
|
||||
#define SCREEN_TYPE_ROWS LABEL(SCREEN)
|
||||
#endif
|
||||
|
||||
#if defined(PCBSTD)
|
||||
#define VARIO_RANGE_ROWS 1
|
||||
#else
|
||||
#define VARIO_RANGE_ROWS 3
|
||||
#endif
|
||||
|
||||
#if defined(REVX)
|
||||
#define TELEMETRY_TYPE_ROWS 0, 0,
|
||||
#elif defined(CPUARM)
|
||||
#define TELEMETRY_TYPE_ROWS 0,
|
||||
#else
|
||||
#define TELEMETRY_TYPE_ROWS
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define TELEMETRY_SCREEN_LINE(x) (TELEMETRY_SCREEN_TYPE(x) == TELEMETRY_SCREEN_TYPE_NONE ? HIDDEN_ROW : (uint8_t)2)
|
||||
#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x), TELEMETRY_SCREEN_LINE(x)
|
||||
#define TELEMETRY_CURRENT_SCREEN(k) (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 0 : (k < ITEM_TELEMETRY_SCREEN_LABEL3 ? 1 : (k < ITEM_TELEMETRY_SCREEN_LABEL4 ? 2 : 3)))
|
||||
#else
|
||||
#define TELEMETRY_SCREEN_ROWS(x) SCREEN_TYPE_ROWS, 2, 2, 2, 2
|
||||
#define TELEMETRY_CURRENT_CHANNEL(k) (k >= ITEM_TELEMETRY_A2_LABEL ? TELEM_ANA_A2 : TELEM_ANA_A1)
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
enum SensorFields {
|
||||
SENSOR_FIELD_NAME,
|
||||
SENSOR_FIELD_TYPE,
|
||||
SENSOR_FIELD_ID,
|
||||
SENSOR_FIELD_FORMULA=SENSOR_FIELD_ID,
|
||||
SENSOR_FIELD_UNIT,
|
||||
SENSOR_FIELD_PRECISION,
|
||||
SENSOR_FIELD_PARAM1,
|
||||
SENSOR_FIELD_PARAM2,
|
||||
SENSOR_FIELD_PARAM3,
|
||||
SENSOR_FIELD_PARAM4,
|
||||
SENSOR_FIELD_AUTOOFFSET,
|
||||
SENSOR_FIELD_ONLYPOSITIVE,
|
||||
SENSOR_FIELD_FILTER,
|
||||
SENSOR_FIELD_PERSISTENT,
|
||||
SENSOR_FIELD_LOGS,
|
||||
SENSOR_FIELD_MAX
|
||||
};
|
||||
|
||||
#define SENSOR_2ND_COLUMN (12*FW)
|
||||
#define SENSOR_3RD_COLUMN (18*FW)
|
||||
|
||||
#define SENSOR_UNIT_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_PREC_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_PARAM1_ROWS (sensor->unit >= UNIT_FIRST_VIRTUAL ? HIDDEN_ROW : (uint8_t)0)
|
||||
#define SENSOR_PARAM2_ROWS (sensor->unit == UNIT_RPMS || sensor->unit == UNIT_GPS || sensor->unit == UNIT_DATETIME || sensor->unit == UNIT_CELLS || (sensor->type==TELEM_TYPE_CALCULATED && (sensor->formula==TELEM_FORMULA_CONSUMPTION || sensor->formula==TELEM_FORMULA_TOTALIZE)) ? HIDDEN_ROW : (uint8_t)0)
|
||||
#define SENSOR_PARAM3_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY) ? (uint8_t)0 : HIDDEN_ROW
|
||||
#define SENSOR_PARAM4_ROWS (sensor->type == TELEM_TYPE_CALCULATED && sensor->formula < TELEM_FORMULA_MULTIPLY) ? (uint8_t)0 : HIDDEN_ROW
|
||||
#define SENSOR_AUTOOFFSET_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_FILTER_ROWS (sensor->isConfigurable() ? (uint8_t)0 : HIDDEN_ROW)
|
||||
#define SENSOR_PERSISTENT_ROWS (sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : HIDDEN_ROW)
|
||||
|
||||
void menuModelSensor(uint8_t event)
|
||||
{
|
||||
TelemetrySensor * sensor = & g_model.telemetrySensors[s_currIdx];
|
||||
|
||||
SUBMENU(STR_MENUSENSOR, SENSOR_FIELD_MAX, {0, 0, sensor->type == TELEM_TYPE_CALCULATED ? (uint8_t)0 : (uint8_t)1, SENSOR_UNIT_ROWS, SENSOR_PREC_ROWS, SENSOR_PARAM1_ROWS, SENSOR_PARAM2_ROWS, SENSOR_PARAM3_ROWS, SENSOR_PARAM4_ROWS, SENSOR_AUTOOFFSET_ROWS, SENSOR_FILTER_ROWS, SENSOR_PERSISTENT_ROWS, 0 });
|
||||
lcdDrawNumber(PSIZE(TR_MENUSENSOR)*FW+1, 0, s_currIdx+1, INVERS|LEFT);
|
||||
|
||||
putsTelemetryChannelValue(SENSOR_2ND_COLUMN, 0, s_currIdx, getValue(MIXSRC_FIRST_TELEM+3*s_currIdx), LEFT);
|
||||
|
||||
int8_t sub = menuVerticalPosition;
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i + menuVerticalOffset;
|
||||
|
||||
for (int j=0; j<k; j++) {
|
||||
if (mstate_tab[j+1] == HIDDEN_ROW)
|
||||
k++;
|
||||
}
|
||||
|
||||
uint8_t attr = (sub==k ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
|
||||
|
||||
switch (k) {
|
||||
|
||||
case SENSOR_FIELD_NAME:
|
||||
editSingleName(SENSOR_2ND_COLUMN, y, STR_NAME, sensor->label, TELEM_LABEL_LEN, event, attr);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_TYPE:
|
||||
sensor->type = selectMenuItem(SENSOR_2ND_COLUMN, y, NO_INDENT(STR_TYPE), STR_VSENSORTYPES, sensor->type, 0, 1, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
sensor->instance = 0;
|
||||
if (sensor->type == TELEM_TYPE_CALCULATED) {
|
||||
sensor->param = 0;
|
||||
sensor->autoOffset = 0;
|
||||
sensor->filter = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_ID:
|
||||
if (sensor->type == TELEM_TYPE_CUSTOM) {
|
||||
lcd_putsLeft(y, STR_ID);
|
||||
lcdDrawHexNumber(SENSOR_2ND_COLUMN, y, sensor->id, LEFT|(menuHorizontalPosition==0 ? attr : 0));
|
||||
lcdDrawNumber(SENSOR_3RD_COLUMN, y, sensor->instance, LEFT|(menuHorizontalPosition==1 ? attr : 0));
|
||||
if (attr) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->id, 0xffff);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->instance, 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
sensor->formula = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_FORMULA, STR_VFORMULAS, sensor->formula, 0, TELEM_FORMULA_LAST, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
sensor->param = 0;
|
||||
if (sensor->formula == TELEM_FORMULA_CELL) {
|
||||
sensor->unit = UNIT_VOLTS;
|
||||
sensor->prec = 2;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_DIST) {
|
||||
sensor->unit = UNIT_DIST;
|
||||
sensor->prec = 0;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
|
||||
sensor->unit = UNIT_MAH;
|
||||
sensor->prec = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_UNIT:
|
||||
lcd_putsLeft(y, "Unit");
|
||||
// TODO flash saving with selectMenuItem where I copied those 2 lines?
|
||||
lcdDrawTextAtIndex(SENSOR_2ND_COLUMN, y, STR_VTELEMUNIT, sensor->unit, attr);
|
||||
if (attr) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, sensor->unit, UNIT_MAX);
|
||||
if (checkIncDec_Ret) {
|
||||
telemetryItems[s_currIdx].clear();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_PRECISION:
|
||||
sensor->prec = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_PRECISION, STR_VPREC, sensor->prec, 0, 2, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
telemetryItems[s_currIdx].clear();
|
||||
}
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_PARAM1:
|
||||
if (sensor->type == TELEM_TYPE_CALCULATED) {
|
||||
if (sensor->formula == TELEM_FORMULA_CELL) {
|
||||
lcd_putsLeft(y, STR_CELLSENSOR);
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->cell.source ? MIXSRC_FIRST_TELEM+3*(sensor->cell.source-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->cell.source = checkIncDec(event, sensor->cell.source, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isCellsSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_DIST) {
|
||||
lcd_putsLeft(y, STR_GPSSENSOR);
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.gps ? MIXSRC_FIRST_TELEM+3*(sensor->dist.gps-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->dist.gps = checkIncDec(event, sensor->dist.gps, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isGPSSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_CONSUMPTION) {
|
||||
lcd_putsLeft(y, STR_CURRENTSENSOR);
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->consumption.source ? MIXSRC_FIRST_TELEM+3*(sensor->consumption.source-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->consumption.source = checkIncDec(event, sensor->consumption.source, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isCurrentSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (sensor->unit == UNIT_RPMS) {
|
||||
lcd_putsLeft(y, NO_INDENT(STR_BLADES));
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.ratio, 1, 30000);
|
||||
lcdDrawNumber(SENSOR_2ND_COLUMN, y, sensor->custom.ratio, LEFT|attr);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(y, STR_RATIO);
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.ratio, 0, 30000);
|
||||
if (sensor->custom.ratio == 0)
|
||||
lcdDrawChar(SENSOR_2ND_COLUMN, y, '-', attr);
|
||||
else
|
||||
lcdDrawNumber(SENSOR_2ND_COLUMN, y, sensor->custom.ratio, LEFT|attr|PREC1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// no break
|
||||
|
||||
case SENSOR_FIELD_PARAM2:
|
||||
if (sensor->type == TELEM_TYPE_CALCULATED) {
|
||||
if (sensor->formula == TELEM_FORMULA_CELL) {
|
||||
sensor->cell.index = selectMenuItem(SENSOR_2ND_COLUMN, y, STR_CELLINDEX, STR_VCELLINDEX, sensor->cell.index, 0, 8, attr, event);
|
||||
break;
|
||||
}
|
||||
else if (sensor->formula == TELEM_FORMULA_DIST) {
|
||||
lcd_putsLeft(y, STR_ALTSENSOR);
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, sensor->dist.alt ? MIXSRC_FIRST_TELEM+3*(sensor->dist.alt-1) : 0, attr);
|
||||
if (attr) {
|
||||
sensor->dist.alt = checkIncDec(event, sensor->dist.alt, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isAltSensor);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(y, NO_INDENT(STR_OFFSET));
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, sensor->custom.offset, -30000, +30000);
|
||||
if (sensor->prec > 0) attr |= (sensor->prec == 2 ? PREC2 : PREC1);
|
||||
lcdDrawNumber(SENSOR_2ND_COLUMN, y, sensor->custom.offset, LEFT|attr);
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
|
||||
case SENSOR_FIELD_PARAM3:
|
||||
// no break
|
||||
|
||||
case SENSOR_FIELD_PARAM4:
|
||||
{
|
||||
drawStringWithIndex(0, y, NO_INDENT(STR_SOURCE), k-SENSOR_FIELD_PARAM1+1);
|
||||
int8_t & source = sensor->calc.sources[k-SENSOR_FIELD_PARAM1];
|
||||
if (attr) {
|
||||
source = checkIncDec(event, source, -MAX_SENSORS, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable);
|
||||
}
|
||||
if (source < 0) {
|
||||
lcdDrawChar(SENSOR_2ND_COLUMN, y, '-', attr);
|
||||
putsMixerSource(lcdNextPos, y, MIXSRC_FIRST_TELEM+3*(-1-source), attr);
|
||||
}
|
||||
else {
|
||||
putsMixerSource(SENSOR_2ND_COLUMN, y, source ? MIXSRC_FIRST_TELEM+3*(source-1) : 0, attr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SENSOR_FIELD_AUTOOFFSET:
|
||||
ON_OFF_MENU_ITEM(sensor->autoOffset, SENSOR_2ND_COLUMN, y, STR_AUTOOFFSET, attr, event);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_ONLYPOSITIVE:
|
||||
ON_OFF_MENU_ITEM(sensor->onlyPositive, SENSOR_2ND_COLUMN, y, STR_ONLYPOSITIVE, attr, event);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_FILTER:
|
||||
ON_OFF_MENU_ITEM(sensor->filter, SENSOR_2ND_COLUMN, y, STR_FILTER, attr, event);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_PERSISTENT:
|
||||
ON_OFF_MENU_ITEM(sensor->persistent, SENSOR_2ND_COLUMN, y, NO_INDENT(STR_PERSISTENT), attr, event);
|
||||
break;
|
||||
|
||||
case SENSOR_FIELD_LOGS:
|
||||
ON_OFF_MENU_ITEM(sensor->logs, SENSOR_2ND_COLUMN, y, STR_LOGS, attr, event);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void onSensorMenu(const char *result)
|
||||
{
|
||||
uint8_t index = menuVerticalPosition - 1 - ITEM_TELEMETRY_SENSOR1;
|
||||
|
||||
if (index < MAX_SENSORS) {
|
||||
if (result == STR_EDIT) {
|
||||
pushMenu(menuModelSensor);
|
||||
}
|
||||
else if (result == STR_DELETE) {
|
||||
delTelemetryIndex(index);
|
||||
index += 1;
|
||||
if (index<MAX_SENSORS && isTelemetryFieldAvailable(index))
|
||||
menuVerticalPosition += 1;
|
||||
else
|
||||
menuVerticalPosition = 1+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];
|
||||
newSensor = sourceSensor;
|
||||
TelemetryItem & sourceItem = telemetryItems[index];
|
||||
TelemetryItem & newItem = telemetryItems[newIndex];
|
||||
newItem = sourceItem;
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(STR_TELEMETRYFULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void menuModelTelemetry(uint8_t event)
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
for (int i=0; i<MAX_SENSORS; i++) {
|
||||
delTelemetryIndex(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
MENU(STR_MENUTELEMETRY, menuTabModel, e_Telemetry, ITEM_TELEMETRY_MAX+1, {0, TELEMETRY_TYPE_ROWS CHANNELS_ROWS RSSI_ROWS SENSORS_ROWS USRDATA_ROWS CASE_VARIO(LABEL(Vario)) CASE_VARIO(0) CASE_VARIO(VARIO_RANGE_ROWS) TELEMETRY_SCREEN_ROWS(0), TELEMETRY_SCREEN_ROWS(1), CASE_CPUARM(TELEMETRY_SCREEN_ROWS(2)) CASE_CPUARM(TELEMETRY_SCREEN_ROWS(3))});
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
switch (event) {
|
||||
case EVT_KEY_BREAK(KEY_DOWN):
|
||||
case EVT_KEY_BREAK(KEY_UP):
|
||||
case EVT_KEY_BREAK(KEY_LEFT):
|
||||
case EVT_KEY_BREAK(KEY_RIGHT):
|
||||
if (s_editMode>0 && sub<=ITEM_TELEMETRY_RSSI_ALARM2)
|
||||
frskySendAlarms(); // update FrSky module when edit mode exited
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i + menuVerticalOffset;
|
||||
#if defined(CPUARM)
|
||||
for (int j=0; j<=k; j++) {
|
||||
if (mstate_tab[j+1] == HIDDEN_ROW)
|
||||
k++;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
uint8_t attr = (sub == k ? blink : 0);
|
||||
|
||||
#if !defined(CPUARM)
|
||||
uint8_t ch = TELEMETRY_CURRENT_CHANNEL(k);
|
||||
FrSkyChannelData & channel = g_model.frsky.channels[ch];
|
||||
uint8_t dest = TELEM_A1-1+ch;
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
if (k>=ITEM_TELEMETRY_SENSOR1 && k<ITEM_TELEMETRY_SENSOR1+MAX_SENSORS) {
|
||||
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);
|
||||
if (telemetryItems[index].isFresh()) {
|
||||
lcdDrawChar(16*FW, y, '*');
|
||||
}
|
||||
TelemetryItem & telemetryItem = telemetryItems[index];
|
||||
if (telemetryItem.isAvailable()) {
|
||||
bool isOld = telemetryItem.isOld();
|
||||
lcdNextPos = TELEM_COL2;
|
||||
if (isOld) lcdDrawChar(lcdNextPos, y, '[');
|
||||
putsTelemetryChannelValue(lcdNextPos, y, index, getValue(MIXSRC_FIRST_TELEM+3*index), LEFT);
|
||||
if (isOld) lcdDrawChar(lcdLastPos, y, ']');
|
||||
}
|
||||
else {
|
||||
lcdDrawText(TELEM_COL2, y, "---", 0); // TODO shortcut
|
||||
}
|
||||
if (attr) {
|
||||
s_editMode = 0;
|
||||
s_currIdx = index;
|
||||
if (event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
killEvents(event);
|
||||
POPUP_MENU_ADD_ITEM(STR_EDIT);
|
||||
POPUP_MENU_ADD_ITEM(STR_COPY);
|
||||
POPUP_MENU_ADD_ITEM(STR_DELETE);
|
||||
POPUP_MENU_START(onSensorMenu);
|
||||
}
|
||||
else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
pushMenu(menuModelSensor);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
switch (k) {
|
||||
#if defined(CPUARM)
|
||||
case ITEM_TELEMETRY_PROTOCOL_TYPE:
|
||||
g_model.telemetryProtocol = selectMenuItem(TELEM_COL2, y, STR_TELEMETRY_TYPE, "\017FrSky S.PORT\0 FrSky D\0 FrSky D (cable)", g_model.telemetryProtocol, PROTOCOL_TELEMETRY_FIRST, CASE_PCBSKY9X(PROTOCOL_FRSKY_D_SECONDARY) attr, event);
|
||||
break;
|
||||
#if defined(REVX)
|
||||
case ITEM_TELEMETRY_INVERTED_SERIAL:
|
||||
ON_OFF_MENU_ITEM(g_model.moduleData[EXTERNAL_MODULE].invertedSerial, TELEM_COL2, y, STR_INVERTED_SERIAL, attr, event);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_TELEMETRY_SENSORS_LABEL:
|
||||
lcd_putsLeft(y, STR_TELEMETRY_SENSORS);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_DISCOVER_SENSORS:
|
||||
lcdDrawText(0, y, allowNewSensors ? STR_STOP_DISCOVER_SENSORS : STR_DISCOVER_SENSORS, attr);
|
||||
if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
allowNewSensors = !allowNewSensors;
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_NEW_SENSOR:
|
||||
lcdDrawText(0, y, STR_TELEMETRY_NEWSENSOR, attr);
|
||||
if (attr && event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
s_editMode = 0;
|
||||
int res = availableTelemetryIndex();
|
||||
if (res >= 0) {
|
||||
s_currIdx = res;
|
||||
pushMenu(menuModelSensor);
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(STR_TELEMETRYFULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_IGNORE_SENSOR_INSTANCE:
|
||||
ON_OFF_MENU_ITEM(g_model.ignoreSensorIds, TELEM_COL2, y, STR_IGNORE_INSTANCE, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM)
|
||||
case ITEM_TELEMETRY_A1_LABEL:
|
||||
case ITEM_TELEMETRY_A2_LABEL:
|
||||
lcd_putsLeft(y, STR_ACHANNEL);
|
||||
lcdDrawNumber(2*FW, y, ch+1, 0);
|
||||
putsTelemetryChannelValue(TELEM_COL2+6*FW, y, dest, telemetryData.analog[ch].value, LEFT);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_A1_RANGE:
|
||||
case ITEM_TELEMETRY_A2_RANGE:
|
||||
lcd_putsLeft(y, STR_RANGE);
|
||||
putsTelemetryChannelValue(TELEM_COL2, y, dest, 255-channel.offset, (menuHorizontalPosition<=0 ? attr : 0)|NO_UNIT|LEFT);
|
||||
lcdDrawTextAtIndex(lcdLastPos, y, STR_VTELEMUNIT, channel.type, menuHorizontalPosition!=0 ? attr : 0);
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
if (menuHorizontalPosition == 0) {
|
||||
uint16_t ratio = checkIncDec(event, channel.ratio, 0, 256, EE_MODEL);
|
||||
if (checkIncDec_Ret) {
|
||||
if (ratio == 127 && channel.multiplier > 0) {
|
||||
channel.multiplier--; channel.ratio = 255;
|
||||
}
|
||||
else if (ratio == 256) {
|
||||
if (channel.multiplier < FRSKY_MULTIPLIER_MAX) { channel.multiplier++; channel.ratio = 128; }
|
||||
}
|
||||
else {
|
||||
channel.ratio = ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
CHECK_INCDEC_MODELVAR_ZERO(event, channel.type, UNIT_A1A2_MAX);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_A1_OFFSET:
|
||||
case ITEM_TELEMETRY_A2_OFFSET:
|
||||
lcd_putsLeft(y, STR_OFFSET);
|
||||
putsTelemetryChannelValue(TELEM_COL2, y, dest, 0, LEFT|attr);
|
||||
if (attr) channel.offset = checkIncDec(event, channel.offset, -256, 256, EE_MODEL);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_A1_ALARM1:
|
||||
case ITEM_TELEMETRY_A1_ALARM2:
|
||||
case ITEM_TELEMETRY_A2_ALARM1:
|
||||
case ITEM_TELEMETRY_A2_ALARM2:
|
||||
{
|
||||
uint8_t alarm = ((k==ITEM_TELEMETRY_A1_ALARM1 || k==ITEM_TELEMETRY_A2_ALARM1) ? 0 : 1);
|
||||
lcd_putsLeft(y, STR_ALARM);
|
||||
lcdDrawTextAtIndex(TELEM_COL2, y, STR_VALARM, ALARM_LEVEL(ch, alarm), menuHorizontalPosition<=0 ? attr : 0);
|
||||
lcdDrawTextAtIndex(TELEM_COL2+4*FW, y, STR_VALARMFN, ALARM_GREATER(ch, alarm), (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
|
||||
putsTelemetryChannelValue(TELEM_COL2+6*FW, y, dest, channel.alarms_value[alarm], ((CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0) | LEFT);
|
||||
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
uint8_t t;
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
t = ALARM_LEVEL(ch, alarm);
|
||||
channel.alarms_level = (channel.alarms_level & ~(3<<(2*alarm))) + (checkIncDecModel(event, t, 0, 3) << (2*alarm));
|
||||
break;
|
||||
case 1:
|
||||
t = ALARM_GREATER(ch, alarm);
|
||||
if (t != checkIncDecModel(event, t, 0, 1)) {
|
||||
channel.alarms_greater ^= (1 << alarm);
|
||||
frskySendAlarms();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
channel.alarms_value[alarm] = checkIncDec(event, channel.alarms_value[alarm], 0, 255, EE_MODEL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case ITEM_TELEMETRY_RSSI_LABEL:
|
||||
lcd_putsLeft(y, PSTR("RSSI"));
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_RSSI_ALARM1:
|
||||
case ITEM_TELEMETRY_RSSI_ALARM2: {
|
||||
uint8_t alarm = k-ITEM_TELEMETRY_RSSI_ALARM1;
|
||||
lcd_putsLeft(y, STR_ALARM);
|
||||
lcdDrawTextAtIndex(TELEM_COL2, y, STR_VALARM, ((2+alarm+g_model.frsky.rssiAlarms[alarm].level)%4), menuHorizontalPosition<=0 ? attr : 0);
|
||||
lcdDrawChar(TELEM_COL2+4*FW, y, '<');
|
||||
lcdDrawNumber(TELEM_COL2+6*FW, y, getRssiAlarmValue(alarm), LEFT|(menuHorizontalPosition!=0 ? attr : 0), 3);
|
||||
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[alarm].level, -3, 2); // circular (saves flash)
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.rssiAlarms[alarm].value, -30, 30);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(CPUARM)
|
||||
#if defined(FRSKY_HUB) || defined(WS_HOW_HIGH)
|
||||
case ITEM_TELEMETRY_USR_LABEL:
|
||||
lcd_putsLeft(y, STR_USRDATA);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_USR_PROTO:
|
||||
lcd_putsLeft(y, STR_PROTO);
|
||||
lcdDrawTextAtIndex(TELEM_COL2, y, STR_VTELPROTO, g_model.frsky.usrProto, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.usrProto, USR_PROTO_LAST);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_USR_BLADES:
|
||||
lcd_putsLeft(y, STR_BLADES);
|
||||
lcdDrawNumber(TELEM_COL2+FWNUM, y, 2+g_model.frsky.blades, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.blades, MAX_BLADES);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_TELEMETRY_USR_VOLTAGE_SOURCE:
|
||||
lcd_putsLeft(y, STR_VOLTAGE);
|
||||
lcdDrawTextAtIndex(TELEM_COL2, y, STR_AMPSRC, g_model.frsky.voltsSource+1, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.voltsSource, FRSKY_VOLTS_SOURCE_LAST);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_USR_CURRENT_SOURCE:
|
||||
lcd_putsLeft(y, STR_CURRENT);
|
||||
lcdDrawTextAtIndex(TELEM_COL2, y, STR_AMPSRC, g_model.frsky.currentSource, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR_ZERO(event, g_model.frsky.currentSource, FRSKY_CURRENT_SOURCE_LAST);
|
||||
break;
|
||||
|
||||
#if defined(FAS_OFFSET) || !defined(CPUM64)
|
||||
case ITEM_TELEMETRY_FAS_OFFSET:
|
||||
lcd_putsLeft(y, STR_FAS_OFFSET);
|
||||
lcdDrawNumber(TELEM_COL2, y, g_model.frsky.fasOffset, attr|LEFT|PREC1);
|
||||
lcdDrawNumber(TELEM_COL2+6*FW, y, telemetryData.hub.current, LEFT|PREC1);
|
||||
lcdDrawChar(TELEM_COL2+8*FW, y, 'A');
|
||||
if (attr) g_model.frsky.fasOffset = checkIncDec(event, g_model.frsky.fasOffset, -120, 120, EE_MODEL);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(VARIO)
|
||||
case ITEM_TELEMETRY_VARIO_LABEL:
|
||||
lcd_putsLeft(y, STR_VARIO);
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_VARIO_SOURCE:
|
||||
lcd_putsLeft(y, STR_SOURCE);
|
||||
#if defined(CPUARM)
|
||||
putsMixerSource(TELEM_COL2, y, g_model.frsky.varioSource ? MIXSRC_FIRST_TELEM+3*(g_model.frsky.varioSource-1) : 0, attr);
|
||||
if (attr) {
|
||||
g_model.frsky.varioSource = checkIncDec(event, g_model.frsky.varioSource, 0, MAX_SENSORS, EE_MODEL|NO_INCDEC_MARKS, isSensorAvailable);
|
||||
}
|
||||
#else
|
||||
lcdDrawTextAtIndex(TELEM_COL2, y, STR_VARIOSRC, g_model.frsky.varioSource, attr);
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioSource, 0, VARIO_SOURCE_LAST);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case ITEM_TELEMETRY_VARIO_RANGE:
|
||||
lcd_putsLeft(y, STR_LIMIT);
|
||||
#if defined(PCBSTD)
|
||||
lcdDrawNumber(TELEM_COL2, y, 5+g_model.frsky.varioCenterMax, (menuHorizontalPosition==0 ? attr : 0)|PREC1|LEFT);
|
||||
lcdDrawNumber(TELEM_COL2+8*FW, y, 10+g_model.frsky.varioMax, (menuHorizontalPosition==1 ? attr : 0));
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -15, +15);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#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, y, 5+g_model.frsky.varioCenterMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0)|PREC1);
|
||||
lcdDrawNumber(TELEM_COL2+13*FW+2, y, 10+g_model.frsky.varioMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==3) ? attr : 0));
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7);
|
||||
break;
|
||||
case 1:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min<int8_t>(10, g_model.frsky.varioCenterMax+5));
|
||||
break;
|
||||
case 2:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMax, -5+max<int8_t>(-10, g_model.frsky.varioCenterMin-5), +15);
|
||||
break;
|
||||
case 3:
|
||||
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMax, -7, 7);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL1:
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL2:
|
||||
#if defined(CPUARM)
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL3:
|
||||
case ITEM_TELEMETRY_SCREEN_LABEL4:
|
||||
{
|
||||
uint8_t screenIndex = TELEMETRY_CURRENT_SCREEN(k);
|
||||
drawStringWithIndex(0*FW, y, STR_SCREEN, screenIndex+1);
|
||||
TelemetryScreenType oldScreenType = TELEMETRY_SCREEN_TYPE(screenIndex);
|
||||
TelemetryScreenType newScreenType = (TelemetryScreenType)selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VTELEMSCREENTYPE, oldScreenType, 0, TELEMETRY_SCREEN_TYPE_MAX, (menuHorizontalPosition==0 ? attr : 0), event);
|
||||
if (newScreenType != oldScreenType) {
|
||||
g_model.frsky.screensType = (g_model.frsky.screensType & (~(0x03 << (2*screenIndex)))) | (newScreenType << (2*screenIndex));
|
||||
memset(&g_model.frsky.screens[screenIndex], 0, sizeof(g_model.frsky.screens[screenIndex]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
#else
|
||||
{
|
||||
uint8_t screenIndex = (k < ITEM_TELEMETRY_SCREEN_LABEL2 ? 1 : 2);
|
||||
drawStringWithIndex(0*FW, y, STR_SCREEN, screenIndex);
|
||||
#if defined(GAUGES)
|
||||
bool screenType = g_model.frsky.screensType & screenIndex;
|
||||
if (screenType != (bool)selectMenuItem(TELEM_SCRTYPE_COL, y, PSTR(""), STR_VTELEMSCREENTYPE, screenType, 0, 1, attr, event))
|
||||
g_model.frsky.screensType ^= screenIndex;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case ITEM_TELEMETRY_SCREEN_LINE1:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE2:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE3:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE4:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE5:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE6:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE7:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE8:
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_TELEMETRY_SCREEN_LINE9:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE10:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE11:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE12:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE13:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE14:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE15:
|
||||
case ITEM_TELEMETRY_SCREEN_LINE16:
|
||||
#endif
|
||||
{
|
||||
uint8_t screenIndex, lineIndex;
|
||||
if (k < ITEM_TELEMETRY_SCREEN_LABEL2) {
|
||||
screenIndex = 0;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE1;
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
else if (k >= ITEM_TELEMETRY_SCREEN_LABEL4) {
|
||||
screenIndex = 3;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE13;
|
||||
}
|
||||
else if (k >= ITEM_TELEMETRY_SCREEN_LABEL3) {
|
||||
screenIndex = 2;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE9;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
screenIndex = 1;
|
||||
lineIndex = k-ITEM_TELEMETRY_SCREEN_LINE5;
|
||||
}
|
||||
|
||||
#if defined(GAUGES)
|
||||
if (IS_BARS_SCREEN(screenIndex)) {
|
||||
FrSkyBarData & bar = g_model.frsky.screens[screenIndex].bars[lineIndex];
|
||||
source_t barSource = bar.source;
|
||||
#if defined(CPUARM)
|
||||
putsMixerSource(TELEM_COL1, y, barSource, menuHorizontalPosition==0 ? attr : 0);
|
||||
if (barSource) {
|
||||
if (barSource <= MIXSRC_LAST_CH) {
|
||||
putsChannelValue(TELEM_BARS_COLMIN, y, barSource, calc100toRESX(bar.barMin), (menuHorizontalPosition==1 ? attr : 0) | LEFT);
|
||||
putsChannelValue(TELEM_BARS_COLMAX, y, barSource, calc100toRESX(bar.barMax), (menuHorizontalPosition==2 ? attr : 0) | LEFT);
|
||||
}
|
||||
else {
|
||||
putsChannelValue(TELEM_BARS_COLMIN, y, barSource, bar.barMin, (menuHorizontalPosition==1 ? attr : 0) | LEFT);
|
||||
putsChannelValue(TELEM_BARS_COLMAX, y, barSource, bar.barMax, (menuHorizontalPosition==2 ? attr : 0) | LEFT);
|
||||
}
|
||||
}
|
||||
#else
|
||||
lcdDrawTextAtIndex(TELEM_COL1, y, STR_VTELEMCHNS, barSource, menuHorizontalPosition==0 ? attr : 0);
|
||||
if (barSource) {
|
||||
putsTelemetryChannelValue(TELEM_BARS_COLMIN, y, barSource-1, convertBarTelemValue(barSource, bar.barMin), (menuHorizontalPosition==1 ? attr : 0) | LEFT);
|
||||
putsTelemetryChannelValue(TELEM_BARS_COLMAX, y, barSource-1, convertBarTelemValue(barSource, 255-bar.barMax), (menuHorizontalPosition==2 ? attr : 0) | LEFT);
|
||||
}
|
||||
#endif
|
||||
else if (attr && menuHorizontalPosition>0) {
|
||||
menuHorizontalPosition = 0;
|
||||
}
|
||||
if (attr && (s_editMode>0 || p1valdiff)) {
|
||||
switch (menuHorizontalPosition) {
|
||||
case 0:
|
||||
#if defined(CPUARM)
|
||||
bar.source = CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, barSource, MIXSRC_LAST_TELEM, isSourceAvailable);
|
||||
#else
|
||||
bar.source = CHECK_INCDEC_MODELVAR_ZERO(event, barSource, TELEM_DISPLAY_MAX);
|
||||
#endif
|
||||
if (checkIncDec_Ret) {
|
||||
bar.barMin = 0;
|
||||
#if defined(CPUARM)
|
||||
bar.barMax = 0;
|
||||
#else
|
||||
bar.barMax = 255 - maxBarTelemValue(bar.source);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
#if defined(CPUARM)
|
||||
bar.barMin = checkIncDec(event, bar.barMin, -30000, bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
|
||||
#else
|
||||
bar.barMin = checkIncDec(event, bar.barMin, 0, 254-bar.barMax, EE_MODEL|NO_INCDEC_MARKS);
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
#if defined(CPUARM)
|
||||
bar.barMax = checkIncDec(event, bar.barMax, bar.barMin, 30000, EE_MODEL|NO_INCDEC_MARKS);
|
||||
#else
|
||||
bar.barMax = 255 - checkIncDec(event, 255-bar.barMax, bar.barMin+1, maxBarTelemValue(barSource), EE_MODEL|NO_INCDEC_MARKS);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (uint8_t c=0; c<NUM_LINE_ITEMS; c++) {
|
||||
uint8_t cellAttr = (menuHorizontalPosition==c ? attr : 0);
|
||||
source_t & value = g_model.frsky.screens[screenIndex].lines[lineIndex].sources[c];
|
||||
uint8_t pos[] = {INDENT_WIDTH, TELEM_COL2};
|
||||
#if defined(CPUARM)
|
||||
putsMixerSource(pos[c], y, value, cellAttr);
|
||||
if (cellAttr && (s_editMode>0 || p1valdiff)) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, MIXSRC_LAST_TELEM, isSourceAvailable);
|
||||
}
|
||||
#else
|
||||
lcdDrawTextAtIndex(pos[c], y, STR_VTELEMCHNS, value, cellAttr);
|
||||
if (cellAttr && (s_editMode>0 || p1valdiff)) {
|
||||
CHECK_INCDEC_MODELVAR_ZERO_CHECK(event, value, (lineIndex==3 && c==0) ? TELEM_STATUS_MAX : TELEM_DISPLAY_MAX, isTelemetrySourceAvailable);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (attr && menuHorizontalPosition == NUM_LINE_ITEMS) {
|
||||
REPEAT_LAST_CURSOR_MOVE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 menuModelTemplates(uint8_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUTEMPLATES, menuTabModel, e_Templates, 1+TMPL_COUNT);
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
if (sub < TMPL_COUNT) {
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
applyTemplate(sub);
|
||||
AUDIO_WARNING2();
|
||||
}
|
||||
if (event==EVT_KEY_BREAK(KEY_ENTER)) {
|
||||
POPUP_CONFIRMATION(STR_VTEMPLATES+1 + (sub * LEN2_VTEMPLATES));
|
||||
s_editMode = 0;
|
||||
}
|
||||
}
|
||||
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1;
|
||||
uint8_t k = 0;
|
||||
for (uint8_t i=0; i<LCD_LINES-1 && k<TMPL_COUNT; i++) {
|
||||
k = i+menuVerticalOffset;
|
||||
lcdDrawNumber(3*FW, y, k, (sub==k ? INVERS : 0)|LEADING0, 2);
|
||||
lcdDrawTextAtIndex(4*FW, y, STR_VTEMPLATES, k, (sub==k ? INVERS : 0));
|
||||
y+=FH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,692 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
vertpos_t menuVerticalOffset;
|
||||
int8_t s_editMode;
|
||||
uint8_t noHighlightCounter;
|
||||
uint8_t calibrationState;
|
||||
vertpos_t menuVerticalPosition;
|
||||
horzpos_t menuHorizontalPosition;
|
||||
|
||||
#if defined(NAVIGATION_POT1)
|
||||
int16_t p1valdiff;
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_POT2)
|
||||
int8_t p2valdiff;
|
||||
#endif
|
||||
|
||||
#if defined(AUTOSWITCH)
|
||||
int8_t checkIncDecMovedSwitch(int8_t val)
|
||||
{
|
||||
if (s_editMode>0) {
|
||||
int8_t swtch = getMovedSwitch();
|
||||
if (swtch) {
|
||||
if (IS_MOMENTARY(val) && swtch==val)
|
||||
val = -val;
|
||||
else
|
||||
val = swtch;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
int8_t checkIncDec_Ret;
|
||||
|
||||
#define DBLKEYS_PRESSED_RGT_LFT(in) ((in & (KEYS_GPIO_PIN_RIGHT + KEYS_GPIO_PIN_LEFT)) == (KEYS_GPIO_PIN_RIGHT + KEYS_GPIO_PIN_LEFT))
|
||||
#define DBLKEYS_PRESSED_UP_DWN(in) ((in & (KEYS_GPIO_PIN_UP + KEYS_GPIO_PIN_DOWN)) == (KEYS_GPIO_PIN_UP + KEYS_GPIO_PIN_DOWN))
|
||||
#define DBLKEYS_PRESSED_RGT_UP(in) ((in & (KEYS_GPIO_PIN_RIGHT + KEYS_GPIO_PIN_UP)) == (KEYS_GPIO_PIN_RIGHT + KEYS_GPIO_PIN_UP))
|
||||
#define DBLKEYS_PRESSED_LFT_DWN(in) ((in & (KEYS_GPIO_PIN_LEFT + KEYS_GPIO_PIN_DOWN)) == (KEYS_GPIO_PIN_LEFT + KEYS_GPIO_PIN_DOWN))
|
||||
|
||||
#if defined(CPUARM)
|
||||
INIT_STOPS(stops100, 3, -100, 0, 100)
|
||||
INIT_STOPS(stops1000, 3, -1000, 0, 1000)
|
||||
INIT_STOPS(stopsSwitch, 15, SWSRC_FIRST, CATEGORY_END(-SWSRC_FIRST_LOGICAL_SWITCH), CATEGORY_END(-SWSRC_FIRST_TRIM), CATEGORY_END(-SWSRC_LAST_SWITCH+1), 0, CATEGORY_END(SWSRC_LAST_SWITCH), CATEGORY_END(SWSRC_FIRST_TRIM-1), CATEGORY_END(SWSRC_FIRST_LOGICAL_SWITCH-1), SWSRC_LAST)
|
||||
|
||||
int checkIncDec(unsigned int event, int val, int i_min, int i_max, unsigned int i_flags, IsValueAvailable isValueAvailable, const CheckIncDecStops &stops)
|
||||
{
|
||||
int newval = val;
|
||||
|
||||
#if defined(DBLKEYS)
|
||||
uint8_t in = KEYS_PRESSED();
|
||||
if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) {
|
||||
bool dblkey = true;
|
||||
if (DBLKEYS_PRESSED_RGT_LFT(in)) {
|
||||
if (!isValueAvailable || isValueAvailable(-val)) {
|
||||
newval = -val;
|
||||
}
|
||||
}
|
||||
else if (DBLKEYS_PRESSED_RGT_UP(in)) {
|
||||
newval = (i_max > stops.max() ? stops.max() : i_max);
|
||||
while (isValueAvailable && !isValueAvailable(newval) && newval>i_min) {
|
||||
--newval;
|
||||
}
|
||||
}
|
||||
else if (DBLKEYS_PRESSED_LFT_DWN(in)) {
|
||||
newval = (i_min < stops.min() ? stops.min() : i_min);
|
||||
while (isValueAvailable && !isValueAvailable(newval) && newval<i_max) {
|
||||
++newval;
|
||||
}
|
||||
}
|
||||
else if (DBLKEYS_PRESSED_UP_DWN(in)) {
|
||||
newval = 0;
|
||||
}
|
||||
else {
|
||||
dblkey = false;
|
||||
}
|
||||
|
||||
if (dblkey) {
|
||||
killEvents(KEY_UP);
|
||||
killEvents(KEY_DOWN);
|
||||
killEvents(KEY_RIGHT);
|
||||
killEvents(KEY_LEFT);
|
||||
event = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) {
|
||||
do {
|
||||
newval++;
|
||||
} while (isValueAvailable && !isValueAvailable(newval) && newval<=i_max);
|
||||
|
||||
if (newval > i_max) {
|
||||
newval = val;
|
||||
killEvents(event);
|
||||
AUDIO_KEY_ERROR();
|
||||
}
|
||||
}
|
||||
else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) {
|
||||
do {
|
||||
if (IS_KEY_REPT(event) && (i_flags & INCDEC_REP10)) {
|
||||
newval -= min(10, val-i_min);
|
||||
}
|
||||
else {
|
||||
newval--;
|
||||
}
|
||||
} while (isValueAvailable && !isValueAvailable(newval) && newval>=i_min);
|
||||
|
||||
if (newval < i_min) {
|
||||
newval = val;
|
||||
killEvents(event);
|
||||
AUDIO_KEY_ERROR();
|
||||
}
|
||||
}
|
||||
|
||||
if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) {
|
||||
s_editMode = 0;
|
||||
newval = !val;
|
||||
}
|
||||
|
||||
#if defined(NAVIGATION_POT1)
|
||||
// change values based on P1
|
||||
newval -= p1valdiff;
|
||||
p1valdiff = 0;
|
||||
#endif
|
||||
|
||||
#if defined(AUTOSWITCH)
|
||||
if (i_flags & INCDEC_SWITCH) {
|
||||
newval = checkIncDecMovedSwitch(newval);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUTOSOURCE)
|
||||
if (i_flags & INCDEC_SOURCE) {
|
||||
if (s_editMode>0) {
|
||||
int8_t source = GET_MOVED_SOURCE(i_min, i_max);
|
||||
if (source) {
|
||||
newval = source;
|
||||
}
|
||||
#if defined(AUTOSWITCH)
|
||||
else {
|
||||
uint8_t swtch = abs(getMovedSwitch());
|
||||
if (swtch) {
|
||||
newval = switchToMix(swtch);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (newval != val) {
|
||||
if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) {
|
||||
pauseEvents(event); // delay before auto-repeat continues
|
||||
}
|
||||
AUDIO_KEY_PRESS();
|
||||
storageDirty(i_flags & (EE_GENERAL|EE_MODEL));
|
||||
checkIncDec_Ret = (newval > val ? 1 : -1);
|
||||
}
|
||||
else {
|
||||
checkIncDec_Ret = 0;
|
||||
}
|
||||
return newval;
|
||||
}
|
||||
#else
|
||||
int16_t checkIncDec(uint8_t event, int16_t val, int16_t i_min, int16_t i_max, uint8_t i_flags)
|
||||
{
|
||||
int16_t newval = val;
|
||||
|
||||
#if defined(DBLKEYS)
|
||||
uint8_t in = KEYS_PRESSED();
|
||||
if (!(i_flags & NO_DBLKEYS) && (EVT_KEY_MASK(event))) {
|
||||
bool dblkey = true;
|
||||
if (DBLKEYS_PRESSED_RGT_LFT(in))
|
||||
newval = -val;
|
||||
else if (DBLKEYS_PRESSED_RGT_UP(in)) {
|
||||
newval = (i_max > 100 ? 100 : i_max);
|
||||
}
|
||||
else if (DBLKEYS_PRESSED_LFT_DWN(in)) {
|
||||
newval = (i_min < -100 ? -100 : i_min);
|
||||
}
|
||||
else if (DBLKEYS_PRESSED_UP_DWN(in)) {
|
||||
newval = 0;
|
||||
}
|
||||
else {
|
||||
dblkey = false;
|
||||
}
|
||||
|
||||
if (dblkey) {
|
||||
killEvents(KEY_UP);
|
||||
killEvents(KEY_DOWN);
|
||||
killEvents(KEY_RIGHT);
|
||||
killEvents(KEY_LEFT);
|
||||
event = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (event==EVT_KEY_FIRST(KEY_RIGHT) || event==EVT_KEY_REPT(KEY_RIGHT) || (s_editMode>0 && (IS_ROTARY_RIGHT(event) || event==EVT_KEY_FIRST(KEY_UP) || event==EVT_KEY_REPT(KEY_UP)))) {
|
||||
newval++;
|
||||
}
|
||||
else if (event==EVT_KEY_FIRST(KEY_LEFT) || event==EVT_KEY_REPT(KEY_LEFT) || (s_editMode>0 && (IS_ROTARY_LEFT(event) || event==EVT_KEY_FIRST(KEY_DOWN) || event==EVT_KEY_REPT(KEY_DOWN)))) {
|
||||
newval--;
|
||||
}
|
||||
|
||||
if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) {
|
||||
s_editMode = 0;
|
||||
newval = !val;
|
||||
}
|
||||
|
||||
#if defined(NAVIGATION_POT1)
|
||||
// change values based on P1
|
||||
newval -= p1valdiff;
|
||||
p1valdiff = 0;
|
||||
#endif
|
||||
|
||||
#if defined(AUTOSWITCH)
|
||||
if (i_flags & INCDEC_SWITCH) {
|
||||
newval = checkIncDecMovedSwitch(newval);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(AUTOSOURCE)
|
||||
if (i_flags & INCDEC_SOURCE) {
|
||||
if (s_editMode>0) {
|
||||
int8_t source = GET_MOVED_SOURCE(i_min, i_max);
|
||||
if (source) {
|
||||
newval = source;
|
||||
}
|
||||
#if defined(AUTOSWITCH)
|
||||
else {
|
||||
uint8_t swtch = abs(getMovedSwitch());
|
||||
if (swtch) {
|
||||
newval = switchToMix(swtch);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (newval > i_max || newval < i_min) {
|
||||
newval = (newval > i_max ? i_max : i_min);
|
||||
killEvents(event);
|
||||
AUDIO_KEY_ERROR();
|
||||
}
|
||||
|
||||
if (newval != val) {
|
||||
if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) {
|
||||
pauseEvents(event); // delay before auto-repeat continues
|
||||
}
|
||||
if (!IS_KEY_REPT(event)) {
|
||||
AUDIO_KEY_PRESS();
|
||||
}
|
||||
storageDirty(i_flags & (EE_GENERAL|EE_MODEL));
|
||||
checkIncDec_Ret = (newval > val ? 1 : -1);
|
||||
}
|
||||
else {
|
||||
checkIncDec_Ret = 0;
|
||||
}
|
||||
return newval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUM64)
|
||||
int8_t checkIncDecModel(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max)
|
||||
{
|
||||
return checkIncDec(event, i_val, i_min, i_max, EE_MODEL);
|
||||
}
|
||||
|
||||
int8_t checkIncDecModelZero(uint8_t event, int8_t i_val, int8_t i_max)
|
||||
{
|
||||
return checkIncDecModel(event, i_val, 0, i_max);
|
||||
}
|
||||
|
||||
int8_t checkIncDecGen(uint8_t event, int8_t i_val, int8_t i_min, int8_t i_max)
|
||||
{
|
||||
return checkIncDec(event, i_val, i_min, i_max, EE_GENERAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SCROLL_TH 64
|
||||
#define SCROLL_POT1_TH 32
|
||||
|
||||
#if defined(CPUARM)
|
||||
#define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0)
|
||||
#else
|
||||
#define CURSOR_NOT_ALLOWED_IN_ROW(row) (MAXCOL(row) == TITLE_ROW)
|
||||
#endif
|
||||
|
||||
#define MAXCOL(row) (horTab ? pgm_read_byte(horTab+min(row, (vertpos_t)horTabMax)) : (const uint8_t)0)
|
||||
#define INC(val, min, max) if (val<max) {val++;} else {val=min;}
|
||||
#define DEC(val, min, max) if (val>min) {val--;} else {val=max;}
|
||||
|
||||
#if defined(CPUARM)
|
||||
tmr10ms_t menuEntryTime;
|
||||
#endif
|
||||
|
||||
void check(check_event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, vertpos_t maxrow)
|
||||
{
|
||||
vertpos_t l_posVert = menuVerticalPosition;
|
||||
horzpos_t l_posHorz = menuHorizontalPosition;
|
||||
|
||||
uint8_t maxcol = MAXCOL(l_posVert);
|
||||
|
||||
#if defined(NAVIGATION_POT1)
|
||||
// check pot 1 - if changed -> scroll values
|
||||
static int16_t p1val;
|
||||
static int16_t p1valprev;
|
||||
p1valdiff = (p1val-calibratedStick[6]) / SCROLL_POT1_TH;
|
||||
if (p1valdiff) {
|
||||
p1valdiff = (p1valprev-calibratedStick[6]) / 2;
|
||||
p1val = calibratedStick[6];
|
||||
}
|
||||
p1valprev = calibratedStick[6];
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_POT2)
|
||||
// check pot 2 - if changed -> scroll menu
|
||||
static int16_t p2valprev;
|
||||
p2valdiff = (p2valprev-calibratedStick[4]) / SCROLL_TH;
|
||||
if (p2valdiff) p2valprev = calibratedStick[4];
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_POT3)
|
||||
// check pot 3 if changed -> cursor down/up
|
||||
static int16_t p3valprev;
|
||||
int8_t scrollUD = (p3valprev-calibratedStick[5]) / SCROLL_TH;
|
||||
if (scrollUD) p3valprev = calibratedStick[5];
|
||||
#else
|
||||
#define scrollUD 0
|
||||
#endif
|
||||
|
||||
if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on
|
||||
|
||||
if (menuTab) {
|
||||
uint8_t attr = 0;
|
||||
|
||||
|
||||
if (l_posVert==0 && !calibrationState) {
|
||||
attr = INVERS;
|
||||
|
||||
int8_t cc = curr;
|
||||
|
||||
if (p2valdiff) {
|
||||
cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1));
|
||||
}
|
||||
|
||||
switch(event) {
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_BREAK:
|
||||
if (s_editMode < 0 && maxrow > 0) {
|
||||
s_editMode = 0;
|
||||
// TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1;
|
||||
l_posHorz = 0;
|
||||
}
|
||||
else {
|
||||
s_editMode = -1;
|
||||
}
|
||||
event = 0;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LEFT:
|
||||
if (s_editMode >= 0)
|
||||
break;
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_LEFT):
|
||||
if (curr > 0)
|
||||
cc = curr - 1;
|
||||
else
|
||||
cc = menuTabSize-1;
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_RIGHT:
|
||||
if (s_editMode >= 0)
|
||||
break;
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
if (curr < (menuTabSize-1))
|
||||
cc = curr + 1;
|
||||
else
|
||||
cc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cc != curr) {
|
||||
chainMenu((MenuHandlerFunc)pgm_read_adr(&menuTab[cc]));
|
||||
}
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
if (IS_RE_NAVIGATION_ENABLE() && s_editMode < 0)
|
||||
attr = INVERS|BLINK;
|
||||
#endif
|
||||
}
|
||||
|
||||
calibrationState = 0;
|
||||
drawScreenIndex(curr, menuTabSize, attr);
|
||||
|
||||
}
|
||||
|
||||
DISPLAY_PROGRESS_BAR(menuTab ? lcdLastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
|
||||
|
||||
if (s_editMode<=0) {
|
||||
if (scrollUD) {
|
||||
l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow);
|
||||
l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
|
||||
}
|
||||
|
||||
if (p2valdiff && l_posVert>0) {
|
||||
l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol);
|
||||
}
|
||||
}
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
#if defined(CPUARM)
|
||||
menuEntryTime = get_tmr10ms();
|
||||
#endif
|
||||
l_posVert = 0;
|
||||
l_posHorz = POS_HORZ_INIT(l_posVert);
|
||||
SET_SCROLLBAR_X(LCD_W-1);
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
if (menuTab) {
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
#else
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ENTRY_UP:
|
||||
s_editMode = 0;
|
||||
SET_SCROLLBAR_X(LCD_W-1);
|
||||
break;
|
||||
|
||||
case EVT_ROTARY_BREAK:
|
||||
if (s_editMode > 1) break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
if (!menuTab || l_posVert>0) {
|
||||
if (READ_ONLY_UNLOCKED()) {
|
||||
s_editMode = (s_editMode<=0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LONG:
|
||||
if (s_editMode > 1) break;
|
||||
killEvents(event);
|
||||
if (l_posVert != 0) {
|
||||
l_posVert = 0;
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
break;
|
||||
}
|
||||
// no break
|
||||
#endif
|
||||
case EVT_KEY_LONG(KEY_EXIT):
|
||||
s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
|
||||
popMenu();
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
AUDIO_KEY_PRESS();
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
if (s_editMode == 0)
|
||||
s_editMode = EDIT_MODE_INIT;
|
||||
else
|
||||
#endif
|
||||
if (s_editMode>0) {
|
||||
s_editMode = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (l_posVert==0 || !menuTab) {
|
||||
popMenu(); // beeps itself
|
||||
}
|
||||
else {
|
||||
l_posVert = 0;
|
||||
l_posHorz = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EVT_KEY_REPT(KEY_RIGHT): //inc
|
||||
if (l_posHorz==maxcol) break;
|
||||
// no break
|
||||
|
||||
case EVT_KEY_FIRST(KEY_RIGHT)://inc
|
||||
if (!horTab || s_editMode>0) break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
CASE_EVT_ROTARY_RIGHT
|
||||
if (s_editMode != 0) break;
|
||||
if (l_posHorz < maxcol) {
|
||||
l_posHorz++;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
l_posHorz = 0;
|
||||
if (!IS_ROTARY_RIGHT(event))
|
||||
break;
|
||||
}
|
||||
#else
|
||||
INC(l_posHorz, 0, maxcol);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_REPT(KEY_DOWN): //inc
|
||||
if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break;
|
||||
// no break
|
||||
|
||||
case EVT_KEY_FIRST(KEY_DOWN): //inc
|
||||
if (s_editMode>0) break;
|
||||
do {
|
||||
INC(l_posVert, 0, maxrow);
|
||||
} while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
s_editMode = 0; // if we go down, we must be in this mode
|
||||
#endif
|
||||
|
||||
l_posHorz = min(l_posHorz, MAXCOL(l_posVert));
|
||||
break;
|
||||
|
||||
case EVT_KEY_REPT(KEY_LEFT): //dec
|
||||
if (l_posHorz==0) break;
|
||||
// no break
|
||||
|
||||
case EVT_KEY_FIRST(KEY_LEFT)://dec
|
||||
if (!horTab || s_editMode>0) break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
CASE_EVT_ROTARY_LEFT
|
||||
if (s_editMode != 0) break;
|
||||
if (l_posHorz > 0) {
|
||||
l_posHorz--;
|
||||
break;
|
||||
}
|
||||
else if (IS_ROTARY_LEFT(event) && s_editMode == 0) {
|
||||
l_posHorz = 0xff;
|
||||
}
|
||||
else {
|
||||
l_posHorz = maxcol;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
DEC(l_posHorz, 0, maxcol);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_REPT(KEY_UP): //dec
|
||||
if (!IS_ROTARY_LEFT(event) && l_posVert==0) break;
|
||||
// no break
|
||||
case EVT_KEY_FIRST(KEY_UP): //dec
|
||||
if (s_editMode>0) break;
|
||||
|
||||
do {
|
||||
DEC(l_posVert, 0, maxrow);
|
||||
} while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
s_editMode = 0; // if we go up, we must be in this mode
|
||||
#endif
|
||||
|
||||
l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t maxLines = menuTab ? LCD_LINES-1 : LCD_LINES-2;
|
||||
|
||||
#if defined(CPUARM)
|
||||
int linesCount = maxrow;
|
||||
if (l_posVert == 0 || (l_posVert==1 && MAXCOL(vertpos_t(0)) >= HIDDEN_ROW) || (l_posVert==2 && MAXCOL(vertpos_t(0)) >= HIDDEN_ROW && MAXCOL(vertpos_t(1)) >= HIDDEN_ROW)) {
|
||||
menuVerticalOffset = 0;
|
||||
if (horTab) {
|
||||
linesCount = 0;
|
||||
for (int i=0; i<maxrow; i++) {
|
||||
if (i>=horTabMax || horTab[i] != HIDDEN_ROW) {
|
||||
linesCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (horTab) {
|
||||
if (maxrow > maxLines) {
|
||||
while (1) {
|
||||
vertpos_t firstLine = 0;
|
||||
for (int numLines=0; firstLine<maxrow && numLines<menuVerticalOffset; firstLine++) {
|
||||
if (firstLine>=horTabMax || horTab[firstLine+1] != HIDDEN_ROW) {
|
||||
numLines++;
|
||||
}
|
||||
}
|
||||
if (l_posVert <= firstLine) {
|
||||
menuVerticalOffset--;
|
||||
}
|
||||
else {
|
||||
vertpos_t lastLine = firstLine;
|
||||
for (int numLines=0; lastLine<maxrow && numLines<maxLines; lastLine++) {
|
||||
if (lastLine>=horTabMax || horTab[lastLine+1] != HIDDEN_ROW) {
|
||||
numLines++;
|
||||
}
|
||||
}
|
||||
if (l_posVert > lastLine) {
|
||||
menuVerticalOffset++;
|
||||
}
|
||||
else {
|
||||
linesCount = menuVerticalOffset + maxLines;
|
||||
for (int i=lastLine; i<maxrow; i++) {
|
||||
if (i>=horTabMax || horTab[i] != HIDDEN_ROW) {
|
||||
linesCount++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (l_posVert<1) {
|
||||
menuVerticalOffset=0;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
if (l_posVert>maxLines+menuVerticalOffset) {
|
||||
menuVerticalOffset = l_posVert-maxLines;
|
||||
}
|
||||
else if (l_posVert<=menuVerticalOffset) {
|
||||
menuVerticalOffset = l_posVert-1;
|
||||
}
|
||||
}
|
||||
|
||||
menuVerticalPosition = l_posVert;
|
||||
menuHorizontalPosition = l_posHorz;
|
||||
#if !defined(CPUM64)
|
||||
// cosmetics on 9x
|
||||
if (menuVerticalOffset > 0) {
|
||||
l_posVert--;
|
||||
if (l_posVert == menuVerticalOffset && CURSOR_NOT_ALLOWED_IN_ROW(l_posVert)) {
|
||||
menuVerticalOffset = l_posVert-1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void check_simple(check_event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t menuTabSize, vertpos_t maxrow)
|
||||
{
|
||||
check(event, curr, menuTab, menuTabSize, 0, 0, maxrow);
|
||||
}
|
||||
|
||||
void check_submenu_simple(check_event_t event, uint8_t maxrow)
|
||||
{
|
||||
check_simple(event, 0, 0, 0, maxrow);
|
||||
}
|
||||
|
||||
void repeatLastCursorMove(uint8_t event)
|
||||
{
|
||||
if (CURSOR_MOVED_LEFT(event) || CURSOR_MOVED_RIGHT(event)) {
|
||||
putEvent(event);
|
||||
}
|
||||
else {
|
||||
menuHorizontalPosition = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
const pm_char * warningText = NULL;
|
||||
const pm_char * warningInfoText;
|
||||
uint8_t warningInfoLength;
|
||||
uint8_t warningType;
|
||||
uint8_t warningResult = 0;
|
||||
|
||||
#if defined(CPUARM)
|
||||
uint8_t warningInfoFlags = ZCHAR;
|
||||
int16_t warningInputValue;
|
||||
int16_t warningInputValueMin;
|
||||
int16_t warningInputValueMax;
|
||||
#endif
|
||||
|
||||
void displayBox()
|
||||
{
|
||||
lcdDrawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE);
|
||||
lcdDrawRect(10, 16, LCD_W-20, 40);
|
||||
#if defined(CPUARM)
|
||||
lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y, warningText, WARNING_LINE_LEN);
|
||||
#else
|
||||
lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y, warningText);
|
||||
#endif
|
||||
// could be a place for a warningInfoText
|
||||
}
|
||||
|
||||
void displayPopup(const pm_char * pstr)
|
||||
{
|
||||
warningText = pstr;
|
||||
displayBox();
|
||||
warningText = NULL;
|
||||
lcdRefresh();
|
||||
}
|
||||
|
||||
const pm_uchar asterisk_lbm[] PROGMEM = {
|
||||
#include "asterisk.lbm"
|
||||
};
|
||||
|
||||
void message(const pm_char *title, const pm_char *t, const char *last MESSAGE_SOUND_ARG)
|
||||
{
|
||||
lcdClear();
|
||||
lcd_img(2, 0, asterisk_lbm, 0, 0);
|
||||
|
||||
#define MESSAGE_LCD_OFFSET 6*FW
|
||||
|
||||
#if defined(TRANSLATIONS_FR) || defined(TRANSLATIONS_IT) || defined(TRANSLATIONS_CZ)
|
||||
lcdDrawText(MESSAGE_LCD_OFFSET, 0, STR_WARNING, DBLSIZE);
|
||||
lcdDrawText(MESSAGE_LCD_OFFSET, 2*FH, title, DBLSIZE);
|
||||
#else
|
||||
lcdDrawText(MESSAGE_LCD_OFFSET, 0, title, DBLSIZE);
|
||||
lcdDrawText(MESSAGE_LCD_OFFSET, 2*FH, STR_WARNING, DBLSIZE);
|
||||
#endif
|
||||
|
||||
lcdDrawFilledRect(0, 0, LCD_W, 32);
|
||||
if (t) lcd_putsLeft(5*FH, t);
|
||||
if (last) {
|
||||
lcd_putsLeft(7*FH, last);
|
||||
AUDIO_ERROR_MESSAGE(sound);
|
||||
}
|
||||
|
||||
#undef MESSAGE_LCD_OFFSET
|
||||
|
||||
lcdRefresh();
|
||||
lcdSetContrast();
|
||||
clearKeyEvents();
|
||||
}
|
||||
|
||||
void displayWarning(uint8_t event)
|
||||
{
|
||||
warningResult = false;
|
||||
displayBox();
|
||||
if (warningInfoText) {
|
||||
lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+FH, warningInfoText, warningInfoLength, WARNING_INFO_FLAGS);
|
||||
}
|
||||
lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+2*FH, warningType == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS);
|
||||
switch (event) {
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_BREAK:
|
||||
#endif
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
if (warningType == WARNING_TYPE_ASTERISK)
|
||||
break;
|
||||
warningResult = true;
|
||||
// no break
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
case EVT_ROTARY_LONG:
|
||||
killEvents(event);
|
||||
#endif
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
warningText = NULL;
|
||||
warningType = WARNING_TYPE_ASTERISK;
|
||||
break;
|
||||
#if defined(CPUARM)
|
||||
default:
|
||||
if (warningType != WARNING_TYPE_INPUT) break;
|
||||
s_editMode = EDIT_MODIFY_FIELD;
|
||||
warningInputValue = checkIncDec(event, warningInputValue, warningInputValueMin, warningInputValueMax);
|
||||
s_editMode = EDIT_SELECT_FIELD;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
void (*popupFunc)(uint8_t event) = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
const char *popupMenuItems[POPUP_MENU_MAX_LINES];
|
||||
uint8_t s_menu_item = 0;
|
||||
uint16_t popupMenuNoItems = 0;
|
||||
uint8_t popupMenuFlags = 0;
|
||||
uint16_t popupMenuOffset = 0;
|
||||
void (*popupMenuHandler)(const char *result);
|
||||
const char * displayPopupMenu(uint8_t event)
|
||||
{
|
||||
const char * result = NULL;
|
||||
|
||||
uint8_t display_count = min<uint8_t>(popupMenuNoItems, POPUP_MENU_MAX_LINES);
|
||||
uint8_t y = (display_count >= 5 ? MENU_Y - FH - 1 : MENU_Y);
|
||||
lcdDrawFilledRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2, SOLID, ERASE);
|
||||
lcdDrawRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2);
|
||||
|
||||
for (uint8_t i=0; i<display_count; i++) {
|
||||
lcdDrawText(MENU_X+6, i*(FH+1) + y + 2, popupMenuItems[i], popupMenuFlags);
|
||||
if (i == s_menu_item) lcdDrawFilledRect(MENU_X+1, i*(FH+1) + y + 1, MENU_W-2, 9);
|
||||
}
|
||||
|
||||
if (popupMenuNoItems > display_count) {
|
||||
drawVerticalScrollbar(MENU_X+MENU_W-1, y+1, POPUP_MENU_MAX_LINES * (FH+1), popupMenuOffset, popupMenuNoItems, POPUP_MENU_MAX_LINES);
|
||||
}
|
||||
|
||||
switch(event) {
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
CASE_EVT_ROTARY_LEFT
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
case EVT_KEY_REPT(KEY_UP):
|
||||
if (s_menu_item > 0) {
|
||||
s_menu_item--;
|
||||
}
|
||||
#if defined(SDCARD)
|
||||
else if (popupMenuOffset > 0) {
|
||||
popupMenuOffset--;
|
||||
result = STR_UPDATE_LIST;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
s_menu_item = display_count - 1;
|
||||
#if defined(SDCARD)
|
||||
if (popupMenuNoItems > POPUP_MENU_MAX_LINES) {
|
||||
popupMenuOffset = popupMenuNoItems - display_count;
|
||||
result = STR_UPDATE_LIST;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
CASE_EVT_ROTARY_RIGHT
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
case EVT_KEY_REPT(KEY_DOWN):
|
||||
if (s_menu_item < display_count - 1 && popupMenuOffset + s_menu_item + 1 < popupMenuNoItems) {
|
||||
s_menu_item++;
|
||||
}
|
||||
#if defined(SDCARD)
|
||||
else if (popupMenuNoItems > popupMenuOffset + display_count) {
|
||||
popupMenuOffset++;
|
||||
result = STR_UPDATE_LIST;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
s_menu_item = 0;
|
||||
#if defined(SDCARD)
|
||||
if (popupMenuOffset) {
|
||||
popupMenuOffset = 0;
|
||||
result = STR_UPDATE_LIST;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
result = popupMenuItems[s_menu_item];
|
||||
// no break
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
CASE_EVT_ROTARY_LONG
|
||||
killEvents(event);
|
||||
#endif
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
popupMenuNoItems = 0;
|
||||
s_menu_item = 0;
|
||||
popupMenuFlags = 0;
|
||||
popupMenuOffset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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 XPOT_DELTA 10
|
||||
#define XPOT_DELAY 10 /* cycles */
|
||||
|
||||
enum CalibrationState {
|
||||
CALIB_START = 0,
|
||||
CALIB_SET_MIDPOINT,
|
||||
CALIB_MOVE_STICKS,
|
||||
CALIB_STORE,
|
||||
CALIB_FINISHED
|
||||
};
|
||||
|
||||
void menuCommonCalib(uint8_t event)
|
||||
{
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) { // get low and high vals for sticks and trims
|
||||
int16_t vt = anaIn(i);
|
||||
reusableBuffer.calib.loVals[i] = min(vt, reusableBuffer.calib.loVals[i]);
|
||||
reusableBuffer.calib.hiVals[i] = max(vt, reusableBuffer.calib.hiVals[i]);
|
||||
if (i >= POT1 && i <= POT_LAST) {
|
||||
if (IS_POT_WITHOUT_DETENT(i)) {
|
||||
reusableBuffer.calib.midVals[i] = (reusableBuffer.calib.hiVals[i] + reusableBuffer.calib.loVals[i]) / 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
calibrationState = reusableBuffer.calib.state; // make sure we don't scroll while calibrating
|
||||
|
||||
switch (event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
reusableBuffer.calib.state = CALIB_START;
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_ENTER):
|
||||
reusableBuffer.calib.state++;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (reusableBuffer.calib.state) {
|
||||
case CALIB_START:
|
||||
// START CALIBRATION
|
||||
if (!READ_ONLY()) {
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+2*FH, STR_MENUTOSTART);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALIB_SET_MIDPOINT:
|
||||
// SET MIDPOINT
|
||||
lcdDrawText(0*FW, MENU_HEADER_HEIGHT+FH, STR_SETMIDPOINT, INVERS);
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+2*FH, STR_MENUWHENDONE);
|
||||
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) {
|
||||
reusableBuffer.calib.loVals[i] = 15000;
|
||||
reusableBuffer.calib.hiVals[i] = -15000;
|
||||
reusableBuffer.calib.midVals[i] = anaIn(i);
|
||||
}
|
||||
break;
|
||||
|
||||
case CALIB_MOVE_STICKS:
|
||||
// MOVE STICKS/POTS
|
||||
STICK_SCROLL_DISABLE();
|
||||
lcdDrawText(0*FW, MENU_HEADER_HEIGHT+FH, STR_MOVESTICKSPOTS, INVERS);
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+2*FH, STR_MENUWHENDONE);
|
||||
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) {
|
||||
if (abs(reusableBuffer.calib.loVals[i]-reusableBuffer.calib.hiVals[i]) > 50) {
|
||||
g_eeGeneral.calib[i].mid = reusableBuffer.calib.midVals[i];
|
||||
int16_t v = reusableBuffer.calib.midVals[i] - reusableBuffer.calib.loVals[i];
|
||||
g_eeGeneral.calib[i].spanNeg = v - v/STICK_TOLERANCE;
|
||||
v = reusableBuffer.calib.hiVals[i] - reusableBuffer.calib.midVals[i];
|
||||
g_eeGeneral.calib[i].spanPos = v - v/STICK_TOLERANCE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CALIB_STORE:
|
||||
g_eeGeneral.chkSum = evalChkSum();
|
||||
storageDirty(EE_GENERAL);
|
||||
reusableBuffer.calib.state = CALIB_FINISHED;
|
||||
break;
|
||||
|
||||
default:
|
||||
reusableBuffer.calib.state = CALIB_START;
|
||||
break;
|
||||
}
|
||||
|
||||
doMainScreenGraphics();
|
||||
}
|
||||
|
||||
void menuGeneralCalib(uint8_t event)
|
||||
{
|
||||
check_simple(event, e_Calib, menuTabGeneral, DIM(menuTabGeneral), 0);
|
||||
|
||||
if (menuEvent) {
|
||||
calibrationState = CALIB_START;
|
||||
}
|
||||
|
||||
TITLE(STR_MENUCALIBRATION);
|
||||
menuCommonCalib(READ_ONLY() ? 0 : event);
|
||||
}
|
||||
|
||||
void menuFirstCalib(uint8_t event)
|
||||
{
|
||||
if (event == EVT_KEY_BREAK(KEY_EXIT) || reusableBuffer.calib.state == CALIB_FINISHED) {
|
||||
calibrationState = CALIB_START;
|
||||
chainMenu(menuMainView);
|
||||
}
|
||||
else {
|
||||
lcd_putsCenter(0*FH, MENUCALIBRATION);
|
||||
lcdInvertLine(0);
|
||||
menuCommonCalib(event);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 menuGeneralDiagAna(uint8_t event)
|
||||
{
|
||||
#if defined(TX_CAPACITY_MEASUREMENT)
|
||||
#define ANAS_ITEMS_COUNT 4
|
||||
#elif defined(PCBSKY9X)
|
||||
#define ANAS_ITEMS_COUNT 3
|
||||
#else
|
||||
#define ANAS_ITEMS_COUNT 2
|
||||
#endif
|
||||
|
||||
SIMPLE_MENU(STR_MENUANA, menuTabGeneral, e_Ana, ANAS_ITEMS_COUNT);
|
||||
|
||||
STICK_SCROLL_DISABLE();
|
||||
|
||||
for (uint8_t i=0; i<NUM_STICKS+NUM_POTS; i++) {
|
||||
#if (NUM_STICKS+NUM_POTS) > 9
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + (i/3)*FH;
|
||||
const uint8_t x_coord[] = {0, 70, 154};
|
||||
uint8_t x = x_coord[i%3];
|
||||
lcdDrawNumber(x, y, i+1, LEADING0|LEFT, 2);
|
||||
lcdDrawChar(x+2*FW-2, y, ':');
|
||||
#else
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + (i/2)*FH;
|
||||
uint8_t x = i&1 ? 64+5 : 0;
|
||||
drawStringWithIndex(x, y, PSTR("A"), i+1);
|
||||
lcdDrawChar(lcdNextPos, y, ':');
|
||||
#endif
|
||||
lcdDrawHexNumber(x+3*FW-1, y, anaIn(i));
|
||||
lcdDraw8bitsNumber(x+10*FW-1, y, (int16_t)calibratedStick[CONVERT_MODE(i)]*25/256);
|
||||
}
|
||||
|
||||
#if !defined(CPUARM)
|
||||
// Display raw BandGap result (debug)
|
||||
lcdDrawText(64+5, MENU_HEADER_HEIGHT+1+3*FH, STR_BG);
|
||||
lcdDrawNumber(64+5+6*FW-3, 1+4*FH, BandGap, 0);
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+1+4*FH, STR_BATT_CALIB);
|
||||
static int32_t adcBatt;
|
||||
adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8;
|
||||
uint32_t batCalV = (adcBatt + adcBatt*(g_eeGeneral.txVoltageCalibration)/128) * 4191;
|
||||
batCalV /= 55296;
|
||||
putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_HEADER_HEIGHT+1+4*FH, batCalV, (menuVerticalPosition==1 ? INVERS : 0));
|
||||
#elif defined(PCBGRUVIN9X)
|
||||
lcd_putsLeft(6*FH-2, STR_BATT_CALIB);
|
||||
// Gruvin wants 2 decimal places and instant update of volts calib field when button pressed
|
||||
static uint16_t adcBatt;
|
||||
adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8; // running average, sourced directly (to avoid unending debate :P)
|
||||
uint32_t batCalV = ((uint32_t)adcBatt*1390 + (10*(int32_t)adcBatt*g_eeGeneral.txVoltageCalibration)/8) / BandGap;
|
||||
lcdDrawNumber(LEN_CALIB_FIELDS*FW+4*FW, 6*FH-2, batCalV, PREC2|(menuVerticalPosition==1 ? INVERS : 0));
|
||||
#else
|
||||
lcd_putsLeft(6*FH-2, STR_BATT_CALIB);
|
||||
putsVolts(LEN_CALIB_FIELDS*FW+4*FW, 6*FH-2, g_vbat100mV, (menuVerticalPosition==1 ? INVERS : 0));
|
||||
#endif
|
||||
if (menuVerticalPosition==1) CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127);
|
||||
|
||||
#if defined(TX_CAPACITY_MEASUREMENT)
|
||||
lcd_putsLeft(6*FH+1, STR_CURRENT_CALIB);
|
||||
putsValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, 6*FH+1, getCurrent(), UNIT_MILLIAMPS, (menuVerticalPosition==2 ? INVERS : 0)) ;
|
||||
if (menuVerticalPosition==2) CHECK_INCDEC_GENVAR(event, g_eeGeneral.txCurrentCalibration, -49, 49);
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
#if defined(TX_CAPACITY_MEASUREMENT)
|
||||
#define TEMP_CALIB_POS 7*FH+1
|
||||
#define TEMP_CALIB_MENU_POS 3
|
||||
#else
|
||||
#define TEMP_CALIB_POS 6*FH+1
|
||||
#define TEMP_CALIB_MENU_POS 2
|
||||
#endif
|
||||
|
||||
lcd_putsLeft(TEMP_CALIB_POS, STR_TEMP_CALIB);
|
||||
putsValueWithUnit(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);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 displayKeyState(uint8_t x, uint8_t y, EnumKeys key)
|
||||
{
|
||||
uint8_t t = switchState(key);
|
||||
lcdDrawChar(x, y, t+'0', t ? INVERS : 0);
|
||||
}
|
||||
|
||||
void menuGeneralDiagKeys(uint8_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUDIAG, menuTabGeneral, e_Keys, 1);
|
||||
|
||||
lcdDrawText(14*FW, MENU_HEADER_HEIGHT+2*FH, STR_VTRIM);
|
||||
|
||||
for(uint8_t i=0; i<9; i++) {
|
||||
coord_t y;
|
||||
|
||||
if (i<8) {
|
||||
y = MENU_HEADER_HEIGHT + FH*3 + FH*(i/2);
|
||||
if (i&1) lcd_img(14*FW, y, sticks, i/2, 0);
|
||||
displayKeyState(i&1? 20*FW : 18*FW, y, (EnumKeys)(TRM_BASE+i));
|
||||
}
|
||||
|
||||
if (i<6) {
|
||||
y = i*FH+MENU_HEADER_HEIGHT+FH;
|
||||
lcdDrawTextAtIndex(0, y, STR_VKEYS, (5-i), 0);
|
||||
displayKeyState(5*FW+2, y, (EnumKeys)(KEY_MENU+(5-i)));
|
||||
}
|
||||
|
||||
if (i != SW_ID0-SW_BASE) {
|
||||
y = MENU_HEADER_HEIGHT+i*FH-2*FH;
|
||||
putsSwitches(8*FW, y, i+1, 0); //ohne off,on
|
||||
displayKeyState(11*FW+2, y, (EnumKeys)(SW_BASE+i));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ROTARY_ENCODERS) || defined(ROTARY_ENCODER_NAVIGATION)
|
||||
for(uint8_t i=0; i<DIM(g_rotenc); i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT /* ??? + 1 ??? */ + i*FH;
|
||||
lcdDrawTextAtIndex(14*FW, y, STR_VRENCODERS, i, 0);
|
||||
lcdDrawNumber(18*FW, y, g_rotenc[i], LEFT|(switchState((EnumKeys)(BTN_REa+i)) ? INVERS : 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 menuGeneralHwItems {
|
||||
ITEM_SETUP_HW_OPTREX_DISPLAY,
|
||||
ITEM_SETUP_HW_STICKS_GAINS_LABELS,
|
||||
ITEM_SETUP_HW_STICK_LV_GAIN,
|
||||
ITEM_SETUP_HW_STICK_LH_GAIN,
|
||||
ITEM_SETUP_HW_STICK_RV_GAIN,
|
||||
ITEM_SETUP_HW_STICK_RH_GAIN,
|
||||
IF_ROTARY_ENCODERS(ITEM_SETUP_HW_ROTARY_ENCODER)
|
||||
CASE_BLUETOOTH(ITEM_SETUP_HW_BT_BAUDRATE)
|
||||
ITEM_SETUP_HW_MAX
|
||||
};
|
||||
|
||||
#define GENERAL_HW_PARAM_OFS (2+(15*FW))
|
||||
void menuGeneralHardware(uint8_t event)
|
||||
{
|
||||
MENU(STR_HARDWARE, menuTabGeneral, e_Hardware, ITEM_SETUP_HW_MAX+1, {0, 0, (uint8_t)-1, 0, 0, 0, IF_ROTARY_ENCODERS(0) CASE_BLUETOOTH(0)});
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
uint8_t attr = (sub == k ? blink : 0);
|
||||
|
||||
switch(k) {
|
||||
case ITEM_SETUP_HW_OPTREX_DISPLAY:
|
||||
g_eeGeneral.optrexDisplay = selectMenuItem(GENERAL_HW_PARAM_OFS, y, STR_LCD, STR_VLCD, g_eeGeneral.optrexDisplay, 0, 1, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HW_STICKS_GAINS_LABELS:
|
||||
lcd_putsLeft(y, PSTR("Sticks"));
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HW_STICK_LV_GAIN:
|
||||
case ITEM_SETUP_HW_STICK_LH_GAIN:
|
||||
case ITEM_SETUP_HW_STICK_RV_GAIN:
|
||||
case ITEM_SETUP_HW_STICK_RH_GAIN:
|
||||
{
|
||||
lcdDrawTextAtIndex(INDENT_WIDTH, y, PSTR("\002LVLHRVRH"), k-ITEM_SETUP_HW_STICK_LV_GAIN, 0);
|
||||
lcdDrawText(INDENT_WIDTH+3*FW, y, PSTR("Gain"));
|
||||
uint8_t mask = (1<<(k-ITEM_SETUP_HW_STICK_LV_GAIN));
|
||||
uint8_t val = (g_eeGeneral.sticksGain & mask ? 1 : 0);
|
||||
lcdDrawChar(GENERAL_HW_PARAM_OFS, y, val ? '2' : '1', attr);
|
||||
if (attr) {
|
||||
CHECK_INCDEC_GENVAR(event, val, 0, 1);
|
||||
if (checkIncDec_Ret) {
|
||||
g_eeGeneral.sticksGain ^= mask;
|
||||
setSticksGain(g_eeGeneral.sticksGain);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(ROTARY_ENCODERS)
|
||||
case ITEM_SETUP_HW_ROTARY_ENCODER:
|
||||
g_eeGeneral.rotarySteps = selectMenuItem(GENERAL_HW_PARAM_OFS, y, PSTR("Rotary Encoder"), PSTR("\0062steps4steps"), g_eeGeneral.rotarySteps, 0, 1, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(BLUETOOTH)
|
||||
case ITEM_SETUP_HW_BT_BAUDRATE:
|
||||
g_eeGeneral.btBaudrate = selectMenuItem(GENERAL_HW_PARAM_OFS, y, STR_BAUDRATE, PSTR("\005115k 9600 19200"), g_eeGeneral.btBaudrate, 0, 2, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
btInit();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* 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 menuGeneralSdManagerInfo(uint8_t event)
|
||||
{
|
||||
SIMPLE_SUBMENU(STR_SD_INFO_TITLE, 1);
|
||||
|
||||
lcd_putsLeft(2*FH, STR_SD_TYPE);
|
||||
lcdDrawText(10*FW, 2*FH, SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD);
|
||||
|
||||
lcd_putsLeft(3*FH, STR_SD_SIZE);
|
||||
lcdDrawNumber(10*FW, 3*FH, sdGetSize(), LEFT);
|
||||
lcdDrawChar(lcdLastPos, 3*FH, 'M');
|
||||
|
||||
lcd_putsLeft(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');
|
||||
|
||||
lcd_putsLeft(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 onSdManagerMenu(const char *result)
|
||||
{
|
||||
TCHAR lfn[_MAX_LFN+1];
|
||||
|
||||
uint8_t index = menuVerticalPosition-1-menuVerticalOffset;
|
||||
if (result == STR_SD_INFO) {
|
||||
pushMenu(menuGeneralSdManagerInfo);
|
||||
}
|
||||
else if (result == STR_SD_FORMAT) {
|
||||
POPUP_CONFIRMATION(STR_CONFIRM_FORMAT);
|
||||
}
|
||||
else if (result == STR_DELETE_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat_P(lfn, PSTR("/"));
|
||||
strcat(lfn, reusableBuffer.sdmanager.lines[index]);
|
||||
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-1;
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
/* TODO else if (result == STR_LOAD_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, reusableBuffer.sdmanager.lines[index]);
|
||||
POPUP_WARNING(eeLoadModelSD(lfn));
|
||||
} */
|
||||
else if (result == STR_PLAY_FILE) {
|
||||
f_getcwd(lfn, _MAX_LFN);
|
||||
strcat(lfn, "/");
|
||||
strcat(lfn, reusableBuffer.sdmanager.lines[index]);
|
||||
audioQueue.stopAll();
|
||||
audioQueue.playFile(lfn, 0, ID_PLAY_FROM_SD_MANAGER);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void menuGeneralSdManager(uint8_t _event)
|
||||
{
|
||||
FILINFO fno;
|
||||
DIR dir;
|
||||
char *fn; /* This function is assuming non-Unicode cfg. */
|
||||
TCHAR lfn[_MAX_LFN + 1];
|
||||
fno.lfname = lfn;
|
||||
fno.lfsize = sizeof(lfn);
|
||||
|
||||
#if defined(SDCARD)
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
displayPopup(STR_FORMATTING);
|
||||
closeLogs();
|
||||
#if defined(PCBSKY9X)
|
||||
Card_state = SD_ST_DATA;
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
audioQueue.stopSD();
|
||||
#endif
|
||||
if (f_mkfs(0, 1, 0) == FR_OK) {
|
||||
f_chdir("/");
|
||||
reusableBuffer.sdmanager.offset = -1;
|
||||
}
|
||||
else {
|
||||
POPUP_WARNING(STR_SDCARD_ERROR);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t event = ((READ_ONLY() && EVT_KEY_MASK(_event) == KEY_ENTER) ? 0 : _event);
|
||||
SIMPLE_MENU(SD_IS_HC() ? STR_SDHC_CARD : STR_SD_CARD, menuTabGeneral, e_Sd, 1+reusableBuffer.sdmanager.count);
|
||||
|
||||
if (s_editMode > 0)
|
||||
s_editMode = 0;
|
||||
|
||||
switch(_event) {
|
||||
case EVT_ENTRY:
|
||||
f_chdir(ROOT_PATH);
|
||||
reusableBuffer.sdmanager.offset = 65535;
|
||||
break;
|
||||
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_FIRST(KEY_RIGHT):
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
{
|
||||
if (menuVerticalPosition > 0) {
|
||||
vertpos_t index = menuVerticalPosition-1-menuVerticalOffset;
|
||||
if (!reusableBuffer.sdmanager.lines[index][SD_SCREEN_FILE_LENGTH+1]) {
|
||||
f_chdir(reusableBuffer.sdmanager.lines[index]);
|
||||
menuVerticalOffset = 0;
|
||||
menuVerticalPosition = 1;
|
||||
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);
|
||||
if (menuVerticalPosition == 0) {
|
||||
POPUP_MENU_ADD_ITEM(STR_SD_INFO);
|
||||
POPUP_MENU_ADD_ITEM(STR_SD_FORMAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
uint8_t index = menuVerticalPosition-1-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 (!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) {
|
||||
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) {
|
||||
for (;;) {
|
||||
res = f_readdir(&dir, &fno); /* Read a directory item */
|
||||
if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
|
||||
if (fno.fname[0] == '.' && fno.fname[1] == '\0') continue; /* Ignore dot entry */
|
||||
#if _USE_LFN
|
||||
fn = *fno.lfname ? fno.lfname : fno.fname;
|
||||
#else
|
||||
fn = fno.fname;
|
||||
#endif
|
||||
if (strlen(fn) > 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, fn, 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, fn);
|
||||
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, fn, 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, fn);
|
||||
line[SD_SCREEN_FILE_LENGTH+1] = isfile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (menuVerticalOffset > reusableBuffer.sdmanager.offset) {
|
||||
if (isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[5]) && isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[6])) {
|
||||
memset(reusableBuffer.sdmanager.lines[6], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
|
||||
strcpy(reusableBuffer.sdmanager.lines[6], fn);
|
||||
reusableBuffer.sdmanager.lines[6][SD_SCREEN_FILE_LENGTH+1] = isfile;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isFilenameLower(isfile, fn, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fn, reusableBuffer.sdmanager.lines[0])) {
|
||||
memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
|
||||
strcpy(reusableBuffer.sdmanager.lines[0], fn);
|
||||
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-1-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); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LANGUAGE_PACKS_DEFINITION
|
||||
|
||||
#include "opentx.h"
|
||||
|
||||
const pm_uchar sticks[] PROGMEM = {
|
||||
#include "sticks.lbm"
|
||||
};
|
||||
|
||||
#define RADIO_SETUP_2ND_COLUMN (LCD_W-6*FW-3-MENUS_SCROLLBAR_WIDTH)
|
||||
#define RADIO_SETUP_TIME_COLUMN (FW*15+9)
|
||||
#define RADIO_SETUP_DATE_COLUMN (FW*15+7)
|
||||
|
||||
#if !defined(CPUM64)
|
||||
#define SLIDER_5POS(y, value, label, event, attr) { \
|
||||
int8_t tmp = value; \
|
||||
drawSlider(RADIO_SETUP_2ND_COLUMN, y, 2+tmp, 4, attr); \
|
||||
value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, NULL, tmp, -2, +2, attr, event); \
|
||||
}
|
||||
#elif defined(GRAPHICS)
|
||||
#define SLIDER_5POS(y, value, label, event, attr) { \
|
||||
int8_t tmp = value; \
|
||||
display5posSlider(RADIO_SETUP_2ND_COLUMN, y, tmp, attr); \
|
||||
value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, NULL, tmp, -2, +2, attr, event); \
|
||||
}
|
||||
#else
|
||||
#define SLIDER_5POS(y, value, label, event, attr) value = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, label, STR_VBEEPLEN, value, -2, +2, attr, event)
|
||||
#endif
|
||||
|
||||
#if defined(SPLASH) && !defined(FSPLASH)
|
||||
#define CASE_SPLASH_PARAM(x) x,
|
||||
#else
|
||||
#define CASE_SPLASH_PARAM(x)
|
||||
#endif
|
||||
|
||||
#if defined(BATTGRAPH)
|
||||
#define CASE_BATTGRAPH(x) x,
|
||||
#else
|
||||
#define CASE_BATTGRAPH(x)
|
||||
#endif
|
||||
|
||||
enum menuGeneralSetupItems {
|
||||
CASE_RTCLOCK(ITEM_SETUP_DATE)
|
||||
CASE_RTCLOCK(ITEM_SETUP_TIME)
|
||||
CASE_BATTGRAPH(ITEM_SETUP_BATT_RANGE)
|
||||
ITEM_SETUP_SOUND_LABEL,
|
||||
CASE_AUDIO(ITEM_SETUP_BEEP_MODE)
|
||||
CASE_BUZZER(ITEM_SETUP_BUZZER_MODE)
|
||||
CASE_VOICE(ITEM_SETUP_SPEAKER_VOLUME)
|
||||
CASE_CPUARM(ITEM_SETUP_BEEP_VOLUME)
|
||||
ITEM_SETUP_BEEP_LENGTH,
|
||||
CASE_AUDIO(ITEM_SETUP_SPEAKER_PITCH)
|
||||
CASE_CPUARM(ITEM_SETUP_WAV_VOLUME)
|
||||
CASE_CPUARM(ITEM_SETUP_BACKGROUND_VOLUME)
|
||||
CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_LABEL)
|
||||
CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_VOLUME)
|
||||
CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_PITCH)
|
||||
CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_RANGE)
|
||||
CASE_VARIO_CPUARM(ITEM_SETUP_VARIO_REPEAT)
|
||||
CASE_HAPTIC(ITEM_SETUP_HAPTIC_LABEL)
|
||||
CASE_HAPTIC(ITEM_SETUP_HAPTIC_MODE)
|
||||
CASE_HAPTIC(ITEM_SETUP_HAPTIC_LENGTH)
|
||||
CASE_HAPTIC(ITEM_SETUP_HAPTIC_STRENGTH)
|
||||
ITEM_SETUP_CONTRAST,
|
||||
ITEM_SETUP_ALARMS_LABEL,
|
||||
ITEM_SETUP_BATTERY_WARNING,
|
||||
CASE_CAPACITY(ITEM_SETUP_CAPACITY_WARNING)
|
||||
CASE_PCBSKY9X(ITEM_SETUP_TEMPERATURE_WARNING)
|
||||
ITEM_SETUP_INACTIVITY_ALARM,
|
||||
ITEM_SETUP_MEMORY_WARNING,
|
||||
ITEM_SETUP_ALARM_WARNING,
|
||||
IF_ROTARY_ENCODERS(ITEM_SETUP_RE_NAVIGATION)
|
||||
ITEM_SETUP_BACKLIGHT_LABEL,
|
||||
ITEM_SETUP_BACKLIGHT_MODE,
|
||||
ITEM_SETUP_BACKLIGHT_DELAY,
|
||||
CASE_CPUARM(ITEM_SETUP_BRIGHTNESS)
|
||||
CASE_PWM_BACKLIGHT(ITEM_SETUP_BACKLIGHT_BRIGHTNESS_OFF)
|
||||
CASE_PWM_BACKLIGHT(ITEM_SETUP_BACKLIGHT_BRIGHTNESS_ON)
|
||||
ITEM_SETUP_FLASH_BEEP,
|
||||
CASE_SPLASH_PARAM(ITEM_SETUP_DISABLE_SPLASH)
|
||||
CASE_GPS(ITEM_SETUP_TIMEZONE)
|
||||
CASE_GPS(ITEM_SETUP_GPSFORMAT)
|
||||
CASE_PXX(ITEM_SETUP_COUNTRYCODE)
|
||||
CASE_CPUARM(ITEM_SETUP_LANGUAGE)
|
||||
CASE_CPUARM(ITEM_SETUP_IMPERIAL)
|
||||
IF_FAI_CHOICE(ITEM_SETUP_FAI)
|
||||
CASE_MAVLINK(ITEM_MAVLINK_BAUD)
|
||||
CASE_CPUARM(ITEM_SETUP_SWITCHES_DELAY)
|
||||
ITEM_SETUP_RX_CHANNEL_ORD,
|
||||
ITEM_SETUP_STICK_MODE_LABELS,
|
||||
ITEM_SETUP_STICK_MODE,
|
||||
ITEM_SETUP_MAX
|
||||
};
|
||||
|
||||
#if defined(FRSKY_STICKS)
|
||||
#define COL_TX_MODE 0
|
||||
#else
|
||||
#define COL_TX_MODE LABEL(TX_MODE)
|
||||
#endif
|
||||
|
||||
void menuGeneralSetup(uint8_t event)
|
||||
{
|
||||
#if defined(RTCLOCK)
|
||||
struct gtm t;
|
||||
gettime(&t);
|
||||
|
||||
if ((menuVerticalPosition==ITEM_SETUP_DATE+1 || menuVerticalPosition==ITEM_SETUP_TIME+1) &&
|
||||
(s_editMode>0) &&
|
||||
(event==EVT_KEY_FIRST(KEY_ENTER) || event==EVT_KEY_FIRST(KEY_EXIT) || IS_ROTARY_BREAK(event) || IS_ROTARY_LONG(event))) {
|
||||
// set the date and time into RTC chip
|
||||
rtcSetTime(&t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FAI_CHOICE)
|
||||
if (warningResult) {
|
||||
warningResult = 0;
|
||||
g_eeGeneral.fai = true;
|
||||
storageDirty(EE_GENERAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
MENU(STR_MENURADIOSETUP, menuTabGeneral, e_Setup, ITEM_SETUP_MAX+1, {0, CASE_RTCLOCK(2) CASE_RTCLOCK(2) CASE_BATTGRAPH(1) LABEL(SOUND), CASE_AUDIO(0) CASE_BUZZER(0) CASE_VOICE(0) CASE_CPUARM(0) CASE_CPUARM(0) CASE_CPUARM(0) 0, CASE_AUDIO(0) CASE_VARIO_CPUARM(LABEL(VARIO)) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_VARIO_CPUARM(0) CASE_HAPTIC(LABEL(HAPTIC)) CASE_HAPTIC(0) CASE_HAPTIC(0) CASE_HAPTIC(0) 0, LABEL(ALARMS), 0, CASE_CAPACITY(0) CASE_PCBSKY9X(0) 0, 0, 0, IF_ROTARY_ENCODERS(0) LABEL(BACKLIGHT), 0, 0, CASE_CPUARM(0) CASE_PWM_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) 0, CASE_SPLASH_PARAM(0) CASE_GPS(0) CASE_GPS(0) CASE_PXX(0) CASE_CPUARM(0) CASE_CPUARM(0) IF_FAI_CHOICE(0) CASE_MAVLINK(0) CASE_CPUARM(0) 0, COL_TX_MODE, 1/*to force edit mode*/});
|
||||
|
||||
if (event == EVT_ENTRY) {
|
||||
reusableBuffer.generalSettings.stickMode = g_eeGeneral.stickMode;
|
||||
}
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
coord_t y = MENU_HEADER_HEIGHT + 1 + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
uint8_t attr = (sub == k ? blink : 0);
|
||||
|
||||
switch(k) {
|
||||
#if defined(RTCLOCK)
|
||||
case ITEM_SETUP_DATE:
|
||||
lcd_putsLeft(y, STR_DATE);
|
||||
lcdDrawChar(RADIO_SETUP_DATE_COLUMN, y, '-'); lcdDrawChar(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, '-');
|
||||
for (uint8_t j=0; j<3; j++) {
|
||||
uint8_t rowattr = (menuHorizontalPosition==j ? attr : 0);
|
||||
switch (j) {
|
||||
case 0:
|
||||
lcdDrawNumber(RADIO_SETUP_DATE_COLUMN, y, t.tm_year+1900, rowattr);
|
||||
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0);
|
||||
break;
|
||||
case 1:
|
||||
lcdDrawNumber(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, t.tm_mon+1, rowattr|LEADING0, 2);
|
||||
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mon = checkIncDec(event, t.tm_mon, 0, 11, 0);
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
int16_t year = 1900 + t.tm_year;
|
||||
int8_t dlim = (((((year%4==0) && (year%100!=0)) || (year%400==0)) && (t.tm_mon==1)) ? 1 : 0);
|
||||
static const pm_uint8_t dmon[] PROGMEM = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
dlim += pgm_read_byte(&dmon[t.tm_mon]);
|
||||
lcdDrawNumber(RADIO_SETUP_DATE_COLUMN+6*FW-4, y, t.tm_mday, rowattr|LEADING0, 2);
|
||||
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mday = checkIncDec(event, t.tm_mday, 1, dlim, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (attr && checkIncDec_Ret) {
|
||||
g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_TIME:
|
||||
lcd_putsLeft(y, STR_TIME);
|
||||
lcdDrawChar(RADIO_SETUP_TIME_COLUMN+1, y, ':'); lcdDrawChar(RADIO_SETUP_TIME_COLUMN+3*FW-2, y, ':');
|
||||
for (uint8_t j=0; j<3; j++) {
|
||||
uint8_t rowattr = (menuHorizontalPosition==j ? attr : 0);
|
||||
switch (j) {
|
||||
case 0:
|
||||
lcdDrawNumber(RADIO_SETUP_TIME_COLUMN, y, t.tm_hour, rowattr|LEADING0, 2);
|
||||
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_hour = checkIncDec(event, t.tm_hour, 0, 23, 0);
|
||||
break;
|
||||
case 1:
|
||||
lcdDrawNumber(RADIO_SETUP_TIME_COLUMN+3*FWNUM, y, t.tm_min, rowattr|LEADING0, 2);
|
||||
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_min = checkIncDec(event, t.tm_min, 0, 59, 0);
|
||||
break;
|
||||
case 2:
|
||||
lcdDrawNumber(RADIO_SETUP_TIME_COLUMN+6*FWNUM, y, t.tm_sec, rowattr|LEADING0, 2);
|
||||
if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_sec = checkIncDec(event, t.tm_sec, 0, 59, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (attr && checkIncDec_Ret)
|
||||
g_rtcTime = gmktime(&t); // update local timestamp and get wday calculated
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(BATTGRAPH)
|
||||
case ITEM_SETUP_BATT_RANGE:
|
||||
lcd_putsLeft(y, STR_BATTERY_RANGE);
|
||||
putsVolts(RADIO_SETUP_2ND_COLUMN, y, 90+g_eeGeneral.vBatMin, (menuHorizontalPosition==0 ? attr : 0)|LEFT|NO_UNIT);
|
||||
lcdDrawChar(lcdLastPos, y, '-');
|
||||
putsVolts(lcdLastPos+FW, y, 120+g_eeGeneral.vBatMax, (menuHorizontalPosition>0 ? attr : 0)|LEFT|NO_UNIT);
|
||||
if (attr && s_editMode>0) {
|
||||
if (menuHorizontalPosition==0)
|
||||
CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMin, -50, g_eeGeneral.vBatMax+29); // min=4.0V
|
||||
else
|
||||
CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatMax, g_eeGeneral.vBatMin-29, +40); // max=16.0V
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_SETUP_SOUND_LABEL:
|
||||
lcd_putsLeft(y, STR_SOUND_LABEL);
|
||||
break;
|
||||
|
||||
#if defined(AUDIO)
|
||||
case ITEM_SETUP_BEEP_MODE:
|
||||
g_eeGeneral.beepMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_SPEAKER, STR_VBEEPMODE, g_eeGeneral.beepMode, -2, 1, attr, event);
|
||||
#if defined(FRSKY)
|
||||
if (attr && checkIncDec_Ret) frskySendAlarms();
|
||||
#endif
|
||||
break;
|
||||
|
||||
#if defined(BUZZER)
|
||||
case ITEM_SETUP_BUZZER_MODE:
|
||||
g_eeGeneral.buzzerMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_BUZZER, STR_VBEEPMODE, g_eeGeneral.buzzerMode, -2, 1, attr, event);
|
||||
#if defined(FRSKY)
|
||||
if (attr && checkIncDec_Ret) frskySendAlarms();
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#elif defined(BUZZER)
|
||||
case ITEM_SETUP_BUZZER_MODE:
|
||||
g_eeGeneral.beepMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_SPEAKER, STR_VBEEPMODE, g_eeGeneral.beepMode, -2, 1, attr, event);
|
||||
#if defined(FRSKY)
|
||||
if (attr && checkIncDec_Ret) frskySendAlarms();
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(VOICE)
|
||||
case ITEM_SETUP_SPEAKER_VOLUME:
|
||||
{
|
||||
lcd_putsLeft(y, STR_SPEAKER_VOLUME);
|
||||
uint8_t b = g_eeGeneral.speakerVolume+VOLUME_LEVEL_DEF;
|
||||
drawSlider(RADIO_SETUP_2ND_COLUMN, y, b, VOLUME_LEVEL_MAX, attr);
|
||||
if (attr) {
|
||||
CHECK_INCDEC_GENVAR(event, b, 0, VOLUME_LEVEL_MAX);
|
||||
if (checkIncDec_Ret) {
|
||||
g_eeGeneral.speakerVolume = (int8_t)b-VOLUME_LEVEL_DEF;
|
||||
#if !defined(CPUARM)
|
||||
setScaledVolume(b);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_SETUP_BEEP_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.beepVolume, STR_BEEP_VOLUME, event, attr);
|
||||
break;
|
||||
case ITEM_SETUP_WAV_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.wavVolume, STR_WAV_VOLUME, event, attr);
|
||||
break;
|
||||
case ITEM_SETUP_BACKGROUND_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.backgroundVolume, STR_BG_VOLUME, event, attr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_SETUP_BEEP_LENGTH:
|
||||
SLIDER_5POS(y, g_eeGeneral.beepLength, STR_BEEP_LENGTH, event, attr);
|
||||
break;
|
||||
|
||||
#if defined(AUDIO)
|
||||
case ITEM_SETUP_SPEAKER_PITCH:
|
||||
lcd_putsLeft( y, STR_SPKRPITCH);
|
||||
#if defined(CPUARM)
|
||||
lcdDrawChar(RADIO_SETUP_2ND_COLUMN, y, '+', attr);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN+FW, y, g_eeGeneral.speakerPitch*15, attr|LEFT);
|
||||
lcdDrawText(lcdLastPos, y, "Hz", attr);
|
||||
#else
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.speakerPitch, attr|LEFT);
|
||||
#endif
|
||||
if (attr) {
|
||||
CHECK_INCDEC_GENVAR(event, g_eeGeneral.speakerPitch, 0, 20);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM) && defined(VARIO)
|
||||
case ITEM_SETUP_VARIO_LABEL:
|
||||
lcd_putsLeft(y, STR_VARIO);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_VOLUME:
|
||||
SLIDER_5POS(y, g_eeGeneral.varioVolume, TR_SPEAKER_VOLUME, event, attr);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_PITCH:
|
||||
lcd_putsLeft(y, STR_PITCH_AT_ZERO);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10), attr|LEFT);
|
||||
lcdDrawText(lcdLastPos, y, "Hz", attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioPitch, -40, 40);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_RANGE:
|
||||
lcd_putsLeft(y, STR_PITCH_AT_MAX);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, VARIO_FREQUENCY_ZERO+(g_eeGeneral.varioPitch*10)+VARIO_FREQUENCY_RANGE+(g_eeGeneral.varioRange*10), attr|LEFT);
|
||||
lcdDrawText(lcdLastPos, y, "Hz", attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRange, -80, 80);
|
||||
break;
|
||||
case ITEM_SETUP_VARIO_REPEAT:
|
||||
lcd_putsLeft(y, STR_REPEAT_AT_ZERO);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, VARIO_REPEAT_ZERO+(g_eeGeneral.varioRepeat*10), attr|LEFT);
|
||||
lcdDrawText(lcdLastPos, y, STR_MS, attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.varioRepeat, -30, 50);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(HAPTIC)
|
||||
case ITEM_SETUP_HAPTIC_LABEL:
|
||||
lcd_putsLeft(y, STR_HAPTIC_LABEL);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HAPTIC_MODE:
|
||||
g_eeGeneral.hapticMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MODE, STR_VBEEPMODE, g_eeGeneral.hapticMode, -2, 1, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HAPTIC_LENGTH:
|
||||
SLIDER_5POS(y, g_eeGeneral.hapticLength, STR_LENGTH, event, attr);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_HAPTIC_STRENGTH:
|
||||
SLIDER_5POS(y, g_eeGeneral.hapticStrength, STR_HAPTICSTRENGTH, event, attr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_SETUP_CONTRAST:
|
||||
lcd_putsLeft(y, STR_CONTRAST);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.contrast, attr|LEFT);
|
||||
if (attr) {
|
||||
CHECK_INCDEC_GENVAR(event, g_eeGeneral.contrast, CONTRAST_MIN, CONTRAST_MAX);
|
||||
lcdSetContrast();
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_ALARMS_LABEL:
|
||||
lcd_putsLeft(y, STR_ALARMS_LABEL);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_BATTERY_WARNING:
|
||||
lcd_putsLeft(y, STR_BATTERYWARNING);
|
||||
putsVolts(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.vBatWarn, attr|LEFT);
|
||||
if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.vBatWarn, 40, 120); //4-12V
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_MEMORY_WARNING:
|
||||
{
|
||||
uint8_t b = 1-g_eeGeneral.disableMemoryWarning;
|
||||
g_eeGeneral.disableMemoryWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_MEMORYWARNING, attr, event);
|
||||
break;
|
||||
}
|
||||
|
||||
case ITEM_SETUP_ALARM_WARNING:
|
||||
{
|
||||
uint8_t b = 1-g_eeGeneral.disableAlarmWarning;
|
||||
g_eeGeneral.disableAlarmWarning = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_ALARMWARNING, attr, event);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(TX_CAPACITY_MEASUREMENT)
|
||||
case ITEM_SETUP_CAPACITY_WARNING:
|
||||
lcd_putsLeft(y, STR_CAPAWARNING);
|
||||
putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.mAhWarn*50, UNIT_MAH, attr|LEFT) ;
|
||||
if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.mAhWarn, 0, 100);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
case ITEM_SETUP_TEMPERATURE_WARNING:
|
||||
lcd_putsLeft(y, STR_TEMPWARNING);
|
||||
putsValueWithUnit(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.temperatureWarn, UNIT_TEMPERATURE, attr|LEFT) ;
|
||||
if(attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureWarn, 0, 120); // 0 means no alarm
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_SETUP_INACTIVITY_ALARM:
|
||||
lcd_putsLeft(y, STR_INACTIVITYALARM);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.inactivityTimer, attr|LEFT);
|
||||
lcdDrawChar(lcdLastPos, y, 'm');
|
||||
if(attr) g_eeGeneral.inactivityTimer = checkIncDec(event, g_eeGeneral.inactivityTimer, 0, 250, EE_GENERAL); //0..250minutes
|
||||
break;
|
||||
|
||||
#if ROTARY_ENCODERS > 0
|
||||
case ITEM_SETUP_RE_NAVIGATION:
|
||||
g_eeGeneral.reNavigation = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_RENAVIG, STR_VRENAVIG, g_eeGeneral.reNavigation, 0, NUM_ROTARY_ENCODERS, attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
g_rotenc[NAVIGATION_RE_IDX()] = 0;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_SETUP_BACKLIGHT_LABEL:
|
||||
lcd_putsLeft(y, STR_BACKLIGHT_LABEL);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_BACKLIGHT_MODE:
|
||||
g_eeGeneral.backlightMode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MODE, STR_VBLMODE, g_eeGeneral.backlightMode, e_backlight_mode_off, e_backlight_mode_on, attr, event);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_FLASH_BEEP:
|
||||
g_eeGeneral.alarmsFlash = editCheckBox(g_eeGeneral.alarmsFlash, RADIO_SETUP_2ND_COLUMN, y, STR_ALARM, attr, event ) ;
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_BACKLIGHT_DELAY:
|
||||
lcd_putsLeft(y, STR_BLDELAY);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.lightAutoOff*5, attr|LEFT);
|
||||
lcdDrawChar(lcdLastPos, y, 's');
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.lightAutoOff, 0, 600/5);
|
||||
break;
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_SETUP_BRIGHTNESS:
|
||||
lcd_putsLeft(y, STR_BRIGHTNESS);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, 100-g_eeGeneral.backlightBright, attr|LEFT) ;
|
||||
if (attr) {
|
||||
uint8_t b = 100 - g_eeGeneral.backlightBright;
|
||||
CHECK_INCDEC_GENVAR(event, b, 0, 100);
|
||||
g_eeGeneral.backlightBright = 100 - b;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PWM_BACKLIGHT)
|
||||
case ITEM_SETUP_BACKLIGHT_BRIGHTNESS_OFF:
|
||||
lcd_putsLeft(y, STR_BLOFFBRIGHTNESS);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.blOffBright, attr|LEFT);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.blOffBright, 0, 15);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_BACKLIGHT_BRIGHTNESS_ON:
|
||||
lcd_putsLeft(y, STR_BLONBRIGHTNESS);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, 15-g_eeGeneral.blOnBright, attr|LEFT);
|
||||
if (attr) g_eeGeneral.blOnBright = 15 - checkIncDecGen(event, 15-g_eeGeneral.blOnBright, 0, 15);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(SPLASH) && !defined(FSPLASH)
|
||||
case ITEM_SETUP_DISABLE_SPLASH:
|
||||
{
|
||||
uint8_t b = 1-g_eeGeneral.splashMode;
|
||||
g_eeGeneral.splashMode = 1 - editCheckBox(b, RADIO_SETUP_2ND_COLUMN, y, STR_SPLASHSCREEN, attr, event);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS)
|
||||
case ITEM_SETUP_TIMEZONE:
|
||||
lcd_putsLeft(y, STR_TIMEZONE);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, g_eeGeneral.timezone, attr|LEFT);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.timezone, -12, 12);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_GPSFORMAT:
|
||||
g_eeGeneral.gpsFormat = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_GPSCOORD, STR_GPSFORMAT, g_eeGeneral.gpsFormat, 0, 1, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(PXX)
|
||||
case ITEM_SETUP_COUNTRYCODE:
|
||||
g_eeGeneral.countryCode = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_COUNTRYCODE, STR_COUNTRYCODES, g_eeGeneral.countryCode, 0, 2, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_SETUP_LANGUAGE:
|
||||
lcd_putsLeft(y, STR_VOICELANG);
|
||||
lcdDrawText(RADIO_SETUP_2ND_COLUMN, y, currentLanguagePack->name, attr);
|
||||
if (attr) {
|
||||
currentLanguagePackIdx = checkIncDec(event, currentLanguagePackIdx, 0, DIM(languagePacks)-2, EE_GENERAL);
|
||||
if (checkIncDec_Ret) {
|
||||
currentLanguagePack = languagePacks[currentLanguagePackIdx];
|
||||
strncpy(g_eeGeneral.ttsLanguage, currentLanguagePack->id, 2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_IMPERIAL:
|
||||
g_eeGeneral.imperial = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_UNITSSYSTEM, STR_VUNITSSYSTEM, g_eeGeneral.imperial, 0, 1, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(FAI_CHOICE)
|
||||
case ITEM_SETUP_FAI:
|
||||
editCheckBox(g_eeGeneral.fai, RADIO_SETUP_2ND_COLUMN, y, PSTR("FAI Mode"), attr, event);
|
||||
if (attr && checkIncDec_Ret) {
|
||||
if (g_eeGeneral.fai)
|
||||
POPUP_WARNING(PSTR("FAI\001mode blocked!"));
|
||||
else
|
||||
POPUP_CONFIRMATION(PSTR("FAI mode?"));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(MAVLINK)
|
||||
case ITEM_MAVLINK_BAUD:
|
||||
g_eeGeneral.mavbaud = selectMenuItem(RADIO_SETUP_2ND_COLUMN, y, STR_MAVLINK_BAUD_LABEL, STR_MAVLINK_BAUDS, g_eeGeneral.mavbaud, 0, 7, attr, event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
case ITEM_SETUP_SWITCHES_DELAY:
|
||||
lcd_putsLeft(y, STR_SWITCHES_DELAY);
|
||||
lcdDrawNumber(RADIO_SETUP_2ND_COLUMN, y, 10*SWITCHES_DELAY(), attr|LEFT);
|
||||
lcdDrawText(lcdLastPos, y, STR_MS, attr);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.switchesDelay, -15, +15);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ITEM_SETUP_RX_CHANNEL_ORD:
|
||||
lcd_putsLeft(y, STR_RXCHANNELORD); // RAET->AETR
|
||||
for (uint8_t i=1; i<=4; i++) {
|
||||
putsChnLetter(RADIO_SETUP_2ND_COLUMN - FW + i*FW, y, channel_order(i), attr);
|
||||
}
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.templateSetup, 0, 23);
|
||||
break;
|
||||
|
||||
case ITEM_SETUP_STICK_MODE_LABELS:
|
||||
lcd_putsLeft(y, NO_INDENT(STR_MODE));
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
lcd_img((6+4*i)*FW, y, sticks, i, 0);
|
||||
#if defined(FRSKY_STICKS)
|
||||
if (g_eeGeneral.stickReverse & (1<<i)) {
|
||||
lcdDrawFilledRect((6+4*i)*FW, y, 3*FW, FH-1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if defined(FRSKY_STICKS)
|
||||
if (attr) {
|
||||
s_editMode = 0;
|
||||
CHECK_INCDEC_GENVAR(event, g_eeGeneral.stickReverse, 0, 15);
|
||||
lcdDrawRect(6*FW-1, y-1, 15*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++) {
|
||||
putsMixerSource((6+4*i)*FW, 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);
|
||||
}
|
||||
else if (reusableBuffer.generalSettings.stickMode != g_eeGeneral.stickMode) {
|
||||
pausePulses();
|
||||
g_eeGeneral.stickMode = reusableBuffer.generalSettings.stickMode;
|
||||
checkTHR();
|
||||
resumePulses();
|
||||
clearKeyEvents();
|
||||
}
|
||||
#if defined(ROTARY_ENCODER_NAVIGATION)
|
||||
MOVE_CURSOR_FROM_HERE();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 TRAINER_CALIB_POS 8
|
||||
|
||||
void menuGeneralTrainer(uint8_t event)
|
||||
{
|
||||
uint8_t y;
|
||||
bool slave = SLAVE_MODE();
|
||||
|
||||
MENU(STR_MENUTRAINER, menuTabGeneral, e_Trainer, (slave ? 1 : 7), {0, 2, 2, 2, 2, 0/*, 0*/});
|
||||
|
||||
if (slave) {
|
||||
lcdDrawText(7*FW, 4*FH, STR_SLAVE);
|
||||
}
|
||||
else {
|
||||
uint8_t attr;
|
||||
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
|
||||
lcdDrawText(3*FW, MENU_HEADER_HEIGHT+1, STR_MODESRC);
|
||||
|
||||
y = MENU_HEADER_HEIGHT + 1 + FH;
|
||||
|
||||
for (uint8_t i=1; i<=NUM_STICKS; i++) {
|
||||
uint8_t chan = channel_order(i);
|
||||
volatile TrainerMix *td = &g_eeGeneral.trainer.mix[chan-1];
|
||||
|
||||
putsMixerSource(0, y, MIXSRC_Rud-1+chan, (menuVerticalPosition==i && CURSOR_ON_LINE()) ? INVERS : 0);
|
||||
|
||||
for (uint8_t j=0; j<3; j++) {
|
||||
|
||||
attr = ((menuVerticalPosition==i && menuHorizontalPosition==j) ? blink : 0);
|
||||
|
||||
switch(j) {
|
||||
case 0:
|
||||
lcdDrawTextAtIndex(4*FW, y, STR_TRNMODE, td->mode, attr);
|
||||
if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->mode, 0, 2);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lcdDrawNumber(11*FW, y, td->studWeight, attr);
|
||||
if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->studWeight, -125, 125);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
lcdDrawTextAtIndex(12*FW, y, STR_TRNCHN, td->srcChn, attr);
|
||||
if (attr&BLINK) CHECK_INCDEC_GENVAR(event, td->srcChn, 0, 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
y += FH;
|
||||
}
|
||||
|
||||
attr = (menuVerticalPosition==5) ? blink : 0;
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+1+5*FH, STR_MULTIPLIER);
|
||||
lcdDrawNumber(LEN_MULTIPLIER*FW+3*FW, MENU_HEADER_HEIGHT+1+5*FH, g_eeGeneral.PPM_Multiplier+10, attr|PREC1);
|
||||
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.PPM_Multiplier, -10, 40);
|
||||
|
||||
attr = (menuVerticalPosition==6) ? INVERS : 0;
|
||||
if (attr) s_editMode = 0;
|
||||
lcdDrawText(0*FW, MENU_HEADER_HEIGHT+1+6*FH, STR_CAL, attr);
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
uint8_t x = (i*TRAINER_CALIB_POS+16)*FW/2;
|
||||
lcdDrawNumber(x, MENU_HEADER_HEIGHT+1+6*FH, (ppmInput[i]-g_eeGeneral.trainer.calib[i])/5, 0);
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
if (event==EVT_KEY_LONG(KEY_ENTER)){
|
||||
memcpy(g_eeGeneral.trainer.calib, ppmInput, sizeof(g_eeGeneral.trainer.calib));
|
||||
storageDirty(EE_GENERAL);
|
||||
AUDIO_WARNING1();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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 menuGeneralVersion(uint8_t event)
|
||||
{
|
||||
SIMPLE_MENU(STR_MENUVERSION, menuTabGeneral, e_Vers, 1);
|
||||
|
||||
lcd_putsLeft(MENU_HEADER_HEIGHT+FH, vers_stamp);
|
||||
|
||||
#if defined(COPROCESSOR)
|
||||
if (Coproc_valid == 1) {
|
||||
lcd_putsLeft(6*FH, PSTR("CoPr:"));
|
||||
lcdDraw8bitsNumber(10*FW, 6*FH, Coproc_read);
|
||||
}
|
||||
else {
|
||||
lcd_putsLeft(6*FH, PSTR("CoPr: ---"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
#if !defined GET_FAR_ADDRESS
|
||||
#define GET_FAR_ADDRESS(var) \
|
||||
({ \
|
||||
uint32_t tmp; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
\
|
||||
"ldi %A0, lo8(%1)" "\n\t" \
|
||||
"ldi %B0, hi8(%1)" "\n\t" \
|
||||
"ldi %C0, hh8(%1)" "\n\t" \
|
||||
"clr %D0" "\n\t" \
|
||||
: \
|
||||
"=d" (tmp) \
|
||||
: \
|
||||
"p" (&(var)) \
|
||||
); \
|
||||
tmp; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if defined(SPLASH)
|
||||
const pm_uchar splashdata[] PROGMEM = {
|
||||
'S','P','S',0,
|
||||
#include "bitmaps/128x64/splash.lbm"
|
||||
'S','P','E',0 };
|
||||
|
||||
const pm_uchar * const splash_lbm = splashdata+4;
|
||||
|
||||
void drawSplash()
|
||||
{
|
||||
lcdClear();
|
||||
#if defined(PCBMEGA2560) && !defined(SIMU)
|
||||
lcd_imgfar(0, 0, (GET_FAR_ADDRESS(splashdata)+4), 0, 0); // use progmem "far" for splash working with all other options enabled
|
||||
#else
|
||||
lcd_img(0, 0, splash_lbm, 0, 0);
|
||||
#endif
|
||||
|
||||
#if MENUS_LOCK == 1
|
||||
if (readonly == false) {
|
||||
lcdDrawFilledRect((LCD_W-(sizeof(TR_UNLOCKED)-1)*FW)/2 - 9, 50, (sizeof(TR_UNLOCKED)-1)*FW+16, 11, SOLID, ERASE|ROUND);
|
||||
lcdDrawText((LCD_W-(sizeof(TR_UNLOCKED)-1)*FW)/2 , 53, STR_UNLOCKED);
|
||||
}
|
||||
#endif
|
||||
|
||||
lcdRefresh();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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"
|
||||
|
||||
const pm_uchar about_bmp[] PROGMEM = {
|
||||
#include "about.lbm"
|
||||
};
|
||||
|
||||
enum AboutScreens {
|
||||
ABOUT_OPENTX,
|
||||
ABOUT_BERTRAND,
|
||||
ABOUT_ANDRE,
|
||||
ABOUT_MIKE,
|
||||
ABOUT_KJELL,
|
||||
ABOUT_MARTIN,
|
||||
ABOUT_ROMOLO,
|
||||
ABOUT_ROB,
|
||||
ABOUT_HARDWARE,
|
||||
ABOUT_PARENTS,
|
||||
ABOUT_END,
|
||||
ABOUT_COUNT,
|
||||
};
|
||||
|
||||
#define ABOUT_X 2
|
||||
#define ABOUT_INDENT 4
|
||||
|
||||
void menuAboutView(uint8_t event)
|
||||
{
|
||||
static uint8_t screenIndex;
|
||||
static uint8_t greyIndex;
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
screenIndex = 0;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
screenIndex < ABOUT_PARENTS ? screenIndex++ : screenIndex = ABOUT_OPENTX;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
screenIndex > ABOUT_OPENTX ? screenIndex-- : screenIndex = ABOUT_PARENTS;
|
||||
greyIndex = 0;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
lcdDrawText(17, 0, STR_ABOUTUS, DBLSIZE|INVERS);
|
||||
lcdDrawSolidHorizontalLine(17, 16, LCD_W-17);
|
||||
lcd_img(8, 0, about_bmp, 0);
|
||||
LcdFlags att = 0;
|
||||
|
||||
uint8_t screenDuration = 150;
|
||||
|
||||
switch (screenIndex) {
|
||||
case ABOUT_OPENTX:
|
||||
case ABOUT_END:
|
||||
lcdDrawText(ABOUT_X, 22, STR_ABOUT_OPENTX_1, SMLSIZE);
|
||||
lcdDrawText(ABOUT_X, 30, STR_ABOUT_OPENTX_2, SMLSIZE);
|
||||
lcdDrawText(ABOUT_X, 38, STR_ABOUT_OPENTX_3, SMLSIZE);
|
||||
lcdDrawText(ABOUT_X, 46, STR_ABOUT_OPENTX_4, SMLSIZE);
|
||||
lcdDrawText(ABOUT_X, 54, STR_ABOUT_OPENTX_5, SMLSIZE);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
|
||||
case ABOUT_BERTRAND:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_BERTRAND_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_BERTRAND_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_BERTRAND_3, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_ANDRE:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_ANDRE_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_ANDRE_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_ANDRE_3, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_MIKE:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_MIKE_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_MIKE_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_MIKE_3, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 52, STR_ABOUT_MIKE_4, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_KJELL:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_KJELL_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_KJELL_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_KJELL_3, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 52, STR_ABOUT_KJELL_4, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_MARTIN:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_MARTIN_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_MARTIN_2, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_ROMOLO:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_ROMOLO_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_ROMOLO_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_ROMOLO_3, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_ROB:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_ROB_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_ROB_2, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_HARDWARE:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_HARDWARE_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_HARDWARE_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_HARDWARE_3, att|SMLSIZE);
|
||||
break;
|
||||
|
||||
case ABOUT_PARENTS:
|
||||
lcdDrawText(ABOUT_X, 24, STR_ABOUT_PARENTS_1, att);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 36, STR_ABOUT_PARENTS_2, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 44, STR_ABOUT_PARENTS_3, att|SMLSIZE);
|
||||
lcdDrawText(ABOUT_X+ABOUT_INDENT, 52, STR_ABOUT_PARENTS_4, att|SMLSIZE);
|
||||
screenDuration = 255;
|
||||
break;
|
||||
}
|
||||
|
||||
if (++greyIndex == screenDuration) {
|
||||
greyIndex = 0;
|
||||
if (++screenIndex == ABOUT_COUNT) {
|
||||
chainMenu(menuMainView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,572 @@
|
||||
/*
|
||||
* 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 BIGSIZE DBLSIZE
|
||||
#define LBOX_CENTERX (LCD_W/4 + 10)
|
||||
#define RBOX_CENTERX (3*LCD_W/4 - 10)
|
||||
#define MODELNAME_X (2*FW-2)
|
||||
#define MODELNAME_Y (0)
|
||||
#define PHASE_X (6*FW-1)
|
||||
#define PHASE_Y (2*FH)
|
||||
#define PHASE_FLAGS 0
|
||||
#define VBATT_X (6*FW)
|
||||
#define VBATT_Y (2*FH)
|
||||
#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 TRIM_LH_X (LCD_W*1/4+2)
|
||||
#define TRIM_LV_X 3
|
||||
#define TRIM_RV_X (LCD_W-4)
|
||||
#define TRIM_RH_X (LCD_W*3/4-2)
|
||||
|
||||
#define TRIM_LEN 27
|
||||
|
||||
void drawPotsBars()
|
||||
{
|
||||
// Optimization by Mike Blandford
|
||||
uint8_t x, i, len ; // declare temporary variables
|
||||
for (x=LCD_W/2-5, i=NUM_STICKS; i<NUM_STICKS+NUM_POTS; x+=5, i++) {
|
||||
if (IS_POT_AVAILABLE(i)) {
|
||||
len = ((calibratedStick[i]+RESX)*BAR_HEIGHT/(RESX*2))+1l; // calculate once per loop
|
||||
V_BAR(x, LCD_H-8, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void doMainScreenGraphics()
|
||||
{
|
||||
int16_t calibStickVert = calibratedStick[CONVERT_MODE(1)];
|
||||
if (g_model.throttleReversed && CONVERT_MODE(1) == THR_STICK)
|
||||
calibStickVert = -calibStickVert;
|
||||
drawStick(LBOX_CENTERX, calibratedStick[CONVERT_MODE(0)], calibStickVert);
|
||||
|
||||
calibStickVert = calibratedStick[CONVERT_MODE(2)];
|
||||
if (g_model.throttleReversed && CONVERT_MODE(2) == THR_STICK)
|
||||
calibStickVert = -calibStickVert;
|
||||
drawStick(RBOX_CENTERX, calibratedStick[CONVERT_MODE(3)], calibStickVert);
|
||||
|
||||
drawPotsBars();
|
||||
}
|
||||
|
||||
void displayTrims(uint8_t phase)
|
||||
{
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
static coord_t x[4] = {TRIM_LH_X, TRIM_LV_X, TRIM_RV_X, TRIM_RH_X};
|
||||
static uint8_t vert[4] = {0,1,1,0};
|
||||
coord_t xm, ym;
|
||||
uint8_t stickIndex = CONVERT_MODE(i);
|
||||
xm = x[stickIndex];
|
||||
uint8_t att = ROUND;
|
||||
int16_t val = getTrimValue(phase, i);
|
||||
|
||||
#if !defined(CPUM64) || !defined(FRSKY)
|
||||
int16_t dir = val;
|
||||
bool exttrim = false;
|
||||
if (val < TRIM_MIN || val > TRIM_MAX) {
|
||||
exttrim = true;
|
||||
}
|
||||
#endif
|
||||
if (val < -(TRIM_LEN+1)*4) {
|
||||
val = -(TRIM_LEN+1);
|
||||
}
|
||||
else if (val > (TRIM_LEN+1)*4) {
|
||||
val = TRIM_LEN+1;
|
||||
}
|
||||
else {
|
||||
val /= 4;
|
||||
}
|
||||
|
||||
if (vert[i]) {
|
||||
ym = 31;
|
||||
lcdDrawSolidVerticalLine(xm, ym-TRIM_LEN, TRIM_LEN*2);
|
||||
if (i!=2 || !g_model.thrTrim) {
|
||||
lcdDrawSolidVerticalLine(xm-1, ym-1, 3);
|
||||
lcdDrawSolidVerticalLine(xm+1, ym-1, 3);
|
||||
}
|
||||
ym -= val;
|
||||
#if !defined(CPUM64) || !defined(FRSKY)
|
||||
lcdDrawFilledRect(xm-3, ym-3, 7, 7, SOLID, att|ERASE);
|
||||
if (dir >= 0) {
|
||||
lcdDrawSolidHorizontalLine(xm-1, ym-1, 3);
|
||||
}
|
||||
if (dir <= 0) {
|
||||
lcdDrawSolidHorizontalLine(xm-1, ym+1, 3);
|
||||
}
|
||||
if (exttrim) {
|
||||
lcdDrawSolidHorizontalLine(xm-1, ym, 3);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && dir != 0) {
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<<i)))) {
|
||||
lcdDrawNumber(dir>0 ? 22 : 54, xm-2, -abs(dir/5), TINSIZE|VERTICAL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ym = 60;
|
||||
lcdDrawSolidHorizontalLine(xm-TRIM_LEN, ym, TRIM_LEN*2);
|
||||
lcdDrawSolidHorizontalLine(xm-1, ym-1, 3);
|
||||
lcdDrawSolidHorizontalLine(xm-1, ym+1, 3);
|
||||
xm += val;
|
||||
#if !defined(CPUM64) || !defined(FRSKY)
|
||||
lcdDrawFilledRect(xm-3, ym-3, 7, 7, SOLID, att|ERASE);
|
||||
if (dir >= 0) {
|
||||
lcdDrawSolidVerticalLine(xm+1, ym-1, 3);
|
||||
}
|
||||
if (dir <= 0) {
|
||||
lcdDrawSolidVerticalLine(xm-1, ym-1, 3);
|
||||
}
|
||||
if (exttrim) {
|
||||
lcdDrawSolidVerticalLine(xm, ym-1, 3);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && dir != 0) {
|
||||
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<<i)))) {
|
||||
lcdDrawNumber((stickIndex==0 ? TRIM_LH_X : TRIM_RH_X)+(dir>0 ? -11 : 20), ym-2, -abs(dir/5), TINSIZE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
lcdDrawSquare(xm-3, ym-3, 7, att);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void displayTimers()
|
||||
{
|
||||
#if defined(TRANSLATIONS_CZ)
|
||||
#define MAINTMR_LBL_COL (9*FW-FW/2-1)
|
||||
#else
|
||||
#define MAINTMR_LBL_COL (9*FW-FW/2+3)
|
||||
#endif
|
||||
// Main timer
|
||||
if (g_model.timers[0].mode) {
|
||||
TimerState & timerState = timersStates[0];
|
||||
LcdFlags att = DBLSIZE | (timerState.val<0 ? BLINK|INVERS : 0);
|
||||
putsTimer(12*FW+2+10*FWNUM-4, FH*2, timerState.val, att, att);
|
||||
uint8_t xLabel = (timerState.val >= 0 ? MAINTMR_LBL_COL : MAINTMR_LBL_COL-7);
|
||||
#if defined(CPUARM)
|
||||
uint8_t len = zlen(g_model.timers[0].name, LEN_TIMER_NAME);
|
||||
if (len > 0) {
|
||||
xLabel += (LEN_TIMER_NAME-len)*FW;
|
||||
lcdDrawSizedText(xLabel, FH*3, g_model.timers[0].name, len, ZCHAR);
|
||||
}
|
||||
else {
|
||||
putsTimerMode(xLabel, FH*3, g_model.timers[0].mode);
|
||||
}
|
||||
#else
|
||||
putsTimerMode(xLabel, FH*3, g_model.timers[0].mode);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void displayBattVoltage()
|
||||
{
|
||||
#if defined(BATTGRAPH)
|
||||
putsVBat(VBATT_X-8, VBATT_Y+1, 0);
|
||||
lcdDrawFilledRect(VBATT_X-25, VBATT_Y+9, 21, 5);
|
||||
lcdDrawSolidVerticalLine(VBATT_X-4, VBATT_Y+10, 3);
|
||||
uint8_t count = GET_TXBATT_BARS();
|
||||
for (uint8_t i=0; i<count; i+=2)
|
||||
lcdDrawSolidVerticalLine(VBATT_X-24+i, VBATT_Y+10, 3);
|
||||
if (!IS_TXBATT_WARNING() || BLINK_ON_PHASE)
|
||||
lcdDrawFilledRect(VBATT_X-26, VBATT_Y, 24, 15);
|
||||
#else
|
||||
LcdFlags att = (IS_TXBATT_WARNING() ? BLINK|INVERS : 0) | BIGSIZE;
|
||||
putsVBat(VBATT_X-1, VBATT_Y, att|NO_UNIT);
|
||||
lcdDrawChar(VBATT_X, VBATTUNIT_Y, 'V');
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
void displayVoltageOrAlarm()
|
||||
{
|
||||
if (g_eeGeneral.temperatureWarn && getTemperature() >= g_eeGeneral.temperatureWarn) {
|
||||
putsValueWithUnit(6*FW-1, 2*FH, getTemperature(), UNIT_TEMPERATURE, BLINK|INVERS|DBLSIZE);
|
||||
}
|
||||
else if (g_eeGeneral.mAhWarn && (g_eeGeneral.mAhUsed + Current_used * (488 + g_eeGeneral.txCurrentCalibration)/8192/36) / 500 >= g_eeGeneral.mAhWarn) {
|
||||
putsValueWithUnit(7*FW-1, 2*FH, (g_eeGeneral.mAhUsed + Current_used*(488 + g_eeGeneral.txCurrentCalibration)/8192/36)/10, UNIT_MAH, BLINK|INVERS|DBLSIZE);
|
||||
}
|
||||
else {
|
||||
displayBattVoltage();
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define displayVoltageOrAlarm() displayBattVoltage()
|
||||
#endif
|
||||
|
||||
#define EVT_KEY_MODEL_MENU EVT_KEY_LONG(KEY_RIGHT)
|
||||
#define EVT_KEY_GENERAL_MENU EVT_KEY_LONG(KEY_LEFT)
|
||||
#define EVT_KEY_TELEMETRY EVT_KEY_LONG(KEY_DOWN)
|
||||
#define EVT_KEY_STATISTICS EVT_KEY_LONG(KEY_UP)
|
||||
#define EVT_KEY_CONTEXT_MENU EVT_KEY_BREAK(KEY_MENU)
|
||||
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
void onMainViewMenu(const char *result)
|
||||
{
|
||||
if (result == STR_RESET_TIMER1) {
|
||||
timerReset(0);
|
||||
}
|
||||
else if (result == STR_RESET_TIMER2) {
|
||||
timerReset(1);
|
||||
}
|
||||
#if TIMERS > 2
|
||||
else if (result == STR_RESET_TIMER3) {
|
||||
timerReset(2);
|
||||
}
|
||||
#endif
|
||||
#if defined(CPUARM)
|
||||
else if (result == STR_VIEW_NOTES) {
|
||||
pushModelNotes();
|
||||
}
|
||||
else if (result == STR_RESET_SUBMENU) {
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_FLIGHT);
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TIMER1);
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TIMER2);
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TIMER3);
|
||||
#if defined(FRSKY)
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TELEMETRY);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#if defined(FRSKY)
|
||||
else if (result == STR_RESET_TELEMETRY) {
|
||||
telemetryReset();
|
||||
}
|
||||
#endif
|
||||
else if (result == STR_RESET_FLIGHT) {
|
||||
flightReset();
|
||||
}
|
||||
else if (result == STR_STATISTICS) {
|
||||
chainMenu(menuStatisticsView);
|
||||
}
|
||||
#if defined(CPUARM)
|
||||
else if (result == STR_ABOUT_US) {
|
||||
chainMenu(menuAboutView);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void menuMainView(uint8_t event)
|
||||
{
|
||||
STICK_SCROLL_DISABLE();
|
||||
|
||||
uint8_t view = g_eeGeneral.view;
|
||||
uint8_t view_base = view & 0x0f;
|
||||
|
||||
switch(event) {
|
||||
|
||||
case EVT_ENTRY:
|
||||
killEvents(KEY_EXIT);
|
||||
killEvents(KEY_UP);
|
||||
killEvents(KEY_DOWN);
|
||||
break;
|
||||
|
||||
/* TODO if timer2 is OFF, it's possible to use this timer2 as in er9x...
|
||||
case EVT_KEY_BREAK(KEY_MENU):
|
||||
if (view_base == VIEW_TIMER2) {
|
||||
Timer2_running = !Timer2_running;
|
||||
AUDIO_KEYPAD_UP();
|
||||
}
|
||||
break;
|
||||
*/
|
||||
|
||||
case EVT_KEY_BREAK(KEY_RIGHT):
|
||||
case EVT_KEY_BREAK(KEY_LEFT):
|
||||
if (view_base <= VIEW_INPUTS) {
|
||||
#if defined(PCBSKY9X)
|
||||
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);
|
||||
#else
|
||||
g_eeGeneral.view ^= ALTERNATE_VIEW;
|
||||
#endif
|
||||
storageDirty(EE_GENERAL);
|
||||
AUDIO_KEY_PRESS();
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(NAVIGATION_MENUS)
|
||||
case EVT_KEY_CONTEXT_MENU:
|
||||
killEvents(event);
|
||||
|
||||
#if defined(CPUARM)
|
||||
if (modelHasNotes()) {
|
||||
POPUP_MENU_ADD_ITEM(STR_VIEW_NOTES);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_SUBMENU);
|
||||
#else
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TIMER1);
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TIMER2);
|
||||
#if defined(FRSKY)
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_TELEMETRY);
|
||||
#endif
|
||||
POPUP_MENU_ADD_ITEM(STR_RESET_FLIGHT);
|
||||
#endif
|
||||
|
||||
POPUP_MENU_ADD_ITEM(STR_STATISTICS);
|
||||
#if defined(CPUARM)
|
||||
POPUP_MENU_ADD_ITEM(STR_ABOUT_US);
|
||||
#endif
|
||||
POPUP_MENU_START(onMainViewMenu);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if MENUS_LOCK != 2 /*no menus*/
|
||||
case EVT_KEY_LONG(KEY_MENU):// go to last menu
|
||||
pushMenu(lastPopMenu());
|
||||
killEvents(event);
|
||||
break;
|
||||
|
||||
CASE_EVT_ROTARY_BREAK
|
||||
case EVT_KEY_MODEL_MENU:
|
||||
pushMenu(menuModelSelect);
|
||||
killEvents(event);
|
||||
break;
|
||||
|
||||
CASE_EVT_ROTARY_LONG
|
||||
case EVT_KEY_GENERAL_MENU:
|
||||
pushMenu(menuGeneralSetup);
|
||||
killEvents(event);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_BREAK(KEY_UP):
|
||||
case EVT_KEY_BREAK(KEY_DOWN):
|
||||
g_eeGeneral.view = (event == EVT_KEY_BREAK(KEY_UP) ? (view_base == VIEW_COUNT-1 ? 0 : view_base+1) : (view_base == 0 ? VIEW_COUNT-1 : view_base-1));
|
||||
storageDirty(EE_GENERAL);
|
||||
break;
|
||||
|
||||
case EVT_KEY_STATISTICS:
|
||||
chainMenu(menuStatisticsView);
|
||||
killEvents(event);
|
||||
break;
|
||||
|
||||
case EVT_KEY_TELEMETRY:
|
||||
#if defined(FRSKY)
|
||||
if (!IS_FAI_ENABLED())
|
||||
chainMenu(menuTelemetryFrsky);
|
||||
#elif defined(JETI)
|
||||
JETI_EnableRXD(); // enable JETI-Telemetry reception
|
||||
chainMenu(menuTelemetryJeti);
|
||||
#elif defined(ARDUPILOT)
|
||||
ARDUPILOT_EnableRXD(); // enable ArduPilot-Telemetry reception
|
||||
chainMenu(menuTelemetryArduPilot);
|
||||
#elif defined(NMEA)
|
||||
NMEA_EnableRXD(); // enable NMEA-Telemetry reception
|
||||
chainMenu(menuTelemetryNMEA);
|
||||
#elif defined(MAVLINK)
|
||||
chainMenu(menuTelemetryMavlink);
|
||||
#else
|
||||
chainMenu(menuStatisticsDebug);
|
||||
#endif
|
||||
killEvents(event);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
#if defined(GVARS) && !defined(PCBSTD)
|
||||
if (gvarDisplayTimer > 0) {
|
||||
gvarDisplayTimer = 0;
|
||||
}
|
||||
#endif
|
||||
if (view == VIEW_TIMER2) {
|
||||
timerReset(1);
|
||||
}
|
||||
break;
|
||||
|
||||
#if !defined(NAVIGATION_MENUS)
|
||||
case EVT_KEY_LONG(KEY_EXIT):
|
||||
flightReset();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
// Flight Mode Name
|
||||
uint8_t mode = mixerCurrentFlightMode;
|
||||
lcdDrawSizedText(PHASE_X, PHASE_Y, g_model.flightModeData[mode].name, sizeof(g_model.flightModeData[mode].name), ZCHAR|PHASE_FLAGS);
|
||||
|
||||
// Model Name
|
||||
putsModelName(MODELNAME_X, MODELNAME_Y, g_model.header.name, g_eeGeneral.currModel, BIGSIZE);
|
||||
|
||||
// Main Voltage (or alarm if any)
|
||||
displayVoltageOrAlarm();
|
||||
|
||||
// Timers
|
||||
displayTimers();
|
||||
|
||||
// Trims sliders
|
||||
displayTrims(mode);
|
||||
}
|
||||
|
||||
if (view_base < VIEW_INPUTS) {
|
||||
// scroll bar
|
||||
lcdDrawHorizontalLine(38, 34, 54, DOTTED);
|
||||
#if defined(PCBSKY9X)
|
||||
lcdDrawSolidHorizontalLine(38 + (g_eeGeneral.view / ALTERNATE_VIEW) * 13, 34, 13, SOLID);
|
||||
#else
|
||||
lcdDrawSolidHorizontalLine((g_eeGeneral.view & ALTERNATE_VIEW) ? 64 : 38, 34, 26, SOLID);
|
||||
#endif
|
||||
|
||||
for (uint8_t i=0; i<8; i++) {
|
||||
uint8_t x0,y0;
|
||||
#if defined(PCBSKY9X)
|
||||
uint8_t chan = 8*(g_eeGeneral.view / ALTERNATE_VIEW) + i;
|
||||
#else
|
||||
uint8_t chan = (g_eeGeneral.view & ALTERNATE_VIEW) ? 8+i : i;
|
||||
#endif
|
||||
|
||||
int16_t val = channelOutputs[chan];
|
||||
|
||||
switch(view_base)
|
||||
{
|
||||
case VIEW_OUTPUTS_VALUES:
|
||||
x0 = (i%4*9+3)*FW/2;
|
||||
y0 = i/4*FH+40;
|
||||
#if defined(PPM_UNIT_US)
|
||||
lcdDrawNumber(x0+4*FW , y0, PPM_CH_CENTER(chan)+val/2, 0);
|
||||
#elif defined(PPM_UNIT_PERCENT_PREC1)
|
||||
lcdDrawNumber(x0+4*FW , y0, calcRESXto1000(val), PREC1);
|
||||
#else
|
||||
lcdDrawNumber(x0+4*FW , y0, calcRESXto1000(val)/10, 0); // G: Don't like the decimal part*
|
||||
#endif
|
||||
break;
|
||||
|
||||
case VIEW_OUTPUTS_BARS:
|
||||
#define WBAR2 (50/2)
|
||||
x0 = i<4 ? LCD_W/4+2 : LCD_W*3/4-2;
|
||||
y0 = 38+(i%4)*5;
|
||||
|
||||
uint16_t lim = g_model.extendedLimits ? 640*2 : 512*2;
|
||||
int8_t len = (abs(val) * WBAR2 + lim/2) / lim;
|
||||
|
||||
if(len>WBAR2) len = WBAR2; // prevent bars from going over the end - comment for debugging
|
||||
lcdDrawHorizontalLine(x0-WBAR2, y0, WBAR2*2+1, DOTTED);
|
||||
lcdDrawSolidVerticalLine(x0,y0-2,5);
|
||||
if (val>0)
|
||||
x0+=1;
|
||||
else
|
||||
x0-=len;
|
||||
lcdDrawSolidHorizontalLine(x0,y0+1,len);
|
||||
lcdDrawSolidHorizontalLine(x0,y0-1,len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (view_base == VIEW_INPUTS) {
|
||||
if (view == VIEW_INPUTS) {
|
||||
// Sticks + Pots
|
||||
doMainScreenGraphics();
|
||||
|
||||
// Switches
|
||||
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;
|
||||
if (i>=SWSRC_AIL) {
|
||||
x = 17*FW-1;
|
||||
y -= 3*FH;
|
||||
}
|
||||
putsSwitches(x, y, sw, getSwitch(i) ? INVERS : 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if defined(PCBMEGA2560) && defined(ROTARY_ENCODERS)
|
||||
for (uint8_t i=0; i<NUM_ROTARY_ENCODERS; i++) {
|
||||
int16_t val = getRotaryEncoder(i);
|
||||
int8_t len = limit((int16_t)0, (int16_t)(((val+1024) * BAR_HEIGHT) / 2048), (int16_t)BAR_HEIGHT);
|
||||
#if ROTARY_ENCODERS > 2
|
||||
#define V_BAR_W 5
|
||||
V_BAR(LCD_W/2-8+V_BAR_W*i, LCD_H-8, len);
|
||||
#else
|
||||
#define V_BAR_W 5
|
||||
V_BAR(LCD_W/2-3+V_BAR_W*i, LCD_H-8, len);
|
||||
#endif
|
||||
}
|
||||
#endif // PCBGRUVIN9X && ROTARY_ENCODERS
|
||||
|
||||
// Logical Switches
|
||||
#if defined(PCBSKY9X)
|
||||
for (uint8_t i=0; i<NUM_LOGICAL_SWITCH; 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);
|
||||
}
|
||||
#elif defined(CPUM2560)
|
||||
for (uint8_t i=0; i<NUM_LOGICAL_SWITCH; i++)
|
||||
putsSwitches(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<NUM_LOGICAL_SWITCH; i++)
|
||||
putsSwitches(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<NUM_LOGICAL_SWITCH; i++)
|
||||
putsSwitches(2*FW-3 + (i/3)*(4*FW), 4*FH+1 + (i%3)*FH, SWSRC_SW1+i, getSwitch(SWSRC_SW1+i) ? INVERS : 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else { // timer2
|
||||
#if defined(TRANSLATIONS_CZ)
|
||||
#define TMR2_LBL_COL (20-FW/2+1)
|
||||
#else
|
||||
#define TMR2_LBL_COL (20-FW/2+5)
|
||||
#endif
|
||||
putsTimer(33+FW+2+10*FWNUM-4, FH*5, timersStates[1].val, DBLSIZE, DBLSIZE);
|
||||
putsTimerMode(timersStates[1].val >= 0 ? TMR2_LBL_COL : TMR2_LBL_COL-7, FH*6, g_model.timers[1].mode);
|
||||
// lcdDrawNumber(33+11*FW, FH*6, s_timerVal_10ms[1], LEADING0, 2); // 1/100s
|
||||
}
|
||||
|
||||
// And ! in case of unexpected shutdown
|
||||
if (unexpectedShutdown) {
|
||||
lcdDrawChar(REBOOT_X, 0*FH, '!', INVERS);
|
||||
}
|
||||
|
||||
#if defined(GVARS) && !defined(PCBSTD)
|
||||
if (gvarDisplayTimer > 0) {
|
||||
gvarDisplayTimer--;
|
||||
warningText = STR_GLOBAL_VAR;
|
||||
displayBox();
|
||||
lcdDrawSizedText(16, 5*FH, g_model.gvars[gvarLastChanged].name, LEN_GVAR_NAME, ZCHAR);
|
||||
lcdDrawText(16+7*FW, 5*FH, PSTR("[\010]"), BOLD);
|
||||
|
||||
lcdDrawNumber(16+7*FW+4*FW+FW/2, 5*FH, GVAR_VALUE(gvarLastChanged, getGVarFlightMode(mixerCurrentFlightMode, gvarLastChanged)), BOLD);
|
||||
warningText = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DSM2)
|
||||
if (moduleFlag[0] == MODULE_BIND) {
|
||||
// Issue 98
|
||||
lcdDrawText(15*FW, 0, PSTR("BIND"), 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,512 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file view_mavlink.cpp
|
||||
* Mavlink menu
|
||||
* Contains the menu specific code for Mavlink support.
|
||||
*/
|
||||
|
||||
#include "view_mavlink.h"
|
||||
|
||||
#define VIEW_MAVLINK_2ND_COLUMN (LCD_W-6*FW-3-MENUS_SCROLLBAR_WIDTH)
|
||||
|
||||
uint8_t MAVLINK_menu = MENU_INFO;
|
||||
|
||||
/*! \brief Top Mavlink Menu definition
|
||||
* \details Registers button events and handles that info. Buttons select menus,
|
||||
* these are launched from the MAVLINK_menu switch statement. Setup menu is
|
||||
* lanuched by the menu button. On exit (with exit button) the mavlink
|
||||
* extension is reinitialized.
|
||||
*/
|
||||
void menuTelemetryMavlink(uint8_t event) {
|
||||
|
||||
switch (event) // new event received, branch accordingly
|
||||
{
|
||||
case EVT_ENTRY:
|
||||
MAVLINK_menu = MENU_INFO;
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
if (MAVLINK_menu > 0)
|
||||
MAVLINK_menu--;
|
||||
else
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
if (MAVLINK_menu < MAX_MAVLINK_MENU - 1)
|
||||
MAVLINK_menu++;
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_MENU):
|
||||
return;
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (MAVLINK_menu) {
|
||||
case MENU_INFO:
|
||||
menuTelemetryMavlinkInfos();
|
||||
break;
|
||||
case MENU_MODE:
|
||||
menuTelemetryMavlinkFlightMode();
|
||||
break;
|
||||
case MENU_BATT:
|
||||
menuTelemetryMavlinkBattery();
|
||||
break;
|
||||
case MENU_NAV:
|
||||
menuTelemetryMavlinkNavigation();
|
||||
break;
|
||||
case MENU_GPS:
|
||||
menuTelemetryMavlinkGPS();
|
||||
break;
|
||||
#ifdef DUMP_RX_TX
|
||||
case MENU_DUMP_TX:
|
||||
case MENU_DUMP_RX:
|
||||
menuTelemetryMavlinkDump(event);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Float variable display helper
|
||||
* \param x x position on the screen
|
||||
* \param y y position on the screen
|
||||
* \param val value to display
|
||||
* \param percis precision to display
|
||||
* \param mode Use one of the defines in lcd.h line 81
|
||||
* \details The maximum value is 9999. The position is the position of the ones, see below for explanation "*" marks
|
||||
* the x position.
|
||||
* \verbatim
|
||||
*
|
||||
9999.9999 \endverbatim
|
||||
*/
|
||||
void lcd_outdezFloat(uint8_t x, uint8_t y, float val, uint8_t precis, uint8_t mode) {
|
||||
char c;
|
||||
int16_t lnum = val;
|
||||
uint8_t x1 = x;
|
||||
val -= lnum;
|
||||
uint8_t xinc = FWNUM;
|
||||
if (mode & DBLSIZE)
|
||||
xinc *= 2;
|
||||
|
||||
int8_t i = 0;
|
||||
lnum = abs(lnum);
|
||||
for (; i < 4; i++) {
|
||||
c = (lnum % 10) + '0';
|
||||
x1 -= xinc;
|
||||
lcdDrawChar(x1, y, c, mode);
|
||||
lnum /= 10;
|
||||
if (lnum == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lnum != 0) {
|
||||
// Error number too big
|
||||
x1 = x;
|
||||
for (i = 0; i < 4; i++) {
|
||||
x1 -= FW;
|
||||
lcdDrawChar(x1, y, '?', mode);
|
||||
}
|
||||
} else {
|
||||
if (val < 0) {
|
||||
val = -val;
|
||||
x1 -= xinc;
|
||||
lcdDrawChar(x1, y, '-', mode);
|
||||
}
|
||||
if (precis)
|
||||
{
|
||||
uint8_t y_temp = y;
|
||||
if (mode & DBLSIZE)
|
||||
y_temp += FH;
|
||||
lcdDrawChar(x, y_temp, '.', (mode & (~DBLSIZE)));
|
||||
x -= (xinc / 2);
|
||||
}
|
||||
for (i = 0; i < precis; i++) {
|
||||
val *= 10;
|
||||
int a = val;
|
||||
c = a + '0';
|
||||
x += xinc;
|
||||
lcdDrawChar(x, y, c, mode);
|
||||
val -= a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Fightmode string printer
|
||||
* \details Decodes the flight mode from Mavlink custom mode enum to a string.
|
||||
* This funtion can handle ArduPilot and ArduCoper code.
|
||||
* To support new autopilot pilots add a STR_MAVLINK_... to the translations,
|
||||
* and if requred a lut (see arduplane for examle) if there are unused modes
|
||||
* in the sequence.
|
||||
*/
|
||||
|
||||
void print_mav_mode(uint8_t x, uint8_t y, uint32_t custom_mode, uint8_t attr) //, const char * mode_text_p)
|
||||
{
|
||||
uint8_t mode = (uint8_t) custom_mode;
|
||||
switch (telemetry_data.type_autopilot) {
|
||||
case MAVLINK_ARDUCOPTER:
|
||||
lcdDrawTextAtIndex(x,y,STR_MAVLINK_AC_MODES,mode,attr);
|
||||
break;
|
||||
case MAVLINK_ARDUPLANE:
|
||||
lcdDrawTextAtIndex(x,y,STR_MAVLINK_AP_MODES,ap_modes_lut[custom_mode],attr);
|
||||
break;
|
||||
default:
|
||||
lcdDrawText (FW, y, PSTR("INV. MAV TYPE"), attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Menu header
|
||||
* \details Small helper function to print the standard header on the screen.
|
||||
*/
|
||||
void mav_title(const pm_char * s, uint8_t index)
|
||||
{
|
||||
lcdDrawText(0, 0, PSTR("MAVLINK"), INVERS);
|
||||
lcdDrawText(10 * FW, 0, s);
|
||||
drawScreenIndex(index, MAX_MAVLINK_MENU, INVERS);
|
||||
lcdDrawChar(7 * FW, 0, (mav_heartbeat > 0) ? '*' : ' ');
|
||||
if (telemetry_data.active)
|
||||
lcdDrawChar(8 * FW, 0, 'A', BLINK);
|
||||
}
|
||||
|
||||
/*! \brief Global info menu
|
||||
* \details Quick status overview menu. The menu should contain current mode,
|
||||
* armed | disarmed, battery status and RSSI info. Menu must be clean and
|
||||
* readable with a quick glance.
|
||||
* \todo Make menu as described as above.
|
||||
*/
|
||||
void menuTelemetryMavlinkInfos(void) {
|
||||
|
||||
mav_title(STR_MAVLINK_INFOS, MAVLINK_menu);
|
||||
|
||||
uint8_t x1, x2, xnum, y;
|
||||
x1 = FW;
|
||||
x2 = 7 * FW;
|
||||
xnum = x2 + 5 * FWNUM;
|
||||
y = FH;
|
||||
/*
|
||||
char * ptr = mav_statustext;
|
||||
for (uint8_t j = 0; j < LEN_STATUSTEXT; j++) {
|
||||
if (*ptr == 0) {
|
||||
lcdDrawChar(x1, y, ' ');
|
||||
} else {
|
||||
lcdDrawChar(x1, y, *ptr++);
|
||||
}
|
||||
x1 += FW;
|
||||
}
|
||||
x1 = FW;
|
||||
y += FH;
|
||||
*/
|
||||
if (telemetry_data.status) {
|
||||
|
||||
lcdDrawSizedText(x1, y, STR_MAVLINK_MODE, 4, 0);
|
||||
if (telemetry_data.active)
|
||||
lcdDrawSizedText(x2, y, PSTR("A"), 1, 0);
|
||||
lcdDrawNumber(xnum, y, telemetry_data.mode, 0);
|
||||
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, PSTR("BATT"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.vbat, PREC1, 5);
|
||||
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, PSTR("DROP"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.packet_drop, 0);
|
||||
/* y += FH;
|
||||
lcdDrawText(x1, y, PSTR("FIX"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.packet_fixed, 0);
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, PSTR("MAV Comp"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.mav_compid, 0);
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, PSTR("MAV Sys"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.mav_sysid, 0);
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, PSTR("Rad Comp"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.radio_compid, 0);
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, PSTR("Rad Sys"));
|
||||
lcdDrawNumber(xnum, y, telemetry_data.radio_sysid, 0);
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Flight mode menu
|
||||
* \details Clear display of current flight mode.
|
||||
* \todo Add functionality to change flight mode.
|
||||
*/
|
||||
void menuTelemetryMavlinkFlightMode(void) {
|
||||
|
||||
mav_title(STR_MAVLINK_MODE, MAVLINK_menu);
|
||||
|
||||
uint8_t x, y;
|
||||
x = 0;
|
||||
y = FH;
|
||||
|
||||
lcdDrawText(x, y, STR_MAVLINK_CUR_MODE);
|
||||
y += FH;
|
||||
print_mav_mode(FW, y, telemetry_data.custom_mode, DBLSIZE);
|
||||
y += 2 * FH;
|
||||
|
||||
char * ptr = mav_statustext;
|
||||
for (uint8_t j = 0; j < LEN_STATUSTEXT; j++) {
|
||||
if (*ptr == 0) {
|
||||
lcdDrawChar(x, y, ' ');
|
||||
} else {
|
||||
lcdDrawChar(x, y, *ptr++);
|
||||
}
|
||||
x += FW;
|
||||
}
|
||||
y += FH;
|
||||
x = 0;
|
||||
|
||||
if (telemetry_data.active)
|
||||
lcdDrawText (FW, y, STR_MAVLINK_ARMED, DBLSIZE);
|
||||
}
|
||||
|
||||
/*! \brief Batterystatus dislplay
|
||||
* \details Shows flight batery status.
|
||||
* Also RC and PC RSSI are in this menu.
|
||||
*/
|
||||
void menuTelemetryMavlinkBattery(void) {
|
||||
|
||||
mav_title(STR_MAVLINK_BAT_MENU_TITLE, MAVLINK_menu);
|
||||
|
||||
uint8_t x, y, ynum;
|
||||
x = 7 * FWNUM;
|
||||
// x = xnum + 0 * FW;
|
||||
ynum = 2 * FH;
|
||||
y = 3 * FH;
|
||||
|
||||
lcdDrawText(0, 1*FH, STR_MAVLINK_BATTERY_LABEL);
|
||||
|
||||
lcdDrawNumber(x, ynum, telemetry_data.vbat, (DBLSIZE | PREC1 | UNSIGN));
|
||||
lcdDrawText(x, y, PSTR("V"));
|
||||
x += 4 * (2 * FWNUM);
|
||||
lcdDrawNumber(x, ynum, telemetry_data.ibat, (DBLSIZE | PREC1 | UNSIGN));
|
||||
lcdDrawText(x, y, PSTR("A"));
|
||||
x += 4 * (2 * FWNUM);
|
||||
lcdDrawNumber(x, ynum, telemetry_data.rem_bat, (DBLSIZE | UNSIGN));
|
||||
lcdDrawText(x, y, PSTR("%"));
|
||||
y += FH;
|
||||
ynum += 3 * FH;
|
||||
|
||||
x = 0;
|
||||
lcdDrawText(x, y, STR_MAVLINK_RC_RSSI_LABEL);
|
||||
lcdDrawNumber(x + 7 * FWNUM, ynum, telemetry_data.rc_rssi, (DBLSIZE | UNSIGN));
|
||||
lcdDrawText(x + 7 * FWNUM, ynum + FH, PSTR("%"));
|
||||
if (g_model.mavlink.pc_rssi_en)
|
||||
{
|
||||
x += 8 * (2 * FWNUM);
|
||||
lcdDrawText(x, y, STR_MAVLINK_PC_RSSI_LABEL);
|
||||
lcdDrawNumber(x + 7 * FWNUM, ynum, telemetry_data.pc_rssi, (DBLSIZE));
|
||||
lcdDrawText(x + 7 * FWNUM, ynum + FH, PSTR("%"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Navigation dislplay
|
||||
* \details Shows Navigation telemetry.
|
||||
* Altitude in this menu is the relative (to the home location) altitude. This
|
||||
* is the same altitude used by the waypoints.
|
||||
* \todo Add a similar menu to fly back to the home location.
|
||||
*/
|
||||
void menuTelemetryMavlinkNavigation(void) {
|
||||
|
||||
mav_title(STR_MAVLINK_NAV_MENU_TITLE, MAVLINK_menu);
|
||||
|
||||
uint8_t x, y, ynum;
|
||||
x = 7 * FWNUM;
|
||||
// x = xnum + 0 * FW;
|
||||
ynum = 2 * FH;
|
||||
y = FH;
|
||||
|
||||
|
||||
x = 0;
|
||||
lcdDrawText(x, y, STR_MAVLINK_COURSE);
|
||||
lcdDrawNumber(x + 7 * FWNUM, ynum, telemetry_data.course, (DBLSIZE | UNSIGN));
|
||||
lcdDrawText(x + 7 * FWNUM, ynum, PSTR("o"));
|
||||
x += 8 * (2 * FWNUM);
|
||||
lcdDrawText(x, y, STR_MAVLINK_HEADING);
|
||||
lcdDrawNumber(x + 7 * FWNUM, ynum, telemetry_data.heading, (DBLSIZE | UNSIGN));
|
||||
lcdDrawText(x + 7 * FWNUM, ynum, PSTR("o"));
|
||||
y += 3 * FH;
|
||||
ynum += 3 * FH;
|
||||
|
||||
x = 0;
|
||||
lcdDrawText(x, y, STR_MAVLINK_BEARING);
|
||||
lcdDrawNumber(x + 7 * FWNUM, ynum, telemetry_data.bearing, (DBLSIZE | UNSIGN));
|
||||
lcdDrawText(x + 7 * FWNUM, ynum, PSTR("o"));
|
||||
x += 8 * (2 * FWNUM);
|
||||
lcdDrawText(x, y, STR_MAVLINK_ALTITUDE);
|
||||
lcd_outdezFloat(x + 4 * FWNUM - 1, ynum, telemetry_data.loc_current.rel_alt, 1, (DBLSIZE));
|
||||
lcdDrawText(x + 7 * FWNUM, ynum + FH, PSTR("m"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! \brief GPS information menu
|
||||
* \details Menu gives a lot of info from the gps like fix type, position,
|
||||
* attitude, heading and velocity. Text is small and the user must focus to
|
||||
* read it.
|
||||
* \todo Text is small. Should we do something about this or leaf it like this.
|
||||
* I don't think will be used much when a user is concentrated on flying.
|
||||
*/
|
||||
void menuTelemetryMavlinkGPS(void) {
|
||||
mav_title(STR_MAVLINK_GPS, MAVLINK_menu);
|
||||
|
||||
uint8_t x1, x2, xnum, xnum2, y;
|
||||
x1 = FW;
|
||||
x2 = x1 + 12 * FW;
|
||||
xnum = 7 * FW + 3 * FWNUM;
|
||||
xnum2 = xnum + 11 * FWNUM;
|
||||
y = FH;
|
||||
|
||||
lcdDrawSizedText(x1, y, STR_MAVLINK_GPS, 3, 0);
|
||||
if (telemetry_data.fix_type < 2) {
|
||||
lcdDrawSizedText(xnum, y, STR_MAVLINK_NO_FIX, 6, 0);
|
||||
} else {
|
||||
lcdDrawNumber(xnum, y, telemetry_data.fix_type, 0, 3);
|
||||
lcdDrawText(xnum, y, PSTR("D"));
|
||||
}
|
||||
lcdDrawText(x2, y, STR_MAVLINK_SAT);
|
||||
lcdDrawNumber(xnum2, y, telemetry_data.satellites_visible, 0, 2);
|
||||
|
||||
// if (telemetry_data.fix_type > 0) {
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, STR_MAVLINK_HDOP);
|
||||
lcd_outdezFloat(xnum, y, telemetry_data.eph, 2);
|
||||
|
||||
y += FH;
|
||||
lcdDrawText(x1, y, STR_MAVLINK_LAT);
|
||||
lcd_outdezFloat(xnum, y, telemetry_data.loc_current.lat, 2);
|
||||
|
||||
lcdDrawSizedText(x2, y, STR_MAVLINK_LON, 3, 0);
|
||||
lcd_outdezFloat(xnum2, y, telemetry_data.loc_current.lon, 2);
|
||||
|
||||
y += FH;
|
||||
lcdDrawSizedText(x1, y, STR_MAVLINK_ALTITUDE, 3, 0);
|
||||
lcdDrawNumber(xnum, y, telemetry_data.loc_current.gps_alt, 0);
|
||||
|
||||
y += FH;
|
||||
lcdDrawSizedText(x1, y, STR_MAVLINK_COURSE, 6, 0);
|
||||
lcd_outdezFloat(xnum, y, telemetry_data.course, 2);
|
||||
|
||||
y += FH;
|
||||
lcdDrawSizedText(x1, y, PSTR("V"), 1, 0);
|
||||
lcdDrawNumber(xnum, y, telemetry_data.v, 0);
|
||||
//}
|
||||
}
|
||||
|
||||
#ifdef DUMP_RX_TX
|
||||
//! \brief Display one byte as hex.
|
||||
void lcd_outhex2(uint8_t x, uint8_t y, uint8_t val) {
|
||||
x += FWNUM * 2;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
x -= FWNUM;
|
||||
char c = val & 0xf;
|
||||
c = c > 9 ? c + 'A' - 10 : c + '0';
|
||||
lcdDrawChar(x, y, c, c >= 'A' ? CONDENSED : 0);
|
||||
val >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
//! \brief Hex dump of the current mavlink message.
|
||||
void menuTelemetryMavlinkDump(uint8_t event) {
|
||||
uint8_t x = 0;
|
||||
uint8_t y = FH;
|
||||
uint16_t count = 0;
|
||||
uint16_t bufferLen = 0;
|
||||
uint8_t *ptr = NULL;
|
||||
switch (MAVLINK_menu) {
|
||||
case MENU_DUMP_RX:
|
||||
mav_dump_rx = 1;
|
||||
mav_title(PSTR("RX"), MAVLINK_menu);
|
||||
bufferLen = mavlinkRxBufferCount;
|
||||
ptr = mavlinkRxBuffer;
|
||||
break;
|
||||
|
||||
case MENU_DUMP_TX:
|
||||
mav_title(PSTR("TX"), MAVLINK_menu);
|
||||
bufferLen = serialTxBufferCount;
|
||||
ptr = ptrTxISR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
for (uint16_t var = 0; var < bufferLen; var++) {
|
||||
uint8_t byte = *ptr++;
|
||||
lcd_outhex2(x, y, byte);
|
||||
x += 2 * FW;
|
||||
count++;
|
||||
if (count > 8) {
|
||||
count = 0;
|
||||
x = 0;
|
||||
y += FH;
|
||||
if (y == (6 * FH))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*! \brief Mavlink General setup menu.
|
||||
* \details Setup menu for generic mavlink settings.
|
||||
* Current menu items
|
||||
* - RC RSSI scale item. Used to adjust the scale of the RSSI indicator to match
|
||||
* the actual rssi value
|
||||
* - PC RSSI enable item. Can be used to dissable PC RSSI display if not used.
|
||||
* This funcion is called from the model setup menus, not directly by the
|
||||
* telemetry menus
|
||||
*/
|
||||
void menuTelemetryMavlinkSetup(uint8_t event) {
|
||||
|
||||
MENU(STR_MAVMENUSETUP_TITLE, menuTabModel, e_MavSetup, ITEM_MAVLINK_MAX + 1, {0, 0, 1/*to force edit mode*/});
|
||||
|
||||
uint8_t sub = menuVerticalPosition - 1;
|
||||
|
||||
for (uint8_t i=0; i<LCD_LINES-1; i++) {
|
||||
uint8_t y = 1 + 1*FH + i*FH;
|
||||
uint8_t k = i+menuVerticalOffset;
|
||||
uint8_t blink = ((s_editMode>0) ? BLINK|INVERS : INVERS);
|
||||
uint8_t attr = (sub == k ? blink : 0);
|
||||
switch(k) {
|
||||
case ITEM_MAVLINK_RC_RSSI_SCALE:
|
||||
lcd_putsLeft(y, STR_MAVLINK_RC_RSSI_SCALE_LABEL);
|
||||
lcdDrawNumber(VIEW_MAVLINK_2ND_COLUMN, y, (25 + g_model.mavlink.rc_rssi_scale * 5), attr|LEFT);
|
||||
lcdDrawChar(lcdLastPos, y, '%');
|
||||
if (attr) CHECK_INCDEC_MODELVAR(event, g_model.mavlink.rc_rssi_scale, 0, 15);
|
||||
break;
|
||||
case ITEM_MAVLINK_PC_RSSI_EN:
|
||||
g_model.mavlink.pc_rssi_en = editCheckBox(g_model.mavlink.pc_rssi_en,
|
||||
VIEW_MAVLINK_2ND_COLUMN,
|
||||
y,
|
||||
STR_MAVLINK_PC_RSSI_EN_LABEL,
|
||||
attr,
|
||||
event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/*! \file view_mavlink.h
|
||||
* Mavlink menu include file
|
||||
*/
|
||||
|
||||
#ifndef _VIEW_MAVLINK_H_
|
||||
#define _VIEW_MAVLINK_H_
|
||||
|
||||
#include "opentx.h"
|
||||
#include "telemetry/mavlink.h"
|
||||
#include "targets/common/avr/serial_driver.h"
|
||||
|
||||
#define APSIZE (BSS | DBLSIZE)
|
||||
|
||||
void menuTelemetryMavlink(uint8_t event);
|
||||
void drawScreenIndex(uint8_t index, uint8_t count, uint8_t attr);
|
||||
void lcd_outdezFloat(uint8_t x, uint8_t y, float val, uint8_t precis, uint8_t mode = 0);
|
||||
void mav_title(const pm_char * s, uint8_t index);
|
||||
void menuTelemetryMavlinkInfos(void);
|
||||
void menuTelemetryMavlinkFlightMode(void);
|
||||
void menuTelemetryMavlinkBattery(void);
|
||||
void menuTelemetryMavlinkNavigation(void);
|
||||
void menuTelemetryMavlinkGPS(void);
|
||||
#ifdef DUMP_RX_TX
|
||||
void lcd_outhex2(uint8_t x, uint8_t y, uint8_t val);
|
||||
void menuTelemetryMavlinkDump(uint8_t event);
|
||||
#endif
|
||||
|
||||
/*! \brief Mavlink menu enumerator
|
||||
* \details Used to create a readable case statement for the
|
||||
* \link menuTelemetryMavlink menuTelemetryMavlink \endlink funtion.
|
||||
*/
|
||||
enum mavlink_menu_ {
|
||||
MENU_INFO = 0, //
|
||||
MENU_MODE,
|
||||
MENU_BATT,
|
||||
MENU_NAV,
|
||||
MENU_GPS, //
|
||||
#ifdef DUMP_RX_TX
|
||||
MENU_DUMP_RX, //
|
||||
MENU_DUMP_TX, //
|
||||
#endif
|
||||
MAX_MAVLINK_MENU
|
||||
};
|
||||
|
||||
//! \brief Pointer array to mavlink settings menus.
|
||||
const MenuHandlerFunc menuTabMav[] PROGMEM = {
|
||||
menuTelemetryMavlinkSetup
|
||||
};
|
||||
|
||||
//! \brief Mavlink setup menu configuration items list.
|
||||
enum menuMavlinkSetupItems {
|
||||
ITEM_MAVLINK_RC_RSSI_SCALE,
|
||||
ITEM_MAVLINK_PC_RSSI_EN,
|
||||
ITEM_MAVLINK_MAX
|
||||
};
|
||||
|
||||
//! \brief Menu index varible, initialized on info menu.
|
||||
extern uint8_t MAVLINK_menu;
|
||||
|
||||
#endif // _VIEW_MAVLINK_H_
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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 menuStatisticsView(uint8_t event)
|
||||
{
|
||||
TITLE(STR_MENUSTAT);
|
||||
|
||||
switch(event)
|
||||
{
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
chainMenu(menuStatisticsDebug);
|
||||
break;
|
||||
|
||||
#if defined(CPUARM)
|
||||
case EVT_KEY_LONG(KEY_MENU):
|
||||
g_eeGeneral.globalTimer = 0;
|
||||
storageDirty(EE_GENERAL);
|
||||
sessionTimer = 0;
|
||||
break;
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
lcdDrawText( 1*FW, FH*0, STR_TOTTM1TM2THRTHP);
|
||||
putsTimer( 5*FW+5*FWNUM+1, FH*1, timersStates[0].val, 0, 0);
|
||||
putsTimer( 12*FW+5*FWNUM+1, FH*1, timersStates[1].val, 0, 0);
|
||||
|
||||
putsTimer( 5*FW+5*FWNUM+1, FH*2, s_timeCumThr, 0, 0);
|
||||
putsTimer( 12*FW+5*FWNUM+1, FH*2, s_timeCum16ThrP/16, 0, 0);
|
||||
|
||||
putsTimer( 12*FW+5*FWNUM+1, FH*0, sessionTimer, 0, 0);
|
||||
|
||||
#if defined(THRTRACE)
|
||||
const coord_t x = 5;
|
||||
const coord_t y = 60;
|
||||
lcdDrawSolidHorizontalLine(x-3, y, MAXTRACE+3+3);
|
||||
lcdDrawSolidVerticalLine(x, y-32, 32+3);
|
||||
for (coord_t i=0; i<MAXTRACE; i+=6) {
|
||||
lcdDrawSolidVerticalLine(x+i+6, y-1, 3);
|
||||
}
|
||||
|
||||
uint16_t traceRd = s_traceWr > MAXTRACE ? s_traceWr - MAXTRACE : 0;
|
||||
for (coord_t i=1; i<=MAXTRACE && traceRd<s_traceWr; i++, traceRd++) {
|
||||
uint8_t h = s_traceBuf[traceRd % MAXTRACE];
|
||||
lcdDrawSolidVerticalLine(x+i, y-h, h);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
#define MENU_DEBUG_COL1_OFS (11*FW-3)
|
||||
#define MENU_DEBUG_COL2_OFS (17*FW)
|
||||
#define MENU_DEBUG_Y_CURRENT (1*FH)
|
||||
#define MENU_DEBUG_Y_MAH (2*FH)
|
||||
#define MENU_DEBUG_Y_CPU_TEMP (3*FH)
|
||||
#define MENU_DEBUG_Y_COPROC (4*FH)
|
||||
#define MENU_DEBUG_Y_MIXMAX (5*FH)
|
||||
#define MENU_DEBUG_Y_RTOS (6*FH)
|
||||
#else
|
||||
#define MENU_DEBUG_COL1_OFS (14*FW)
|
||||
#endif
|
||||
|
||||
void menuStatisticsDebug(uint8_t event)
|
||||
{
|
||||
TITLE(STR_MENUDEBUG);
|
||||
|
||||
switch(event)
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
case EVT_KEY_LONG(KEY_ENTER):
|
||||
g_eeGeneral.mAhUsed = 0;
|
||||
g_eeGeneral.globalTimer = 0;
|
||||
storageDirty(EE_GENERAL);
|
||||
#if defined(PCBSKY9X)
|
||||
Current_used = 0;
|
||||
#endif
|
||||
sessionTimer = 0;
|
||||
killEvents(event);
|
||||
break;
|
||||
#endif
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
#if !defined(CPUARM)
|
||||
g_tmr1Latency_min = 0xff;
|
||||
g_tmr1Latency_max = 0;
|
||||
#endif
|
||||
maxMixerDuration = 0;
|
||||
break;
|
||||
|
||||
#if defined(DEBUG_TRACE_BUFFER)
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
pushMenu(menuTraceBuffer);
|
||||
return;
|
||||
#endif
|
||||
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
chainMenu(menuStatisticsView);
|
||||
break;
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
if ((ResetReason&RSTC_SR_RSTTYP) == (2<<8)) {
|
||||
lcdDrawText(LCD_W-8*FW, 0*FH, "WATCHDOG");
|
||||
}
|
||||
else if (unexpectedShutdown) {
|
||||
lcdDrawText(LCD_W-13*FW, 0*FH, "UNEXP.SHTDOWN");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TX_CAPACITY_MEASUREMENT)
|
||||
// current
|
||||
lcd_putsLeft(MENU_DEBUG_Y_CURRENT, STR_CPU_CURRENT);
|
||||
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CURRENT, getCurrent(), UNIT_MILLIAMPS, LEFT);
|
||||
uint32_t current_scale = 488 + g_eeGeneral.txCurrentCalibration;
|
||||
lcdDrawChar(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CURRENT, '>');
|
||||
putsValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CURRENT, Current_max*10*current_scale/8192, UNIT_RAW, LEFT);
|
||||
// consumption
|
||||
lcd_putsLeft(MENU_DEBUG_Y_MAH, STR_CPU_MAH);
|
||||
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MAH, g_eeGeneral.mAhUsed + Current_used*current_scale/8192/36, UNIT_MAH, LEFT|PREC1);
|
||||
#endif
|
||||
|
||||
#if defined(PCBSKY9X)
|
||||
lcd_putsLeft(MENU_DEBUG_Y_CPU_TEMP, STR_CPU_TEMP);
|
||||
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_CPU_TEMP, getTemperature(), UNIT_TEMPERATURE, LEFT);
|
||||
lcdDrawChar(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_CPU_TEMP, '>');
|
||||
putsValueWithUnit(MENU_DEBUG_COL2_OFS+FW+1, MENU_DEBUG_Y_CPU_TEMP, maxTemperature+g_eeGeneral.temperatureCalib, UNIT_TEMPERATURE, LEFT);
|
||||
#endif
|
||||
|
||||
#if defined(COPROCESSOR)
|
||||
lcd_putsLeft(MENU_DEBUG_Y_COPROC, STR_COPROC_TEMP);
|
||||
|
||||
if (Coproc_read==0) {
|
||||
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Co Proc NACK"),INVERS);
|
||||
}
|
||||
else if (Coproc_read==0x81) {
|
||||
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Inst.TinyApp"),INVERS);
|
||||
}
|
||||
else if (Coproc_read<3) {
|
||||
lcdDrawText(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, PSTR("Upgr.TinyApp"),INVERS);
|
||||
}
|
||||
else {
|
||||
putsValueWithUnit(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_COPROC, Coproc_temp, UNIT_TEMPERATURE, LEFT);
|
||||
putsValueWithUnit(MENU_DEBUG_COL2_OFS, MENU_DEBUG_Y_COPROC, Coproc_maxtemp, UNIT_TEMPERATURE, LEFT);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
lcd_putsLeft(MENU_DEBUG_Y_MIXMAX, STR_TMIXMAXMS);
|
||||
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_MIXMAX, DURATION_MS_PREC2(maxMixerDuration), PREC2|LEFT);
|
||||
lcdDrawText(lcdLastPos, MENU_DEBUG_Y_MIXMAX, "ms");
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
lcd_putsLeft(MENU_DEBUG_Y_RTOS, STR_FREESTACKMINB);
|
||||
lcdDrawNumber(MENU_DEBUG_COL1_OFS, MENU_DEBUG_Y_RTOS+2, menusStack.available(), UNSIGN|LEFT|TINSIZE);
|
||||
lcdDrawText(lcdLastPos, MENU_DEBUG_Y_RTOS, "/");
|
||||
lcdDrawNumber(lcdLastPos, MENU_DEBUG_Y_RTOS+2, mixerStack.available(), UNSIGN|LEFT|TINSIZE);
|
||||
lcdDrawText(lcdLastPos, MENU_DEBUG_Y_RTOS, "/");
|
||||
lcdDrawNumber(lcdLastPos, MENU_DEBUG_Y_RTOS+2, audioStack.available(), UNSIGN|LEFT|TINSIZE);
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM)
|
||||
lcd_putsLeft(1*FH, STR_TMR1LATMAXUS);
|
||||
lcdDraw8bitsNumber(MENU_DEBUG_COL1_OFS , 1*FH, g_tmr1Latency_max/2 );
|
||||
lcd_putsLeft(2*FH, STR_TMR1LATMINUS);
|
||||
lcdDraw8bitsNumber(MENU_DEBUG_COL1_OFS , 2*FH, g_tmr1Latency_min/2 );
|
||||
lcd_putsLeft(3*FH, STR_TMR1JITTERUS);
|
||||
lcdDraw8bitsNumber(MENU_DEBUG_COL1_OFS , 3*FH, (g_tmr1Latency_max - g_tmr1Latency_min) /2 );
|
||||
lcd_putsLeft(4*FH, STR_TMIXMAXMS);
|
||||
lcdDrawNumber(MENU_DEBUG_COL1_OFS, 4*FH, DURATION_MS_PREC2(maxMixerDuration), PREC2);
|
||||
lcd_putsLeft(5*FH, STR_FREESTACKMINB);
|
||||
lcdDrawNumber(14*FW, 5*FH, stackAvailable(), UNSIGN) ;
|
||||
#endif
|
||||
|
||||
lcdDrawText(4*FW, 7*FH+1, STR_MENUTORESET);
|
||||
lcdInvertLastLine();
|
||||
}
|
||||
@@ -0,0 +1,545 @@
|
||||
/*
|
||||
* 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 STATUS_BAR_Y (7*FH+1)
|
||||
#define TELEM_2ND_COLUMN (10*FW)
|
||||
|
||||
#if defined(FRSKY_HUB) && defined(GAUGES)
|
||||
bar_threshold_t barsThresholds[THLD_MAX];
|
||||
#endif
|
||||
|
||||
uint8_t s_frsky_view = 0;
|
||||
|
||||
#define BAR_LEFT 25
|
||||
#define BAR_WIDTH 100
|
||||
|
||||
void displayRssiLine()
|
||||
{
|
||||
if (TELEMETRY_STREAMING()) {
|
||||
lcdDrawSolidHorizontalLine(0, 55, 128, 0); // separator
|
||||
uint8_t rssi;
|
||||
#if !defined(CPUARM)
|
||||
rssi = min((uint8_t)99, telemetryData.rssi[1].value);
|
||||
lcd_putsLeft(STATUS_BAR_Y, STR_TX); lcdDrawNumber(4*FW+1, STATUS_BAR_Y, rssi, LEADING0, 2);
|
||||
lcdDrawRect(BAR_LEFT+1, 57, 38, 7);
|
||||
lcdDrawFilledRect(BAR_LEFT+1, 58, 4*rssi/11, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID);
|
||||
#endif
|
||||
rssi = min((uint8_t)99, TELEMETRY_RSSI());
|
||||
lcdDrawText(104, STATUS_BAR_Y, STR_RX); lcdDrawNumber(105+4*FW, STATUS_BAR_Y, rssi, LEADING0, 2);
|
||||
lcdDrawRect(65, 57, 38, 7);
|
||||
uint8_t v = 4*rssi/11;
|
||||
lcdDrawFilledRect(66+36-v, 58, v, 5, (rssi < getRssiAlarmValue(0)) ? DOTTED : SOLID);
|
||||
}
|
||||
else {
|
||||
lcdDrawText(7*FW, STATUS_BAR_Y, STR_NODATA, BLINK);
|
||||
lcdInvertLastLine();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FRSKY) && defined(FRSKY_HUB) && defined(GPS) && !defined(CPUARM)
|
||||
void displayGpsTime()
|
||||
{
|
||||
uint8_t att = (TELEMETRY_STREAMING() ? LEFT|LEADING0 : LEFT|LEADING0|BLINK);
|
||||
lcdDrawNumber(CENTER_OFS+6*FW+7, STATUS_BAR_Y, telemetryData.hub.hour, att, 2);
|
||||
lcdDrawChar(CENTER_OFS+8*FW+4, STATUS_BAR_Y, ':', att);
|
||||
lcdDrawNumber(CENTER_OFS+9*FW+2, STATUS_BAR_Y, telemetryData.hub.min, att, 2);
|
||||
lcdDrawChar(CENTER_OFS+11*FW-1, STATUS_BAR_Y, ':', att);
|
||||
lcdDrawNumber(CENTER_OFS+12*FW-3, STATUS_BAR_Y, telemetryData.hub.sec, att, 2);
|
||||
lcdInvertLastLine();
|
||||
}
|
||||
|
||||
void displayGpsCoord(uint8_t y, char direction, int16_t bp, int16_t ap)
|
||||
{
|
||||
if (telemetryData.hub.gpsFix >= 0) {
|
||||
if (!direction) direction = '-';
|
||||
lcdDrawNumber(TELEM_2ND_COLUMN, y, bp / 100, LEFT); // ddd before '.'
|
||||
lcdDrawChar(lcdLastPos, y, '@');
|
||||
uint8_t mn = bp % 100; // TODO div_t
|
||||
if (g_eeGeneral.gpsFormat == 0) {
|
||||
lcdDrawChar(lcdLastPos+FWNUM, y, direction);
|
||||
lcdDrawNumber(lcdLastPos+FW+FW+1, y, mn, LEFT|LEADING0, 2); // mm before '.'
|
||||
lcdDrawSolidVerticalLine(lcdLastPos, y, 2);
|
||||
uint16_t ss = ap * 6;
|
||||
lcdDrawNumber(lcdLastPos+3, y, ss / 1000, LEFT|LEADING0, 2); // ''
|
||||
lcdDrawPoint(lcdLastPos, y+FH-2, 0); // small decimal point
|
||||
lcdDrawNumber(lcdLastPos+2, y, ss % 1000, LEFT|LEADING0, 3); // ''
|
||||
lcdDrawSolidVerticalLine(lcdLastPos, y, 2);
|
||||
lcdDrawSolidVerticalLine(lcdLastPos+2, y, 2);
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(lcdLastPos+FW, y, mn, LEFT|LEADING0, 2); // mm before '.'
|
||||
lcdDrawPoint(lcdLastPos, y+FH-2, 0); // small decimal point
|
||||
lcdDrawNumber(lcdLastPos+2, y, ap, LEFT|UNSIGN|LEADING0, 4); // after '.'
|
||||
lcdDrawChar(lcdLastPos+1, y, direction);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no fix
|
||||
lcdDrawText(TELEM_2ND_COLUMN, y, STR_VCSWFUNC+1/*----*/);
|
||||
}
|
||||
}
|
||||
#elif !defined(CPUARM)
|
||||
#define displayGpsTime()
|
||||
#define displayGpsCoord(...)
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM)
|
||||
void displayVoltageScreenLine(uint8_t y, uint8_t index)
|
||||
{
|
||||
drawStringWithIndex(0, y, STR_A, index+1, 0);
|
||||
if (TELEMETRY_STREAMING()) {
|
||||
putsTelemetryChannelValue(3*FW+6*FW+4, y-FH, index+TELEM_A1-1, telemetryData.analog[index].value, DBLSIZE);
|
||||
lcdDrawChar(12*FW-1, y-FH, '<'); putsTelemetryChannelValue(17*FW, y-FH, index+TELEM_A1-1, telemetryData.analog[index].min, NO_UNIT);
|
||||
lcdDrawChar(12*FW, y, '>'); putsTelemetryChannelValue(17*FW, y, index+TELEM_A1-1, telemetryData.analog[index].max, NO_UNIT);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t barCoord(int16_t value, int16_t min, int16_t max)
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
if (value <= min)
|
||||
return 0;
|
||||
else if (value >= max)
|
||||
return BAR_WIDTH-1;
|
||||
else
|
||||
return ((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min);
|
||||
#else
|
||||
return limit((uint8_t)0, (uint8_t)(((int32_t)(BAR_WIDTH-1) * (value - min)) / (max - min)), (uint8_t)BAR_WIDTH);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(CPUARM)
|
||||
void displayVoltagesScreen()
|
||||
{
|
||||
// Volts / Amps / Watts / mAh
|
||||
uint8_t analog = 0;
|
||||
lcdDrawTextAtIndex(0, 2*FH, STR_AMPSRC, g_model.frsky.voltsSource+1, 0);
|
||||
switch (g_model.frsky.voltsSource) {
|
||||
case FRSKY_VOLTS_SOURCE_A1:
|
||||
case FRSKY_VOLTS_SOURCE_A2:
|
||||
displayVoltageScreenLine(2*FH, g_model.frsky.voltsSource);
|
||||
analog = 1+g_model.frsky.voltsSource;
|
||||
break;
|
||||
#if defined(FRSKY_HUB)
|
||||
case FRSKY_VOLTS_SOURCE_FAS:
|
||||
putsTelemetryChannelValue(3*FW+6*FW+4, FH, TELEM_VFAS-1, telemetryData.hub.vfas, DBLSIZE);
|
||||
break;
|
||||
case FRSKY_VOLTS_SOURCE_CELLS:
|
||||
putsTelemetryChannelValue(3*FW+6*FW+4, FH, TELEM_CELLS_SUM-1, telemetryData.hub.cellsSum, DBLSIZE);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_model.frsky.currentSource) {
|
||||
lcdDrawTextAtIndex(0, 4*FH, STR_AMPSRC, g_model.frsky.currentSource, 0);
|
||||
switch(g_model.frsky.currentSource) {
|
||||
case FRSKY_CURRENT_SOURCE_A1:
|
||||
case FRSKY_CURRENT_SOURCE_A2:
|
||||
displayVoltageScreenLine(4*FH, g_model.frsky.currentSource-1);
|
||||
break;
|
||||
#if defined(FRSKY_HUB)
|
||||
case FRSKY_CURRENT_SOURCE_FAS:
|
||||
putsTelemetryChannelValue(3*FW+6*FW+4, 3*FH, TELEM_CURRENT-1, telemetryData.hub.current, DBLSIZE);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
putsTelemetryChannelValue(4, 5*FH, TELEM_POWER-1, telemetryData.hub.power, LEFT|DBLSIZE);
|
||||
putsTelemetryChannelValue(3*FW+4+4*FW+6*FW+FW, 5*FH, TELEM_CONSUMPTION-1, telemetryData.hub.currentConsumption, DBLSIZE);
|
||||
}
|
||||
else {
|
||||
displayVoltageScreenLine(analog > 0 ? 5*FH : 4*FH, analog ? 2-analog : 0);
|
||||
if (analog == 0) displayVoltageScreenLine(6*FH, 1);
|
||||
}
|
||||
|
||||
#if defined(FRSKY_HUB)
|
||||
// Cells voltage
|
||||
if (telemetryData.hub.cellsCount > 0) {
|
||||
uint8_t y = 1*FH;
|
||||
for (uint8_t k=0; k<telemetryData.hub.cellsCount && k<6; k++) {
|
||||
#if defined(GAUGES)
|
||||
uint8_t attr = (barsThresholds[THLD_CELL] && telemetryData.hub.cellVolts[k] < barsThresholds[THLD_CELL]) ? BLINK|PREC2 : PREC2;
|
||||
#else
|
||||
uint8_t attr = PREC2;
|
||||
#endif
|
||||
lcdDrawNumber(LCD_W, y, TELEMETRY_CELL_VOLTAGE(k), attr, 4);
|
||||
y += 1*FH;
|
||||
}
|
||||
lcdDrawSolidVerticalLine(LCD_W-3*FW-2, 8, 47);
|
||||
}
|
||||
#endif
|
||||
|
||||
displayRssiLine();
|
||||
}
|
||||
|
||||
void displayAfterFlightScreen()
|
||||
{
|
||||
uint8_t line=1*FH+1;
|
||||
if (IS_GPS_AVAILABLE()) {
|
||||
// Latitude
|
||||
lcd_putsLeft(line, STR_LATITUDE);
|
||||
displayGpsCoord(line, telemetryData.hub.gpsLatitudeNS, telemetryData.hub.gpsLatitude_bp, telemetryData.hub.gpsLatitude_ap);
|
||||
// Longitude
|
||||
line+=1*FH+1;
|
||||
lcd_putsLeft(line, STR_LONGITUDE);
|
||||
displayGpsCoord(line, telemetryData.hub.gpsLongitudeEW, telemetryData.hub.gpsLongitude_bp, telemetryData.hub.gpsLongitude_ap);
|
||||
displayGpsTime();
|
||||
line+=1*FH+1;
|
||||
}
|
||||
// Rssi
|
||||
lcd_putsLeft(line, STR_MINRSSI);
|
||||
lcdDrawText(TELEM_2ND_COLUMN, line, STR_TX);
|
||||
lcdDrawNumber(TELEM_2ND_COLUMN+3*FW, line, telemetryData.rssi[1].min, LEFT|LEADING0, 2);
|
||||
lcdDrawText(TELEM_2ND_COLUMN+6*FW, line, STR_RX);
|
||||
lcdDrawNumber(TELEM_2ND_COLUMN+9*FW, line, telemetryData.rssi[0].min, LEFT|LEADING0, 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool displayGaugesTelemetryScreen(FrSkyScreenData & screen)
|
||||
{
|
||||
// Custom Screen with gauges
|
||||
uint8_t barHeight = 5;
|
||||
for (int8_t i=3; i>=0; i--) {
|
||||
FrSkyBarData & bar = screen.bars[i];
|
||||
source_t source = bar.source;
|
||||
#if defined(CPUARM)
|
||||
getvalue_t barMin = bar.barMin;
|
||||
getvalue_t barMax = bar.barMax;
|
||||
if (source <= MIXSRC_LAST_CH) {
|
||||
barMin = calc100toRESX(barMin);
|
||||
barMax = calc100toRESX(barMax);
|
||||
}
|
||||
#else
|
||||
getvalue_t barMin = convertBarTelemValue(source, bar.barMin);
|
||||
getvalue_t barMax = convertBarTelemValue(source, 255-bar.barMax);
|
||||
#endif
|
||||
if (source && barMax > barMin) {
|
||||
uint8_t y = barHeight+6+i*(barHeight+6);
|
||||
#if defined(CPUARM)
|
||||
putsMixerSource(0, y+barHeight-5, source, 0);
|
||||
#else
|
||||
lcdDrawTextAtIndex(0, y+barHeight-5, STR_VTELEMCHNS, source, 0);
|
||||
#endif
|
||||
lcdDrawRect(BAR_LEFT, y, BAR_WIDTH+1, barHeight+2);
|
||||
#if defined(CPUARM)
|
||||
getvalue_t value = getValue(source);
|
||||
#else
|
||||
getvalue_t value = getValue(MIXSRC_FIRST_TELEM+source-1);
|
||||
#endif
|
||||
|
||||
uint8_t thresholdX = 0;
|
||||
|
||||
#if !defined(CPUARM)
|
||||
getvalue_t threshold = 0;
|
||||
if (source <= TELEM_TIMER_MAX)
|
||||
threshold = 0;
|
||||
else if (source <= TELEM_RSSI_RX)
|
||||
threshold = getRssiAlarmValue(source-TELEM_RSSI_TX);
|
||||
else if (source <= TELEM_A2)
|
||||
threshold = g_model.frsky.channels[source-TELEM_A1].alarms_value[0];
|
||||
#if defined(FRSKY_HUB)
|
||||
else {
|
||||
#if defined(GAUGES)
|
||||
threshold = convertBarTelemValue(source, barsThresholds[source-TELEM_ALT]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (threshold) {
|
||||
thresholdX = barCoord(threshold, barMin, barMax);
|
||||
if (thresholdX == 100)
|
||||
thresholdX = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t width = barCoord(value, barMin, barMax);
|
||||
|
||||
#if defined(CPUARM)
|
||||
uint8_t barShade = SOLID;
|
||||
#else
|
||||
// reversed barshade for T1/T2
|
||||
uint8_t barShade = ((threshold > value) ? DOTTED : SOLID);
|
||||
if (source == TELEM_T1 || source == TELEM_T2) {
|
||||
barShade = -barShade;
|
||||
}
|
||||
#endif
|
||||
|
||||
lcdDrawFilledRect(BAR_LEFT+1, y+1, width, barHeight, barShade);
|
||||
|
||||
for (uint8_t j=24; j<99; j+=25) {
|
||||
if (j>thresholdX || j>width) {
|
||||
lcdDrawSolidVerticalLine(j*BAR_WIDTH/100+BAR_LEFT+1, y+1, barHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (thresholdX) {
|
||||
lcdDrawVerticalLine(BAR_LEFT+1+thresholdX, y-2, barHeight+3, DOTTED);
|
||||
lcdDrawSolidHorizontalLine(BAR_LEFT+thresholdX, y-2, 3);
|
||||
}
|
||||
}
|
||||
else {
|
||||
barHeight += 2;
|
||||
}
|
||||
}
|
||||
displayRssiLine();
|
||||
return barHeight < 13;
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
bool displayNumbersTelemetryScreen(FrSkyScreenData & screen)
|
||||
{
|
||||
// Custom Screen with numbers
|
||||
uint8_t fields_count = 0;
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
for (uint8_t j=0; j<NUM_LINE_ITEMS; j++) {
|
||||
source_t field = screen.lines[i].sources[j];
|
||||
if (field > 0) {
|
||||
fields_count++;
|
||||
}
|
||||
if (i==3) {
|
||||
lcdDrawSolidVerticalLine(63, 8, 48);
|
||||
if (!TELEMETRY_STREAMING()) {
|
||||
displayRssiLine();
|
||||
return fields_count;
|
||||
}
|
||||
}
|
||||
if (field) {
|
||||
LcdFlags att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT);
|
||||
coord_t pos[] = {0, 65, 130};
|
||||
if (field >= MIXSRC_FIRST_TIMER && field <= MIXSRC_LAST_TIMER && i!=3) {
|
||||
// there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead
|
||||
drawStringWithIndex(pos[j], 1+FH+2*FH*i, "T", field-MIXSRC_FIRST_TIMER+1, 0);
|
||||
}
|
||||
else if (field >= MIXSRC_FIRST_TELEM && isGPSSensor(1+(field-MIXSRC_FIRST_TELEM)/3) && telemetryItems[(field-MIXSRC_FIRST_TELEM)/3].isAvailable()) {
|
||||
// we don't display GPS name, no space for it
|
||||
}
|
||||
else {
|
||||
putsMixerSource(pos[j], 1+FH+2*FH*i, field, 0);
|
||||
}
|
||||
|
||||
if (field >= MIXSRC_FIRST_TELEM) {
|
||||
TelemetryItem & telemetryItem = telemetryItems[(field-MIXSRC_FIRST_TELEM)/3]; // TODO macro to convert a source to a telemetry index
|
||||
if (!telemetryItem.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
else if (telemetryItem.isOld()) {
|
||||
att |= INVERS|BLINK;
|
||||
}
|
||||
}
|
||||
|
||||
putsChannel(pos[j+1]-2, (i==3 ? 1+FH+2*FH*i:FH+2*FH*i), field, att);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
lcdInvertLastLine();
|
||||
return fields_count;
|
||||
}
|
||||
#else
|
||||
bool displayNumbersTelemetryScreen(FrSkyScreenData & screen)
|
||||
{
|
||||
// Custom Screen with numbers
|
||||
uint8_t fields_count = 0;
|
||||
for (uint8_t i=0; i<4; i++) {
|
||||
for (uint8_t j=0; j<NUM_LINE_ITEMS; j++) {
|
||||
uint8_t field = screen.lines[i].sources[j];
|
||||
if (field > 0) {
|
||||
fields_count++;
|
||||
}
|
||||
if (i==3) {
|
||||
lcdDrawSolidVerticalLine(63, 8, 48);
|
||||
if (TELEMETRY_STREAMING()) {
|
||||
#if defined(FRSKY_HUB)
|
||||
if (field == TELEM_ACC) {
|
||||
lcd_putsLeft(STATUS_BAR_Y, STR_ACCEL);
|
||||
lcdDrawNumber(4*FW, STATUS_BAR_Y, telemetryData.hub.accelX, LEFT|PREC2);
|
||||
lcdDrawNumber(10*FW, STATUS_BAR_Y, telemetryData.hub.accelY, LEFT|PREC2);
|
||||
lcdDrawNumber(16*FW, STATUS_BAR_Y, telemetryData.hub.accelZ, LEFT|PREC2);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if defined(FRSKY_HUB) && defined(GPS)
|
||||
else if (field == TELEM_GPS_TIME) {
|
||||
displayGpsTime();
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
displayRssiLine();
|
||||
return fields_count;
|
||||
}
|
||||
}
|
||||
if (field) {
|
||||
getvalue_t value = getValue(MIXSRC_FIRST_TELEM+field-1);
|
||||
uint8_t att = (i==3 ? NO_UNIT : DBLSIZE|NO_UNIT);
|
||||
coord_t pos[] = {0, 65, 130};
|
||||
putsTelemetryChannelValue(pos[j+1]-2, FH+2*FH*i, field-1, value, att);
|
||||
|
||||
if (field >= TELEM_TIMER1 && field <= TELEM_TIMER_MAX && i!=3) {
|
||||
// there is not enough space on LCD for displaying "Tmr1" or "Tmr2" and still see the - sign, we write "T1" or "T2" instead
|
||||
field = field-TELEM_TIMER1+TELEM_T1;
|
||||
}
|
||||
|
||||
lcdDrawTextAtIndex(pos[j], 1+FH+2*FH*i, STR_VTELEMCHNS, field, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
lcdInvertLastLine();
|
||||
return fields_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CPUARM)
|
||||
bool displayCustomTelemetryScreen(uint8_t index)
|
||||
{
|
||||
FrSkyScreenData & screen = g_model.frsky.screens[index];
|
||||
|
||||
#if defined(GAUGES)
|
||||
if (IS_BARS_SCREEN(s_frsky_view)) {
|
||||
return displayGaugesTelemetryScreen(screen);
|
||||
}
|
||||
#endif
|
||||
|
||||
displayNumbersTelemetryScreen(screen);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool displayCustomTelemetryScreen(uint8_t index)
|
||||
{
|
||||
FrSkyScreenData & screen = g_model.frsky.screens[index];
|
||||
|
||||
#if defined(GAUGES)
|
||||
if (IS_BARS_SCREEN(s_frsky_view)) {
|
||||
return displayGaugesTelemetryScreen(screen);
|
||||
}
|
||||
#endif
|
||||
|
||||
return displayNumbersTelemetryScreen(screen);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool displayTelemetryScreen()
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
if (TELEMETRY_SCREEN_TYPE(s_frsky_view) == TELEMETRY_SCREEN_TYPE_NONE) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
lcdDrawTelemetryTopBar();
|
||||
|
||||
if (s_frsky_view < MAX_TELEMETRY_SCREENS) {
|
||||
return displayCustomTelemetryScreen(s_frsky_view);
|
||||
}
|
||||
|
||||
#if !defined(CPUARM)
|
||||
if (s_frsky_view == TELEMETRY_VOLTAGES_SCREEN) {
|
||||
displayVoltagesScreen();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CPUARM) && defined(FRSKY_HUB)
|
||||
else {
|
||||
displayAfterFlightScreen();
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
enum NavigationDirection {
|
||||
none,
|
||||
up,
|
||||
down
|
||||
};
|
||||
#define decrTelemetryScreen() direction = up
|
||||
#define incrTelemetryScreen() direction = down
|
||||
#else
|
||||
void decrTelemetryScreen()
|
||||
{
|
||||
if (s_frsky_view-- == 0)
|
||||
s_frsky_view = TELEMETRY_VIEW_MAX;
|
||||
}
|
||||
void incrTelemetryScreen()
|
||||
{
|
||||
if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
|
||||
s_frsky_view = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void menuTelemetryFrsky(uint8_t event)
|
||||
{
|
||||
#if defined(CPUARM)
|
||||
enum NavigationDirection direction = none;
|
||||
#endif
|
||||
|
||||
switch (event) {
|
||||
case EVT_KEY_FIRST(KEY_EXIT):
|
||||
killEvents(event);
|
||||
chainMenu(menuMainView);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
decrTelemetryScreen();
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
incrTelemetryScreen();
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_ENTER):
|
||||
telemetryReset();
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(CPUARM)
|
||||
for (int i=0; i<=TELEMETRY_SCREEN_TYPE_MAX; i++) {
|
||||
if (direction == up) {
|
||||
if (s_frsky_view-- == 0)
|
||||
s_frsky_view = TELEMETRY_VIEW_MAX;
|
||||
}
|
||||
else if (direction == down) {
|
||||
if (s_frsky_view++ == TELEMETRY_VIEW_MAX)
|
||||
s_frsky_view = 0;
|
||||
}
|
||||
else {
|
||||
direction = down;
|
||||
}
|
||||
if (displayTelemetryScreen()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
lcdDrawTelemetryTopBar();
|
||||
lcdDrawText(8*FW, 3*FH, "No Telemetry Screens");
|
||||
displayRssiLine();
|
||||
#else
|
||||
if (!displayTelemetryScreen()) {
|
||||
putEvent(event == EVT_KEY_FIRST(KEY_UP) ? event : EVT_KEY_FIRST(KEY_DOWN));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* 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 TEXT_FILENAME_MAXLEN 40
|
||||
#define TEXT_FILE_MAXSIZE 2048
|
||||
|
||||
char s_text_file[TEXT_FILENAME_MAXLEN];
|
||||
char s_text_screen[LCD_LINES-1][LCD_COLS+1];
|
||||
|
||||
void readTextFile(int & lines_count)
|
||||
{
|
||||
FIL file;
|
||||
int result;
|
||||
char c;
|
||||
unsigned int sz;
|
||||
int line_length = 0;
|
||||
int escape = 0;
|
||||
char escape_chars[2];
|
||||
int current_line = 0;
|
||||
|
||||
memset(s_text_screen, 0, sizeof(s_text_screen));
|
||||
|
||||
result = f_open(&file, s_text_file, FA_OPEN_EXISTING | FA_READ);
|
||||
if (result == FR_OK) {
|
||||
for (int i=0; i<TEXT_FILE_MAXSIZE && f_read(&file, &c, 1, &sz)==FR_OK && sz==1 && (lines_count==0 || current_line-menuVerticalOffset<LCD_LINES-1); i++) {
|
||||
if (c == '\n') {
|
||||
++current_line;
|
||||
line_length = 0;
|
||||
escape = 0;
|
||||
}
|
||||
else if (c!='\r' && current_line>=menuVerticalOffset && current_line-menuVerticalOffset<LCD_LINES-1 && line_length<LCD_COLS) {
|
||||
if (c=='\\' && escape==0) {
|
||||
escape = 1;
|
||||
continue;
|
||||
}
|
||||
else if (c!='\\' && escape>0 && escape<3) {
|
||||
escape_chars[escape-1] = c;
|
||||
if (escape == 2 && !strncmp(escape_chars, "up", 2)) {
|
||||
c = '\300';
|
||||
escape = 0;
|
||||
}
|
||||
else if (escape == 2 && !strncmp(escape_chars, "dn", 2)) {
|
||||
c = '\301';
|
||||
escape = 0;
|
||||
}
|
||||
else {
|
||||
escape++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (c=='~') {
|
||||
c = 'z'+1;
|
||||
}
|
||||
else if (c=='\t') {
|
||||
c = 0x1D; //tab
|
||||
}
|
||||
escape = 0;
|
||||
s_text_screen[current_line-menuVerticalOffset][line_length++] = c;
|
||||
}
|
||||
}
|
||||
if (c != '\n') {
|
||||
current_line += 1;
|
||||
}
|
||||
f_close(&file);
|
||||
}
|
||||
|
||||
if (lines_count == 0) {
|
||||
lines_count = current_line;
|
||||
}
|
||||
}
|
||||
|
||||
void menuTextView(uint8_t event)
|
||||
{
|
||||
static int lines_count;
|
||||
|
||||
switch (event) {
|
||||
case EVT_ENTRY:
|
||||
menuVerticalOffset = 0;
|
||||
lines_count = 0;
|
||||
readTextFile(lines_count);
|
||||
break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_UP):
|
||||
if (menuVerticalOffset == 0)
|
||||
break;
|
||||
else
|
||||
menuVerticalOffset--;
|
||||
// no break;
|
||||
|
||||
case EVT_KEY_FIRST(KEY_DOWN):
|
||||
// if (event == EVT_KEY_BREAK(KEY_DOWN)) {
|
||||
if (menuVerticalOffset+LCD_LINES-1 >= lines_count)
|
||||
break;
|
||||
else
|
||||
++menuVerticalOffset;
|
||||
// }
|
||||
readTextFile(lines_count);
|
||||
break;
|
||||
|
||||
case EVT_KEY_BREAK(KEY_EXIT):
|
||||
popMenu();
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i=0; i<LCD_LINES-1; i++) {
|
||||
lcdDrawText(0, i*FH+FH+1, s_text_screen[i], FIXEDWIDTH);
|
||||
}
|
||||
|
||||
char *title = s_text_file;
|
||||
#if defined(SIMU)
|
||||
if (!strncmp(title, "./", 2)) title += 2;
|
||||
#else
|
||||
// TODO?
|
||||
#endif
|
||||
lcdDrawText(LCD_W/2-strlen(title)*FW/2, 0, title);
|
||||
lcdInvertLine(0);
|
||||
|
||||
if (lines_count > LCD_LINES-1) {
|
||||
drawVerticalScrollbar(LCD_W-1, FH, LCD_H-FH, menuVerticalOffset, lines_count, LCD_LINES-1);
|
||||
}
|
||||
}
|
||||
|
||||
void pushMenuTextView(const char *filename)
|
||||
{
|
||||
if (strlen(filename) < TEXT_FILENAME_MAXLEN) {
|
||||
strcpy(s_text_file, filename);
|
||||
pushMenu(menuTextView);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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 drawStick(coord_t centrex, int16_t xval, int16_t yval)
|
||||
{
|
||||
#define BOX_CENTERY (LCD_H-9-BOX_WIDTH/2)
|
||||
#define MARKER_WIDTH 5
|
||||
lcdDrawSquare(centrex-BOX_WIDTH/2, BOX_CENTERY-BOX_WIDTH/2, BOX_WIDTH);
|
||||
lcdDrawSolidVerticalLine(centrex, BOX_CENTERY-1, 3);
|
||||
lcdDrawSolidHorizontalLine(centrex-1, BOX_CENTERY, 3);
|
||||
lcdDrawSquare(centrex + (xval/((2*RESX)/(BOX_WIDTH-MARKER_WIDTH))) - MARKER_WIDTH/2, BOX_CENTERY - (yval/((2*RESX)/(BOX_WIDTH-MARKER_WIDTH))) - MARKER_WIDTH/2, MARKER_WIDTH, ROUND);
|
||||
#undef BOX_CENTERY
|
||||
#undef MARKER_WIDTH
|
||||
}
|
||||
|
||||
void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr)
|
||||
{
|
||||
#if defined(GRAPHICS)
|
||||
if (value)
|
||||
lcdDrawChar(x+1, y, '#');
|
||||
if (attr)
|
||||
lcdDrawFilledRect(x, y, 7, 7);
|
||||
else
|
||||
lcdDrawSquare(x, y, 7);
|
||||
#else
|
||||
/* ON / OFF version */
|
||||
lcdDrawTextAtIndex(x, y, STR_OFFON, value, attr ? INVERS:0) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
void drawScreenIndex(uint8_t index, uint8_t count, uint8_t attr)
|
||||
{
|
||||
lcdDrawNumber(LCD_W, 0, count, attr);
|
||||
coord_t x = 1+LCD_W-FW*(count>9 ? 3 : 2);
|
||||
lcdDrawChar(x, 0, '/', attr);
|
||||
lcdDrawNumber(x, 0, index+1, attr);
|
||||
}
|
||||
|
||||
#if !defined(CPUM64)
|
||||
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible)
|
||||
{
|
||||
lcdDrawVerticalLine(x, y, h, DOTTED);
|
||||
coord_t yofs = (h * offset) / count;
|
||||
coord_t yhgt = (h * visible) / count;
|
||||
if (yhgt + yofs > h)
|
||||
yhgt = h - yofs;
|
||||
lcdDrawVerticalLine(x, y + yofs, yhgt, SOLID, FORCE);
|
||||
}
|
||||
#endif
|
||||
|
||||
void title(const pm_char * s)
|
||||
{
|
||||
lcdDrawText(0, 0, s, INVERS);
|
||||
}
|
||||
|
||||
select_menu_value_t selectMenuItem(coord_t x, coord_t y, const pm_char *label, const pm_char *values, select_menu_value_t value, select_menu_value_t min, select_menu_value_t max, LcdFlags attr, uint8_t event)
|
||||
{
|
||||
lcd_putsColumnLeft(x, y, label);
|
||||
if (values) lcdDrawTextAtIndex(x, y, values, value-min, attr);
|
||||
if (attr) value = checkIncDec(event, value, min, max, (menuVerticalPositions[0] == 0) ? EE_MODEL : EE_GENERAL);
|
||||
return value;
|
||||
}
|
||||
|
||||
uint8_t editCheckBox(uint8_t value, coord_t x, coord_t y, const pm_char *label, LcdFlags attr, uint8_t event )
|
||||
{
|
||||
#if defined(GRAPHICS)
|
||||
drawCheckBox(x, y, value, attr);
|
||||
return selectMenuItem(x, y, label, NULL, value, 0, 1, attr, event);
|
||||
#else
|
||||
return selectMenuItem(x, y, label, STR_OFFON, value, 0, 1, attr, event);
|
||||
#endif
|
||||
}
|
||||
|
||||
int8_t switchMenuItem(coord_t x, coord_t y, int8_t value, LcdFlags attr, uint8_t event)
|
||||
{
|
||||
lcd_putsColumnLeft(x, y, STR_SWITCH);
|
||||
putsSwitches(x, y, value, attr);
|
||||
if (attr) CHECK_INCDEC_MODELSWITCH(event, value, SWSRC_FIRST_IN_MIXES, SWSRC_LAST_IN_MIXES, isSwitchAvailableInMixes);
|
||||
return value;
|
||||
}
|
||||
|
||||
#if !defined(CPUM64)
|
||||
void drawSlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr)
|
||||
{
|
||||
lcdDrawChar(x+(value*4*FW)/max, y, '$');
|
||||
lcdDrawSolidHorizontalLine(x, y+3, 5*FW-1, FORCE);
|
||||
if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) lcdDrawFilledRect(x, y, 5*FW-1, FH-1);
|
||||
}
|
||||
#elif defined(GRAPHICS)
|
||||
void display5posSlider(coord_t x, coord_t y, uint8_t value, uint8_t attr)
|
||||
{
|
||||
lcdDrawChar(x+2*FW+(value*FW), y, '$');
|
||||
lcdDrawSolidHorizontalLine(x, y+3, 5*FW-1, SOLID);
|
||||
if (attr && (!(attr & BLINK) || !BLINK_ON_PHASE)) lcdDrawFilledRect(x, y, 5*FW-1, FH-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(GVARS) && defined(CPUARM)
|
||||
bool noZero(int val)
|
||||
{
|
||||
return val != 0;
|
||||
}
|
||||
|
||||
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, uint8_t event)
|
||||
{
|
||||
uint16_t delta = GV_GET_GV1_VALUE(max);
|
||||
bool invers = (attr & INVERS);
|
||||
|
||||
// TRACE("editGVarFieldValue(val=%d min=%d max=%d)", value, min, max);
|
||||
|
||||
if (invers && event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
s_editMode = !s_editMode;
|
||||
if (attr & PREC1)
|
||||
value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode)*10 : delta);
|
||||
else
|
||||
value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
|
||||
if (GV_IS_GV_VALUE(value, min, max)) {
|
||||
if (attr & LEFT)
|
||||
attr -= LEFT; /* because of ZCHAR */
|
||||
else
|
||||
x -= 2*FW+FWNUM;
|
||||
|
||||
attr &= ~PREC1;
|
||||
|
||||
int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta);
|
||||
if (idx >= 0) ++idx; // transform form idx=0=GV1 to idx=1=GV1 in order to handle double keys invert
|
||||
if (invers) {
|
||||
CHECK_INCDEC_MODELVAR_CHECK(event, idx, -MAX_GVARS, MAX_GVARS, noZero);
|
||||
if (idx == 0) idx = 1; // handle reset to zero, map to GV1
|
||||
}
|
||||
if (idx < 0) {
|
||||
value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta);
|
||||
idx = -idx;
|
||||
lcdDrawChar(x-6, y, '-', attr);
|
||||
}
|
||||
else {
|
||||
value = (int16_t) GV_CALC_VALUE_IDX_POS(idx-1, delta);
|
||||
}
|
||||
drawStringWithIndex(x, y, STR_GV, idx, attr);
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(x, y, value, attr);
|
||||
if (invers) value = checkIncDec(event, value, min, max, EE_MODEL | editflags);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
#elif defined(GVARS)
|
||||
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event)
|
||||
{
|
||||
uint16_t delta = GV_GET_GV1_VALUE(max);
|
||||
bool invers = (attr & INVERS);
|
||||
|
||||
// TRACE("editGVarFieldValue(val=%d min=%d max=%d)", value, min, max);
|
||||
|
||||
if (invers && event == EVT_KEY_LONG(KEY_ENTER)) {
|
||||
s_editMode = !s_editMode;
|
||||
value = (GV_IS_GV_VALUE(value, min, max) ? GET_GVAR(value, min, max, mixerCurrentFlightMode) : delta);
|
||||
storageDirty(EE_MODEL);
|
||||
}
|
||||
if (GV_IS_GV_VALUE(value, min, max)) {
|
||||
if (attr & LEFT)
|
||||
attr -= LEFT; /* because of ZCHAR */
|
||||
else
|
||||
x -= 2*FW+FWNUM;
|
||||
|
||||
int8_t idx = (int16_t) GV_INDEX_CALC_DELTA(value, delta);
|
||||
if (invers) {
|
||||
idx = checkIncDec(event, idx, -MAX_GVARS, MAX_GVARS-1, EE_MODEL|NO_DBLKEYS); // disable double keys
|
||||
}
|
||||
if (idx < 0) {
|
||||
value = (int16_t) GV_CALC_VALUE_IDX_NEG(idx, delta);
|
||||
idx = -idx;
|
||||
lcdDrawChar(x-6, y, '-', attr);
|
||||
}
|
||||
else {
|
||||
value = (int16_t) GV_CALC_VALUE_IDX_POS(idx, delta);
|
||||
idx++;
|
||||
}
|
||||
drawStringWithIndex(x, y, STR_GV, idx, attr);
|
||||
}
|
||||
else {
|
||||
lcdDrawNumber(x, y, value, attr);
|
||||
if (invers) value = checkIncDec(event, value, min, max, EE_MODEL);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
#else
|
||||
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t event)
|
||||
{
|
||||
lcdDrawNumber(x, y, value, attr);
|
||||
if (attr&INVERS) value = checkIncDec(event, value, min, max, EE_MODEL);
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD)
|
||||
char statusLineMsg[STATUS_LINE_LENGTH];
|
||||
tmr10ms_t statusLineTime = 0;
|
||||
uint8_t statusLineHeight = 0;
|
||||
|
||||
void showStatusLine()
|
||||
{
|
||||
statusLineTime = get_tmr10ms();
|
||||
}
|
||||
|
||||
#define STATUS_LINE_DELAY (3 * 100) /* 3s */
|
||||
void drawStatusLine()
|
||||
{
|
||||
if (statusLineTime) {
|
||||
if ((tmr10ms_t)(get_tmr10ms() - statusLineTime) <= (tmr10ms_t)STATUS_LINE_DELAY) {
|
||||
if (statusLineHeight < FH) statusLineHeight++;
|
||||
}
|
||||
else if (statusLineHeight) {
|
||||
statusLineHeight--;
|
||||
}
|
||||
else {
|
||||
statusLineTime = 0;
|
||||
}
|
||||
|
||||
lcdDrawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID, ERASE);
|
||||
lcdDrawText(5, LCD_H+1-statusLineHeight, statusLineMsg, BSS);
|
||||
lcdDrawFilledRect(0, LCD_H-statusLineHeight, LCD_W, FH, SOLID);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user