Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 2135 → Rev 2136

/Transportables_Koptertool/PKT/GPL_PKT_V3_85f/utils/menuctrl.c
0,0 → 1,1501
/*****************************************************************************
* Copyright (C) 2013 Oliver Gemesi *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*****************************************************************************/
 
//############################################################################
//# HISTORY menuctrl.c
//#
//# 11.06.2014 OG
//# - add: MenuCtrl_GetMenuIndex()
//#
//# 31.05.2014 OG
//# - chg: MenuCtrl_Refresh() - umgestellt auf PKT_KeylineUpDown()
//#
//# 14.05.2014 OG
//# - chg: include "../mk/paramset.h" geaendert auf "../mksettings/paramset.h"
//# - chg: include "../mk/mkparameters.h" geaendert auf "../mksettings/mkparameters.h"
//#
//# 11.05.2014 OG
//# - add: MenuCtrl_SetTitleFromParentItem()
//# - add: MenuCtrl_GetItemText(), MenuCtrl_IsItemTextPGM()
//# - chg: _MenuCtrl_Error() - auf PKT_Popup_P() umgestellt, Layout geaendert und
//# einen neuen Fehler (NOPARENTMENU) hinzugefuegt
//#
//# 09.05.2014 OG
//# - fix: MenuCtrl_Refresh() Anzeige von deaktivierten MK-Parametern (Favoriten)
//# Wenn MK-Paramketer-Menueeintraege deaktiviert sind werden sie vom
//# aktuellen MK-Parameterset nicht unterstuetzt - dennoch wurde der
//# aktuelle Wert des MK-Parameters im Menuepunkt (ganz rechts) angezeigt.
//# Das ist jetzt behoben - es wird kein Wert angezeigt (stattdessen "***")
//# und auch keine entsprechende editParam-Funktionen aufgerufen.
//#
//# 07.05.2014 OG
//# - add: MenuCtrl_PushSeparatorID()
//#
//# 06.05.2014 OG
//# - chg: MenuCtrl_Refresh() Keyline leicht angepasst
//# - chg: 'not possible' Anzeige (bei deaktiviertem Item) umgestellt auf
//# PKT_Popup_P()
//# - add: MenuCtrl_GetItemIdByIndex(), MenuCtrl_GetItemCount()
//#
//# 05.05.2014 OG
//# - chg: MenuCtrl_Control()
//# -> Unterstuetzung fuer: MenuCtrl_SetMove() - Menueeintraege verschieben
//# - chg: MenuCtrl_Refresh() - Anpassung Slider fuer MenuCtrl_SetDelete()
//# - add: MenuCtrl_SetDelete(), MenuCtrl_SetMove()
//# - add: _MenuCtrl_SwapItem()
//# - add: die Datenstruktur vom Menue wurde erweitert um die Eigenschaften
//# canMove und canDelete
//#
//# 17.04.2014 OG
//# - chg: MENUCTRL_MAXITEMS von 22 auf 28 erhoeht
//#
//# 30.03.2014 OG
//# - del: MenuCtrl_PushML_P(), MenuCtrl_PushML() (Umstellung Sprachen abgeschlossen)
//# - add: MenuCtrl_PushML2(), MenuCtrl_PushML2_P() fuer Umstellung von 3 auf 2 Sprachen
//#
//# 29.03.2014 OG
//# - chg: default MENUDEFAULT_SHOWBATT auf true umgestellt (=PKT-Batterie anzeigen)
//# - chg: MenuCtrl_Control() umgestellt auf clear_key_all()
//#
//# 24.03.2014 OG
//# - add: MenuCtrl_PushSeparator() - fuegt eine Trennlinie im Menue ein
//# - chg: MenuCtrl_Refresh() Codeoptimierung bzgl. topspace/Zeile loeschen/Slider
//# - fix: MenuCtrl_Control() es wurde zuoft ein Screen-Refresh durchgefuehrt
//#
//# 23.03.2014 OG
//# - add: Unterstuetzung fuer MK-Parameter-Edit (mkparameters.c)
//# - chg: MenuCtrl_Refresh() Unterstuetzung fuer MENU_PARAMEDIT
//# - add: MenuCtrl_PushParamEdit()
//# - add: paramset.h und mkparameters.h
//#
//# 04.03.2014 OG
//# - fix: MenuCtrl_Refresh() bei einem blauen Display (das ist wohl schneller
//# in der Anzeige als das S/W-Display) flackerte der Menue-Slider
//#
//# 17.02.2014 OG
//# - add: MenuCtrl_SetTopSpace()
//# - chg: MenuCtrl_Refresh() angepasst auf MenuCtrl_SetTopSpace()
//#
//# 15.02.2014 OG
//# - add: MenuCtrl_ItemSelect()
//#
//# 01.02.2014 OG
//# - chg: MENUCTRL_MAXITEMS von 16 auf 22 fuer MK_parameters
//# - fix: _MenuCtrl_Error() Anzeigezeit von Menu-Errors auf 8 Sekunden verlaengert
//# und Anzeige von "menuctrl.c"
//#
//# 07.07.2013 OG
//# - add: MenuCtrl_ItemMarkR() - Markiert einen Menueeintrag mit einem Haken am ENDE (Rechts)
//#
//# 24.05.2013 OG
//# - chg: MenuCtrl_Push... Funktionen vereinheitlicht mit internen Aenderungen
//# betrifft externe Funktionsaufrufe die geƤndert wurden
//# - chg: MenuCtrl_Refresh() Anpassungen und Optimierung
//# - add: MenuCtrl_ItemMark()
//# - del: MenuCtrl_PushSimple_P(), MenuCtrl_PushSimple()
//#
//# 23.05.2013 OG
//# - add: MenuCtrl_PushSimple_P(), MenuCtrl_PushSimple()
//# - fix: MenuCtrl_Control() Eventcode Rueckgabe bei KEY_ENTER
//#
//# 22.05.2013 OG
//# - fix: nach Aufruf einer Menuefunktion in MenuCtrl_Control() jetzt
//# get_key_press(KEY_ALL)
//#
//# 21.05.2013 OG
//# - add: MenuCtrl_ShowLevel()
//#
//# 20.05.2013 OG
//# - chg: MenuCtrl_Control() wieder mit get_key_press(KEY_ALL) ergaenzt
//# wenn aufgerufen mit MENUCTRL_EVENT oder erster Aufruf mit RETURN
//#
//# 20.05.2013 OG
//# - chg: Space am Anfang der Titelanzeige
//#
//# 19.05.2013 OG
//# - add: define MENU_SHOWLEVEL mit dem der aktuelle Menuelevel in der
//# Titelzeile angezeigt werden kann
//# - fix: Redraw-Logik bei MENUCTRL_RETURN
//# - chg: MenuCtrl_Control() erweitert um PKT_Update()
//#
//# 18.05.2013 OG - NEU
//############################################################################
 
#include "../cpu.h"
#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <string.h> // memset
#include <stdarg.h>
 
#include "../main.h"
#include "../lcd/lcd.h"
#include "../eeprom/eeprom.h"
#include "../messages.h"
#include "../lipo/lipo.h"
#include "../menu.h"
#include "../pkt/pkt.h"
#include "../mksettings/paramset.h"
#include "../mksettings/mkparameters.h"
#include "menuctrl.h"
 
 
//#############################################################################################
//# internal defines & structs
//#############################################################################################
 
#define MENU_SHOWLEVEL false // Anzeige der Menue-Verschachtelungstiefe in der Titelzeile
// zeigt dem Benutzer wie weit er wieder zurueckspringen muss
// um in das Hauptmenue zu kommen
 
#define MENUDEFAULT_CYCLE false // cycle: wenn Menue am Ende dann wieder zum Anfang
#define MENUDEFAULT_SHOWBATT true // showbatt: zeigt PKT-Batterie im Menuetitel ganz rechts
#define MENUDEFAULT_BEEP true // beep: wenn Cursor ueber Ende/Anfang
 
 
#define MENUCTRL_MAXMENUES 6 // Anzahl max. verschachlteter Menues
//#define MENUCTRL_MAXITEMS 22 // Anzahl max. Menu-Items pro Menue (verbraucht Speicher)
//#define MENUCTRL_MAXITEMS 28 // Anzahl max. Menu-Items pro Menue (verbraucht Speicher)
#define MENUCTRL_MAXITEMS 34 // Anzahl max. Menu-Items pro Menue (verbraucht Speicher)
#define ERROR_NOMENU 1 // Errorcode
#define ERROR_MAXMENU 2 // Errorcode
#define ERROR_MAXITEM 3 // Errorcode
#define ERROR_NOITEM 4 // Errorcode
#define ERROR_NOPARENTMENU 5 // Errorcode
 
//-----------------------------------------------------------
// typedef: scrollbox_key_t
//-----------------------------------------------------------
typedef struct
{
uint8_t active; // Taste aktiv? (true/false)
const char *text; // Tastentext
void (*func)(void); // ggf. Funktions-Pointer (0=keine Funktion)
} menue_key_t;
 
 
//---------------------------
// typedef: einzelnes Menueitem
//---------------------------
typedef struct
{
uint8_t id;
uint8_t type; // MENU_ITEM, MENU_SUB, MENU_PARAMEDIT
uint8_t disabled; // true / false (deaktiviert einen Menuepunkt)
uint8_t mark; // true / false (markiert einen Menuepunkt Links '*')
uint8_t markR; // true / false (markiert einen Menuepunkt Rechts)
uint8_t textPGM; // true / false (true = text in PROGMEN; false = text im RAM)
uint8_t textcount; // 1 .. NUM_LANG
const char *text[NUM_LANG]; // de, en, nl (NUM_LANG aus messages.h)
void (*func)(void);
} menue_item_t;
 
 
//---------------------------
// typedef: Menueitem Liste
//---------------------------
typedef struct
{
uint8_t active; // aktives item
uint8_t itemcount; // Anzahl Items
uint8_t scroll_pos; // aktuelle obere Anzeigezeile
uint8_t display_pos; // aktuelle obere Anzeigezeile
uint8_t topspace; // obere Leerzeilen - default=0 (Vorsicht! ggf. nur bedingt einsetzbar bei Menues die ohne scrollen auskommen!)
uint8_t firstredraw; // true / false (flag fuer ein erstes redraw bei MENUCTRL_RETURN)
uint8_t cycle; // true / false
uint8_t showbatt; // true / false
uint8_t beep; // true / false
uint8_t canMove; // true / false
uint8_t canDelete; // false/0 = kein entfernen; true/1 = entfernen mit Nachfrage; 2 = entfernen ohne Nachfrage
uint8_t titlePGM; // true / false
const char *title; // Menuetitel (oberste Zeile) (ggf. Multisprache machen?)
uint8_t lastkey; // verwendet von GetKey()
menue_key_t key_enter;
menue_key_t key_enter_long;
menue_key_t key_esc;
menue_key_t key_esc_long;
menue_item_t item[MENUCTRL_MAXITEMS];
} menue_t;
 
uint8_t showlevel = MENU_SHOWLEVEL; // Anzeige Menulevel in der Titelanzeige
int8_t midx = -1; // aktives Menue; -1 = kein Menue
menue_t menu[MENUCTRL_MAXMENUES]; // Stack fuer n geschachltete Menues
 
 
 
//#############################################################################################
//# PRIVAT funcs
//#############################################################################################
 
 
//--------------------------------------------------------------
// INTERN
//--------------------------------------------------------------
void _MenuCtrl_Error( uint8_t error )
{
const char *pStr = NULL;
 
switch( error )
{
case ERROR_NOMENU: pStr = PSTR("NOMENU"); break;
case ERROR_MAXMENU: pStr = PSTR("MAXMENU"); break;
case ERROR_MAXITEM: pStr = PSTR("MAXITEM"); break;
case ERROR_NOITEM: pStr = PSTR("NOITEM"); break;
case ERROR_NOPARENTMENU: pStr = PSTR("NOPARENTMENU"); break;
}
 
set_beep( 1000, 0x000f, BeepNormal); // Beep Error
PKT_Popup_P( 10000, PSTR("menuctrl.c"), 0, PSTR("* ERROR *"), pStr ); // 10000 = max. 100 Sekunden anzeigen
}
 
 
//--------------------------------------------------------------
// INTERN
//--------------------------------------------------------------
int8_t _MenuCtrl_FindItem( uint8_t itemid )
{
int8_t i;
 
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return -1; }
 
for( i=0; i<menu[midx].itemcount; i++)
{
if( itemid == menu[midx].item[i].id )
{
return i; // found: return index
}
}
return -1; // not found
}
 
 
//--------------------------------------------------------------
// INTERN
//--------------------------------------------------------------
void _MenuCtrl_CalcDisplayPos( void )
{
int8_t i;
 
i = menu[midx].active - menu[midx].display_pos;
 
if( i < 0 )
menu[midx].display_pos = menu[midx].active;
else if( i > 5 )
menu[midx].display_pos = (menu[midx].active - 5);
}
 
 
//--------------------------------------------------------------
// INTERN
//--------------------------------------------------------------
void _MenuCtrl_Beep( void )
{
if( menu[midx].beep )
set_beep( 25, 0xffff, BeepNormal );
}
 
 
//--------------------------------------------------------------
// INTERN
// Dreieckstausch von zwei Menuepunkten.
// Wird verwendet um Menueitems zu verschieben.
//--------------------------------------------------------------
void _MenuCtrl_SwapItem( uint8_t itemindex_1, uint8_t itemindex_2 )
{
menue_item_t tmpItem;
 
memcpy( &tmpItem , &menu[midx].item[itemindex_1], sizeof(menue_item_t) );
memcpy( &menu[midx].item[itemindex_1] , &menu[midx].item[itemindex_2], sizeof(menue_item_t) );
memcpy( &menu[midx].item[itemindex_2] , &tmpItem, sizeof(menue_item_t) );
}
 
 
 
//#############################################################################################
//# PUBLIC funcs
//#############################################################################################
 
 
//--------------------------------------------------------------
// MenuCtrl_Create()
//--------------------------------------------------------------
void MenuCtrl_Create( void )
{
if( midx >= MENUCTRL_MAXMENUES) { _MenuCtrl_Error( ERROR_MAXMENU ); return; }
 
midx++;
memset( &menu[midx], 0, sizeof(menue_t) );
menu[midx].cycle = MENUDEFAULT_CYCLE;
menu[midx].showbatt = MENUDEFAULT_SHOWBATT;
menu[midx].beep = MENUDEFAULT_BEEP;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_Destroy()
//--------------------------------------------------------------
void MenuCtrl_Destroy( void )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
midx--;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_ShowLevel( value )
//
// Diese Einstellung ist Global und wirkt sich direkt auf alle
// Menues aus!
// Man kann das also nicht fuer einzelne Menues ein-/ausschalten.
//
// Parameter:
// value: true / false
//--------------------------------------------------------------
void MenuCtrl_ShowLevel( uint8_t value )
{
showlevel = value;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_SetTitle_P( *title )
//
// Parameter:
// title: Menuetitel; Zeiger auf String PROGMEM
//--------------------------------------------------------------
void MenuCtrl_SetTitle_P( const char *title )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].title = title;
menu[midx].titlePGM = true;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_SetTitle( *title )
//
// Parameter:
// title: Menuetitel; Zeiger auf String im RAM
//--------------------------------------------------------------
void MenuCtrl_SetTitle( const char *title )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].title = title;
menu[midx].titlePGM = false;
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_SetTitleFromParentItem()
//
// setzte anhand des uebergeordneten Menuepunktes (dem aufrufenden
// Menuepunkt) den Titel des neuen Menues
//
// wird u.a. verwendet in setup.c
//--------------------------------------------------------------
void MenuCtrl_SetTitleFromParentItem( void )
{
uint8_t lang;
const char *pStr;
uint8_t mparent;
 
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
if( midx < 1) { _MenuCtrl_Error( ERROR_NOPARENTMENU ); return; }
 
mparent = midx-1;
 
//--------------------------
// Sprache: Multilanguage oder 0 wenn wenn nur ein Text
//--------------------------
lang = (menu[mparent].item[ menu[mparent].active ].textcount == 1) ? 0 : Config.DisplayLanguage;
 
//--------------------------
// Text vom uebergeordneten Menuepunkt
//--------------------------
pStr = menu[mparent].item[ menu[mparent].active ].text[lang];
 
//--------------------------
// Titel setzen
//--------------------------
if( menu[mparent].item[ menu[mparent].active ].textPGM )
{
MenuCtrl_SetTitle_P( pStr );
}
else
{
MenuCtrl_SetTitle( pStr );
}
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_SetCycle( value )
//
// Parameter:
// value: true / false
//--------------------------------------------------------------
void MenuCtrl_SetCycle( uint8_t value )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].cycle = value;
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_SetBeep( value )
//
// Parameter:
// value: true / false
//--------------------------------------------------------------
void MenuCtrl_SetBeep( uint8_t value )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].beep = value;
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_SetMove( value )
//
// Schaltet in einem Menue die Moeglichkeit ein Menueeintraege nach
// oben oder nach unten zu verschieben.
// Zum verschieden eines Menueeintrages muessen die PLUS/MINUS Tasten
// lange gedrueckt werden.
//
// Parameter:
// value: true / false (Default: false)
//--------------------------------------------------------------
void MenuCtrl_SetMove( uint8_t value )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].canMove = value;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_SetDelete( value )
//
// Schaltet in einem Menue die Moeglichkeit ein Menueeintraege zu loeschen.
// Zum loeschen eines Menueeintrages muss dann die ganz rechte 'OK' Taste
// lange gedrueckt werden.
//
// Parameter:
// value: true / false (Default: false)
//--------------------------------------------------------------
void MenuCtrl_SetDelete( uint8_t value )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].canDelete = value;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_SetShowBatt( value )
//
// Parameter:
// value: true / false
//--------------------------------------------------------------
void MenuCtrl_SetShowBatt( uint8_t value )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].showbatt = value;
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_SetTopSpace( n )
//
// fuegt oben im Menue n Leerzeichen ein um Abstand vom Menuetitel
// zu erhalten
//
// ACHTUNG! Das funktioniert nur mit Menues die nicht Scrollen!
// -> also weniger als 6 Eintraege haben (je nach Anzahl von TopSpace)
//
// ACHTUNG! Keine Absicherung bzgl. obigem Warnpunkt! Das kann man
// zwar machen - ist aber aktuell nicht so!
//
// Parameter:
// value: 0..n Anzahl der Leerzeilen ueber dem Menue
//--------------------------------------------------------------
void MenuCtrl_SetTopSpace( uint8_t n )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
 
menu[midx].topspace = n;
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_SetKey( key, *keytext, *keyfunc )
//
// Parameter:
// key : KEY_ENTER, KEY_ENTER_LONG, KEY_ESC, KEY_ESC_LONG
// keytext: Pointer auf Text PROGMEM oder NOTEXT (=0)
// keyfunc: Pointer auf Funktion oder NOFUNC (=0)
//--------------------------------------------------------------
void MenuCtrl_SetKey( uint8_t key, const char *keytext, void (*keyfunc)(void) )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; } // kein aktives Menue
 
if( key == KEY_ENTER )
{
menu[midx].key_enter.active = true;
menu[midx].key_enter.text = keytext;
menu[midx].key_enter.func = keyfunc;
}
 
if( key == KEY_ENTER_LONG )
{
menu[midx].key_enter_long.active = true;
menu[midx].key_enter_long.text = keytext;
menu[midx].key_enter_long.func = keyfunc;
}
 
if( key == KEY_ESC )
{
menu[midx].key_esc.active = true;
menu[midx].key_esc.text = keytext;
menu[midx].key_esc.func = keyfunc;
}
 
if( key == KEY_ESC_LONG )
{
menu[midx].key_esc_long.active = true;
menu[midx].key_esc_long.text = keytext;
menu[midx].key_esc_long.func = keyfunc;
}
}
 
 
//--------------------------------------------------------------
// key = MenuCtrl_GetKey()
//
// Rueckgabe:
// key: z.B. KEY_ENTER oder KEY_ENTER_LONG
//--------------------------------------------------------------
uint8_t MenuCtrl_GetKey( void )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein aktives Menue
 
return menu[midx].lastkey;
}
 
 
 
//--------------------------------------------------------------
// menuindex = MenuCtrl_GetMenuIndex()
//
// gibt den aktuellen Menuindex zurueck
//
// Rueckgabe:
// menuindex: <0 = keine Menue (-1)
// =0 = Hauptmenue (Toplevel)
// >0 = Untermenue Level
//--------------------------------------------------------------
int8_t MenuCtrl_GetMenuIndex( void )
{
return midx;
}
 
 
 
//--------------------------------------------------------------
// itemid = MenuCtrl_GetItemId()
//
// gibt die itemID des aktuell angewaehlten Menuepunktes zurueck
//
// Rueckgabe:
// itemid:
//--------------------------------------------------------------
uint8_t MenuCtrl_GetItemId( void )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein aktives Menue
 
return menu[midx].item[ menu[midx].active ].id;
}
 
 
 
//--------------------------------------------------------------
// itemid = MenuCtrl_GetItemIdByIndex( index )
//
// damit koennen die aktuell vorhanden itemID's der Menuepunkte
// ermittelt wenn im Menue via SetMove oder SetDelete Menuepunkte
// durch den Benutzer verschoben oder geloescht wurden.
//
// Parameter:
// index: von 0..itemcount-1
//--------------------------------------------------------------
uint8_t MenuCtrl_GetItemIdByIndex( uint8_t index )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein aktives Menue
 
if( (menu[midx].itemcount == 0) || (index > menu[midx].itemcount-1) ) return 0; // index ausserhalb aktiver Menuepunkte
 
return menu[midx].item[ index ].id;
}
 
 
 
//--------------------------------------------------------------
// num = MenuCtrl_GetItemCount()
//
// gibt die Anzahl der Menuepunkte zurueck
//
// Rueckgabe:
// num: Anzahl der Menuepunkte
//--------------------------------------------------------------
uint8_t MenuCtrl_GetItemCount( void )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein aktives Menue
 
return menu[midx].itemcount;
}
 
 
//--------------------------------------------------------------
// textPtr = MenuCtrl_GetItemText()
//
// gibt einen Pointer auf den Text des aktuellen Menuepunktes zurueck
//
// ACHTUNG! Der Pointer kann auf RAM oder auch auf PGM zeigen!
//
// Um herauszufinden auf welchen Bereich der Pointer zeigt kann
// MenuCtrl_IsItemTextPGM() verwendet werden.
//
// Rueckgabe:
// textPtr: in RAM oder PGM
//--------------------------------------------------------------
const char * MenuCtrl_GetItemText( void )
{
uint8_t lang;
 
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein aktives Menue
 
//--------------------------
// Sprache: Multilanguage oder 0 wenn wenn nur ein Text
//--------------------------
lang = (menu[midx].item[ menu[midx].active ].textcount == 1) ? 0 : Config.DisplayLanguage;
 
return menu[midx].item[ menu[midx].active ].text[lang];
}
 
 
 
//--------------------------------------------------------------
// isPGM = MenuCtrl_IsItemTextPGM()
//
// gibt true/false zurueck je nachdem der Text von MenuCtrl_GetItemText()
// im Progmem (=true) oder im RAM (=false) ist
//
// Rueckgabe:
// isPGM: true / false (true = text in PROGMEN; false = text im RAM)
//--------------------------------------------------------------
uint8_t MenuCtrl_IsItemTextPGM( void )
{
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein aktives Menue
 
return menu[midx].item[ menu[midx].active ].textPGM;
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_ItemSelect( itemid )
//
// aktiviert einen Menuepunkt / setzt den Menue-Cursor darauf
//
// die Funktion ist nicht durchgetestet, funktioniert aber
// in MKSettings_Menu() / mkparameters.c
//
// es kann sein das es zu Problemen kommt wenn das Menue
// scrollt (mehr als 6 Menueeintraege)
//
// Parameter:
// itemid: ID des Menuitems
//--------------------------------------------------------------
void MenuCtrl_ItemSelect( uint8_t itemid )
{
int8_t i;
 
i = _MenuCtrl_FindItem( itemid );
 
if( i >= 0 )
{
menu[midx].active = i;
}
}
 
 
//--------------------------------------------------------------
// MenuCtrl_ItemActive( itemid, value )
//
// Parameter:
// itemid: ID des Menuitems
// value : true / false
//--------------------------------------------------------------
void MenuCtrl_ItemActive( uint8_t itemid, uint8_t value )
{
int8_t i;
 
i = _MenuCtrl_FindItem( itemid );
 
if( i >= 0 )
{
menu[midx].item[i].disabled = !value;
}
}
 
 
//--------------------------------------------------------------
// MenuCtrl_ItemMark( itemid, value )
//
// Markiert einen Menueeintrag mit einem '*' am Anfang (Links).
// Wird u.a. von BT_SelectDevice() (setup.c) verwendet
//
// Parameter:
// itemid: ID des Menuitems
// value : true / false
//--------------------------------------------------------------
void MenuCtrl_ItemMark( uint8_t itemid, uint8_t value )
{
int8_t i;
 
i = _MenuCtrl_FindItem( itemid );
 
if( i >= 0 )
{
menu[midx].item[i].mark = value;
}
}
 
 
//--------------------------------------------------------------
// MenuCtrl_ItemMarkR( itemid, value )
//
// Markiert einen Menueeintrag mit einem Haken am ENDE (Rechts).
// Wird u.a. von ... (setup.c) verwendet
//
// Parameter:
// itemid: ID des Menuitems
// value : true / false
//--------------------------------------------------------------
void MenuCtrl_ItemMarkR( uint8_t itemid, uint8_t value )
{
int8_t i;
 
i = _MenuCtrl_FindItem( itemid );
 
if( i >= 0 )
{
menu[midx].item[i].markR = value;
}
}
 
 
//--------------------------------------------------------------
// INTERN
//
// fuer: MenuCtrl_PushML_P(), MenuCtrl_Push()
//--------------------------------------------------------------
void _MenuCtrl_Push( uint8_t useprogmem, uint8_t numlang, uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), ... )
{
va_list ap;
uint8_t idx;
uint8_t i;
 
if( midx < 0 ) { _MenuCtrl_Error( ERROR_NOMENU ); return; }
if( menu[midx].itemcount >= MENUCTRL_MAXITEMS ) { _MenuCtrl_Error( ERROR_MAXITEM ); return; }
//if( numlang > NUM_LANG ) { _MenuCtrl_Error( ERROR_MAXLANG ); return; }
 
idx = menu[midx].itemcount;
 
menu[midx].item[idx].id = itemid;
menu[midx].item[idx].type = itemtype; // MENU_ITEM, MENU_SUB
menu[midx].item[idx].mark = false;
menu[midx].item[idx].func = menufunc;
menu[midx].item[idx].textPGM = useprogmem;
menu[midx].item[idx].textcount= numlang;
 
va_start(ap, menufunc);
 
for( i=0; i<numlang; i++)
{
menu[midx].item[idx].text[i] = va_arg( ap, const char *);
}
 
va_end(ap);
 
menu[midx].itemcount++;
}
 
 
//--------------------------------------------------------------
// MenuCtrl_PushML2_P( itemid, itemtype, *menufunc, *text_de, *text_en, *text_nl )
//
// MultiLanguage Texte fuer 2 Sprachen (DE, EN)
// PROGMEN Version
//
// Parameter:
// itemid : ID des Menueitems
// itemtype: MENU_ITEM oder MENU_SUB (bei MENU_SUB wird noch ein ">" angezeigt)
// menufunc: Pointer auf Funktion oder NOFUNC (=0) wenn keine Funktion
// texte : alles Zeiger auf PROGMEM
//--------------------------------------------------------------
void MenuCtrl_PushML2_P( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text_de, const char *text_en )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( true, NUM_LANG, itemid, itemtype, menufunc, text_de, text_en );
}
 
 
//--------------------------------------------------------------
// MenuCtrl_PushML2( itemid, itemtype, *menufunc, *text_de, *text_en, *text_nl )
//
// MultiLanguage Texte fuer 2 Sprachen (DE, EN)
// RAM Version
//
// Parameter:
// itemid : ID des Menueitems
// itemtype: MENU_ITEM oder MENU_SUB (bei MENU_SUB wird noch ein ">" angezeigt)
// menufunc: Pointer auf Funktion oder NOFUNC (=0) wenn keine Funktion
// texte : alles Zeiger auf RAM
//--------------------------------------------------------------
void MenuCtrl_PushML2( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text_de, const char *text_en )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( false, NUM_LANG, itemid, itemtype, menufunc, text_de, text_en );
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void MenuCtrl_Push_P( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( true, 1, itemid, itemtype, menufunc, text );
}
 
 
//--------------------------------------------------------------
//--------------------------------------------------------------
void MenuCtrl_Push( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( false, 1, itemid, itemtype, menufunc, text );
}
 
 
//--------------------------------------------------------------
// Spezialfunktion fuer mkparameters.c !
//
// -> siehe: mkparameters.c / Menu_EditCategory()
//
// ACHTUNG!
// Die externe Variable paramEditItem muss in mkparameters.c
// vor Aufruf dieser Funktion richtig initialisiert sein!
// Ich habe darauf verzichtet hier nochmal ein find_paramEditItem()
// aufzurufen um Speicherplatz zu sparen.
//--------------------------------------------------------------
void MenuCtrl_PushParamEdit( uint8_t paramID )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( true, 2, paramID, MENU_PARAMEDIT, NOFUNC, paramEditItem.title_de, paramEditItem.title_en );
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_PushSeparator()
//
// fuegt eine Trennlinie im Menue ein
// (die itemID ist dabei 0)
//--------------------------------------------------------------
void MenuCtrl_PushSeparator( void )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( true, 0, 0, MENU_SEPARATOR, NOFUNC );
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_PushSeparatorID( itemId )
//
// fuegt eine Trennlinie im Menue ein mit einer eigenen itemID
//--------------------------------------------------------------
void MenuCtrl_PushSeparatorID( uint8_t itemid )
{
//_MenuCtrl_Push( useprogmem, numlang, itemid, itemtype, void (*menufunc)(void), ... )
_MenuCtrl_Push( true, 0, itemid, MENU_SEPARATOR, NOFUNC );
}
 
 
 
//--------------------------------------------------------------
// MenuCtrl_Refresh( mode )
//
// Parameter:
// mode: MENU_REDRAW || MENU_REFRESH
//--------------------------------------------------------------
void MenuCtrl_Refresh( uint8_t mode )
{
uint8_t y;
uint8_t item;
uint8_t sh;
uint8_t sy;
uint8_t actchar;
uint8_t markchar;
uint8_t markcharR;
uint8_t lang;
 
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return; } // kein Menue vorhanden
 
if( mode == MENU_REDRAW )
{
//--------------------------
// Clear
//--------------------------
lcd_frect( 0, 8, 6, 47, 0); // Clear: ganz linke Spalte des Sliders
lcd_frect( 127-2, 0, 2, 63, 0); // Clear: ganz rechts 2 Pixel
 
//--------------------------
// Titel
//--------------------------
if( menu[midx].title != 0 )
{
if( showlevel )
{
if( menu[midx].titlePGM )
lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR(" %19S"), menu[midx].title );
else
lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR(" %19s"), menu[midx].title );
 
writex_ndigit_number_u( 0, 0, midx, 1, 0, MINVERS, 1,0); // Menuelevel zeigen
}
else
{
if( menu[midx].titlePGM )
lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR(" %20S"), menu[midx].title );
else
lcdx_printf_at_P( 0, 0, MINVERS, 0,0 , PSTR(" %20s"), menu[midx].title );
}
}
else
lcd_frect( 0, 0, 128, 7, 1); // Titel: Leerzeile
 
 
//--------------------------
// Keyline Beschriftung
//--------------------------
lcdx_cls_row( 7, MNORMAL, 0);
PKT_KeylineUpDown( 1, 7, 0,0);
lcd_printp_at( 12, 7, strGet(KEYLINE4), MNORMAL);
 
 
// Taste: KEY_ENTER
if( menu[midx].key_enter.active && menu[midx].key_enter.text != 0 )
{
lcdx_printf_at_P( 17, 7, MNORMAL, 0,0 , PSTR("%4S"), menu[midx].key_enter.text );
}
 
// Taste: KEY_ESC
if( menu[midx].key_esc.active && menu[midx].key_esc.text != 0 )
{
lcdx_printf_at_P( 12, 7, MNORMAL, 0,0 , PSTR("%5S"), menu[midx].key_esc.text );
}
}
 
 
//--------------------------
// PKT Batterie Anzeige
//--------------------------
if( menu[midx].showbatt )
{
show_Lipo();
}
 
 
//--------------------------
// Zeilen
//--------------------------
for( y=0; y<6; y++)
{
item = y + menu[midx].display_pos;
 
if( item < menu[midx].itemcount )
{
//--------------------------
// char: aktuelle Auswahl
//--------------------------
actchar = ' ';
if( item == menu[midx].active )
{
if( menu[midx].item[item].disabled ) actchar = 0x15; // aktuelle Auswahl: Pfeil disabled
else actchar = 0x1d; // aktuelle Auswahl: Pfeil
}
 
//--------------------------
// char: markiert
//--------------------------
markchar = ' ';
if( menu[midx].item[item].mark ) markchar = '*';
 
//--------------------------
// char: markiert RECHTS
//--------------------------
markcharR = ' ';
if( menu[midx].item[item].type == MENU_SUB ) markcharR = 0x1d;
if( menu[midx].item[item].markR ) markcharR = SYMBOL_CHECK;
 
//--------------------------
// Sprache: Multilanguage oder 0 wenn wenn nur ein Text
//--------------------------
lang = (menu[midx].item[item].textcount == 1) ? 0 : Config.DisplayLanguage;
 
//--------------------------
// Ausgabe: RAM oder PROGMEM
//--------------------------
if( MENU_SEPARATOR == menu[midx].item[item].type )
{
lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%18S") , actchar, markchar, PSTR("") );
lcd_frect( 6*3, ((y+1)*8)+3, 124-(6*3), 0, 1); // Trennlinie
}
else if( MENU_PARAMEDIT == menu[midx].item[item].type )
{
// SPEZIELL fuer mkparameters.c - zeigt die paramID-Bezeichnung inkl. dem aktuellen WERT an!
strcpy_P( mkparam_strValueBuffer, PSTR("***")); // Vorbelegung von mkparam_strValueBuffer
if( !menu[midx].item[item].disabled ) // nur wenn Menuepunkt nicht deaktiviert (disabled = paramID nicht vorhanden)
{ // -> ermittle den aktuellen Wert der paramID fuer Anzeige
find_paramEditItem( menu[midx].item[item].id ); // paramID suchen (Ergebnis in Variable 'paramEditItem')
paramEditItem.editfunc( paramEditItem.paramID, MKPARAM_SHORTVALUE ); // Wert von paramID in mkparam_strValueBuffer darstellen
}
lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%14S %3s") , actchar, markchar, menu[midx].item[item].text[lang], mkparam_strValueBuffer );
}
else
{
// Anmerkung zu menu[midx].topspace: NUR fuer Menues OHNE scrollen!!
if( menu[midx].item[item].textPGM )
{
// String im PGM
if( menu[midx].item[item].type == MENU_SUB || menu[midx].item[item].markR )
lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%16S%c "), actchar, markchar, menu[midx].item[item].text[lang], markcharR );
else
lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%17S ") , actchar, markchar, menu[midx].item[item].text[lang] );
}
else
{
// String im RAM
if( menu[midx].item[item].type == MENU_SUB || menu[midx].item[item].markR )
lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%16s%c "), actchar, markchar, menu[midx].item[item].text[lang], markcharR );
else
lcdx_printf_at_P( 1, y+1+menu[midx].topspace, MNORMAL, 0,0 , PSTR("%c%c%17s ") , actchar, markchar, menu[midx].item[item].text[lang] );
}
}
 
} // end: if( item < menu[midx].itemcount )
 
 
//--------------------------
// evtl. Leerzeile loeschen
//--------------------------
if( (y < menu[midx].topspace) || (item >= menu[midx].itemcount+menu[midx].topspace) )
{
lcd_frect( 6, (y+1)*8, 128-6, 7, 0); // Zeile loeschen
}
 
}
 
 
//--------------------------
// Slider
//--------------------------
#define SLIDERH 45 // Finetuning der Slider-Hoehe
 
lcd_frect( 0, 8+1, 1, SLIDERH, 0); // Slider: full Clear
 
if( menu[midx].itemcount > 6 ) // Slider nur bei mehr als 6 Menueitems
{
// Slider: 7 zeilen * 8 pixel = 56 pixel
sh = (SLIDERH * 6) / menu[midx].itemcount; // Slider: Hoehe
sh = (sh > SLIDERH) ? SLIDERH : sh;
 
sy = 8+(menu[midx].display_pos * (SLIDERH-sh)) / (menu[midx].itemcount-6); // Slider: Position
 
//lcd_frect( 0, 8+1, 1, SLIDERH, 0); // Slider: full Clear (flackert auf blauen Display!)
//lcd_frect( 0, 8+1, 1, sy-(8), 0); // Slider: Clear / oben (nicht mehr notwendig da Aenderung am Refresh)
//lcd_frect( 0, sy+1+sh+1, 1, SLIDERH-(sh-sy+1), 0); // Slider: Clear / unten (nicht mehr notwendig da Aenderung am Refresh)
lcd_frect( 0, sy+1, 1, sh, 1); // Slider: Draw
}
}
 
 
 
//--------------------------------------------------------------
// event = MenuCtrl_Control( ctrlmode )
//
// Parameter:
// ctrlmode: MENUCTRL_EVENT || MENUCTRL_RETURN
//
// Rueckgabe:
// event: MENUEVENT_NONE || MENUEVENT_ITEM || MENUEVENT_KEY
//--------------------------------------------------------------
uint8_t MenuCtrl_Control( uint8_t ctrlmode )
{
uint8_t menu_event;
uint8_t refreshmode;
uint8_t item;
uint8_t wahl;
uint8_t i;
uint8_t goUp = false;
uint8_t goDown = false;
 
if( midx < 0) { _MenuCtrl_Error( ERROR_NOMENU ); return 0; } // kein Menue vorhanden
if( menu[midx].itemcount == 0) { _MenuCtrl_Error( ERROR_NOITEM ); return 0; } // kein Menueitem vorhanden
 
 
// bei MENUCTRL_RETURN muss man ggf. selber fuer ein Redraw sorgen
// (beim ersten Aufruf wird es jedoch dennoch erzwungen)
if( ctrlmode == MENUCTRL_EVENT || !menu[midx].firstredraw )
{
MenuCtrl_Refresh( MENU_REDRAW );
menu[midx].firstredraw = true;
}
 
clear_key_all();
 
do
{
menu_event = MENUEVENT_NONE;
menu[midx].lastkey = KEY_NONE;
refreshmode = false;
 
//--------------------------
// Pruefe PKT Update oder
// andere PKT-Aktion
//--------------------------
if( PKT_CtrlHook() ) // Update vom Updatetool angefordert?
{
refreshmode = MENU_REDRAW;
}
 
//--------------------------
// PKT Batterie Anzeige
//--------------------------
if( menu[midx].showbatt )
{
show_Lipo();
}
 
 
//--------------------------
// Cursor: nach oben (UP)
//--------------------------
//+++++
// UP - Verschiebemodus AKTIV
//+++++
if( menu[midx].canMove )
{
if( get_key_long(1 << KEY_MINUS) )
{
if( (menu[midx].active > 0) && (menu[midx].itemcount > 0) )
{
_MenuCtrl_SwapItem( menu[midx].active, menu[midx].active-1 );
goUp = true;
}
else _MenuCtrl_Beep(); // am oberen Ende angelangt
}
 
if( get_key_short(1 << KEY_MINUS) ) // up
{
goUp = true;
}
} // end: UP - Verschiebemodus AKTIV
 
 
//+++++
// UP - Verschiebemodus NICHT aktiv
//+++++
if( !menu[midx].canMove ) // up
{
if( get_key_press(1 << KEY_MINUS) || get_key_long_rpt_sp((1 << KEY_MINUS),2) ) // up
{
goUp = true;
}
} // end: UP - Verschiebemodus NICHT aktiv
 
 
//+++++
// UP - goUp
//+++++
if( goUp ) // up
{
refreshmode = MENU_REFRESH;
if( (menu[midx].active > 0) && (menu[midx].itemcount > 0) )
{
menu[midx].active--;
}
else if( menu[midx].cycle )
{
menu[midx].active = menu[midx].itemcount-1;
}
else
{
_MenuCtrl_Beep(); // am oberen Ende angelangt
}
_MenuCtrl_CalcDisplayPos();
}
 
 
//--------------------------
// Cursor: nach unten (DOWN)
//--------------------------
//+++++
// DOWN - Verschiebemodus AKTIV
//+++++
if( menu[midx].canMove )
{
if( get_key_long(1 << KEY_PLUS) )
{
if( menu[midx].active < menu[midx].itemcount-1 )
{
_MenuCtrl_SwapItem( menu[midx].active, menu[midx].active+1 );
goDown = true;
}
else _MenuCtrl_Beep(); // am unteren Ende angelangt
}
 
if( get_key_short(1 << KEY_PLUS) ) // up
{
goDown = true;
}
} // end: DOWN - Verschiebemodus AKTIV
 
 
//+++++
// DOWN - Verschiebemodus NICHT aktiv
//+++++
if( !menu[midx].canMove ) // up
{
if( get_key_press(1 << KEY_PLUS) || get_key_long_rpt_sp((1 << KEY_PLUS),2) ) // up
{
goDown = true;
}
} // end: DOWN - Verschiebemodus NICHT aktiv
 
 
//+++++
// DOWN - goDown
//+++++
if( goDown ) // down
{
refreshmode = MENU_REFRESH;
if( menu[midx].active < menu[midx].itemcount-1 )
{
menu[midx].active++;
}
else if( menu[midx].cycle )
{
menu[midx].active = 0;
}
else
{
_MenuCtrl_Beep(); // am unteren Ende angelangt
}
_MenuCtrl_CalcDisplayPos();
}
 
 
//--------------------------
//--------------------------
item = menu[midx].active;
goUp = false;
goDown = false;
 
 
//--------------------------
// KEY_ENTER
//--------------------------
if( get_key_short(1 << KEY_ENTER) )
{
refreshmode = MENU_REFRESH;
// todo: keyfunc
if( menu[midx].item[item].type == MENU_SEPARATOR )
{
// do nothing
}
else if( menu[midx].item[item].disabled )
{
set_beep( 200, 0x00ff, BeepNormal); // Beep
PKT_Popup_P( 200, strGet(STR_MENUCTRL_NOTPOSSIBLE),0,0,0); // "nicht mƶglich!"
refreshmode = MENU_REDRAW;
}
else if( menu[midx].item[item].func != NOFUNC )
{
menu[midx].item[item].func();
refreshmode = MENU_REDRAW;
}
else if( menu[midx].key_enter.func != NOFUNC )
{
menu[midx].key_enter.func();
refreshmode = MENU_REDRAW;
}
else
{
menu[midx].lastkey = KEY_ENTER;
menu_event = MENUEVENT_ITEM;
}
}
 
 
//--------------------------
// KEY_ENTER_LONG (Deletemodus AKTIV)
//
// loescht einen Menueeintrag
//--------------------------
if( menu[midx].canDelete && get_key_long(1 << KEY_ENTER) && (menu[midx].itemcount > 0) )
{
wahl = 1;
if( menu[midx].canDelete == 1 ) // ==1 -> mit Nachfrage
{
set_beep( 200, 0xffff, BeepNormal); // Beep
PKT_Popup_P( 0, strGet(STR_MENUCTRL_DELASK),PSTR(""),0,0); // "Eintrag entfernen?"
lcd_printp_at( 12, 7, strGet(YESNO), MINVERS);
 
wahl = 0;
while( !wahl )
{
if( get_key_short(1<<KEY_ESC) ) wahl = 1; // "Ja"
if( get_key_short(1<<KEY_ENTER) ) wahl = 2; // "Nein"
}
refreshmode = MENU_REDRAW;
}
 
if( wahl==1 )
{
for( i=menu[midx].active; i<menu[midx].itemcount-1; i++)
{
_MenuCtrl_SwapItem( i, i+1 );
}
menu[midx].itemcount--;
 
if( (menu[midx].display_pos > 0) && (menu[midx].display_pos+6 > menu[midx].itemcount) )
{
menu[midx].display_pos--;
menu[midx].active--;
}
 
if( menu[midx].active >= menu[midx].itemcount )
menu[midx].active = menu[midx].itemcount-1;
 
_MenuCtrl_CalcDisplayPos();
refreshmode = MENU_REDRAW;
 
if( menu[midx].canDelete == 2 ) // ==2 -> direkt loeschen, ohne Nachfrage
{
set_beep( 200, 0xffff, BeepNormal); // Beep
PKT_Popup_P( 200, strGet(STR_MENUCTRL_DELITEM),0,0,0); // "Eintrag entfernt!"
}
}
}
 
 
//--------------------------
// KEY_ENTER_LONG (NICHT Deletemodus)
//--------------------------
if( !menu[midx].canDelete && menu[midx].key_enter_long.active && get_key_long(1 << KEY_ENTER) )
{
refreshmode = MENU_REFRESH;
if( menu[midx].key_enter_long.func != NOFUNC )
{
menu[midx].key_enter_long.func();
refreshmode = MENU_REDRAW;
}
else
{
menu_event = MENUEVENT_KEY;
menu[midx].lastkey = KEY_ENTER_LONG;
}
}
 
 
//--------------------------
// KEY_ESC_LONG
//--------------------------
if( menu[midx].key_esc_long.active && get_key_long(1 << KEY_ESC) )
{
refreshmode = MENU_REFRESH;
if( menu[midx].key_esc_long.func != NOFUNC )
{
menu[midx].key_esc_long.func();
refreshmode = MENU_REDRAW;
}
else
{
menu_event = MENUEVENT_KEY;
menu[midx].lastkey = KEY_ESC_LONG;
}
}
 
 
//--------------------------
// KEY_ESC
//--------------------------
if( get_key_short(1 << KEY_ESC) )
{
refreshmode = MENU_REFRESH;
if( menu[midx].key_esc.func != NOFUNC )
{
menu[midx].key_esc.func();
refreshmode = MENU_REDRAW;
}
else
{
menu_event = MENUEVENT_KEY;
menu[midx].lastkey = KEY_ESC;
}
}
 
if( refreshmode )
{
MenuCtrl_Refresh( refreshmode );
clear_key_all();
}
}
while ( menu_event == MENUEVENT_NONE && ctrlmode == MENUCTRL_EVENT );
 
return menu_event;
}
 
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property
/Transportables_Koptertool/PKT/GPL_PKT_V3_85f/utils/menuctrl.h
0,0 → 1,138
/*****************************************************************************
* Copyright (C) 2013 Oliver Gemesi *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*****************************************************************************/
 
//############################################################################
//# HISTORY menuctrl.h
//#
//# 11.06.2014 OG
//# - add: MenuCtrl_GetMenuIndex()
//#
//# 11.05.2014 OG
//# - add: MenuCtrl_SetTitleFromParentItem()
//# - add: MenuCtrl_GetItemText(), MenuCtrl_IsItemTextPGM()
//#
//# 07.05.2014 OG
//# - add: MenuCtrl_PushSeparatorID()
//#
//# 06.05.2014 OG
//# - add: MenuCtrl_GetItemIdByIndex(), MenuCtrl_GetItemCount()
//#
//# 05.05.2014 OG
//# - add: MenuCtrl_SetDelete(), MenuCtrl_SetMove()
//#
//# 30.03.2014 OG
//# - del: MenuCtrl_PushML_P(), MenuCtrl_PushML() (Umstellung Sprachen abgeschlossen)
//# - add: MenuCtrl_PushML2(), MenuCtrl_PushML2_P() fuer Umstellung von 3 auf 2 Sprachen
//#
//# 24.03.2014 OG
//# - add: MenuCtrl_PushSeparator()
//# - add: MENU_SEPARATOR
//# - chg: Wert von MENU_REFRESH und MENU_REDRAW
//#
//# 23.03.2014 OG
//# - add: Unterstuetzung fuer MK-Parameter-Edit (mkparameters.c)
//# - add: MenuCtrl_PushParamEdit()
//# - add: define MENU_PARAMEDIT
//#
//# 17.02.2014 OG
//# - add: MenuCtrl_SetTopSpace()
//#
//# 15.02.2014 OG
//# - add: MenuCtrl_ItemSelect()
//#
//# 07.07.2013 OG
//# - add: MenuCtrl_ItemMarkR()
//#
//# 24.05.2013 OG
//# - chg: MenuCtrl_Push... Funktionen vereinheitlicht mit internen Aenderungen
//# betrifft externe Funktionsaufrufe die geƤndert wurden
//# - del: MenuCtrl_PushSimple_P(), MenuCtrl_PushSimple()
//# - add: MenuCtrl_ItemMark()
//#
//# 23.05.2013 OG
//# - add: MenuCtrl_PushSimple_P(), MenuCtrl_PushSimple()
//#
//# 21.05.2013 OG
//# - add: MenuCtrl_ShowLevel()
//#
//# 17.05.2013 OG - NEU
//############################################################################
 
#ifndef MENUCTRL_H
#define MENUCTRL_H
 
#define MENU_ITEM 1 // Typ des Menueitems: normaler Eintrag ohne ">" am Ende
#define MENU_SUB 2 // Typ des Menueitems: Submenue - es wird noch ein ">" angezeigt
#define MENU_SEPARATOR 3 // nur fuer MenuCtrl_PushSeparator() fuer (verwendet von mkparameters.c)
#define MENU_PARAMEDIT 4 // nur fuer MenuCtrl_PushParamEdit() fuer (verwendet von mkparameters.c)
 
#define NOFUNC 0 // keine Funktion uebergeben
#define NOTEXT 0 // kein Text uebergeben
 
#define MENUEVENT_NONE 0 // wird von MenuCtrl_Ctrl() zurueckgegeben
#define MENUEVENT_ITEM 1 // wird von MenuCtrl_Ctrl() zurueckgegeben
#define MENUEVENT_KEY 2 // wird von MenuCtrl_Ctrl() zurueckgegeben
 
#define MENUCTRL_EVENT 0 // Parameter fuer MenuCtrl_Ctrl() - Ruecksprung nur bei einem Event
#define MENUCTRL_RETURN 1 // Parameter fuer MenuCtrl_Ctrl() - Ruecksprung immer
 
 
#define MENU_REFRESH 1 // MenuCtrl_Refresh()
#define MENU_REDRAW 2 // MenuCtrl_Refresh()
 
 
void MenuCtrl_Create( void );
void MenuCtrl_Destroy( void );
void MenuCtrl_ShowLevel( uint8_t value );
 
void MenuCtrl_SetTitle( const char *title );
void MenuCtrl_SetTitle_P( const char *title );
void MenuCtrl_SetTitleFromParentItem( void );
void MenuCtrl_SetCycle( uint8_t value );
void MenuCtrl_SetShowBatt( uint8_t value );
void MenuCtrl_SetBeep( uint8_t value );
void MenuCtrl_SetKey( uint8_t key, const char *keytext, void (*keyfunc)(void) );
void MenuCtrl_SetTopSpace( uint8_t value );
void MenuCtrl_SetMove( uint8_t value );
void MenuCtrl_SetDelete( uint8_t value );
 
int8_t MenuCtrl_GetMenuIndex( void );
uint8_t MenuCtrl_GetItemId( void );
uint8_t MenuCtrl_GetKey( void );
uint8_t MenuCtrl_GetItemIdByIndex( uint8_t index );
uint8_t MenuCtrl_GetItemCount( void );
const char * MenuCtrl_GetItemText( void );
uint8_t MenuCtrl_IsItemTextPGM( void );
 
void MenuCtrl_ItemSelect( uint8_t itemid );
void MenuCtrl_ItemActive( uint8_t itemid, uint8_t value );
void MenuCtrl_ItemMark( uint8_t itemid, uint8_t value );
void MenuCtrl_ItemMarkR( uint8_t itemid, uint8_t value );
 
void MenuCtrl_PushML2_P( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text_de, const char *text_en );
void MenuCtrl_PushML2( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text_de, const char *text_en );
void MenuCtrl_Push_P( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text );
void MenuCtrl_Push( uint8_t itemid, uint8_t itemtype, void (*menufunc)(void), const char *text );
void MenuCtrl_PushParamEdit( uint8_t itemid );
void MenuCtrl_PushSeparator( void );
void MenuCtrl_PushSeparatorID( uint8_t itemid );
 
void MenuCtrl_Refresh( uint8_t mode );
uint8_t MenuCtrl_Control( uint8_t ctrlmode );
 
#endif // MENUCTRL_H
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property
/Transportables_Koptertool/PKT/GPL_PKT_V3_85f/utils/scrollbox.c
0,0 → 1,570
/*****************************************************************************
* Copyright (C) 2013 Oliver Gemesi *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*****************************************************************************/
 
//############################################################################
//# HISTORY scrollbox.c
//#
//# 31.05.2014 OG
//# - chg: ScrollBox_Refresh() - umgestellt auf PKT_KeylineUpDown()
//#
//# 29.03.2014 OG
//# - chg: ScrollBox_Show() umgestellt auf clear_key_all()
//#
//# 22.05.2013 OG
//# - fix: include pkt/pkt.h
//#
//# 19.05.2013 OG
//# - chg: ScrollBox_Show() erweitert um PKT_CtrlHook() um u.a. PKT-Updates
//# zu ermoeglichen
//#
//# 04.05.2013 OG
//# - chg: angepasst auf xutils.c
//#
//# 28.04.2013 OG
//# - add: ScrollBox_Push() - Variante fuer 'format' im RAM
//# - chg: ScrollBox_Push_P() -> keine Rueckgabe mehr (void)
//# - chg: auf xprintf umgestellt (siehe utils/xstring.c)
//# - add: verschiedene Beschreibungen ueber Funktionen
//#
//# 20.04.2013 OG - NEU
//############################################################################
 
//#define USE_SCROLLBOX_DEBUG // Debug-Funktionen einkompilieren/aktivieren (gesendet wird an uart1)
 
#include "../cpu.h"
#include <avr/pgmspace.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
 
#include "../main.h"
#include "../lcd/lcd.h"
#include "../eeprom/eeprom.h"
#include "../messages.h"
#include "../pkt/pkt.h"
#include "../utils/xutils.h" // xprintf
#include "scrollbox.h"
 
// Debug
#ifdef USE_SCROLLBOX_DEBUG
#include "../uart/uart1.h"
#include <util/delay.h>
#endif
 
#define SCROLLBOX_ALLOC_MEM // dynamische RAM-Belegen (malloc) verwenden? (Standardeinstellung: ja)
 
#define SCROLLBOX_LINESIZE 20+1 // Ausgabezeile der ScrollBox (20 Chars + 0x00)
#define SCROLLBOX_KEYSIZE 4+1 // Textlabel einer Taste (4 Chars + 0x00)
 
#define SCROLLBOX_W 20 // Textbreite
#define SCROLLBOX_H 7 // Textzeilen
#define MSBLINE 10 // drawmode-code fuer: Linie
 
 
 
 
//-----------------------------------------------------------
// statischer Speicher wenn nicht SCROLLBOX_ALLOC_MEM
// verwendet wird
//-----------------------------------------------------------
#ifndef SCROLLBOX_ALLOC_MEM
#define SCROLLBOX_BUFFER_SIZE 2048 // 2 KByte - ram-size in bytes
char scrollbox_buffer[SCROLLBOX_BUFFER_SIZE];
#endif
 
 
//-----------------------------------------------------------
// typedef: scrollbox_key_t
//-----------------------------------------------------------
typedef struct
{
uint8_t active; // Taste aktiv? (true/false)
char text[SCROLLBOX_KEYSIZE]; // Tastentext
} scrollbox_key_t;
 
 
//-----------------------------------------------------------
// typedef: scrollbox_line_t
//-----------------------------------------------------------
typedef struct
{
uint8_t mode; // drawmode: MNORMAL, MINVERSE oder MSBLINE
char line[SCROLLBOX_LINESIZE]; // malloc: lines * 21 bytes (20 chars + 0)
} scrollbox_line_t;
 
 
//-----------------------------------------------------------
// typedef: scrollbox_t
//-----------------------------------------------------------
typedef struct
{
scrollbox_line_t *buffer; // malloc: lines * 22 bytes (21 chars + 0)
uint8_t maxlines; // max. reservierte Lines (malloc buffer)
uint8_t lines; // Anzahl gepushte lines
uint8_t display_pos; // aktuelle obere Anzeigezeile
scrollbox_key_t key_enter;
scrollbox_key_t key_enter_long;
} scrollbox_t;
 
 
//-----------------------------------------------------------
// Buffer & Co.
//-----------------------------------------------------------
scrollbox_t scrollbox;
char buffer_sbline[SCROLLBOX_LINESIZE];
 
 
//#############################################################################################
//#############################################################################################
 
 
 
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#ifdef USE_SCROLLBOX_DEBUG
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//--------------------------------------------------------------
// nur wenn define: USE_SCROLLBOX_DEBUG
//--------------------------------------------------------------
void ScrollBox_Debug( void )
{
char s[33];
uint8_t i,j;
char *p;
scrollbox_line_t *sboxp;
uint32_t h;
 
uart1_puts_p( PSTR("\r\nScrollBox_Debug: BEGIN\r\n\r\n") );
 
ltoa( scrollbox.buffer, s, 16);
uart1_puts_p( PSTR("address: buffer = 0x") );
uart1_puts( s );
ltoa( scrollbox.buffer, s, 10);
uart1_puts( " (" );
uart1_puts( s );
uart1_puts( ")\r\n" );
 
ltoa( scrollbox_buffer, s, 16);
uart1_puts_p( PSTR("address: scrollbox_buffer = 0x") );
uart1_puts( s );
ltoa( scrollbox.buffer, s, 10);
uart1_puts( " (" );
uart1_puts( s );
uart1_puts( ")\r\n" );
 
 
itoa( sizeof(scrollbox_line_t), s, 10);
uart1_puts_p( PSTR("sizeof(scrollbox_line_t) = ") );
uart1_puts( s );
uart1_puts( "\r\n" );
 
uart1_puts( "\r\n" );
 
itoa( scrollbox.lines, s, 10);
uart1_puts_p( PSTR("scrollbox.lines = ") );
uart1_puts( s );
uart1_puts( "\r\n" );
 
itoa( scrollbox.maxlines, s, 10);
uart1_puts_p( PSTR("scrollbox.maxlines = ") );
uart1_puts( s );
uart1_puts( "\r\n" );
 
itoa( scrollbox.display_pos, s, 10);
uart1_puts_p( PSTR("scrollbox.display_pos = ") );
uart1_puts( s );
uart1_puts( "\r\n" );
 
uart1_puts( "\r\n" );
 
for(i=0; i<scrollbox.lines; i++)
{
itoa( i, s, 10);
if( strlen(s)<2 ) uart1_puts( " " );
uart1_puts( s );
uart1_puts( ": " );
 
//sboxp = scrollbox.buffer + sizeof(scrollbox_line_t)*i;
sboxp = scrollbox.buffer + i;
 
ltoa( sboxp, s, 16); // hex
uart1_puts( "[0x" );
uart1_puts( s );
uart1_puts( "]" );
 
ltoa( sboxp, s, 10); // dec
uart1_puts( "[" );
uart1_puts( s );
uart1_puts( "] " );
 
itoa( sboxp->mode, s, 10);
if( strlen(s)<2 ) uart1_puts( " " );
uart1_puts( s );
uart1_puts( ": " );
 
p = sboxp->line;
 
if( sboxp->mode != 10 )
{
uart1_puts( p );
}
 
uart1_puts( "|\r\n" );
}
 
//--------------------------------------------------------------
// Hier wird fuer eine gewisse Zeit (insgesamt 2500 mal) permanent die Zeile 23 ausgegeben.
// Wenn ich das richtig sehe schreibe ich hierbei nicht ;-)
// Aber was sagt das Empfangsterminal....
//--------------------------------------------------------------
sboxp = scrollbox.buffer + 23;
for( h=0; h<10; h++)
{
itoa( h, s, 10);
uart1_puts( s );
uart1_puts( "# " );
 
uart1_puts( sboxp->line );
uart1_puts( "|\r\n" );
_delay_ms(10);
}
//--------------------------------------------------------------
 
uart1_puts_p( PSTR("\r\nScrollBox_Debug: END\r\n") );
uart1_puts( "##########################################\r\n\r\n" );
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#endif // USER_SCROLLBOX_DEBUG
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 
 
 
//--------------------------------------------------------------
// ok = ScrollBox_Create( uint8_t maxlines )
//
// Rueckgabe:
// true = ok
// false = kein Speicher
//
// - reserviert speicher fuer max. maxlines
// - initialisiert scrollbox-Datenstruktur
//--------------------------------------------------------------
uint8_t ScrollBox_Create( uint8_t maxlines )
{
scrollbox.buffer = 0;
 
#ifdef SCROLLBOX_ALLOC_MEM
scrollbox.buffer = malloc( maxlines * sizeof(scrollbox_line_t));
//scrollbox.buffer = calloc( maxlines, sizeof(scrollbox_line_t) );
#else
scrollbox.buffer = (scrollbox_line_t *) scrollbox_buffer;
#endif
 
if( !scrollbox.buffer ) // kein RAM mehr
{
lcd_cls();
lcd_printp_at( 1, 3, PSTR("Error: ScrollBox"), MNORMAL);
lcd_printp_at( 1, 4, PSTR("No more RAM"), MNORMAL);
set_beep ( 500, 0x3333, BeepNormal);
while (!get_key_short (1 << KEY_ESC));
return false;
}
 
scrollbox.maxlines = maxlines;
scrollbox.lines = 0;
scrollbox.display_pos = 0;
 
scrollbox.key_enter.active = false;
scrollbox.key_enter_long.active = false;
return true;
}
 
 
 
//--------------------------------------------------------------
// ScrollBox_Destroy()
//
// gibt reservierten Speicher wieder frei
// Wichtig! Da malloc verwendet wird!
//--------------------------------------------------------------
void ScrollBox_Destroy( void )
{
if( scrollbox.buffer )
{
#ifdef SCROLLBOX_ALLOC_MEM
free( scrollbox.buffer );
#endif
}
scrollbox.buffer = 0;
}
 
 
//--------------------------------------------------------------
// ScrollBox_PushLine()
//
// fuegt eine Trennlinie hinzu
//--------------------------------------------------------------
void ScrollBox_PushLine( void )
{
scrollbox_line_t *sboxp;
 
if( scrollbox.lines < scrollbox.maxlines )
{
sboxp = scrollbox.buffer + scrollbox.lines;
sboxp->mode = MSBLINE;
scrollbox.lines++;
}
}
 
 
 
//--------------------------------------------------------------
// _scrollbox_push(...)
//
// intern fuer: ScrollBox_Push_P(), ScrollBox_Push()
// Beschreibung siehe dort
//--------------------------------------------------------------
void _scrollbox_push( uint8_t useprogmem, uint8_t mode, const char *format, va_list ap )
{
scrollbox_line_t *sboxp;
 
if( scrollbox.lines < scrollbox.maxlines )
{
sboxp = scrollbox.buffer + scrollbox.lines;
 
_xvsnprintf( useprogmem, buffer_sbline, SCROLLBOX_LINESIZE, format, ap);
 
strncpyfill( sboxp->line, buffer_sbline, SCROLLBOX_LINESIZE); // copy: buffer_sbline zur scrollbox
sboxp->mode = mode;
 
scrollbox.lines++;
}
}
 
 
 
//--------------------------------------------------------------
// ScrollBox_Push_P( mode, format, ...)
//
// Textzeile hinzufuegen - 'format' ist im PROGMEM.
//
// Parameter:
// mode : MNORMAL, MINVERS
// format : siehe xprint-Doku in utils/xstring.c
// ... : Parameterliste fuer 'format'
//--------------------------------------------------------------
void ScrollBox_Push_P( uint8_t mode, const char *format, ... )
{
va_list ap;
 
va_start(ap, format);
_scrollbox_push( true, mode, format, ap);
va_end(ap);
}
 
 
//--------------------------------------------------------------
// ScrollBox_Push( mode, format, ...)
//
// Textzeile hinzufuegen - 'format' ist im RAM.
//
// Parameter:
// mode : MNORMAL, MINVERS
// format : siehe xprint-Doku in utils/xstring.c
// ... : Parameterliste fuer 'format'
//--------------------------------------------------------------
void ScrollBox_Push( uint8_t mode, const char *format, ... )
{
va_list ap;
 
va_start(ap, format);
_scrollbox_push( false, mode, format, ap);
va_end(ap);
}
 
 
//--------------------------------------------------------------
// key: KEY_ENTER, KEY_ENTER_LONG (keine weiteren bisher!)
//--------------------------------------------------------------
void ScrollBox_SetKey( uint8_t key, const char *keytext )
{
if( key == KEY_ENTER )
{
scrollbox.key_enter.active = true;
strncpyfill( scrollbox.key_enter.text, keytext, SCROLLBOX_KEYSIZE);
}
 
if( key == KEY_ENTER_LONG )
{
scrollbox.key_enter_long.active = true;
strncpyfill( scrollbox.key_enter_long.text, keytext, SCROLLBOX_KEYSIZE);
}
}
 
 
 
//--------------------------------------------------------------
// ScrollBox_Refresh()
//
// zeigt die ScrollBox - wird normalerweise von ScrollBox_Show()
// automatisch durchgefuehrt
//--------------------------------------------------------------
void ScrollBox_Refresh( void )
{
uint8_t y;
uint8_t sh;
uint8_t sy;
scrollbox_line_t *sboxp;
 
//--------------------------
// Text
//--------------------------
for( y=0; y<7; y++)
{
sboxp = scrollbox.buffer + (scrollbox.display_pos + y);
 
if( y + scrollbox.display_pos < scrollbox.lines )
{
 
if( sboxp->mode == MSBLINE )
{
lcd_frect( (21-SCROLLBOX_W)*6, (y*8), (SCROLLBOX_W*6), 7, 0); // clear
lcd_line ( (21-SCROLLBOX_W)*6, (y*8)+3, 125, (y*8)+3, 1); // line
}
else
{
lcd_puts_at( 21-SCROLLBOX_W, y, sboxp->line, sboxp->mode);
}
//p += sizeof(scrollbox_line_t);
}
else // clear
{
lcd_frect( (21-SCROLLBOX_W)*6, (y*8), (SCROLLBOX_W*6), 7, 0); // clear
}
}
 
 
//--------------------------
// Slider
//--------------------------
#define SLIDERH 55 // Finetuning der Slider-Hoehe
 
// Slider: 7 zeilen * 8 pixel = 56 pixel
sh = (SLIDERH * 7) / scrollbox.lines; // Slider: Hoehe
sh = (sh > SLIDERH) ? SLIDERH : sh;
 
sy = (scrollbox.display_pos * (SLIDERH-sh)) / (scrollbox.lines-7); // Slider: Position
 
lcd_frect( 0, 0, 1, SLIDERH, 0); // Slider: Clear
lcd_frect( 0, sy, 1, sh, 1); // Slider: draw // Slider: Draw
 
 
//--------------------------
// Keyline
//--------------------------
PKT_KeylineUpDown( 1, 7, 0,0); // Keyline: Up / Down
lcd_printp_at( 12, 7, strGet(ENDE), MNORMAL); // Keyline: Ende
 
if( scrollbox.key_enter.active ) lcd_print_at (17, 7, (uint8_t *)scrollbox.key_enter.text , MNORMAL);
else if ( scrollbox.key_enter_long.active ) lcd_print_at (17, 7, (uint8_t *)scrollbox.key_enter_long.text, MNORMAL);
else lcd_printp_at(17, 7, PSTR(" ") , MNORMAL);
 
//ScrollBox_Debug();
}
 
 
//--------------------------------------------------------------
// key = ScrollBox_Show()
//
//--------------------------------------------------------------
uint8_t ScrollBox_Show( void )
{
uint8_t keyexit = 0;
 
clear_key_all();
 
if( scrollbox.buffer )
{
ScrollBox_Refresh();
 
do
{
//--------------------------
// Pruefe auf PKT-Update und
// andere interne PKT-Aktionen
//--------------------------
if( PKT_CtrlHook() ) // Update vom Updatetool angefordert?
{
lcd_cls();
ScrollBox_Refresh();
}
 
//--------------------------
// scrollen: nach unten
//--------------------------
if( get_key_press(1 << KEY_PLUS) || get_key_long_rpt_sp( (1 << KEY_PLUS),2 )) // down
{
if( scrollbox.display_pos < ( scrollbox.lines - SCROLLBOX_H) )
{
scrollbox.display_pos++;
ScrollBox_Refresh();
}
else
{
set_beep ( 25, 0xffff, BeepNormal); // am unteren Ende angelangt
}
}
 
//--------------------------
// scrollen: nach oben
//--------------------------
if( get_key_press(1 << KEY_MINUS) || get_key_long_rpt_sp( (1 << KEY_MINUS),2 )) // up
{
if( scrollbox.display_pos > 0 )
{
scrollbox.display_pos--;
ScrollBox_Refresh();
}
else
{
set_beep ( 25, 0xffff, BeepNormal); // am oberen Ende angelangt
}
}
 
//--------------------------
//--------------------------
if( scrollbox.key_enter.active && get_key_short(1 << KEY_ENTER) )
{
keyexit = KEY_ENTER;
}
 
//--------------------------
//--------------------------
if( scrollbox.key_enter_long.active && get_key_long(1 << KEY_ENTER) )
{
keyexit = KEY_ENTER_LONG;
}
 
} while( !get_key_press(1 << KEY_ESC) && (keyexit == 0) );
}
 
//get_key_press(KEY_ALL); // ersetzt durch obiges clear_key_all()
 
return keyexit;
}
 
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property
/Transportables_Koptertool/PKT/GPL_PKT_V3_85f/utils/scrollbox.h
0,0 → 1,49
/*****************************************************************************
* Copyright (C) 2013 Oliver Gemesi *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*****************************************************************************/
 
//############################################################################
//# HISTORY scrollbox.h
//#
//# 17.05.2013 OG
//# - del: defines KEY_xyz_LONG verschoben nach HAL_HW3_9.h
//#
//# 28.04.2013 OG
//# - add: ScrollBox_Push()
//# - chg: ScrollBox_Push_P() (keine Rueckgabe mehr)
//# - add: include <stdarg.h>
//#
//# 20.04.2013 OG - NEU
//############################################################################
 
#ifndef _SCROLLBOX_H
#define _SCROLLBOX_H
 
#include <stdarg.h> // Notwendig! (OG)
 
 
uint8_t ScrollBox_Create( uint8_t maxlines );
void ScrollBox_Destroy( void );
void ScrollBox_PushLine( void );
void ScrollBox_Push_P( uint8_t mode, const char *format, ... );
void ScrollBox_Push( uint8_t mode, const char *format, ... );
void ScrollBox_SetKey( uint8_t key, const char *keytext );
void ScrollBox_Refresh( void );
uint8_t ScrollBox_Show( void );
//void ScrollBox_Debug( void );
 
#endif
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property
/Transportables_Koptertool/PKT/GPL_PKT_V3_85f/utils/xutils.c
0,0 → 1,765
/*****************************************************************************
* Copyright (C) 2013 Oliver Gemesi *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*****************************************************************************/
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+ xutils.c - erweiterte String-Funktionen, xprintf (Info nach History)
//+ und weitere Hilfsfunktionen wie z.B. UTCdatetime2local()
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
//############################################################################
//# HISTORY xutils.c
//#
//# 12.04.2014 OG
//# - chg: strncpyat(), strncpyat_P(), _strncpyat() erweitert um Parameter 'sepcharcount'
//#
//# 08.04.2014 OG
//# - add: strncpyat(), strncpyat_P(), _strncpyat()
//#
//# 28.02.2014 OG
//# - add: buffered_sprintf(), buffered_sprintf_P()
//# - add: buffer sprintf_buffer[]
//# - chg: PGMBUFF_SIZE und ARGBUFF_SIZE von 80 auf 40 geaendert
//#
//# 24.06.2013 OG
//# - add: strrtrim() entfernt Leerzeichen auf der rechten Seite
//#
//# 14.05.2013 OG
//# - chg: Kommentarkopf von UTCdatetime2local() aktualisiert
//#
//# 05.05.2013 OG
//# - chg: UTCdatetime2local() auf Config.timezone/summertime umgestellt
//# - add: include eeprom.h
//#
//# 04.05.2013 OG
//# - chg: umbenannt zu xutils.c
//#
//# 03.05.2013 OG
//# - add: UTCdatetime2local()
//# - fix: _xvsnprintf() Darstellung kleiner negativer Nachkommazahlen (-1<z<0)
//#
//# 29.04.2013 OG
//# - chg: Doku zu xprintf Ergaenzt bei 'bekannte Einschraenkungen'
//# - chg: includes reduziert auf das Notwendige
//#
//# 28.04.2013 OG - NEU
//############################################################################
 
 
//############################################################################
//# xprintf
//#
//# Diese Variante von printf ist angepasst auf das PKT:
//#
//# - Unterstuetzung von Festkomma-Integer Anzeige
//# - Overflow-Anzeige durch '*' wenn eine Zahl die Format-Maske sprengt
//# - progmen wird optional unterstuetz fuer den format-String als auch fuer
//# String Argumente
//# - strikte Einhaltung von Laengen einer Format-Maske
//# (ggf. wird die Ausgabe gekuerzt)
//#
//# In diesem Source sind nur die Basis-xprintf zum Erzeugen von formatierten
//# Strings. Die direkten Ausgabefunktionen auf den Screen sind in lcd.c
//# als lcdx_printf_at() und lcdx_printf_at_P().
//#
//# FORMAT ANGABEN:
//#
//# %d: dezimal int signed (Rechtsbuendige Ausgabe) (Wandlung via itoa)
//# "%d" arg: 1234 -> "1234"
//# "%5d" arg: 1234 -> " 1234"
//# "%5.2d" arg: 1234 -> " 12.34"
//# "%05d" arg: 123 -> "00123"
//# "%3.2d" arg: -13 -> " -0.13"
//#
//# %u: dezimal int unsigned (Rechtsbuendige Ausgabe) (Wandlung via utoa)
//# wie %d jedoch mittels utoa
//#
//# %h: hex int unsigned -> Hex-Zahl Rechtsbuendig, Laenge wird unterstuetzt z.B. "%4h"
//# %o: octal int unsigned -> Octal-Zahl Rechtsbuendig, Laenge wird unterstuetzt z.B. "%2o"
//# %b: binary int unsigned -> Binaer-Zahl Rechtsbuendig, Laenge wird unterstuetzt z.B. "%8b"
//#
//# %ld, %lu, %lh, %lo, %lb:
//# wie die obigen jedoch fuer long-zahlen (via ltoa, ultoa)
//# nur wenn define USE_XPRINTF_LONG gesetzt ist!
//# Bespiele: "%ld", "%5.6ld" usw.
//#
//# %s: String aus RAM -> Linksbuendig, Laenge wird unterstuetzt (z.B. "%8s")
//# %S: String aus progmem -> Linksbuendig, Laenge wird unterstuetzt (z.B. "%8s")
//#
//# %c: einzelnes char -> Linksbuendig, Laenge wird unterstuetzt (z.B. "%8s")
//# %%: Ausgabe von "%"
//#
//#
//# BEISPIELE:
//#
//# vorhanden in: osd/osdata.c, lcd/lcd.c
//#
//#
//# BEKANNTE EINSCHRAENKUNGEN:
//#
//# 1. padding '0' mit negativen Zahlen wenn padding aktiv ist ergibt z.B. "00-1.5"
//# 2. der Entwickler muss auf eine korrekte Format-Maske achten. Andernfalls
//# kommt es zu nicht vorhersehbaren Ausgaben.
//# 3. nicht in ISR's verwenden - dazu muss ggf. eine Anpassung durchgefuert werden
//#
//# KOMPILIER OPTIONEN
//#
//# define: USE_XPRINTF_LONG
//# Unterstuetzung von long int / unsigned long int ('l' Modifier in Maske)
// Wird in der main.h gesetzt
//############################################################################
 
#define USE_XPRINTF_LONG // Unterstuetzung von long integer - Achtung! Muss fuer PKT gesetzt sein
// da in Sourcen verwendet!
 
 
#include <avr/pgmspace.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdbool.h>
 
#include "../main.h"
#include "../timer/timer.h"
#include "../eeprom/eeprom.h"
 
 
#define PGMBUFF_SIZE 40 // max. 40 chars bei format-String aus progmem
#define ARGBUFF_SIZE 40 // buffer fuer xprintf Parameter (strings, itoa, utoa) (fuer ltoa ggf. anpassen)
 
 
#define SPRINTF_BUFFER_SIZE 40 // max. 40 Chars fuer den Buffer fuer xsnprintf(), xsnprintf_P()
char sprintf_buffer[SPRINTF_BUFFER_SIZE];
 
 
//----------------------
// xprintf parser data
//----------------------
typedef struct
{
uint8_t parse; // true / false
char cmd; // char: d u h o b s S c %
uint8_t prelen; // Vorkomma
uint8_t declen; // decimal (Nachkomma)
uint8_t point; // true / false
uint8_t uselong; // true / false
uint8_t mask; // true / false
char pad; // ' ' oder '0'
} xprintf_t;
 
 
//----------------------
// Buffers
//----------------------
char cmddigit[7];
char argbuff[ARGBUFF_SIZE];
char pgmbuff[PGMBUFF_SIZE];
 
 
//####################################################################################
 
 
//---------------------------------------------------------------------
// Basisfunktion von xprintf
// Doku: siehe oben
//---------------------------------------------------------------------
void _xvsnprintf( uint8_t useprogmem, char *buffer, uint8_t n, const char *format, va_list ap )
{
const char *p_fmt; // pointer auf den format-String
char *p_dst; // pointer auf den destination buffer
const char *p_str; // pointer auf einen arg-String wenn ein String ausgegeben werden soll
char *p_cmddigit = 0; // pointer auf den Digit-Buffer fuer eine Maske (Laenge/Nachkommastellen)
const char *p_fmtbuff; // pointer auf den format-Buffer (fuer progmem)
const char *p_argbuff; // pointer auf den argbuffer
uint8_t fmtlen, arglen, overflow;
uint8_t i,j,dec;
uint8_t dstcnt;
uint8_t minus;
xprintf_t cmd; // parser Daten
 
p_fmtbuff = format;
 
if( useprogmem ) // format von progmem in's RAM kopieren
{
strncpy_P( pgmbuff, format, PGMBUFF_SIZE);
pgmbuff[PGMBUFF_SIZE-1] = 0;
p_fmtbuff = pgmbuff;
}
 
cmd.parse = false;
p_fmt = p_fmtbuff-1; // -1 -> wird am Anfang der Schleife korrigiert
p_dst = buffer;
dstcnt = 0;
 
do
{
if( dstcnt >= n ) // max. Anzahl von Zeichen fuer Ziel 'buffer' erreicht?
break;
 
p_fmt++; // naechstes Zeichen von format
 
//########################
//# 1. PARSE
//########################
 
//------------------------
// START: parse cmd
//------------------------
if( cmd.parse == false && *p_fmt == '%' )
{
memset( &cmd, 0, sizeof(xprintf_t) ); // init
cmd.parse = true;
cmd.pad = ' ';
p_cmddigit = cmddigit;
continue;
}
 
//------------------------
// NO parse: copy char
//------------------------
if( cmd.parse == false )
{
*p_dst = *p_fmt;
p_dst++;
dstcnt++;
continue;
}
 
//------------------------
// set: pad (eine '0' ganz am Anfang der Formatmaske)
//------------------------
if( cmd.parse == true && *p_fmt == '0' && p_cmddigit == cmddigit )
{
cmd.pad = '0';
continue;
}
 
//------------------------
// set: vor/nach-kommastellen
//------------------------
if( cmd.parse == true && *p_fmt >= '0' && *p_fmt <= '9' )
{
*p_cmddigit = *p_fmt;
p_cmddigit++;
continue;
}
 
//------------------------
// set: point
//------------------------
if( cmd.parse == true && *p_fmt == '.' && cmd.point == false )
{
cmd.point = true;
*p_cmddigit = 0;
cmd.prelen = atoi( cmddigit );
p_cmddigit = cmddigit;
continue;
}
 
//------------------------
// set: uselong
//------------------------
#ifdef USE_XPRINTF_LONG
if( cmd.parse == true && *p_fmt == 'l' )
{
cmd.uselong = true;
continue;
}
#endif
 
//------------------------
// END: parse cmd
//------------------------
if( cmd.parse == true && (*p_fmt == 'd' || *p_fmt == 'u' || *p_fmt == 'x' || *p_fmt == 'b' || *p_fmt == 'o' ||
*p_fmt == 's' || *p_fmt == 'S' || *p_fmt == 'c' || *p_fmt == '%') )
{
cmd.cmd = *p_fmt;
cmd.parse = false;
 
*p_cmddigit = 0;
if( cmd.point == false ) cmd.prelen = atoi(cmddigit);
else cmd.declen = atoi(cmddigit);
 
if( cmd.point || cmd.prelen>0 )
cmd.mask = true;
}
 
 
//########################
//# 2. EXECUTE
//########################
 
//------------------------
// exec cmd: "d,u,x,b,o"
//------------------------
if( cmd.cmd == 'd' || cmd.cmd == 'u' || cmd.cmd == 'x' || cmd.cmd == 'b' || cmd.cmd == 'o' )
{
if( cmd.uselong )
{
#ifdef USE_XPRINTF_LONG
switch(cmd.cmd)
{
case 'd': ltoa ( va_arg(ap, long) , argbuff, 10); break; // LONG dezimal int signed
case 'u': ultoa( va_arg(ap, unsigned long), argbuff, 10); break; // LONG dezimal int unsigned
case 'x': ultoa( va_arg(ap, unsigned long), argbuff, 16); break; // LONG hex int unsigned
case 'b': ultoa( va_arg(ap, unsigned long), argbuff, 2); break; // LONG binary int unsigned
case 'o': ultoa( va_arg(ap, unsigned long), argbuff, 8); break; // LONG octal int unsigned
}
#endif
}
else
{
switch(cmd.cmd)
{
case 'd': itoa( va_arg(ap, int) , argbuff, 10); break; // dezimal int signed
case 'u': utoa( va_arg(ap, unsigned int), argbuff, 10); break; // dezimal int unsigned
case 'x': utoa( va_arg(ap, unsigned int), argbuff, 16); break; // hex int unsigned
case 'b': utoa( va_arg(ap, unsigned int), argbuff, 2); break; // binary int unsigned
case 'o': utoa( va_arg(ap, unsigned int), argbuff, 8); break; // octal int unsigned
}
}
 
minus = (argbuff[0] == '-');
arglen = strlen(argbuff);
 
fmtlen = cmd.prelen + cmd.declen + (cmd.point ? 1 : 0);
arglen = strlen(argbuff);
 
overflow = cmd.mask && // Zahl zu gross -> "*" anzeigen statt der Zahl
(arglen > cmd.prelen + cmd.declen || cmd.prelen < 1+minus);
 
if( overflow ) // overflow: Zahl passt nicht in Maske
{ // -> zeige '*.*'
for( i=0; (i < fmtlen) && (dstcnt < n); i++)
{
if( cmd.point && i==cmd.prelen ) *p_dst = '.';
else *p_dst = '*';
p_dst++;
dstcnt++;
}
}
else // else: if( overflow )
{
if( !cmd.mask ) // keine Maske: alles von der Zahl ausgeben
fmtlen = arglen;
 
p_argbuff = argbuff;
if( minus ) // wenn Zahl negativ: merken und auf dem argbuff nehmen
{
p_argbuff++;
arglen--;
}
 
//-----------------
// die Zahl wird 'Rueckwaerts' uebertragen
//-----------------
dec = -1; // wird am Anfang der Schleife auf 0 gesetzt
j = 1; // zaehler fuer argbuff
for( i=1; i<=fmtlen; i++ )
{
dec++; // Zaehler Dizmalstellen
 
if( dstcnt+fmtlen-i <= n ) // wenn Zielbuffer nicht ueberschritten
{
if( cmd.point && (dec == cmd.declen) ) // Dezimalpunkt setzen
{
p_dst[fmtlen-i] = '.';
continue;
}
 
if( j <= arglen ) // Ziffer uebertragen aus argbuff
{
p_dst[fmtlen-i] = p_argbuff[arglen-j];
j++;
continue;
}
 
if( cmd.declen > 0 && // Nachkomma und 1. Vorkommastelle ggf. auf '0'
(dec < cmd.declen || dec == cmd.declen+1) ) // setzen wenn die Zahl zu klein ist
{
p_dst[fmtlen-i] = '0';
continue;
}
 
if( minus && ( (cmd.pad == ' ') || // ggf. Minuszeichen setzen
(cmd.pad != ' ' && i == fmtlen) ) ) // Minuszeichen bei '0'-padding an erster Stelle setzen
{
minus = false;
p_dst[fmtlen-i] = '-';
continue;
}
 
p_dst[fmtlen-i] = cmd.pad; // padding ' ' oder '0'
} // end: if( dstcnt+fmtlen-i <= n )
}
p_dst += fmtlen;
dstcnt += fmtlen;
}
continue;
}
 
//------------------------
// exec cmd: "s", "S", "c"
//------------------------
if( cmd.cmd == 's' || cmd.cmd == 'S' || cmd.cmd == 'c' )
{
switch(cmd.cmd)
{
case 's': p_str = va_arg( ap, char *); // String aus dem RAM
break;
 
case 'S': strncpy_P( argbuff, va_arg( ap, char *), ARGBUFF_SIZE); // String liegt im progmem -> in's RAM kopieren
argbuff[ARGBUFF_SIZE-1] = 0;
p_str = argbuff;
break;
 
case 'c': argbuff[0] = va_arg( ap, int); // einzelnes char
argbuff[1] = 0;
p_str = argbuff;
break;
}
 
fmtlen = cmd.prelen;
arglen = strlen(p_str);
 
if( !cmd.mask ) // keine Maske: alles vom String ausgeben
fmtlen = arglen;
 
for( i=0; i<fmtlen; i++)
{
if( dstcnt < n ) // wenn Zielbuffer nicht ueberschritten
{
if( *p_str ) // char uebertragen
{
*p_dst = *p_str;
p_str++;
}
else // padding
{
*p_dst = ' ';
}
p_dst++;
}
dstcnt++;
}
 
continue;
}
 
//------------------------
// exec cmd: "%"
//------------------------
if( cmd.cmd == '%' )
{
*p_dst = '%';
p_dst++;
dstcnt++;
continue;
}
 
} while( (dstcnt < n) && *p_fmt );
 
*(p_dst + (dstcnt < n ? 0 : -1)) = 0; // terminierende 0 im Ausgabebuffer setzen
}
 
 
 
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void xsnprintf( char *buffer, uint8_t n, const char *format, ... )
{
va_list ap;
 
va_start(ap, format);
_xvsnprintf( false, buffer, n, format, ap);
va_end(ap);
}
 
 
//---------------------------------------------------------------------
//---------------------------------------------------------------------
void xsnprintf_P( char *buffer, uint8_t n, const char *format, ... )
{
va_list ap;
 
va_start(ap, format);
_xvsnprintf( true, buffer, n, format, ap);
va_end(ap);
}
 
 
 
//-----------------------------------------------------------
// buffered_sprintf_P( format, ...)
//
// Ausgabe direkt in einen internen Buffer.
// Der Pointer auf den RAM-Buffer wird zurueckgegeben.
// Abgesichert bzgl. Buffer-Overflow.
//
// Groesse des Buffers: PRINTF_BUFFER_SIZE
//
// Parameter:
// format : String aus PROGMEM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
char * buffered_sprintf( const char *format, ... )
{
va_list ap;
 
va_start( ap, format );
_xvsnprintf( false, sprintf_buffer, SPRINTF_BUFFER_SIZE, format, ap );
va_end(ap);
return sprintf_buffer;
}
 
 
 
//-----------------------------------------------------------
// buffered_sprintf_P( format, ...)
//
// Ausgabe direkt in einen internen Buffer.
// Der Pointer auf den RAM-Buffer wird zurueckgegeben.
// Abgesichert bzgl. Buffer-Overflow.
//
// Groesse des Buffers: PRINTF_BUFFER_SIZE
//
// Parameter:
// format : String aus PROGMEM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
char * buffered_sprintf_P( const char *format, ... )
{
va_list ap;
 
va_start( ap, format );
_xvsnprintf( true, sprintf_buffer, SPRINTF_BUFFER_SIZE, format, ap );
va_end(ap);
return sprintf_buffer;
}
 
 
 
//--------------------------------------------------------------
// kopiert einen String von src auf dst mit fester Laenge und
// ggf. Space paddings rechts
//
// - fuellt ggf. den dst-String auf size Laenge mit Spaces
// - setzt Terminierung's 0 bei dst auf Position size
//--------------------------------------------------------------
void strncpyfill( char *dst, const char *src, size_t size)
{
uint8_t i;
uint8_t pad = false;
 
for( i=0; i<size; i++)
{
if(*src == 0) pad = true;
 
if( pad ) *dst = ' ';
else *dst = *src;
 
src++;
dst++;
}
dst--;
*dst = 0;
}
 
 
 
//--------------------------------------------------------------
// entfernt rechte Leerzeichen aus einem String
//--------------------------------------------------------------
void strrtrim( char *dst)
{
char *p;
 
p = dst + strlen(dst) - 1;
 
while( (p != dst) && (*p == ' ') ) p--;
 
if( (*p != ' ') && (*p != 0) ) p++;
*p = 0;
}
 
 
 
//--------------------------------------------------------------
// INTERN - fuer strncpyat(), strncpyat_P()
//--------------------------------------------------------------
void _strncpyat( char *dst, const char *src, size_t size, const char sepchar, uint8_t sepcharcount, uint8_t progmem)
{
uint8_t i;
 
if( progmem )
strncpy_P( dst, src, size);
else
strncpy( dst, src, size);
 
for( i=0; i<size; i++)
{
if( *dst == 0) return;
if( *dst == sepchar)
{
sepcharcount--;
if( sepcharcount==0 )
{
*dst = 0;
return;
}
}
dst++;
}
dst--;
*dst = 0;
}
 
 
//--------------------------------------------------------------
// strncpyat( dst, src, size, sepchar)
//
// kopiert einen String von 'src 'auf 'dst' mit max. Laenge 'size'
// oder bis 'sepchar' gefunden wird.
//
// src in PROGMEM
//--------------------------------------------------------------
void strncpyat( char *dst, const char *src, size_t size, const char sepchar, uint8_t sepcharcount)
{
_strncpyat( dst, src, size, sepchar, sepcharcount, false);
}
 
 
//--------------------------------------------------------------
// strncpyat_P( dst, src, size, sepchar)
//
// kopiert einen String von 'src 'auf 'dst' mit max. Laenge 'size'
// oder bis 'sepchar' gefunden wird.
//
// src in RAM
//--------------------------------------------------------------
void strncpyat_P( char *dst, const char *src, size_t size, const char sepchar, uint8_t sepcharcount)
{
_strncpyat( dst, src, size, sepchar, sepcharcount, true);
}
 
 
 
//--------------------------------------------------------------
// UTCdatetime2local( PKTdatetime_t *dtbuffer, PKTdatetime_t dt )
//
// konvertiert die UTC-Time 'dt' in die lokale Zeit und speichert
// dieses in 'dtbuffer' ab.
//
// Parameter:
//
// dtdst: Pointer Destination (PKTdatetime_t) (Speicher muss alloziiert sein!)
// dtsrc: Pointer Source (PKTdatetime_t)
//
// Hinweise:
//
// Schaltjahre (bzw. der 29.02.) werden nicht unterstuetzt
//--------------------------------------------------------------
void UTCdatetime2local( PKTdatetime_t *dtdst, PKTdatetime_t *dtsrc )
{
int8_t timeoffset;
int32_t v;
int8_t diff;
// 01 02 03 04 05 06 07 08 09 10 11 12 Monat
int8_t daymonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
 
//--------------------------
// timezone: Einstellbereich -12 .. 0 .. 12 (+1 = Berlin)
// summertime: Einstellung: 0 oder 1 (0=Winterzeit, 1=Sommerzeit)
//--------------------------
timeoffset = Config.timezone + Config.summertime;
//timeoffset = 2; // solange noch nicht in PKT-Config: Berlin, Sommerzeit
 
 
memcpy( dtdst, dtsrc, sizeof(PKTdatetime_t) ); // copy datetime to destination
 
//--------------------------
// Zeitzonenanpassung
//--------------------------
if( dtdst->year != 0 && dtdst->month >= 1 && dtdst->month <= 12 ) // nur wenn gueltiges Datum vorhanden
{
//--------------------------
// 1. Sekunden
//--------------------------
v = (int32_t)dtdst->seconds;
v += timeoffset*3600; // Stunden korrigieren
diff = 0;
 
if( v > 86400 ) // Tagesueberschreitung? (86400 = 24*60*60 bzw. 24 Stunden)
{
v -= 86400;
diff++; // inc: Tag
}
else if( v < 0 ) // Tagesunterschreitung?
{
v += 86400;
diff--; // dec: Tag
}
dtdst->seconds = (uint32_t)v; // SET: seconds
 
//--------------------------
// 2. Tag
//--------------------------
v = (int32_t)dtdst->day;
v += diff;
diff = 0;
 
if( v > daymonth[dtdst->month-1] ) // Monatsueberschreitung?
{
v = 1; // erster Tag des Monats
diff++; // inc: Monat
}
else if( v < 1 ) // Monatsunterschreitung?
{
if( dtdst->month > 1 )
v = daymonth[dtdst->month-1-1]; // letzter Tag des vorherigen Monats
else
v = 31; // letzter Tag im Dezember des vorherigen Jahres
diff--; // dec: Monat
}
dtdst->day = (uint8_t)v; // SET: day
 
//--------------------------
// 3. Monat
//--------------------------
v = (int32_t)dtdst->month;
v += diff;
diff = 0;
 
if( v > 12 ) // Jahresueberschreitung?
{
v = 1;
diff++; // inc: Jahr
}
else if( v < 1 ) // Jahresunterschreitung?
{
v = 12;
diff--; // dec: Jahr
}
dtdst->month = (uint8_t)v; // SET: month
 
//--------------------------
// 4. Jahr
//--------------------------
dtdst->year += diff; // SET: year
}
}
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property
/Transportables_Koptertool/PKT/GPL_PKT_V3_85f/utils/xutils.h
0,0 → 1,64
/*****************************************************************************
* Copyright (C) 2013 Oliver Gemesi *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* 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. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
*****************************************************************************/
 
//############################################################################
//# HISTORY xutils.h
//#
//# 12.04.2014 OG
//# - chg: strncpyat(), strncpyat_P(), _strncpyat() erweitert um Parameter 'sepcharcount'
//#
//# 08.04.2014 OG
//# - add: strncpyat(), strncpyat_P()
//#
//# 28.02.2014 OG
//# - add: buffered_sprintf(), buffered_sprintf_P()
//#
//# 24.06.2013 OG
//# - add: strrtrim()
//#
//# 04.05.2013 OG
//# - chg: umbenannt zu xutils.h
//#
//# 03.05.2013 OG
//# - add: UTCdatetime2local()
//#
//# 28.04.2013 OG - NEU
//############################################################################
 
#ifndef _XUTILS_H
#define _XUTILS_H
 
#include <stdarg.h>
 
 
void _xvsnprintf( uint8_t useprogmem, char *buffer, uint8_t n, const char *format, va_list ap );
void xsnprintf( char *buffer, uint8_t n, const char *format, ... );
void xsnprintf_P( char *buffer, uint8_t n, const char *format, ... );
 
char *buffered_sprintf( const char *format, ... );
char *buffered_sprintf_P( const char *format, ... );
 
void strncpyfill( char *dst, const char *src, size_t size);
void strrtrim( char *dst);
void strncpyat( char *dst, const char *src, size_t size, const char sepchar, uint8_t sepcharcount);
void strncpyat_P( char *dst, const char *src, size_t size, const char sepchar, uint8_t sepcharcount);
 
 
void UTCdatetime2local( PKTdatetime_t *dtdst, PKTdatetime_t *dtsrc );
 
#endif
Property changes:
Added: svn:mime-type
+text/plain
\ No newline at end of property