Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 1197 → Rev 1198

/NGVideo5_8/tags/v1.21/menue.c
0,0 → 1,1795
 
/****************************************************************/
/* */
/* NG-Video 5,8GHz */
/* */
/* Copyright (C) 2011 - gebad */
/* */
/* This code is distributed under the GNU Public License */
/* which can be found at http://www.gnu.org/licenses/gpl.txt */
/* */
/****************************************************************/
 
#include <util/delay.h>
 
#include "config.h"
#include "ngvideo.h"
#include "keys.h"
#include "menue.h"
#include "servo.h"
#include "messages.c"
 
typedef uint8_t scr_menu_t[SCROLL_MAIN_MAX + 3]; // einmal, da Index mit 0 beginnt plus Vergrößerung für 2 zusätzlich eingeblendete Punkte
uint8_t m_pkt; // um bei Rücksprung auf ursprünglichen Arrayeintrag(Menüpunkt), Scroll_Menu zeigen
uint8_t servo_nr; // zwischen Servo 1 und 2 wird nur mit global servo_nr unterschieden
uint8_t chrxs; // zum Laden lcdSpecialChrLs oder lcdSpecialChrRs
 
// Menügliederung im Flash belassen
const char cmdStr0[] PROGMEM = "0";
const char cmdStr01[] PROGMEM = "01";
const char cmdStr02[] PROGMEM = "02";
const char cmdStr03[] PROGMEM = "03";
const char cmdStr031[] PROGMEM = "031";
const char cmdStr032[] PROGMEM = "032";
const char cmdStr033[] PROGMEM = "033";
const char cmdStr04[] PROGMEM = "04";
const char cmdStr05[] PROGMEM = "05";
const char cmdStr051[] PROGMEM = "051";
const char cmdStr052[] PROGMEM = "052"; // zwischen Servo 1 und 2 wird danach
const char cmdStr0521[] PROGMEM = "0521"; // mit global servo_nr unterschieden
const char cmdStr0522[] PROGMEM = "0522";
const char cmdStr0523[] PROGMEM = "0523";
const char cmdStr0524[] PROGMEM = "0524";
const char cmdStr053[] PROGMEM = "053";
const char cmdStr0531[] PROGMEM = "0531";
const char cmdStr0532[] PROGMEM = "0532";
const char cmdStr0533[] PROGMEM = "0533";
const char cmdStr0534[] PROGMEM = "0534";
const char cmdStr06[] PROGMEM = "06";
const char cmdStr061[] PROGMEM = "061";
const char cmdStr062[] PROGMEM = "062";
const char cmdStr0621[] PROGMEM = "0621";
const char cmdStr0622[] PROGMEM = "0622";
const char cmdStr0623[] PROGMEM = "0623";
const char cmdStr0624[] PROGMEM = "0624";
const char cmdStr0625[] PROGMEM = "0625";
const char cmdStr063[] PROGMEM = "063";
const char cmdStr064[] PROGMEM = "064";
const char cmdStr07[] PROGMEM = "07";
const char cmdStr071[] PROGMEM = "071";
const char cmdStr072[] PROGMEM = "072";
const char cmdStr08[] PROGMEM = "08";
const char cmdStr081[] PROGMEM = "081";
const char cmdStr082[] PROGMEM = "082";
const char cmdStr083[] PROGMEM = "083";
const char cmdStr0831[] PROGMEM = "0831";
const char cmdStr0832[] PROGMEM = "0832";
const char cmdStr0833[] PROGMEM = "0833";
const char cmdStr0834[] PROGMEM = "0834";
const char cmdStr0835[] PROGMEM = "0835";
const char cmdStr09[] PROGMEM = "09";
const char cmdStr0d[] PROGMEM = "0:"; // wird nur bei Tracking RSSI oder GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
const char cmdStr0e[] PROGMEM = "0;"; // wird nur bei Tracking GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
const char cmdStr0e1[] PROGMEM = "0;1"; // nach '9' (0x39) folgt ':' (0x3a) ';' (0x3b)
const char cmdStr0e2[] PROGMEM = "0;2";
const char cmdStr0e3[] PROGMEM = "0;3";
const char cmdStr0e4[] PROGMEM = "0;4";
const char cmdStr0e5[] PROGMEM = "0;5";
 
command_table_t command_table[] PROGMEM = // Befehls-Tabelle
{
{cmdStr0, Menu_Main},
{cmdStr01, Menu_AV_Source},
{cmdStr02, Menu_RX_Channel},
{cmdStr03, Menu_RSSI_Calibr},
{cmdStr031, Menu_RSSI_min},
{cmdStr032, Menu_RSSI_min_all},
{cmdStr033, Menu_RSSI_max},
{cmdStr04, Menu_Language},
{cmdStr05, Menu_Servo_Calibr},
{cmdStr051, Menu_Servo_Steps},
{cmdStr052, Menu_Servo1}, // zwischen Servo 1 und 2 wird danach
{cmdStr0521, Menu_Servo1_rev}, // mit global servo_nr unterschieden
{cmdStr0522, Menu_Servo1_left},
{cmdStr0523, Menu_Servo1_right},
{cmdStr0524, Menu_Servo1_middle},
{cmdStr053, Menu_Servo2},
{cmdStr0531, Menu_Servo2_rev},
{cmdStr0532, Menu_Servo2_left},
{cmdStr0533, Menu_Servo2_right},
{cmdStr0534, Menu_Servo2_middle},
{cmdStr06, Menu_Servo_Test},
{cmdStr061, Menu_Test_PulseWidth},
{cmdStr062, Menu_Test_Continuous},
{cmdStr0621, Menu_Test_Start},
{cmdStr0622, Menu_Test_SingleStep},
{cmdStr0623, Menu_Test_Repeat},
{cmdStr0624, Menu_Test_Pause},
{cmdStr0625, Menu_Test_Pause_Step},
{cmdStr063, Menu_Test_ServoNr},
{cmdStr064, Menu_Test_Frame},
{cmdStr07, Menu_lcd},
{cmdStr071, Menu_lcd_Contrast},
{cmdStr072, Menu_lcd_Backgr_Light},
{cmdStr08, Menu_Battery},
{cmdStr081, Menu_Low_U_Setup},
{cmdStr082, Menu_U_Offset},
{cmdStr083, Menu_MK_Battery},
{cmdStr0831, Menu_MK_BatteryNr},
{cmdStr0832, Menu_MK_BatteryCapacity},
{cmdStr0833, Menu_MK_I_Offset},
{cmdStr0834, Menu_MK_I_Faktor},
{cmdStr0835, Menu_MK_W_Faktor},
{cmdStr09, Menu_Tracking_Ant},
{cmdStr0d, Menu_Tracking_Option}, // wird nur bei Tracking RSSI oder GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
{cmdStr0e, Menu_GPS_Display}, // wird nur bei Tracking GPS eingeblendet - SCROLL_MAIN_MAX wird geändert
{cmdStr0e1, Menu_GPS_Display_FLAG}, // nach '9' (0x39) folgt ':' (0x3a)
{cmdStr0e2, Menu_GPS_Display_FLAG},
{cmdStr0e3, Menu_GPS_Display_FLAG},
{cmdStr0e4, Menu_GPS_Display_FLAG},
{cmdStr0e5, Menu_GPS_Displ_RX_Time}
};
 
 
typedef void (*Displ_Fnct_t)( uint32_t );
uint32_t Change_Value(uint32_t val, uint32_t min_val, uint32_t max_val, uint8_t pos, Displ_Fnct_t Displ_Fnct, uint8_t vrepeat);
 
 
/**************************************************************/
/* */
/* Steuerung der Menüs */
/* */
/**************************************************************/
 
/************************************************************************************/
/* sucht nach übergebenen String in der Kommandotabelle und springt zum daneben */
/* stehenden Menü-Programm */
/* Parameter: */
/* char *pmenu :zu suchender String in Kommandotabelle */
/* */
/************************************************************************************/
void Jump_Menu(char *pmenu)
{ uint8_t i;
void (*func)(void);
 
if (pmenu[0] != '\0'){
for (i=0; i < sizeof(command_table) / sizeof(command_table_t); i++) {
// Ist das der gesuchte String?
if (!(strcmp_P(pmenu, (char*)pgm_read_word(&(command_table[i].menu_nr))))) {
func = (void(*)(void))pgm_read_word(&(command_table[i].fp));
func();
break;
}
}
}
}
 
/************************************************************************************/
/* */
/* Abfrage Short- oder Long-Enter */
/* verbleibt in Abfrage bis Enter betätigt; Rückgabe => Short-Enter True/False */
/* */
/************************************************************************************/
void Long_Enter(void)
{
Tasks_unvisible();
// falls Akku leer ==> Menü verlassen und Anzeige __ACCU_LOW
U_Messen_cmp(DISABLE_BTIMER);
if ((Get_Key_Long( 1<<SW_ENTER )) || (bat_low == 0)) pmenu[0] ='\0'; // direkt in das Hauptprogramm
}
 
uint8_t Short_Enter(void)
{ uint8_t ret;
 
// bis Short- oder Long-Enter, auch Akku leer
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0') && !exit_while) {
Long_Enter();
}
lcdClear();
if (pmenu[0] == '\0') Displ_Main_Disp(); else Beep(BEEPENTER); // bei ShortEnter Beep
ret = (pmenu[0] != '\0') && !exit_while;
exit_while = 0;
return(ret); // ShortEnter bringt 1 zurück
}
 
/************************************************************************************/
/* */
/* Unterprogramm vom Scroll_Menu(...) stellt Menüpunkte dar */
/* Parameter: */
/* scr_menu_t scr_menu : Array mit Strings der Menüanzeige */
/* uint8_t scr_idx : ausgewählter Menüpunkt */
/* uint8_t scroll_max: scrollen bis Wert */
/* */
/************************************************************************************/
void Displ_Scroll_Menu(scr_menu_t scr_menu, uint8_t scr_idx, uint8_t scroll_max)
{
uint8_t i;
const uint8_t p = 2; // LCD Beginn x-Position, 2 Zeichen rechts eingerückt
if (scr_idx > 0) scr_idx--; else scr_idx = scroll_max;
for (i = 0; i < LCD_LINES; i++) {
lcdGotoXY(p, i);
lcdPuts(Msg(scr_menu[scr_idx]));
// ab Stringende bis zum Zeilenende löschen; LCD löschen flackert sonst zu sehr
for (int8_t n = LCD_COLS - strlen(Msg(scr_menu[scr_idx])) - p; n > 0; n--)
lcdPutc(' ');
if (scr_idx < scroll_max) scr_idx++; else scr_idx = 0;
}
}
 
/************************************************************************************/
/* */
/* Unterprogramm vom Scroll_Menu(...) und Change_Value(...) */
/* bei Rücksprung auf ursprünglichen Menüpunkt zeigen */
/* Parameter: */
/* uint8_t l : Strinlänge von pmenue */
/* */
/************************************************************************************/
void return_m_pkt(uint8_t l)
{
if (l > 0) {
l--;
m_pkt = pmenu[l] - '0'; // um bei Rücksprung auf ursprünglichen Arrayeintrag(Menüpunkt) zeigen
pmenu[l] ='\0'; // auf letztes Zeichen Stringende schreiben
}
if (l == 0) Displ_Main_Disp();
}
 
/************************************************************************************/
/* */
/* scrollt Menü über Mehrzeilige LCD */
/* */
/* Taste<Enter> lang springt in Hauptanzeige, kurz geht in den angewälten Menüpunkt*/
/* Taste<+> eine Zeile nach oben */
/* Taste<-> eine Zeile nach unten */
/* Parameter: */
/* scr_menu_t scr_menu : Array mit Strings der Menüanzeige */
/* uint8_t scroll_max: scrollen bis Wert */
/* uint8_t scr_idx : Index für array von Displ_Scroll_Menu(...) */
/* */
/************************************************************************************/
void Scroll_Menu(scr_menu_t scr_menu, uint8_t scroll_max, uint8_t scr_idx)
{ uint8_t l;
 
// pmenu[1] == '\0' entspricht <wenn Hauptmenue>, da jetzt nur noch Servo x für Scrollemenue (rev,min,max,mid)
if ((pmenu[1] == '\0') && ((tracking == TRACKING_RSSI) || (tracking == TRACKING_GPS) || (tracking == TRACKING_MKCOCKPIT))) {
++scroll_max;
if (tracking == TRACKING_RSSI) scr_menu[scroll_max] = MSG_TRACK_SERVO_HYTERESE;
if (tracking == TRACKING_GPS) {
scr_menu[scroll_max] = MSG_TRACK_TX_OSD_DATA;
++scroll_max; // zusätzliche Anzeige zu GPS
}
if (tracking == TRACKING_MKCOCKPIT) scr_menu[scroll_max] = MSG_COM;
}
lcdClear();
lcdGotoXY(0, 1);
lcdPutc(MARKER_SELECT); // '>>'
Displ_Scroll_Menu(scr_menu, scr_idx, scroll_max);
// bis Menueeingabe bestätigt oder zum vorherigen Menue
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0') && !exit_while)
{
// >> Menueauswahl nach oben
if( Get_Key_Press( 1<<SW_PLUS ) || Get_Key_Rpt( 1<<SW_PLUS ))
{
if (scr_idx > 0) scr_idx--; else scr_idx = scroll_max;
Displ_Scroll_Menu(scr_menu, scr_idx, scroll_max);
}
// >> Menueauswahl nach unten
if( Get_Key_Press( 1<<SW_MINUS ) || Get_Key_Rpt( 1<<SW_MINUS ))
{
if (scr_idx < scroll_max) scr_idx++; else scr_idx = 0;
Displ_Scroll_Menu(scr_menu, scr_idx, scroll_max);
}
Long_Enter();
}
lcdClear();
if ((pmenu[0] =='\0'))
Displ_Main_Disp();
else
if (!exit_while) { // wegen Aufruf Menu_MK_BatteryChangeNr() in Task
l = strlen(pmenu);
if (scr_idx > 0) {
m_pkt = 1; // 0 wäre "zurück", so aber ins Untermenü immer erster Menüpunkt
pmenu[l] = scr_idx + '0'; // nächsten MenueIndex anhängen 1 oder 2 oder ...
pmenu[l + 1] ='\0';
Beep(BEEPENTER);
}
else {
return_m_pkt(l); // um bei Rücksprung auf ursprünglichen Menüpunkt zu zeigen oder Displ_Main_Disp()
}
}
else
m_pkt = scr_idx; // nach Task Menu_MK_BatteryChangeNr() wieder zum ursprünlichen Anzeigepunkt
exit_while = 0;
}
 
/************************************************************************************/
/* */
/* Ändern der Werte mit Tasten +,- und Anzeige */
/* z.B. für U-Offset, Batterie leer Eingabe ... */
/* */
/* Parameter: */
/* uint32_t val :zu ändernter Wert */
/* uint32_t min_val, max_val :min, max Grenze Wert ändern darf */
/* uint8_t posX, posY :Darstellung Wert xPos, YPos auf LCD */
/* Displ_Fnct_t Displ_Fnct :Index um variable Display Funktion aufzurufen */
/* uint8_t cycle :0 begrenzt Anzeige bei man_val, bzw. max_val */
/* :1 springt nach max_val auf min_val und umgedreht */
/* uint8_t vrepeat :beschleunigte Repeat-Funktion aus/ein */
/* uint32_t Change_Value_plmi(...) :Rückgabe geänderter Wert */
/* */
/************************************************************************************/
uint32_t Change_Value_plmi(uint32_t val, uint32_t min_val, uint32_t max_val, uint8_t posX, uint8_t posY, \
Displ_Fnct_t Displ_Fnct, uint8_t cycle, uint8_t vrepeat)
{
// >> Menueauswahl nach oben
if( Get_Key_Press( 1<<SW_PLUS ) || Get_Key_Rpt( 1<<SW_PLUS )){
if (val < max_val) {
val++;
Key_Speedup_rpt(vrepeat); // beschleunigte Repeat-Funktion
}
else
if (cycle) {
val = min_val;
}
lcdGotoXY(posX, posY); // lcd Position Wert
Displ_Fnct(val); // geänderten Wert darstellen, je nach Menüpunkt
}
// >> Menueauswahl nach unten
if( Get_Key_Press( 1<<SW_MINUS ) || Get_Key_Rpt( 1<<SW_MINUS )) {
if (val > min_val) {
val--;
Key_Speedup_rpt(vrepeat); // beschleunigte Repeat-Funktion
}
else
if (cycle) {
val = max_val;
}
lcdGotoXY(posX, posY); // noch einmal lcd Position, sonst zum Teil + und - gleichzeitig, Anzeige verrutscht
Displ_Fnct(val); // geänderten Wert darstellen, je nach Menüpunkt
}
return(val);
}
 
/************************************************************************************/
/* */
/* Ändern der Werte mit Tasten +,- repetierend; (long)Entertaste und Anzeige */
/* z.B. für U-Offset, Batterie leer Eingabe ... */
/* */
/* Parameter: */
/* uint32_t val :zu ändernter Wert */
/* uint32_t min_val, max_val :min, max Grenze Wert ändern darf */
/* uint8_t pos :Darstellung Wert xPos auf LCD */
/* Displ_Fnct_t Displ_Fnct :Index um variable Display Funktion aufzurufen */
/* uint8_t vrepeat :beschleunigte Repeat-Funktion aus/ein */
/* uint32_t Change_Value(...) :Rückgabe geänderter Wert */
/* */
/************************************************************************************/
uint32_t Change_Value(uint32_t val, uint32_t min_val, uint32_t max_val, uint8_t pos, Displ_Fnct_t Displ_Fnct, \
uint8_t vrepeat)
{ uint32_t tmp_val;
 
tmp_val = val;
lcdGotoXY(pos, ZLE_VAL); // Position Wert
Displ_Fnct(val); // initiale Wertdarstellung, je nach Menüpunkt
// bis Menueeingabe bestätigt oder zum vorherigen Menue
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0') && !exit_while)
{
val = Change_Value_plmi(val, min_val, max_val, pos, ZLE_VAL, Displ_Fnct, 0, vrepeat);
Long_Enter();
}
lcdClear();
if (exit_while) {
exit_while = 0;
val = tmp_val;
}
else
return_m_pkt(strlen(pmenu)); // um bei Rücksprung auf ursprünglichen Menüpunkt zeigen oder Displ_Main_Disp()
return(val);
}
 
 
/**************************************************************/
/* */
/* LCD-Darstellungen der Menüs */
/* Zur Unterstützung der Auswahl werden einige Einstellungen */
/* sofort ausgeführt. Z.B.: Kontrast, Servo-Endausschlag */
/* */
/**************************************************************/
 
/************************************************************************************/
/* stellt eine String mittig auf Display dar */
/* Parameter: */
/* char *str : darzustellende Zeichenkette */
/* uint8_t zle : Display-Zeile */
/* */
/************************************************************************************/
void Displ_Str_mid(char *str, uint8_t zle)
{ int8_t x;
 
lcdGotoXY(0,zle);
for (x = 0; x < LCD_COLS; x++) lcdPutc(' '); // Zeile löschen
x = (LCD_COLS - strlen(str))/2; // Array-String mittig schreiben
lcdGotoXY(x,zle);
lcdPuts(str);
}
 
/************************************************************************************/
/* zeigt Menü- * Überschrift * auf erste Zeile mittig auf Display an */
/* Parameter: */
/* uint8_t message : index (MSG_) der darzustellenden Zeichenkette */
/* */
/************************************************************************************/
void Displ_Title(uint8_t message)
{ uint8_t l;
uint8_t x = 0;
 
l = strlen(Msg(message));
if ( LCD_COLS > l) x = (LCD_COLS - l)/2;
if (x > 1) {
lcdGotoXY(x - 2, 0);
lcdPuts("* ");
lcdPuts(Msg(message));
lcdPutc(' ');
}
else {
lcdGotoXY(0, 0);
lcdPutc('*');
lcdGotoXY(x, 0);
lcdPuts(Msg(message));
lcdGotoXY(LCD_COLS - 1, 0);
}
lcdPutc('*');
}
 
/************************************************************************************/
/* zeigt bei Programmstart Firmware- und DOGM-Version auf Display an */
/* */
/************************************************************************************/
void Displ_Version(void)
{
lcdGotoXY(0, 0);
lcdPuts(Msg(MSG_VERSION1));
if (dogm_vers == DOGM3V)
lcdPuts(Msg(MSG_UHW33V));
else
lcdPuts(Msg(MSG_UHW5V));
lcdPuts(Msg(MSG_VERSION2));
delay_ms100x(30);
lcdClear();
}
 
/************************************************************************************/
/* zeigt auszuwählenden/-gewählten Kanal und Frequenz auf Display an */
/* Parameter: */
/* uint32_t k :Index anzuzeigender Wert = Kanal + 0x30 als Char, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Channels(uint32_t k)
{ char *channels[] = {"5740", "5760","5780", "5800", "5820", "5840", "5860"};
 
lcdPutc(k+0x30);
lcdPuts(": ");
lcdPuts(channels[k-1]);
lcdPuts("MHz");
}
 
/************************************************************************************/
/* zeigt Source AV1, AV2 oder Diversity zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_AV_Source(uint32_t q)
{ uint8_t av_src_table[] = {MSG_AV1, MSG_AV2, MSG_DIVERSITY};
 
Displ_Str_mid(Msg(av_src_table[q]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Tracking-Varianten zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_sel_Tracking(uint32_t q)
{ uint8_t track_sel_table[] = {MSG_OFF, MSG_TRACK_RSSI, MSG_TRACK_GPS, MSG_TRACK_MKCOCKPIT};
 
Displ_Str_mid(Msg(track_sel_table[q]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Senden der OSD-Daten Anforderung zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_track_TX(uint32_t q)
{ uint8_t track_TX_table[] = {MSG_OFF, MSG_TRACK_TX_ON};
 
Displ_Str_mid(Msg(track_TX_table[q]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt einen max. 3-stelligen Integerwert auf Display an */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Format_Int(uint32_t val)
{
lcdPuts(my_itoa(val, 0, 3, 0, 0));
}
 
/************************************************************************************/
/* zeigt den Kontrastwert auf Display an mit sofortiger Änderung */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Set_Contrast(uint32_t val)
{
Displ_Format_Int(val);
lcdContrast(dogm_vers, val);
}
 
/************************************************************************************/
/* zeigt die Zeit zur Abschaltung der LCD-Hintergrundbeleuchtung an */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Backgr_Light(uint32_t val)
{ char str[5];
uint8_t l;
l = strlen(Msg(MSG_LIGHT)); // etwas Aufwand um Zeilenende sauber zu löschen
switch(val) {
case BACKGR_LIGHT_MIN : l += strlen(Msg(MSG_LIGHT_OFF));
lcdPuts(Msg(MSG_LIGHT_OFF));
break;
case BACKGR_LIGHT_MAX : l += strlen(Msg(MSG_LIGHT_ON));
lcdPuts(Msg(MSG_LIGHT_ON));
break;
default : itoa (val * 10, str, 10);
lcdPutc(' ');
lcdPuts(str);
lcdPuts(Msg(MSG_SEC));
l += 1 + strlen(str) + strlen(Msg(MSG_SEC));
}
l = LCD_COLS - l;
for (uint8_t x = 0; x < l; x++) lcdPutc(' '); // Zeilenende löschen
}
 
/************************************************************************************/
/* zeigt ein oder aus zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t val :0 = aus oder 1 = ein, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Off_On(uint32_t val)
{
if (val == 0) lcdPuts(Msg(MSG_OFF)); else lcdPuts(Msg(MSG_ON));
}
 
/************************************************************************************/
/* zeigt Servoschritte zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t val :0 = 255 oder 1 = 1023, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Steps(uint32_t val)
{ uint8_t servo_step_table[] = {MSG_STEPS_255, MSG_STEPS_1023};
 
Displ_Str_mid(Msg(servo_step_table[val]), ZLE_VAL);
}
 
/************************************************************************************/
/* zeigt Servo-Anschlagposition links auf Display an */
/* mit sofortiger Wirkung auf Servo */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Min(uint32_t val)
{ uint16_t steps = 0;
 
Displ_Format_Int(val);
servoSet_min(servo_nr, val); // Wert setzen damit nachfolgend die
if (servo[servo_nr].rev) steps = ServoSteps();
servoSetPosition(servo_nr, steps); // Änderung direkt am Servo sichtbar ist
}
 
/************************************************************************************/
/* zeigt Servo-Anschlagposition rechts auf Display an */
/* mit sofortiger Wirkung auf Servo */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Max(uint32_t val)
{ uint16_t steps = ServoSteps();
 
Displ_Format_Int(val);
servoSet_max(servo_nr, val); // Wert setzen damit nachfolgend die
if (servo[servo_nr].rev) steps = 0;
servoSetPosition(servo_nr, steps); // Änderung direkt am Servo sichtbar ist
}
 
/************************************************************************************/
/* zeigt Servo-Anschlagposition Mitte auf Display an */
/* mit sofortiger Wirkung auf Servo */
/* Parameter: */
/* uint32_t val :anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Servo_Mid(uint32_t val)
{ int16_t mid_val;
mid_val = val - ServoSteps()/2;
lcdPuts(my_itoa(mid_val, 1, 3, 0, 0));
servoSet_mid(servo_nr, val); // Wert setzen damit nachfolgend die
servoSetPosition(servo_nr, ServoSteps()/2);// Änderung direkt am Servo sichtbar ist
}
 
/************************************************************************************/
/* zeigt zu testende Servonummer zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t val :0 = Servo 1 oder 1 = Servo 2, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_ServoNr(uint32_t val)
{
if (val == 0) lcdPuts(Msg(MSG_SERVO1)); else lcdPuts(Msg(MSG_SERVO2));
}
 
 
/************************************************************************************/
/* zeigt Servoausschlag in ms, in % und als Bargraph auf Display an */
/* Parameter: */
/* int16_t PosProzent : aktuell eingestellte Position vom 0-Punkt (Mitte) aus */
/* int16_t range : maximaler absoluter Ausschlag vom 0-Punkt aus */
/* */
/************************************************************************************/
// leerer Rahmen für Bar
char* empty_Bar(void)
{ static char tmp_empty[LCD_COLS];
uint8_t i;
tmp_empty[0] = '\0';
for (i = 1; i < 15; i++)
tmp_empty[i] = '\x07';
tmp_empty[i] = '\x06';
return(tmp_empty);
}
 
void draw_bar(int16_t PosProzent, int16_t range, uint8_t zle)
{ int8_t i, sp_quad, sp_ch;
int8_t lz = 8;
char* bar;
bar = empty_Bar(); // leerer Rahmen für Bar
sp_quad = abs(PosProzent) * 7 / range;
 
sp_ch = (abs(PosProzent) -(range * sp_quad / 7)) * 35 / range; // Unterteilung Kästchen in 6 senkrechte Striche
if (sp_ch > 4) sp_ch = 4; // bei 28 (7*4) wäre keine Korrektur erforderlich aber so kontinuierlicher
if (PosProzent < 0){
lz -= sp_quad; // Position für volles Kästchen bei Linksausschlag
if (sp_ch > 0) bar[lz-1] = sp_ch; // vor erstes volles Kästchen Kästchenunterteilung schreiben
} // Unterteilung Kästchen der 4 senkrechte Striche nach Bar (0 und 5 entfallen)
else
if (sp_ch > 0) bar[lz+sp_quad] = sp_ch;// nach lezten vollen Kästchen Kästchenunterteilung schreiben
 
for (i = 0; i < sp_quad; i++)
bar[i+lz] = '\x05'; // volle Kästchen schreiben
lcdGotoXY(0,zle);
for (uint8_t i = 0; i < LCD_COLS; i++) lcdPutc(bar[i]);// kpl. Bar zum Display
}
 
uint16_t calc_range(int16_t PosProzent, int16_t min, int16_t max, int16_t mid)
{ uint16_t range;
 
if (PosProzent < 0) {
range = mid - min;
if (chrxs == CHRRS) { // falls Richtung geändert, anderen Zeichensatz laden
chrxs = CHRLS;
lcdWriteCGRAM_Array(lcdSpecialChrLs, 5);// LCD-Char mit Rahmensymbole vom Graph
}
}
else {
range = max - mid;
if (chrxs == CHRLS) { // falls Richtung geändert, anderen Zeichensatz laden
lcdWriteCGRAM_Array(lcdSpecialChrRs, 5);// LCD-Char mit Rahmensymbole vom Graph
chrxs = CHRRS;
}
}
return(range);
}
 
void Displ_PulseWidth(uint32_t val)
{ int16_t PosProzent, range;
uint16_t Pos_us;
char me[3] = {"ms"};
 
servoSetPositionRaw(servo_nr, val);
PosProzent = val - steps_pw[sIdxSteps].mid;
range = calc_range(PosProzent, steps_pw[sIdxSteps].min, steps_pw[sIdxSteps].max, steps_pw[sIdxSteps].mid);
draw_bar(PosProzent, range, 2); // auf 3. Display-Zeile
PosProzent = (int32_t)1000 * PosProzent / range;
lcdGotoXY(1, 1);
Pos_us = pw_us(val); // Zeit in µs bei x Servoschritte
if (Pos_us < 1000) {
me[0] = 'u'; // soll 'µ' => programmierbarer Zeichensatz zu klein
lcdPuts(" ");
lcdPuts(my_itoa(Pos_us, 0, 3, 0, 0));
}
else {
lcdPuts(my_itoa(Pos_us, 0, 5, 3, 3));
}
lcdPuts(me);
lcdGotoXY(8, 1);
lcdPuts(my_itoa(PosProzent, 1, 5, 1, 1));
lcdPutc('%');
}
 
/************************************************************************************/
/* zeigt Pausenlänge der Links-, Miettel- und Rechtsposition auf Display an */
/* Parameter: */
/* uint32_t val : Zeit in 1ms * 100 */
/* */
/************************************************************************************/
void Displ_Pause(uint32_t val)
{
if (val > 9) {
lcdPuts(my_itoa(val, 0, 3, 1, 1));
lcdPuts("s ");
}
else {
lcdPuts(my_itoa(val * 100, 0, 3, 0, 0));
lcdPuts("ms");
}
}
 
/************************************************************************************/
/* zeigt aus oder Integerwert auf Display an */
/* Parameter: */
/* uint32_t val : val = 0 ==> aus, sont Integerwert */
/* */
/************************************************************************************/
void Displ_Off_Format_Int(uint32_t val)
{
if (val == 0)
Displ_Str_mid(Msg(MSG_OFF), ZLE_VAL);
else {
lcdGotoXY(5,ZLE_VAL);
Displ_Format_Int(val);
lcdPutc(' ');
}
}
 
/************************************************************************************/
/* zeigt aus oder Pausenzeit zwischen 2 Servoschritte auf Display an */
/* Parameter: */
/* uint32_t val : val = 0 ==> aus, sont Integerwert */
/* */
/************************************************************************************/
void Displ_Pause_Step(uint32_t val)
{
Displ_Off_Format_Int(val);
if (val > 0) {
lcdGotoXY(8,ZLE_VAL);
lcdPuts("ms");
}
}
/************************************************************************************/
/* zeigt Baudrate für COM bei MKCockpit zur Auswahl auf Display an */
/* Parameter: */
/* uint32_t q :Index anzuzeigender Wert, */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Baudrate(uint32_t q)
{ char str[7];
 
ltoa(baud[q], str, 10);
Displ_Str_mid(str, ZLE_VAL);
}
 
void Displ_TimeHMS(uint32_t time)
{ char str[9];
 
time /= T2SECDIV; // Zähler aller 500µs
str[8] = '\0';
time = TimeBase60(str, time, 7);
time = TimeBase60(str, time, 4);
TimeBase60(str, time, 1);
str[2] = ':';
str[5] = ':';
lcdPuts(str);
}
 
void Displ_RX_Time(void)
{
lcdGotoXY(6, 1);
Displ_TimeHMS(rxcount0);
lcdGotoXY(6, 2);
Displ_TimeHMS(rxcount1);
}
 
/************************************************************************************/
/* zeigt eingestellte Akku-Kapazität des MK auf Display an */
/* Parameter: */
/* uint32_t val :Akku-Kapazität in 50mAh Schritte */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_MK_Capacity(uint32_t val)
{
lcdPuts(my_itoa(val * 50, 0, 4, 0, 0));
lcdPuts("mAh");
}
 
/************************************************************************************/
/* zeigt Offset (Korrektur Ruhestrom) für Strom des MK auf Display an */
/* Parameter: */
/* uint32_t val :Korrekturfaktor */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_I_Offset(uint32_t val)
{
lcdPuts(my_itoa((int8_t)val - MK_I_OFFSET_5,1,3,1,1));
lcdPutc('A');
}
 
 
/************************************************************************************/
/* zeigt Korrekturfaktor für Strom und Arbeit des MK auf Display an */
/* Parameter: */
/* uint32_t val :Korrekturfaktor */
/* unint32_t wegen Vereinheitlichung f. Funktionsaufrauf */
/* */
/************************************************************************************/
void Displ_Faktor_2Nk(uint32_t val)
{
lcdPuts(my_itoa(val,0,4,2,2));
}
 
/************************************************************************************/
/* zeigt den Marker in Hauptdarstellung auf selektierten RX an */
/* d Diversity, << fester RX */
/* Parameter: */
/* uint8_t p :x-Position des Markers */
/* uint8_t marker :Markerzeichen z.B.:'' oder 'd' oder 's' */
/* */
/************************************************************************************/
void Displ_AV_Mark(uint8_t p, char marker)
{
if (p < 2) {
lcdGotoXY(15,2 - p); // da p immer neue Position 0 oder 1
lcdPutc(' '); // bisherigen AVx-, Diversity-Marker löschen
lcdGotoXY(15,p + 1); // an neuer Positon
lcdPutc(marker); // übergebenes Markerzeichen darstellen
}
else { // falls beim Einschalten Diversity auf aktiv, keine Marker
lcdGotoXY(15,1);
lcdPutc(' ');
lcdGotoXY(15,2);
lcdPutc(' ');
}
}
 
/************************************************************************************/
/* Hauptanzeige unter Berücksichtigung von VBat */
/* */
/************************************************************************************/
void Displ_Main_Disp(void)
{ char marker;
 
lcdClear();
if (bat_low != 0) {
lcdClear();
Displ_Channels(channel);
lcdGotoXY(LCD_COLS - 1, 0);
lcdPuts("V\n1\n2");
if (av_source < DIVERSITY)
marker = MARKER_AV; // wird nur bei gesetzten Diversity überschrieben
else
marker = MARKER_RSSI; // nur Schönheit, damit man sofort Umschaltung sieht
Displ_AV_Mark(sw_avx, marker);
Displ_VBat(); // muss zuletzt stehen
}
else {
Displ_Str_mid(Msg(MSG_ACCU_LOW), 0);
}
}
 
 
 
/**************************************************************/
/* */
/* Menüs */
/* */
/**************************************************************/
 
/**************************/
/* */
/* Haupmenü */
/* */
/**************************/
void Menu_Main(void)
{ scr_menu_t scr_main_menu = {MSG_RETURN, MSG_AV_SOURCE, MSG_RX_CHANNEL, MSG_RSSI_CALIBR, MSG_LANGUAGE, MSG_SERVO_CALIBR, \
MSG_TEST_SERVO, MSG_LCD , MSG_BATTERY, MSG_TRACKING, 0, MSG_GPS_DISPLAY};
 
strcpy(pmenu, "0");
Scroll_Menu(scr_main_menu, SCROLL_MAIN_MAX, m_pkt); // pmenu global
Jump_Menu(pmenu); //gewähltes Untermenü anspringen oder nur Return
}
 
/**************************/
/* */
/* AV-Quelle */
/* */
/**************************/
void Menu_AV_Source(void)
{ char marker;
uint32_t eep_val;
 
Displ_Title(MSG_AV_SOURCE);
eep_val = Change_Value(av_source, AV_SOURCE_MIN, AV_SOURCE_MAX, 3, Displ_AV_Source, C_REPEAT); // pmenu global
if (eep_val != av_source) {
cli();
av_source = eep_val;
eeprom_write_byte(&ep_av_source, av_source);
Double_Beep(DBEEPWR, DBEEPWRP);
sw_avx = Set_AV_Source(av_source);
if (pmenu[0] == '\0') { // sonst ist AV-Source marker im Hauptdisplay nicht aktuallisiert
if (av_source < DIVERSITY)
marker = MARKER_AV; // wird nur bei gesetzten Diversity überschrieben
else
marker = MARKER_RSSI; // nur Schönheit, damit man sofort Umschaltung sieht
Displ_AV_Mark(sw_avx, marker);// da erst jetzt die Variable für main_display geändert ist!
}
sei();
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Kanal */
/* */
/**************************/
void Menu_RX_Channel(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_RX_CHANNEL);
eep_val = Change_Value(channel, CHANNEL_MIN, CHANNEL_MAX, 3, Displ_Channels, C_REPEAT); // pmenu global
if ((eep_val != channel) || (eep_val != ch_stored)) { // oder Channel wurde im Hauptdisplay geändert
channel = eep_val;
ch_stored = eep_val;
eeprom_write_byte(&ep_channel, channel);
Double_Beep(DBEEPWR, DBEEPWRP);
Set_Channel(channel);
if (pmenu[0] == '\0') { // sonst ist channel im Hauptdisplay nicht aktuallisiert
lcdGotoXY(0,0);
Displ_Channels(channel); // da erst jetzt die Variable für main_display geändert ist!
}
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* RSSI */
/* */
/**************************/
void Menu_RSSI_Calibr(void)
{ uint8_t scr_sub_menu[4] = {MSG_RETURN, MSG_RSSI_MIN, MSG_RSSI_MIN_ALL, MSG_RSSI_MAX};
 
Scroll_Menu(scr_sub_menu, 3, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_RSSI_min(void)
{ char str[20];
 
Displ_Title(MSG_RSSI_MIN);
strcpy(str, Msg(MSG_TX));
strcat(str, Msg(MSG_TX_OFF));
Displ_Str_mid(str, 1);
Displ_Str_mid(Msg(MSG_CONTINUE), 2);
if (Short_Enter()) { // pmenu global
RSSI_Min_Calibrate(0, pbar_udbm);
pmenu[0] = '\0'; // zur Hauptdarstellung
Displ_Main_Disp(); // da erst jetzt die Variable für main_display geändert ist!
}
else
Jump_Menu(pmenu);
}
 
void Displ_RSSImin_allError(char *str_ch)
{ char str[LCD_COLS + 1];
lcdClear();
strcpy(str, Msg(MSG_CALIB));
strcat(str, "-");
strcat(str, Msg(MSG_ERROR));
Displ_Str_mid(str,0);
Displ_Str_mid(Msg(MSG_RX_CHANNEL),1);
Displ_Str_mid(str_ch, 2);
delay_ms100x(30);
}
 
void Menu_RSSI_min_all(void)
{ char str[20];
char not_cal[15];
uint8_t f = 0;
 
Displ_Title(MSG_RSSI_MIN_ALL);
strcpy(str, Msg(MSG_TX));
strcat(str, Msg(MSG_TX_OFF));
Displ_Str_mid(str, 1);
Displ_Str_mid(Msg(MSG_CONTINUE), 2);
if (Short_Enter()) { // pmenu global
for ( uint8_t i = 1; i <= CHANNEL_MAX; i++) {
Set_Channel(i);
if (!RSSI_Min_Calibrate(i, pbar_udbm)) {
not_cal[f++] = i + 0x30;
not_cal[f++] = ',';
}
}
Set_Channel(channel);
Double_Beep(DBEEPWR, DBEEPWRP);
if (f > 0) { // Konnten einige Kanäle nicht auf RSSI-Min kalibiert werden?
not_cal[--f] = '\0'; // letzes Komma durch Stringende ersetzen
Displ_RSSImin_allError(not_cal);
}
pmenu[0] = '\0'; // zur Hauptdarstellung
Displ_Main_Disp(); // da erst jetzt die Variable für main_display geändert ist!
}
else
Jump_Menu(pmenu);
}
 
void Menu_RSSI_max(void)
{ char str[20];
 
Displ_Title(MSG_RSSI_MAX);
strcpy(str, Msg(MSG_TX));
strcat(str, Msg(MSG_TX_ON));
Displ_Str_mid(str, 1);
Displ_Str_mid(Msg(MSG_CONTINUE), 2);
if (Short_Enter()) { // pmenu global
RSSI_Max_Calibrate(pbar_udbm);
pmenu[0] = '\0'; // zur Hauptdarstellung
Displ_Main_Disp(); // da erst jetzt die Variable für main_display geändert ist!
}
else
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Sprache */
/* */
/**************************/
void Displ_Language(uint32_t i)
{ uint8_t lanuage_table[3] = {MSG_GERMAN, MSG_ENGLISH, MSG_FRENCH};
 
Displ_Str_mid(Msg(lanuage_table[i]), ZLE_VAL);
}
 
void Menu_Language(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_LANGUAGE);
eep_val = Change_Value(language, GERMAN, LAST_LANG, 3, Displ_Language, C_REPEAT); // pmenu global
language = eeprom_read_byte(&ep_language); // damit bei Erstinbetriebnahme Sprache gespeichert wird NO_LANGUAGE
if (eep_val != language) {
language = eep_val;
eeprom_write_byte(&ep_language, language);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Servos */
/* */
/**************************/
void Menu_Servo_Calibr(void)
{ uint8_t scr_sub_menu[4] = {MSG_RETURN, MSG_SERVO_STEPS, MSG_SERVO1, MSG_SERVO2};
 
Scroll_Menu(scr_sub_menu, 3, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Servo_NewValues(uint8_t idx_presc)
{
for (uint8_t i = 0; i < SERVO_NUM_CHANNELS; i++) {
if (idx_presc == STEPS_255) { // Werte umrechnen für Prescaler = 256
servo[i].min /= 4;
servo[i].max /= 4;
servo[i].mid /= 4;
}
else { // Werte umrechnen für Prescaler = 64
servo[i].min *= 4;
servo[i].max *= 4;
servo[i].mid = (servo[i].mid + 1) * 4 - 1;
}
servoSet_min(i, servo[i].min);
servoSet_max(i, servo[i].max);
servoSet_mid(i, servo[i].mid);
eeprom_write_block(&servo[i],&ep_servo[i],sizeof(servo_t));
}
// Vorberechnung von ServoChannels[channel].duty
servoSetDefaultPos(); // Ausgangsstellung beider Servos
}
 
void Menu_Servo_Steps(void)
{ uint32_t eep_val;
Displ_Title(MSG_SERVO_STEPS);
lcdGotoXY(8, ZLE_VAL);
eep_val = Change_Value(sIdxSteps, STEPS_255, STEPS_1023, 5, Displ_Servo_Steps, C_REPEAT); // pmenu global
if (eep_val != sIdxSteps) {
cli();
sIdxSteps = eep_val;
eeprom_write_byte(&ep_sIdxSteps, sIdxSteps);
Servo_NewValues(sIdxSteps); // hier ist der neue Index anzugeben!
servoInit(SERVO_PERIODE);
sei();
if (tracking == TRACKING_MIN) {
delay_ms100x(4); // sonst werden Impulse bereits vor erreichen der Servo-default-Stellung abgeschaltet
servoOff(); // Servos sind nur zum Tracking oder bei Kalibrierung eingeschaltet
}
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Servo1(void)
{ uint8_t scr_servo_menu[5] = {MSG_RETURN, MSG_SERVO1_REVERSE, MSG_CALIB1_LEFT, MSG_CALIB1_RIGHT, MSG_CALIB1_MIDDLE};
Scroll_Menu(scr_servo_menu, SCROLL_SERVO_MAX, m_pkt); // pmenu global
servo_nr = 0;
Jump_Menu(pmenu);
}
 
void Menu_Servo2(void)
{ uint8_t scr_servo_menu[5] = {MSG_RETURN, MSG_SERVO2_REVERSE, MSG_CALIB2_LEFT, MSG_CALIB2_RIGHT, MSG_CALIB2_MIDDLE};
Scroll_Menu(scr_servo_menu, SCROLL_SERVO_MAX, m_pkt); // pmenu global
servo_nr = 1;
Jump_Menu(pmenu);
}
 
uint8_t Servo_tmp_on(uint8_t servo_period)
{ uint8_t tmp_tracking = tracking;
 
tracking = 0; // Servopositionierung durch tracking abschalten
if (tracking == TRACKING_MIN) servoInit(servo_period); // falls aus, Servos einschalten
lcdGotoXY(0, 0); // lcd Cursor vorpositionieren
return(tmp_tracking);
}
 
void Servo_tmp_Original(uint8_t track)
{ uint16_t steps;
 
if (servo_nr == SERVO_PAN)
steps = ServoSteps()/2; // PAN auf Mittelstellung
else
steps = 0; // Tilt auf Endausschlag
servoSetPosition(servo_nr, steps); // Bei PAN auf ServoSteps/2 und bei Tilt auf 0 oder ServoSteps NICHT!!! reverse beachten
tracking = track; // ursprünglicher Wert Tracking aus, RSSI oder GPS
if (tracking == TRACKING_MIN) {
delay_ms100x(4); // sonst werden Impulse bereits vor erreichen der Servo-default-Stellung abgeschaltet
servoOff(); // Servos sind nur zum Tracking oder bei Kalibrierung eingeschaltet
}
Jump_Menu(pmenu);
}
 
void Menu_Servo_rev(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on(SERVO_PERIODE);
eep_val = Change_Value(servo[servo_nr].rev, 0, 1, 6, Displ_Off_On, C_REPEAT); // pmenu global; reverse gibt es nur 0=off, 1=on
if (eep_val != servo[servo_nr].rev) {
servo[servo_nr].rev = eep_val;
servoSet_rev(servo_nr, eep_val);
eeprom_write_block(&servo[servo_nr],&ep_servo[servo_nr],sizeof(servo_t));
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_rev(void)
{
Displ_Title(MSG_SERVO1_REVERSE);
Menu_Servo_rev();
}
 
void Menu_Servo2_rev(void)
{
Displ_Title(MSG_SERVO2_REVERSE);
Menu_Servo_rev();
}
 
void Menu_Servo_left(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on(SERVO_PERIODE);
servoSetPosition(servo_nr, ServoSteps()); // Linkssanschlag um Kalibrierung am Servo zu sehen
eep_val = Change_Value(servo[servo_nr].max, servo_limit[sIdxSteps][LEFT].min, servo_limit[sIdxSteps][LEFT].max, 6, Displ_Servo_Max, V_REPEAT); // pmenu global
if (eep_val != servo[servo_nr].max) {
servo[servo_nr].max = eep_val;
eeprom_write_block(&servo[servo_nr],&ep_servo[servo_nr],sizeof(servo_t));
servoSet_mid(servo_nr, servo[servo_nr].mid); // Mittelposition muss sich bei Ausschlagsänderung verschieben
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_left(void)
{
Displ_Title(MSG_CALIB1_LEFT);
Menu_Servo_left();
}
 
void Menu_Servo2_left(void)
{
Displ_Title(MSG_CALIB2_LEFT);
Menu_Servo_left();
}
 
void Menu_Servo_right(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on(SERVO_PERIODE);
servoSetPosition(servo_nr, 0); // Rechtsanschlag um Kalibrierung am Servo zu sehen
eep_val = Change_Value(servo[servo_nr].min, servo_limit[sIdxSteps][RIGHT].min, servo_limit[sIdxSteps][RIGHT].max, 6, Displ_Servo_Min, V_REPEAT); // pmenu global
if (eep_val != servo[servo_nr].min) {
servo[servo_nr].min = eep_val;
eeprom_write_block(&servo[servo_nr],&ep_servo[servo_nr],sizeof(servo_t));
servoSet_mid(servo_nr, servo[servo_nr].mid); // Mittelposition muss sich bei Ausschlagsänderung verschieben
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_right(void)
{
Displ_Title(MSG_CALIB1_RIGHT);
Menu_Servo_right();
}
 
void Menu_Servo2_right(void)
{
Displ_Title(MSG_CALIB2_RIGHT);
Menu_Servo_right();
}
 
void Menu_Servo_middle(void)
{ uint32_t eep_val;
uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on(SERVO_PERIODE);
servoSetPosition(servo_nr, ServoSteps()/2); // Mittelposition um Kalibrierung am Servo zu sehen
eep_val = Change_Value(servo[servo_nr].mid, servo_limit[sIdxSteps][MIDDLE].min, servo_limit[sIdxSteps][MIDDLE].max, 5, Displ_Servo_Mid, V_REPEAT); // pmenu global
if (eep_val != servo[servo_nr].mid) {
servo[servo_nr].mid = eep_val;
eeprom_write_block(&servo[servo_nr], &ep_servo[servo_nr], sizeof(servo_t));
Double_Beep(DBEEPWR, DBEEPWRP);
}
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Servo1_middle(void)
{
Displ_Title(MSG_CALIB1_MIDDLE);
Menu_Servo_middle();
}
 
void Menu_Servo2_middle(void)
{
Displ_Title(MSG_CALIB2_MIDDLE);
Menu_Servo_middle();
}
 
/**************************/
/* Servos-Test */
/**************************/
void Menu_Servo_Test(void)
{ uint8_t scr_sub_menu[5] = {MSG_RETURN, MSG_PULSE_WIDTH, MSG_CONTINOUS, MSG_SERVO, MSG_FRAME};
 
Scroll_Menu(scr_sub_menu, 4, m_pkt); // pmenu global
servo_nr = eeprom_read_byte(&ep_servo_nr);
Jump_Menu(pmenu);
}
 
void Menu_Test_Frame(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_FRAME);
lcdGotoXY(8, ZLE_VAL);
lcdPuts("ms");
eep_val = Change_Value(servo_frame, SERVO_PERIODE_MIN, SERVO_PERIODE_MAX, 5, Displ_Format_Int, V_REPEAT); // pmenu global
if (eep_val != servo_frame) {
servo_frame = eep_val;
eeprom_write_byte(&ep_servo_frame, servo_frame);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Test_ServoNr(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_SERVO);
eep_val = Change_Value(servo_nr, 0, 1, 4, Displ_ServoNr, C_REPEAT); // pmenu global; es gibt nur 0=Servo1, 1=Servo2
if (eep_val != servo_nr) {
servo_nr = eep_val;
eeprom_write_byte(&ep_servo_nr, servo_nr);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
// Dieser Test im raw-Modus ohne Anschlagkalibrierung (normiert) z.B.: für Modelleinstellungen ohne Empfänger
void Menu_Test_PulseWidth(void)
{ uint8_t tmp_tracking;
 
tmp_tracking = Servo_tmp_on(servo_frame);
lcdWriteCGRAM_Array(lcdSpecialChrLs, 8); // LCD-Char mit Rahmensymbole vom Graph
chrxs = CHRLS; // verhindert wiederholtes Lesen bereits geladener LCD-Char
Displ_Title(MSG_PULSE_WIDTH);
Change_Value(steps_pw[sIdxSteps].mid, steps_pw[sIdxSteps].min, steps_pw[sIdxSteps].max, 4, Displ_PulseWidth, V_REPEAT); // pmenu global
lcdWriteCGRAM_Array(lcdSpecialChr, 7); // LCD-Char für Bargraph zurückschreiben
cli();
servoInit(SERVO_PERIODE);
sei();
Servo_tmp_Original(tmp_tracking);
}
 
void Menu_Test_Continuous(void)
{ uint8_t scr_sub_menu[6] = {MSG_RETURN, MSG_START, MSG_SINGLE_STEP, MSG_REPEAT, MSG_PAUSE, MSG_PAUSE_STEP};
 
Scroll_Menu(scr_sub_menu, 5, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_Test_SingleStep(void)
{uint32_t eep_val;
 
Displ_Title(MSG_SINGLE_STEP);
eep_val = Change_Value(single_step, SINGLE_STEP_MIN, SINGLE_STEP_MAX, 5, Displ_Off_Format_Int, V_REPEAT); // pmenu global
if (eep_val != single_step) {
single_step = eep_val;
eeprom_write_byte(&ep_single_step, single_step);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Test_Repeat(void)
{uint32_t eep_val;
 
Displ_Title(MSG_REPEAT);
eep_val = Change_Value(repeat, REPEAT_MIN, REPEAT_MAX, 5, Displ_Format_Int, V_REPEAT); // pmenu global
if (eep_val != repeat) {
repeat = eep_val;
eeprom_write_byte(&ep_repeat, repeat);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Test_Pause(void)
{uint32_t eep_val;
 
Displ_Title(MSG_PAUSE);
eep_val = Change_Value(pause, PAUSE_MIN, PAUSE_MAX, 5, Displ_Pause, V_REPEAT); // pmenu global
if (eep_val != pause) {
pause = eep_val;
eeprom_write_byte(&ep_pause, pause);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Test_Pause_Step(void)
{uint32_t eep_val;
 
Displ_Title(MSG_PAUSE_STEP);
eep_val = Change_Value(pause_step, PAUSE_STEP_MIN, PAUSE_STEP_MAX, 5, Displ_Pause_Step, V_REPEAT); // pmenu global
if (eep_val != pause_step) {
pause_step = eep_val;
eeprom_write_byte(&ep_pause_step, pause_step);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
int8_t calc_dir(uint8_t idx, int16_t *Position)
{ uint8_t nextIdx;
int8_t nextDir = 1;
 
nextIdx = idx;
if ((idx + 1) < POSIDX_MAX)
nextIdx++;
else
nextIdx = 0;
if (Position[PosIdx[idx]] > Position[PosIdx[nextIdx]]) nextDir = -1;
return(nextDir);
}
 
// Test über Scalierung der Servos mit Anschlagkalibrierung
void Menu_Test_Start(void)
{ uint8_t tmp_tracking, idx, rep;
int8_t dir;
int16_t sPos;
int16_t Position[3];
int16_t range;
tmp_tracking = Servo_tmp_on(servo_frame);
lcdWriteCGRAM_Array(lcdSpecialChrLs, 8); // LCD-Char mit Rahmensymbole vom Graph
chrxs = CHRLS; // Flag, welche Kästchensymbole geladen
Displ_Title(MSG_CONTINOUS);
Position[0] = 0; // skalierte Servoposition aber unterschiedliche Schrittanzahl möglich
Position[1] = ServoSteps()/2;
Position[2] = ServoSteps();
// init Einzelschritt
idx = 0;
dir = calc_dir(idx, Position);
sPos = Position[PosIdx[idx]];
idx++;
rep = repeat;
// Test bis Ende der Wiederholungen oder irgendein Enter
while( !Get_Key_Short( 1<<SW_ENTER ) && (pmenu[0] !='\0') && (rep > 0)) {
range = calc_range(sPos - Position[1], Position[0], Position[2], Position[1]);
draw_bar(sPos - Position[1], range, 1);// eingerahmter Balkengraph auf 2. Display-Zeile
servoSetPosition(servo_nr, sPos);
 
if ( sPos != Position[PosIdx[idx]]) { // Links-, Mittel- oder Rechtsposotion erreicht?
sPos += (single_step * dir); // variable Schrittweite subtrahieren oder addieren
if (((dir < 0) && (sPos < Position[PosIdx[idx]])) || ((dir > 0) && (sPos > Position[PosIdx[idx]])) || !(single_step))
sPos = Position[PosIdx[idx]]; // Überlauf bei variabler Schrittweite berücksichtigen oder Einzelschritt
_delay_ms(servo_frame + 1 + pause_step); // Bei Schrittweite um 1 würden welche übersprungen, zusätzlich pro Servoschritt verzögert
}
else {
dir = calc_dir(idx, Position); // Richtungsänderung
if (idx < (POSIDX_MAX - 1)) {
if (idx == 0) rep--; // bei jeden vollen Durchlauf Wiederholzähler verringern
idx++; // Index für nächsten Positionswert ==> Array PosIdx[] bestimmt Anschlagreihenfolge
}
else
idx = 0;
delay_ms100x(pause); // variable Pause bei Links-, Mittel- und Rechtsposotion Mindestzeit 400ms (Servolauf)
}
Long_Enter();
}
lcdClear();
if (pmenu[0] == '\0')
Displ_Main_Disp();
else
return_m_pkt(strlen(pmenu)); // um bei Rücksprung auf ursprünglichen Menüpunkt zeigen oder Displ_Main_Disp()
lcdWriteCGRAM_Array(lcdSpecialChr, 7);// LCD-Char für Bargraph zurückschreiben
cli();
servoInit(SERVO_PERIODE);
sei();
Servo_tmp_Original(tmp_tracking);
}
 
 
/**************************/
/* */
/* LCD */
/* */
/**************************/
void Menu_lcd(void)
{ uint8_t scr_sub_menu[3] = {MSG_RETURN, MSG_CONTRAST, MSG_BACKGR_LIGHT};
 
Scroll_Menu(scr_sub_menu, 2, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_lcd_Contrast(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_LCD);
lcdGotoXY(2, ZLE_VAL);
lcdPuts(Msg(MSG_CONTRAST));
lcdPuts(": ");
eep_val = Change_Value(contrast, CONTRAST_MIN, CONTRAST_MAX, 11, Displ_Set_Contrast, C_REPEAT); // pmenu global
if (eep_val != contrast) {
contrast = eep_val;
eeprom_write_byte(&ep_contrast, contrast);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_lcd_Backgr_Light(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_BACKGR_LIGHT);
lcdGotoXY(0, ZLE_VAL);
lcdPuts(Msg(MSG_LIGHT));
eep_val = Change_Value(light_time, BACKGR_LIGHT_MIN, BACKGR_LIGHT_MAX, 6, Displ_Backgr_Light, V_REPEAT); // pmenu global
if (eep_val != light_time) {
light_time = eep_val;
eeprom_write_byte(&ep_light_time, light_time);
Double_Beep(DBEEPWR, DBEEPWRP);
if (light_time == BACKGR_LIGHT_MIN) lcdSet_BackgrLight_Off(); // Hintergrundbeleuchtung immer aus ==> sofort schalten
}
Jump_Menu(pmenu);
}
 
/**************************/
/* */
/* Batterie */
/* */
/**************************/
void Menu_Battery(void)
{ uint8_t scr_sub_menu[4] = {MSG_RETURN, MSG_U_SETUP, MSG_U_OFFSET, MSG_MK_BATTERY};
 
Scroll_Menu(scr_sub_menu, 3, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_Low_U_Setup(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_U_MIN);
eep_val = Change_Value(u_min, U_MIN_MIN, U_MIN_MAX, 4, Displ_U_2Nk, V_REPEAT); // pmenu global
if (eep_val != u_min) {
u_min = eep_val;
eeprom_write_dword(&ep_u_min, u_min);
hyst_u_min = u_min;
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_U_Offset(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_U_OFFSET);
eep_val = Change_Value(u_offset, U_OFFSET_MIN, U_OFFSET_MAX, 4, Displ_U_2Nk, V_REPEAT); // pmenu global
if (eep_val != u_offset) {
u_offset = eep_val;
eeprom_write_byte(&ep_u_offset, u_offset);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_MK_Battery(void)
{ uint8_t scr_sub_menu[6] = {MSG_RETURN, MSG_MK_BAT_NR, MSG_MK_BAT_CAPACITY, MSG_MK_I_OFFSET, MSG_MK_I_FAKTOR, MSG_MK_W_FAKTOR};
 
Scroll_Menu(scr_sub_menu, 5, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_MK_BatteryChangeNr(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_MK_BAT_NR);
eep_val = Change_Value(akku_nr+1, AKKU_NR_MIN+1, AKKU_NR_MAX+1, 5, Displ_Format_Int, V_REPEAT); // pmenu global
eep_val--;
if (eep_val != akku_nr) {
akku_nr = eep_val;
eeprom_write_byte(&ep_akku_nr, akku_nr);
eeprom_read_block(&lipo,&ep_lipo[akku_nr],sizeof(lipo_t));
Double_Beep(DBEEPWR, DBEEPWRP);
}
}
 
void Menu_MK_BatteryNr(void)
{
Menu_MK_BatteryChangeNr();
Jump_Menu(pmenu);
}
 
void Menu_MK_BatteryCapacity(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_MK_BAT_CAPACITY);
eep_val = Change_Value(lipo.Capacity/50, AKKU_CAPACITY_MIN/50, AKKU_CAPACITY_MAX/50, 5, Displ_MK_Capacity, V_REPEAT); // pmenu global
if (eep_val != lipo.Capacity/50) {
lipo.Capacity = eep_val * 50;
eeprom_write_block(&lipo,&ep_lipo[akku_nr],sizeof(lipo_t));
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_MK_I_Offset(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_MK_I_OFFSET);
eep_val = Change_Value(mk_i_offset, MK_I_OFFSET_MIN, MK_I_OFFSET_MAX, 5, Displ_I_Offset, V_REPEAT); // pmenu global
if (eep_val != mk_i_offset) {
mk_i_offset = eep_val;
eeprom_write_byte(&ep_mk_i_offset, mk_i_offset);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_MK_I_Faktor(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_MK_I_FAKTOR);
eep_val = Change_Value(mk_i_faktor, MK_I_FAKTOR_MIN, MK_I_FAKTOR_MAX, 6, Displ_Faktor_2Nk, V_REPEAT); // pmenu global
if (eep_val != mk_i_faktor) {
mk_i_faktor = eep_val;
eeprom_write_byte(&ep_mk_i_faktor, mk_i_faktor);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_MK_W_Faktor(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_MK_W_FAKTOR);
eep_val = Change_Value(mk_w_faktor, MK_W_FAKTOR_MIN, MK_W_FAKTOR_MAX, 6, Displ_Faktor_2Nk, V_REPEAT); // pmenu global
if (eep_val != mk_w_faktor) {
mk_w_faktor = eep_val;
eeprom_write_byte(&ep_mk_w_faktor, mk_w_faktor);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
 
/**************************/
/* */
/* Antennennachführung */
/* */
/**************************/
void Menu_Tracking_Ant(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_TRACKING);
eep_val = Change_Value(tracking, TRACKING_MIN, TRACKING_MAX, 3, Displ_sel_Tracking, C_REPEAT); // pmenu global
if (eep_val != tracking) {
cli();
tracking = eep_val;
sei();
eeprom_write_byte(&ep_tracking, tracking);
Double_Beep(DBEEPWR, DBEEPWRP);
USART_RX_Mode(tracking); // Unterschied Datenempfang GPS/MKCockpit
coldstart = 1;
rxcount0 = 0;
rxcount1 = 0;
servoSetDefaultPos(); // Ausgangsstellung beider Servos
if (tracking > TRACKING_MIN)
servoInit(SERVO_PERIODE);
else {
delay_ms100x(4); // sonst wird Impuls bereits vor erreichen der Mittelstellung abgeschaltet
servoOff();
}
USART_Init_Baudrate();
}
Jump_Menu(pmenu);
}
 
/**************************/
/* Optionen */
/* Antennennachführung */
/* */
/**************************/
void Menu_Tracking_HYST(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_HYSTERESE);
eep_val = Change_Value(track_hyst, TRACKING_HYST_MIN, TRACKING_HYST_MAX, 7, Displ_Format_Int, V_REPEAT); // pmenu gloabal
if (eep_val != track_hyst) {
track_hyst = eep_val;
eeprom_write_byte(&ep_track_hyst, track_hyst);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Tracking_TXOSD(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_TRACK_TX_OSD_DATA);
eep_val = Change_Value(track_tx, 0, 1, 3, Displ_track_TX, C_REPEAT); // pmenu global; Senden gibt es nur 0=off, 1=on
if (eep_val != track_tx) {
track_tx = eep_val;
eeprom_write_byte(&ep_track_tx, track_tx);
Double_Beep(DBEEPWR, DBEEPWRP);
}
Jump_Menu(pmenu);
}
 
void Menu_Baudrate(void)
{ uint32_t eep_val;
 
Displ_Title(MSG_BAUDRATE);
eep_val = Change_Value(baudrate, BAUDRATE_MIN, BAUDRATE_MAX, 3, Displ_Baudrate, C_REPEAT); // pmenu global; Senden gibt es nur 0=off, 1=on
if (eep_val != baudrate) {
baudrate = eep_val;
eeprom_write_byte(&ep_baudrate, baudrate);
Double_Beep(DBEEPWR, DBEEPWRP);
USART_Init(baud[baudrate]);
}
Jump_Menu(pmenu);
}
 
void Menu_Tracking_Option(void)
{ // im Menü ist dies der gleiche Gliederungspunkt aber mit geänderter Auswahl
switch(tracking) {
case TRACKING_RSSI: Menu_Tracking_HYST();
break;
case TRACKING_GPS: Menu_Tracking_TXOSD();
break;
case TRACKING_MKCOCKPIT: Menu_Baudrate();
}
}
 
/**************************/
/* */
/* Anzeige GPS */
/* */
/**************************/
void Menu_GPS_Display(void)
{ uint8_t scr_sub_menu[6] = {MSG_RETURN, MSG_GPS_CALCULATE, MSG_GPS_CURRENT, MSG_GPS_HOME, MSG_GPS_MISC, MSG_RX_TIME};
 
Scroll_Menu(scr_sub_menu, 5, m_pkt); // pmenu global
Jump_Menu(pmenu);
}
 
void Menu_GPS_Display_FLAG(void) // ist Flag in tracking.c Tracking_GPS(void)
{ uint8_t slen;
slen = strlen(pmenu) - 1;
gps_display = pmenu[slen] - '0'; // char to byte 1 bis 3 im String enthalten
m_pkt = gps_display;
gps_disp_clear = 1; // damit Text "...keine Daten empf..." nach Datenempfang gelöscht wird
if (gps_display != GPS_MISC) lcdPuts(Msg(MSG_GPS_NO_DATA));
if (Short_Enter()) // pmenu global
pmenu[slen] = '\0'; // Menüpunkt zurück
gps_display = GPS_DISP_NONE; // nach Tastaturabfrage keine Anzeige GPS, sondern normales Menü
Jump_Menu(pmenu);
}
 
void Menu_GPS_Displ_RX_Time(void)
{
Displ_Title(MSG_RX_TIME);
lcdGotoXY(0, 1);
lcdPuts(Msg(MSG_RX1));
lcdGotoXY(0, 2);
lcdPuts(Msg(MSG_RX2));
Displ_RX_Time();
gps_display = GPS_RX_COUNT;
m_pkt = gps_display;
if (Short_Enter()) // pmenu global
pmenu[strlen(pmenu) - 1] = '\0';// Menüpunkt zurück
gps_display = GPS_DISP_NONE; // nach Tastaturabfrage keine Anzeige GPS, sondern normales Menü
Jump_Menu(pmenu);
}