/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 |