1
0
Fork 0
mirror of https://github.com/opentx/opentx.git synced 2025-07-20 14:55:13 +03:00
opentx/src/menus.cpp
mihlit@mihlit.cz acd523e699 make code compatible with up-to-date build environment
These changes make it possible to compile open9x with old (avr-gcc 4.3.3, 
avr-libc 1.6.7) and up-to-date (avr-gcc 4.6.2, avr-libc 1.8.0) build
environments. See Issue 1 for more details.
2012-02-02 11:23:38 +00:00

396 lines
9.9 KiB
C++

/*
* Authors (alphabetical order)
* - Bertrand Songis <bsongis@gmail.com>
* - Bryan J. Rentoul (Gruvin) <gruvin@gmail.com>
*
* gruvin9x is based on code named er9x by
* Author - Erez Raviv <erezraviv@gmail.com>, which is in turn
* was based on the original (and ongoing) project by Thomas Husterer,
* th9x -- http://code.google.com/p/th9x/
*
* 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 "open9x.h"
#include "templates.h"
#include "menus.h"
int16_t calibratedStick[NUM_STICKS+NUM_POTS];
int16_t ex_chans[NUM_CHNOUT]; // Outputs + intermidiates
uint8_t s_pgOfs;
int8_t s_editMode;
uint8_t s_noHi;
uint8_t s_noScroll;
int16_t g_chans512[NUM_CHNOUT]; // TODO not here!
void menu_lcd_onoff( uint8_t x,uint8_t y, uint8_t value, uint8_t mode )
{
lcd_putsnAtt(x, y, STR_OFFON+LEN_OFFON*value, LEN_OFFON, mode ? INVERS:0) ;
}
void DisplayScreenIndex(uint8_t index, uint8_t count, uint8_t attr)
{
lcd_outdezAtt(128,0,count,attr);
lcd_putcAtt(1+128-FW*(count>9 ? 3 : 2),0,'/',attr);
lcd_outdezAtt(1+128-FW*(count>9 ? 3 : 2),0,index+1,attr);
}
#if defined(NAVIGATION_POT1) || defined(NAVIGATION_RE1)
int16_t p1valdiff;
#endif
int8_t checkIncDec_Ret;
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;
uint8_t kpl=KEY_RIGHT, kmi=KEY_LEFT, kother = -1;
if(event & _MSK_KEY_DBL){
uint8_t hlp=kpl;
kpl=kmi;
kmi=hlp;
event=EVT_KEY_FIRST(EVT_KEY_MASK & event);
}
if(event==EVT_KEY_FIRST(kpl) || event== EVT_KEY_REPT(kpl) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_UP) || event== EVT_KEY_REPT(KEY_UP))) ) {
newval++;
AUDIO_KEYPAD_UP();
kother=kmi;
}
else if(event==EVT_KEY_FIRST(kmi) || event== EVT_KEY_REPT(kmi) || (s_editMode>0 && (event==EVT_KEY_FIRST(KEY_DOWN) || event== EVT_KEY_REPT(KEY_DOWN))) ) {
newval--;
AUDIO_KEYPAD_DOWN();
kother=kpl;
}
if((kother != (uint8_t)-1) && keyState((EnumKeys)kother)){
newval=-val;
killEvents(kmi);
killEvents(kpl);
}
if(i_min==0 && i_max==1 && event==EVT_KEY_FIRST(KEY_MENU)) {
s_editMode = 0;
newval=!val;
killEvents(event);
}
#if defined(NAVIGATION_POT1) || defined (NAVIGATION_RE1)
//change values based on P1
newval -= p1valdiff;
#endif
if(newval > i_max)
{
newval = i_max;
killEvents(event);
AUDIO_WARNING2();
}
if(newval < i_min)
{
newval = i_min;
killEvents(event);
AUDIO_WARNING2();
}
if(newval != val){
if(newval==0) {
pauseEvents(event); // delay before auto-repeat continues
if (newval>val) // TODO check if without AUDIO it's optimized!
AUDIO_KEYPAD_UP();
else
AUDIO_KEYPAD_DOWN();
}
eeDirty(i_flags & (EE_GENERAL|EE_MODEL));
checkIncDec_Ret = (newval > val ? 1 : -1);
}
else {
checkIncDec_Ret = 0;
}
return newval;
}
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 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);
}
bool check_simple(uint8_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, uint8_t maxrow)
{
return check(event, curr, menuTab, menuTabSize, 0, 0, maxrow);
}
bool check_submenu_simple(uint8_t event, uint8_t maxrow)
{
return check_simple(event, 0, 0, 0, maxrow);
}
#define SCROLL_TH 64
#define SCROLL_POT1_TH 32
#define MAXCOL(row) (horTab ? pgm_read_byte(horTab+min(row, horTabMax)) : (const uint8_t)0)
#define INC(val,max) if(val<max) {val++;} else {val=0;}
#define DEC(val,max) if(val>0 ) {val--;} else {val=max;}
bool check(uint8_t event, uint8_t curr, const MenuFuncP *menuTab, uint8_t menuTabSize, const pm_uint8_t *horTab, uint8_t horTabMax, uint8_t maxrow)
{
#ifdef NAVIGATION_RE1
// check rotary encoder 1 if changed -> cursor down/up
static int16_t re1valprev;
p1valdiff = 0;
int8_t scrollRE = re1valprev - g_rotenc[0];
if (scrollRE) {
re1valprev = g_rotenc[0];
if (s_editMode > 0) {
p1valdiff = scrollRE;
scrollRE = 0;
}
}
if (event == EVT_KEY_FIRST(BTN_RE1)) {
scrollRE = 0;
if (s_editMode++ > 0) s_editMode = 0;
if (s_editMode > 0 && m_posVert == 0) s_editMode = -1;
}
#else
#define scrollRE 0
#endif
#ifdef NAVIGATION_POT1
// check pot 1 - if changed -> scroll values
static int16_t p1valprev;
p1valdiff = (p1valprev-calibratedStick[6]) / SCROLL_POT1_TH;
if (p1valdiff) p1valprev = calibratedStick[6];
#endif
#ifdef NAVIGATION_POT2
// check pot 2 - if changed -> scroll menu
static int16_t p2valprev;
int8_t scrollLR = (p2valprev-calibratedStick[4]) / SCROLL_TH;
if (scrollLR) p2valprev = calibratedStick[4];
#else
#define scrollLR 0
#endif
#ifdef 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(scrollLR || scrollUD || p1valdiff) g_LightOffCounter = g_eeGeneral.lightAutoOff*500; // on keypress turn the light on 5*100
if (menuTab) {
uint8_t attr = 0;
if (m_posVert==0 && !s_noScroll) {
attr = INVERS;
int8_t cc = curr;
if (scrollLR || (scrollRE && s_editMode < 0)) {
cc = limit((int8_t)0, (int8_t)(curr - scrollLR - scrollRE), (int8_t)(menuTabSize-1));
}
switch(event) {
case EVT_KEY_FIRST(KEY_LEFT):
if (curr > 0)
cc = curr - 1;
else
cc = menuTabSize-1;
break;
case EVT_KEY_FIRST(KEY_RIGHT):
if (curr < (menuTabSize-1))
cc = curr + 1;
else
cc = 0;
break;
}
if (cc != curr) {
chainMenu((MenuFuncP)pgm_read_adr(&menuTab[cc]));
return false;
}
}
s_noScroll = 0;
DisplayScreenIndex(curr, menuTabSize, attr);
}
theFile.DisplayProgressBar(menuTab ? lcd_lastPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
uint8_t maxcol = MAXCOL(m_posVert);
if (s_editMode<=0) {
if (scrollUD) {
m_posVert = limit((int8_t)0, (int8_t)(m_posVert - scrollUD), (int8_t)maxrow);
m_posHorz = min(m_posHorz, MAXCOL(m_posVert));
BLINK_SYNC;
}
if (scrollLR && m_posVert>0) {
m_posHorz = limit((int8_t)0, (int8_t)(m_posHorz - scrollLR), (int8_t)maxcol);
BLINK_SYNC;
}
#ifdef NAVIGATION_RE1
while (scrollRE) {
if (scrollRE > 0) {
--scrollRE;
if (++m_posHorz > MAXCOL(m_posVert)) {
m_posHorz = 0;
if (++m_posVert > maxrow) {
m_posVert = maxrow;
m_posHorz = MAXCOL(m_posVert);
scrollRE = 0;
}
}
}
else {
++scrollRE;
if (m_posHorz-- == 0) {
if (m_posVert-- == 0) {
m_posVert = 0;
m_posHorz = 0;
scrollRE = 0;
}
else {
m_posHorz = MAXCOL(m_posVert);
}
}
}
}
#endif
}
switch(event)
{
case EVT_ENTRY:
minit();
s_editMode = -1;
break;
case EVT_KEY_FIRST(KEY_MENU):
if (maxcol > 0)
s_editMode = (s_editMode<=0);
break;
case EVT_KEY_LONG(KEY_EXIT):
s_editMode = 0;
popMenu();
break;
case EVT_KEY_BREAK(KEY_EXIT):
if(s_editMode>0) {
s_editMode = 0;
break;
}
if(m_posVert==0 || !menuTab) {
popMenu(); //beeps itself
}
else {
AUDIO_MENUS();
minit();
BLINK_SYNC;
}
break;
case EVT_KEY_REPT(KEY_RIGHT): //inc
if(m_posHorz==maxcol) break;
case EVT_KEY_FIRST(KEY_RIGHT)://inc
if(!horTab || s_editMode>0)break;
INC(m_posHorz,maxcol);
BLINK_SYNC;
break;
case EVT_KEY_REPT(KEY_LEFT): //dec
if(m_posHorz==0) break;
case EVT_KEY_FIRST(KEY_LEFT)://dec
if(!horTab || s_editMode>0)break;
DEC(m_posHorz,maxcol);
BLINK_SYNC;
break;
case EVT_KEY_REPT(KEY_DOWN): //inc
if(m_posVert==maxrow) break;
case EVT_KEY_FIRST(KEY_DOWN): //inc
if(s_editMode>0)break;
do {
INC(m_posVert,maxrow);
} while(MAXCOL(m_posVert) == (uint8_t)-1);
m_posHorz = min(m_posHorz, MAXCOL(m_posVert));
BLINK_SYNC;
break;
case EVT_KEY_REPT(KEY_UP): //dec
if(m_posVert==0) break;
case EVT_KEY_FIRST(KEY_UP): //dec
if(s_editMode>0)break;
do {
DEC(m_posVert,maxrow);
} while(MAXCOL(m_posVert) == (uint8_t)-1);
m_posHorz = min(m_posHorz, MAXCOL(m_posVert));
BLINK_SYNC;
break;
}
uint8_t max = menuTab ? 7 : 6;
if(m_posVert<1) s_pgOfs=0;
else if(m_posVert-s_pgOfs>max) s_pgOfs = m_posVert-max;
else if(m_posVert-s_pgOfs<1) s_pgOfs = m_posVert-1;
return true;
}
MenuFuncP g_menuStack[5];
uint8_t g_menuPos[4];
uint8_t g_menuStackPtr = 0;
uint8_t m_posVert;
uint8_t m_posHorz;
void popMenu()
{
if (g_menuStackPtr>0) {
g_menuStackPtr = g_menuStackPtr-1;
AUDIO_KEYPAD_UP();
m_posHorz = 0;
m_posVert = g_menuPos[g_menuStackPtr];
(*g_menuStack[g_menuStackPtr])(EVT_ENTRY_UP);
}
else {
alert(STR_MENUSERROR);
}
}
void chainMenu(MenuFuncP newMenu)
{
g_menuStack[g_menuStackPtr] = newMenu;
(*newMenu)(EVT_ENTRY);
AUDIO_MENUS();
}
void pushMenu(MenuFuncP newMenu)
{
g_menuPos[g_menuStackPtr] = m_posVert;
g_menuStackPtr++;
if(g_menuStackPtr >= DIM(g_menuStack))
{
g_menuStackPtr--;
alert(STR_MENUSERROR);
return;
}
AUDIO_MENUS();
g_menuStack[g_menuStackPtr] = newMenu;
(*newMenu)(EVT_ENTRY);
}