/*****************************************************************************
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net *
* - original LCD control by Thomas "thkais" Kaiser *
* - special number formating routines taken from C-OSD *
* from Claas Anders "CaScAdE" Rathje *
* - some extension, ellipse and circ_line by Peter "woggle" Mack *
* *
* 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 lcd.c
//#
//# 10.11.2014 cebra
//# - fix: lcd_init() weiter Helligkeitseinstellungen korrigiert (OCR2A)
//#
//# 28.06.2014 OG
//# - chg: lcdx_cls_rowwidth() kompatibel zu mode MINVERSX und MNORMALX
//# - chg: lcdx_cls_row() auf lcdx_cls_rowwidth() umgestellt
//# - fix: lcdx_printp() umgestellt auf strlen_P() statt strlen()
//#
//# 27.06.2014 OG
//# - add: die lcd-print Funktionen wurden um MINVERSX und MNORMALX erweitert
//# um einen zusaetzlichen Rand links und oben als Linie zu zeichnen
//# (wird z.B. in followme.c verwendet)
//#
//# 11.06.2014 OG
//# - add: lcd_set_contrast()
//# - add: include <avr/interrupt.h>
//#
//# 04.06.2014 OG
//# - add: lcdx_cls_rowwidth()
//#
//# 26.05.2014 OG
//# - chg: LCD_Init() - LCD-Modus nur noch normal (kein Invers mehr)
//#
//# 02.05.2014 OG
//# - add: Popup_Draw() (ehemals in osd.c)
//#
//# 13.04.2014 OG
//# - add: lcd_print_LF()
//#
//# 11.04.2014 OG
//# - add: lcdx_cls_row()
//#
//# 10.04.2014 OG
//# - add: include: lipo.h
//#
//# 08.04.2014 OG
//# - add: lcdx_printf_center(), lcdx_printf_center_P()
//#
//# 07.04.2014 OG
//# - add: lcd_setpos(), lcd_print_char()
//#
//# 04.04.2014 OG
//# - add: ShowTitle_P()
//#
//# 28.02.2014 OG
//# - del: show_baudrate()
//# - chg: PRINTF_BUFFER_SIZE von 80 auf 40
//#
//# 16.02.2014 OG
//# - add: lcdx_printp_center(), lcdx_print_center()
//#
//# 13.02.2014 OG
//# - add: lcd_frect_round()
//# - chg: lcd_rect_round() um R2 ergaenzt
//#
//# 12.02.2014 OG
//# - add: lcd_rect_round()
//#
//# 04.02.2014 OG
//# - fix: writex_ndigit_number_u_100th() Aufbau der Formatmaske
//#
//# 03.02.2014 OG
//# - fix: writex_ndigit_number_u_100th() Berechnung Formatstring korrigiert
//# - fix: writex_ndigit_number_u_100th() Parameter 'mode' fehlte
//#
//# 16.06.2013 OG
//# - chg: LCD_ORIENTATION festgesetzt auf 0 (Normal)
//#
//# 04.05.2013 OG
//# - chg: angepasst auf xutils.c
//# - chg: writex_datetime_time(), writex_datetime_date() Lokalzeitberechnung
//# via UTCdatetime2local()
//#
//# 03.05.2013 OG
//# - fix: writex_gpspos() - Anzeige negativer GPS-Koordinaten
//# - fix: Anzeigefehler writex_datetime_time()
//# - chg: writex_datetime_date() & writex_datetime_time() Parameter
//# 'timeoffset' entfernt da das durch PKT-Config geregelt werden soll
//#
//# 29.04.2013 OG
//# - chg: lcd_cls() geaendert auf memset
//#
//# 28.04.2013 OG
//# - chg: high-level Funktionen wie writex_ndigit... auf xprintf umgebaut
//# - add: lcdx_printf_at(), lcdx_printf_at_P()
//# lcd_printf_at(), lcd_printf_at_P()
//# siehe dazu: Doku in utils/xstring.h fuer xprintf
//#
//# 27.03.2013 OG
//# - add: writex_datetime_time()
//# - add: writex_datetime_date()
//# - add: Show_PKTError_NoRAM()
//#
//# 22.03.2013 OG
//# - add: writex_gpspos()
//#
//# 11.03.2013 OG
//# - fix: writex_time() Ausgabe Doppelpunkt ":" ergaenzt um mode,xoffs,yoffs
//#
//# 07.03.2013 OG
//# - del: Kompatibilitaetsfunktion lcd_printpj_at() entfernt
//#
//# 06.03.2013 OG
//# - lcdx_putc() wurde erweitert mit Unterstuetzung des 8x8 Font (alte Jeti
//# Funktionen) und Pixel-Verschiebung (xoffs,yoffs)
//# - etliche Char basierte Funktionen wurden erweitert um Parameter xoffs,yoffs
//# um die Ausgabe um +/- Pixel zu verschieben. Fuer Pixelgenaue Positionierung
//# von OSD-Screen Elementen.
//# Die neuen Funktionen mit Pixel-Verschiebung beginnen mit lcdx_, writex_ ...
//# - add: Kompatibilitaet gewaehrleistet durch Mapper-Funktionen
//# - add: defines fuer Char-Drawmode's (MNORMAL, MINVERS, MBIG, MBIGINVERS)
//# - del: Jeti-Funktionen (teilweise ersetzt durch Kompatibilitaetsfunktionen)
//############################################################################
#include "../cpu.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdarg.h>
#include "../eeprom/eeprom.h"
#include "../timer/timer.h"
#include "lcd.h"
#include "../main.h"
#include "../HAL_HW3_9.h"
#include "../utils/xutils.h" // xprintf, UTCdatetime2local
#include "../lipo/lipo.h" // show_Lipo()
#include "font8x6.h"
#ifdef USE_FONT_BIG
#include "Font8x8.h"
#endif
#define DISP_W 128
#define DISP_H 64
#define DISP_BUFFER ((DISP_H * DISP_W) / 8)
#define LINE_BUFFER (((DISP_H/8) * DISP_W) / 8)
#define Jeti 1 // Jeti Routinen
volatile uint8_t display_buffer
[DISP_BUFFER
]; // Display-Puffer, weil nicht zurückgelesen werden kann
volatile uint8_t line_buffer
[LINE_BUFFER
]; // Zeilen-Puffer, weil nicht zurückgelesen werden kann
volatile uint16_t display_buffer_pointer
; // Pointer auf das aktuell übertragene Byte
volatile uint8_t display_buffer_counter
; // Hilfszähler zur Selektierung der Page
volatile uint8_t display_page_counter
; // aktuelle Page-Nummer
volatile uint8_t display_mode
; // Modus für State-Machine
volatile uint8_t LCD_ORIENTATION
= 0; // 0=Normal / 1=reversed
// DOG: 128 x 64 with 6x8 Font => 21 x 8
// MAX7456: 30 x 16
uint8_t lcd_xpos
;
uint8_t lcd_ypos
;
char s
[7];
#define PRINTF_BUFFER_SIZE 40 // max. 40 Chars fuer den Buffer fuer lcdx_printf_at() / lcdx_printf_at_P()
char printf_buffer
[PRINTF_BUFFER_SIZE
];
char format_buffer
[20];
//-----------------------------------------------------------
void send_byte
( uint8_t data
)
{
clr_cs
();
SPDR
= data
;
while (!(SPSR
& (1<<SPIF
)));
//SPSR = SPSR;
set_cs
();
}
//-----------------------------------------------------------
// * Writes one command byte
// * cmd - the command byte
//
void lcd_command
( uint8_t cmd
)
{
// LCD_SELECT();
// LCD_CMD();
// spi_write(cmd);
// LCD_UNSELECT();
clr_cs
();
SPDR
= cmd
;
while (!(SPSR
& (1<<SPIF
)));
//SPSR = SPSR;
set_cs
();
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcd_set_contrast
( uint8_t value
)
{
cli
();
clr_A0
();
send_byte
( 0x81 );
send_byte
( value
); // Daten zum LCD senden
set_A0
();
sei
();
}
//-----------------------------------------------------------
void lcd_cls
( void )
{
uint16_t i
, j
;
memset( (void *)display_buffer
, 0, 1024);
// for (i = 0; i < DISP_BUFFER; i++)
// display_buffer[i] = 0x00;
for (i
= 0; i
< 8; i
++)
{
clr_A0
();
send_byte
(0xB0 + i
); //1011xxxx
send_byte
(0x10); //00010000
// send_byte(0x04); //00000100 gedreht plus 4 Byte
// send_byte(0x00); //00000000
send_byte
(LCD_ORIENTATION
); //00000000
set_A0
();
for (j
= 0; j
< 128; j
++)
send_byte
(0x00);
}
lcd_xpos
= 0;
lcd_ypos
= 0;
}
//-----------------------------------------------------------
void set_adress
(uint16_t adress
, uint8_t data
)
{
uint8_t page
;
uint8_t column
;
page
= adress
>> 7;
clr_A0
();
send_byte
(0xB0 + page
);
column
= (adress
& 0x7F) + LCD_ORIENTATION
;
send_byte
(0x10 + (column
>> 4));
send_byte
(column
& 0x0F);
set_A0
();
send_byte
(data
);
}
//-----------------------------------------------------------
void scroll
(void)
{
uint16_t adress
;
for (adress
= 0; adress
< 896; adress
++)
{
display_buffer
[adress
] = display_buffer
[adress
+ 128];
set_adress
(adress
, display_buffer
[adress
]);
}
for (adress
= 896; adress
< 1024; adress
++)
{
display_buffer
[adress
] = 0;
set_adress
(adress
, 0);
}
}
//####################################################################################
//####################################################################################
//-----------------------------------------------------------
// + Plot (set one Pixel)
//-----------------------------------------------------------
// mode:
// 0=Clear, 1=Set, 2=XOR
void lcd_plot
(uint8_t xpos
, uint8_t ypos
, uint8_t mode
)
{
uint16_t adress
;
uint8_t mask
;
if ((xpos
< DISP_W
) && (ypos
< DISP_H
))
{
adress
= (ypos
/ 8) * DISP_W
+ xpos
; // adress = 0/8 * 128 + 0 = 0
mask
= 1 << (ypos
& 0x07); // mask = 1<<0 = 1
adress
&= DISP_BUFFER
- 1;
switch (mode
)
{
case 0:
display_buffer
[adress
] &= ~mask
;
break;
case 1:
display_buffer
[adress
] |= mask
;
break;
case 2:
display_buffer
[adress
] ^= mask
;
break;
}
set_adress
(adress
, display_buffer
[adress
]);
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_putc
( uint8_t x
, uint8_t y
, uint8_t c
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
uint8_t ch
;
uint16_t adress
;
uint8_t x1
,y1
;
uint8_t x0
,y0
;
uint8_t xw
;
uint8_t mask
;
uint8_t bit
;
uint8_t *font
;
//------------------------
// char translate
//------------------------
switch (c
)
{ // ISO 8859-1
case 0xc4: c
= 0x01; break; // Ã
case 0xe4: c
= 0x02; break; // ä
case 0xd6: c
= 0x03; break; // Ã
case 0xf6: c
= 0x04; break; // ö
case 0xdc: c
= 0x05; break; // Ã
case 0xfc: c
= 0x06; break; // ü
case 0xdf: c
= 0x1e; break; // à c = 0x07; ° (used by Jeti)
}
c
&= 0x7f;
//------------------------
// Font Parameter setzen
//------------------------
#ifdef USE_FONT_BIG
if( mode
<=2 ) // normaler font (8x6)
{
font
= (uint8_t *) &font8x6
[0][0];
xw
= 6;
}
else // grosser font (8x8)
{
font
= (uint8_t *) &Font8x8
[0][0];
xw
= 8;
}
#else
font
= (uint8_t *) &font8x6
[0][0];
xw
= 6;
#endif
//------------------------
//------------------------
x0
= (x
*xw
) + xoffs
;
y0
= (y
*8) + yoffs
;
if( yoffs
== 0)
{
//----------------------------------------------------------
// orginaler Character Algo
//
// funktioniert auch mit x Verschiebung aber nicht
// mit y Verschiebung.
//
// Da 8 Bit aufeinmal gesetzt werden ist dieser Algo
// bzgl. Geschwindigkeit effektiver als der Y-Algo.
//----------------------------------------------------------
if( mode
==MINVERS
|| mode
==MBIGINVERS
)
lcd_frect
( (x
*xw
)+xoffs
, (y
*8), xw
-1, 7, 1); // invertierte Darstellung
adress
= y
* 128 + x
* xw
+ xoffs
;
adress
&= 0x3FF;
for( x1
= 0; x1
< xw
; x1
++)
{
ch
= pgm_read_byte
(font
+ x1
+ c
* xw
);
if( mode
==MINVERS
|| mode
==MBIGINVERS
)
display_buffer
[adress
+ x1
] ^= ch
;
else
display_buffer
[adress
+ x1
] = ch
;
set_adress
(adress
+ x1
, display_buffer
[adress
+ x1
]);
}
}
else
{
//----------------------------------------------------------
// Y-Algo
// neuer Character Algo (nur wenn Pixel y-Verschiebung)
//----------------------------------------------------------
for( x1
= 0; x1
< xw
; x1
++ )
{
ch
= pgm_read_byte
(font
+ x1
+ c
* xw
);
mask
= 1;
for( y1
= 0; y1
< 8; y1
++ )
{
bit
= (ch
& mask
);
if( bit
)
lcd_plot
( x0
+x1
, y0
+y1
, ( (mode
==MINVERS
|| mode
==MBIGINVERS
) ? 0 : 1) );
else
lcd_plot
( x0
+x1
, y0
+y1
, ( (mode
==MINVERS
|| mode
==MBIGINVERS
) ? 1 : 0) );
mask
= (mask
<< 1);
}
}
}
}
//-----------------------------------------------------------
//--- Kompatibilitaet
//-----------------------------------------------------------
void lcd_putc
( uint8_t x
, uint8_t y
, uint8_t c
, uint8_t mode
)
{
lcdx_putc
( x
, y
, c
, mode
, 0,0 );
}
//####################################################################################
//####################################################################################
//-----------------------------------------------------------
void lcd_cls_line
(uint8_t x
, uint8_t y
, uint8_t w
)
{
uint8_t lcd_width
;
uint8_t lcd_zpos
;
uint8_t i
;
uint8_t max
= 21;
lcd_width
= w
;
lcd_xpos
= x
;
lcd_ypos
= y
;
if ((lcd_xpos
+ lcd_width
) > max
)
lcd_width
= max
- lcd_xpos
;
lcd_zpos
= lcd_xpos
+ lcd_width
;
for (i
= lcd_xpos
; i
< lcd_zpos
; i
++)
lcd_putc
(i
, lcd_ypos
, 0x20, 0);
}
//-----------------------------------------------------------
void wait_1ms
(void)
{
_delay_ms
(1);
}
//-----------------------------------------------------------
void wait_ms
(uint16_t time)
{
uint16_t i
;
for (i
= 0; i
< time; i
++)
wait_1ms
();
}
//-----------------------------------------------------------
void LCD_Init
( uint8_t LCD_Mode
) // LCD_Mode 0= Default Mode 1= EEPROM-Parameter)
{
lcd_xpos
= 0;
lcd_ypos
= 0;
// DDRB = 0xFF;
// SPI max. speed
// the DOGM128 lcd controller can work at 20 MHz
SPCR
= (1 << SPE
) | (1 << MSTR
) | (1 << CPHA
) | (1 << CPOL
);
SPSR
= (1 << SPI2X
);
set_cs
();
clr_reset
();
wait_ms
(10);
set_reset
();
clr_cs
();
clr_A0
();
send_byte
( 0x40 ); //Display start line = 0
//------------------------------------------------------------
// 10.11.2014 cebra
// Umschaltung der Displayansicht wird nicht mehr benötigt
// if (LCD_Mode == 1)
// {
// if (LCD_ORIENTATION == 0)
// {
// send_byte( 0xA1 ); // A1 normal A0 reverse(original)
// send_byte( 0xC0 ); // C0 normal C8 reverse(original)
// }
// else
// {
// send_byte( 0xA0 ); // A1 normal A0 reverse(original)
// send_byte( 0xC8 ); // C0 normal C8 reverse(original)
// }
// }
// else
// {
send_byte
( 0xA1 ); // A1 normal A0 reverse(original)
send_byte
( 0xC0 ); // C0 normal C8 reverse(original)
// }
/*
//------------------------------------------------------------
// 26.05.2014 OG: einstellen von Normal/Invers durch den User
// nicht mehr unterstuetzt, da der Modus Invers beim PKT
// auf verschiedenen Display's nicht gut aussieht.
// Ab jetzt nur noch LC-Modus Normal.
//------------------------------------------------------------
if (LCD_Mode == 1)
{
if (Config.LCD_DisplayMode == 0)
send_byte (0xA6); //Display normal, not mirrored
else
send_byte (0xA7); //Display reverse, not mirrored
}
else
send_byte (0xA6);
*/
send_byte
( 0xA6 ); //Display normal, not mirrored
send_byte
( 0xA2 ); //Set bias 1/9 (Duty 1/65)
send_byte
( 0x2F ); //Booster, regulator and follower on
send_byte
( 0xF8 ); //Set internal booster to 4x
send_byte
( 0x00 ); //Set internal booster to 4x
send_byte
( 0x27 ); //resistor ratio set
if( LCD_Mode
== 1 )
{
send_byte
( 0x81 ); //Electronic volume register set
send_byte
( Config.
LCD_Kontrast ); //Electronic volume register set
}
else
{
send_byte
( 0x81 );
send_byte
( 0x16 );
}
send_byte
( 0xAC ); //Cursor
send_byte
( 0x00 ); //No Cursor
send_byte
( 0xAF ); //No indicator
if( Config.
HWSound == 0 )
{
if( LCD_Mode
== 1 )
{
//------------------------------------------------------------
//10.11.2014 cebra,
//Helligkeitseinstellungen werden nicht mehr genutzt
// Helligkeit setzen
// OCR2A = Config.LCD_Helligkeit * 2.55;
//OCR2A = 255;
}
else
{
// OCR2A = 255;
}
}
lcd_cls
();
}
//-----------------------------------------------------------
// sicher eine Zeile für die Statusanzeige
void copy_line
(uint8_t y
)
{
uint8_t i
;
uint16_t adress
;
adress
= y
* 128 + 0 * 6;
adress
&= 0x3FF;
for (i
= 0; i
< 6*21; i
++)
{
line_buffer
[i
] = display_buffer
[adress
+i
];
set_adress
(adress
+ i
, display_buffer
[adress
+ i
]);
}
}
//-----------------------------------------------------------
// holt gesicherte Zeile wieder zurück
void paste_line
(uint8_t y
)
{
uint8_t i
;
uint16_t adress
;
adress
= y
* 128 + 0 * 6;
adress
&= 0x3FF;
for (i
= 0; i
< 6*21; i
++)
{
display_buffer
[adress
+i
] =line_buffer
[i
];
set_adress
(adress
+ i
, display_buffer
[adress
+ i
]);
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_puts_at
( uint8_t x
, uint8_t y
, const char *s
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
while (*s
)
{
lcdx_putc
(x
, y
, *s
++, mode
, xoffs
,yoffs
);
x
++;
}
}/* lcd_puts */
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcd_puts_at
( uint8_t x
, uint8_t y
, const char *s
, uint8_t mode
)
{
lcdx_puts_at
( x
, y
, s
, mode
, 0,0 );
}
//-----------------------------------------------------------
void new_line
(void)
{
lcd_ypos
++;
if (lcd_ypos
> 7)
{
scroll
();
lcd_ypos
= 7;
}
}
//-----------------------------------------------------------
void lcd_printpns
(const char *text
, uint8_t mode
)
{
while (pgm_read_byte
(text
))
{
switch (pgm_read_byte
(text
))
{
case 0x0D:
lcd_xpos
= 0;
break;
case 0x0A:
new_line
();
break;
default:
lcd_putc
(lcd_xpos
, lcd_ypos
, pgm_read_byte
(text
), mode
);
lcd_xpos
++;
if (lcd_xpos
> 21)
{
lcd_xpos
= 0;
// new_line ();
}
break;
}
text
++;
}
}
//-----------------------------------------------------------
void lcd_printpns_at
(uint8_t x
, uint8_t y
, const char *text
, uint8_t mode
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_printpns
(text
, mode
);
}
//--------------------------------------------------------------
// INTERN
//
// erweitert bei mode MINVERSX und MNORMALX links und oben den
// Text um jeweils einen Pixel -> der Invers-Modus sieht besser aus
//--------------------------------------------------------------
uint8_t _lcdx_print_modeextend
( uint8_t progmem
, uint8_t x
, uint8_t y
, uint8_t textlen
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
uint8_t draw
= 0;
if( (mode
== MNORMALX
) || (mode
== MINVERSX
) )
{
if( mode
== MNORMALX
) mode
= MNORMAL
;
else mode
= MINVERS
;
if( mode
== MINVERS
)
draw
= 1;
if( (y
*8)+yoffs
-1 >= 0 )
lcd_line
( (x
*6)+xoffs
, (y
*8)+yoffs
-1, (x
*6)+xoffs
+(textlen
*6)-1, (y
*8)+yoffs
-1, draw
); // horizontale Linie ueber dem Text
if( (x
*6)+xoffs
-1 >= 0 )
lcd_line
( (x
*6)+xoffs
-1, (y
*8)+yoffs
-1, (x
*6)+xoffs
-1, (y
*8)+yoffs
+7, draw
); // vertikale Linie links neben dem Text
}
return mode
;
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void _lcdx_print_outchar
( unsigned char c
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
switch( c
)
{
case 0x0D: lcd_xpos
= 0;
break;
case 0x0A: new_line
();
break;
default: lcdx_putc
( lcd_xpos
, lcd_ypos
, c
, mode
, xoffs
,yoffs
);
lcd_xpos
++;
if( lcd_xpos
> 21 )
{
lcd_xpos
= 0;
new_line
();
}
break;
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_print
( uint8_t *text
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
mode
= _lcdx_print_modeextend
( false, lcd_xpos
, lcd_ypos
, strlen( (const char *)text
), mode
, xoffs
, yoffs
); // RAM Modus
while( *text
)
{
_lcdx_print_outchar
( *text
, mode
, xoffs
,yoffs
);
text
++;
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_printp
( const char *text
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
char c
;
mode
= _lcdx_print_modeextend
( true, lcd_xpos
, lcd_ypos
, strlen_P
( (const char *)text
), mode
, xoffs
, yoffs
); // PROGMEM Modus
while( (c
= pgm_read_byte
(text
)) )
{
_lcdx_print_outchar
( c
, mode
, xoffs
,yoffs
);
text
++;
}
}
/*
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_print( uint8_t *text, uint8_t mode, int8_t xoffs, int8_t yoffs)
{
mode = _lcdx_print_invers_extend( false, lcd_xpos, lcd_ypos, strlen( (const char *)text), mode, xoffs, yoffs ); // RAM Modus
while( *text )
{
switch( *text )
{
case 0x0D: lcd_xpos = 0;
break;
case 0x0A: new_line();
break;
default: lcdx_putc (lcd_xpos, lcd_ypos, *text, mode, xoffs,yoffs);
lcd_xpos++;
if( lcd_xpos > 21 )
{
lcd_xpos = 0;
new_line();
}
break;
}
text++;
}
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_printp( const char *text, uint8_t mode, int8_t xoffs, int8_t yoffs)
{
mode = _lcdx_print_invers_extend( true, lcd_xpos, lcd_ypos, strlen( (const char *)text), mode, xoffs, yoffs ); // PROGMEM Modus
while( pgm_read_byte(text) )
{
switch( pgm_read_byte(text) )
{
case 0x0D: lcd_xpos = 0;
break;
case 0x0A: new_line();
break;
default: lcdx_putc (lcd_xpos, lcd_ypos, pgm_read_byte(text), mode, xoffs,yoffs);
lcd_xpos++;
if( lcd_xpos > 21 )
{
lcd_xpos = 0;
new_line();
}
break;
}
text++;
}
}
*/
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcd_printp
(const char *text
, uint8_t mode
)
{
lcdx_printp
( text
, mode
, 0,0);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_printp_at
(uint8_t x
, uint8_t y
, const char *text
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcdx_printp
(text
, mode
, xoffs
,yoffs
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcd_printp_at
(uint8_t x
, uint8_t y
, const char *text
, uint8_t mode
)
{
lcdx_printp_at
( x
, y
, text
, mode
, 0,0);
}
//-----------------------------------------------------------
//--- lcd_print: Kompatibilitaet
//-----------------------------------------------------------
void lcd_print
(uint8_t *text
, uint8_t mode
)
{
lcdx_print
(text
, mode
, 0,0 );
}
//-----------------------------------------------------------
void lcdx_print_at
(uint8_t x
, uint8_t y
, uint8_t *text
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcdx_print
(text
, mode
, xoffs
, yoffs
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_print_center
( uint8_t y
, uint8_t *text
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
xoffs
= xoffs
+ ((uint8_t)(64 - ( (strlen((const char *)text
)*6) /2))); // Pixelgenau zentrieren (fuer 6x8 font)
lcdx_print_at
( 0, y
, text
, mode
, xoffs
,yoffs
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcdx_printp_center
( uint8_t y
, const char *text
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
xoffs
= xoffs
+ ((uint8_t)(64 - ( (strlen_P
(text
)*6) /2))); // Pixelgenau zentrieren (fuer 6x8 font)
lcdx_printp_at
( 0, y
, text
, mode
, xoffs
,yoffs
);
}
//-----------------------------------------------------------
// lcdx_printf_center( y, mode, xoffs,yoffs, format, ...)
//
// Ausgabe von n-Parametern via Formattierung
// mit erweitertem xoffs,yoffs
//
// Die Ausgabe wird zentriert,
//
// Parameter:
// y : Position in Char y
// mode : MNORMAL, MINVERS, ...
// xoffs,yoffs: Verschiebung in Pixel
// format : String aus PROGMEM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
void lcdx_printf_center
( uint8_t y
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
, const char *format
, ...
)
{
va_list ap
;
va_start( ap
, format
);
_xvsnprintf
( false, printf_buffer
, PRINTF_BUFFER_SIZE
, format
, ap
);
va_end(ap
);
lcdx_print_center
( y
, (unsigned char *)printf_buffer
, mode
, xoffs
, yoffs
);
}
//-----------------------------------------------------------
// lcdx_printf_center_P( y, mode, xoffs,yoffs, format, ...)
//
// Ausgabe von n-Parametern via Formattierung
// mit erweitertem xoffs,yoffs (PROGMEN-Version)
//
// Die Ausgabe wird zentriert,
//
// Parameter:
// y : Position in Char y
// mode : MNORMAL, MINVERS, ...
// xoffs,yoffs: Verschiebung in Pixel
// format : String aus PROGMEM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
void lcdx_printf_center_P
( uint8_t y
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
, const char *format
, ...
)
{
va_list ap
;
va_start( ap
, format
);
_xvsnprintf
( true, printf_buffer
, PRINTF_BUFFER_SIZE
, format
, ap
);
va_end(ap
);
lcdx_print_center
( y
, (unsigned char *)printf_buffer
, mode
, xoffs
, yoffs
);
}
//-----------------------------------------------------------
//--- lcd_print_at: Kompatibilitaet
//-----------------------------------------------------------
void lcd_print_at
(uint8_t x
, uint8_t y
, uint8_t *text
, uint8_t mode
)
{
lcdx_print_at
( x
, y
, text
, mode
, 0,0);
}
//-----------------------------------------------------------
void print_display
(uint8_t *text
)
{
while (*text
)
{
lcd_putc
(lcd_xpos
, lcd_ypos
, *text
, 0);
lcd_xpos
++;
if (lcd_xpos
>= 20)
{
lcd_xpos
= 0;
new_line
();
}
text
++;
}
}
//-----------------------------------------------------------
void print_display_at
(uint8_t x
, uint8_t y
, uint8_t *text
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
print_display
(text
);
}
//-----------------------------------------------------------
// + Line (draws a line from x1,y1 to x2,y2
// + Based on Bresenham line-Algorithm
// + found in the internet, modified by thkais 2007
//-----------------------------------------------------------
void lcd_line
( unsigned char x1
, unsigned char y1
, unsigned char x2
, unsigned char y2
, uint8_t mode
)
{
int x
, y
, count
, xs
, ys
, xm
, ym
;
x
= (int) x1
;
y
= (int) y1
;
xs
= (int) x2
- (int) x1
;
ys
= (int) y2
- (int) y1
;
if (xs
< 0)
xm
= -1;
else
if (xs
> 0)
xm
= 1;
else
xm
= 0;
if (ys
< 0)
ym
= -1;
else
if (ys
> 0)
ym
= 1;
else
ym
= 0;
if (xs
< 0)
xs
= -xs
;
if (ys
< 0)
ys
= -ys
;
lcd_plot
((unsigned char) x
, (unsigned char) y
, mode
);
if (xs
> ys
) // Flat Line <45 degrees
{
count
= -(xs
/ 2);
while (x
!= x2
)
{
count
= count
+ ys
;
x
= x
+ xm
;
if (count
> 0)
{
y
= y
+ ym
;
count
= count
- xs
;
}
lcd_plot
((unsigned char) x
, (unsigned char) y
, mode
);
}
}
else // Line >=45 degrees
{
count
=- (ys
/ 2);
while (y
!= y2
)
{
count
= count
+ xs
;
y
= y
+ ym
;
if (count
> 0)
{
x
= x
+ xm
;
count
= count
- ys
;
}
lcd_plot
((unsigned char) x
, (unsigned char) y
, mode
);
}
}
}
//-----------------------------------------------------------
// + Filled rectangle
// + x1, y1 = upper left corner
//-----------------------------------------------------------
void lcd_frect
( uint8_t x1
, uint8_t y1
, uint8_t widthx
, uint8_t widthy
, uint8_t mode
)
{
uint16_t x2
, y2
;
uint16_t i
;
if (x1
>= DISP_W
)
x1
= DISP_W
- 1;
if (y1
>= DISP_H
)
y1
= DISP_H
- 1;
x2
= x1
+ widthx
;
y2
= y1
+ widthy
;
if (x2
> DISP_W
)
x2
= DISP_W
;
if (y2
> DISP_H
)
y2
= DISP_H
;
for (i
= y1
; i
<= y2
; i
++)
{
lcd_line
(x1
, i
, x2
, i
, mode
);
}
}
//-----------------------------------------------------------
// ausgefuelltes Rechteck mit abgerundeten Ecken
//
// Hinweis:
// r (Radius) ist aktuell 'pseudo' und unterstuetzt
// nur R0 (=0), R1 (=1) oder R2 (=2=
//-----------------------------------------------------------
void lcd_frect_round
( uint8_t x1
, uint8_t y1
, uint8_t widthx
, uint8_t widthy
, uint8_t mode
, uint8_t r
)
{
lcd_frect
( x1
, y1
, widthx
, widthy
, mode
);
switch(r
)
{
case R0
: break;
case R2
:
lcd_plot
( x1
+1 , y1
, !mode
); // Ecke links oben
lcd_plot
( x1
, y1
+1 , !mode
);
lcd_plot
( x1
+widthx
-1, y1
, !mode
); // Ecke rechts oben
lcd_plot
( x1
+widthx
, y1
+1 , !mode
);
lcd_plot
( x1
, y1
+widthy
-1, !mode
); // Ecke links unten
lcd_plot
( x1
+1 , y1
+widthy
, !mode
);
lcd_plot
( x1
+widthx
-1, y1
+widthy
, !mode
); // Ecke rechts unten
lcd_plot
( x1
+widthx
, y1
+widthy
-1, !mode
);
case R1
:
lcd_plot
( x1
, y1
, !mode
); // Ecke links oben
lcd_plot
( x1
+widthx
, y1
, !mode
); // Ecke rechts oben
lcd_plot
( x1
, y1
+widthy
, !mode
); // Ecke links unten
lcd_plot
( x1
+widthx
, y1
+widthy
, !mode
); // Ecke rechts unten
}
}
//-----------------------------------------------------------
// + outline of rectangle
// + x1, y1 = upper left corner
//-----------------------------------------------------------
void lcd_rect
( uint8_t x1
, uint8_t y1
, uint8_t widthx
, uint8_t widthy
, uint8_t mode
)
{
uint16_t x2
, y2
;
if (x1
>= DISP_W
)
x1
= DISP_W
- 1;
if (y1
>= DISP_H
)
y1
= DISP_H
- 1;
x2
= x1
+ widthx
;
y2
= y1
+ widthy
;
if (x2
> DISP_W
)
x2
= DISP_W
;
if (y2
> DISP_H
)
y2
= DISP_H
;
lcd_line
(x1
, y1
, x2
, y1
, mode
);
lcd_line
(x2
, y1
, x2
, y2
, mode
);
lcd_line
(x2
, y2
, x1
, y2
, mode
);
lcd_line
(x1
, y2
, x1
, y1
, mode
);
}
//-----------------------------------------------------------
// Rechteck mit mit abgerundeten Ecken
//
// Hinweis:
// r (Radius) ist aktuell 'pseudo' und unterstuetzt
// nur R0 (=0), R1 (=1) oder R2 (=2=
//-----------------------------------------------------------
void lcd_rect_round
( uint8_t x1
, uint8_t y1
, uint8_t widthx
, uint8_t widthy
, uint8_t mode
, uint8_t r
)
{
lcd_rect
( x1
, y1
, widthx
, widthy
, mode
);
switch(r
)
{
case R0
: break;
case R2
:
lcd_plot
( x1
+1 , y1
, !mode
); // Ecke links oben
lcd_plot
( x1
, y1
+1 , !mode
);
lcd_plot
( x1
+1 , y1
+1 , mode
);
lcd_plot
( x1
+widthx
-1, y1
, !mode
); // Ecke rechts oben
lcd_plot
( x1
+widthx
, y1
+1 , !mode
);
lcd_plot
( x1
+widthx
-1, y1
+1 , mode
);
lcd_plot
( x1
, y1
+widthy
-1, !mode
); // Ecke links unten
lcd_plot
( x1
+1 , y1
+widthy
, !mode
);
lcd_plot
( x1
+1 , y1
+widthy
-1, mode
);
lcd_plot
( x1
+widthx
-1, y1
+widthy
, !mode
); // Ecke rechts unten
lcd_plot
( x1
+widthx
, y1
+widthy
-1, !mode
);
lcd_plot
( x1
+widthx
-1, y1
+widthy
-1, mode
);
case R1
:
lcd_plot
( x1
, y1
, !mode
); // Ecke links oben
lcd_plot
( x1
+widthx
, y1
, !mode
); // Ecke rechts oben
lcd_plot
( x1
, y1
+widthy
, !mode
); // Ecke links unten
lcd_plot
( x1
+widthx
, y1
+widthy
, !mode
); // Ecke rechts unten
}
}
//-----------------------------------------------------------
// + outline of a circle
// + Based on Bresenham-algorithm found in wikipedia
// + modified by thkais (2007)
//-----------------------------------------------------------
void lcd_circle
(int16_t x0
, int16_t y0
, int16_t radius
, uint8_t mode
)
{
int16_t f
= 1 - radius
;
int16_t ddF_x
= 0;
int16_t ddF_y
= -2 * radius
;
int16_t x
= 0;
int16_t y
= radius
;
lcd_plot
(x0
, y0
+ radius
, mode
);
lcd_plot
(x0
, y0
- radius
, mode
);
lcd_plot
(x0
+ radius
, y0
, mode
);
lcd_plot
(x0
- radius
, y0
, mode
);
while (x
< y
)
{
if (f
>= 0)
{
y
--;
ddF_y
+= 2;
f
+= ddF_y
;
}
x
++;
ddF_x
+= 2;
f
+= ddF_x
+ 1;
lcd_plot
(x0
+ x
, y0
+ y
, mode
);
lcd_plot
(x0
- x
, y0
+ y
, mode
);
lcd_plot
(x0
+ x
, y0
- y
, mode
);
lcd_plot
(x0
- x
, y0
- y
, mode
);
lcd_plot
(x0
+ y
, y0
+ x
, mode
);
lcd_plot
(x0
- y
, y0
+ x
, mode
);
lcd_plot
(x0
+ y
, y0
- x
, mode
);
lcd_plot
(x0
- y
, y0
- x
, mode
);
}
}
//-----------------------------------------------------------
// + filled Circle
// + modified circle-algorithm thkais (2007)
//-----------------------------------------------------------
void lcd_fcircle
(int16_t x0
, int16_t y0
, int16_t radius
,uint8_t mode
)
{
int16_t f
= 1 - radius
;
int16_t ddF_x
= 0;
int16_t ddF_y
= -2 * radius
;
int16_t x
= 0;
int16_t y
= radius
;
lcd_line
(x0
, y0
+ radius
, x0
, y0
- radius
, mode
);
lcd_line
(x0
+ radius
, y0
, x0
- radius
, y0
, mode
);
while (x
< y
)
{
if (f
>= 0)
{
y
--;
ddF_y
+= 2;
f
+= ddF_y
;
}
x
++;
ddF_x
+= 2;
f
+= ddF_x
+ 1;
lcd_line
(x0
+ x
, y0
+ y
, x0
- x
, y0
+ y
, mode
);
lcd_line
(x0
+ x
, y0
- y
, x0
- x
, y0
- y
, mode
);
lcd_line
(x0
+ y
, y0
+ x
, x0
- y
, y0
+ x
, mode
);
lcd_line
(x0
+ y
, y0
- x
, x0
- y
, y0
- x
, mode
);
}
}
//-----------------------------------------------------------
//
void lcd_circ_line
(uint8_t x
, uint8_t y
, uint8_t r
, uint16_t deg
, uint8_t mode
)
{
uint8_t xc
, yc
;
double deg_rad
;
deg_rad
= (deg
* M_PI
) / 180.0;
yc
= y
- (uint8_t) round
(cos (deg_rad
) * (double) r
);
xc
= x
+ (uint8_t) round
(sin (deg_rad
) * (double) r
);
lcd_line
(x
, y
, xc
, yc
, mode
);
}
//-----------------------------------------------------------
//
void lcd_ellipse_line
(uint8_t x
, uint8_t y
, uint8_t rx
, uint8_t ry
, uint16_t deg
, uint8_t mode
)
{
uint8_t xc
, yc
;
double deg_rad
;
deg_rad
= (deg
* M_PI
) / 180.0;
yc
= y
- (uint8_t) round
(cos (deg_rad
) * (double) ry
);
xc
= x
+ (uint8_t) round
(sin (deg_rad
) * (double) rx
);
lcd_line
(x
, y
, xc
, yc
, mode
);
}
//-----------------------------------------------------------
//
void lcd_ellipse
(int16_t x0
, int16_t y0
, int16_t rx
, int16_t ry
, uint8_t mode
)
{
const int16_t rx2
= rx
* rx
;
const int16_t ry2
= ry
* ry
;
int16_t F
= round
(ry2
- rx2
* ry
+ 0.25 * rx2
);
int16_t ddF_x
= 0;
int16_t ddF_y
= 2 * rx2
* ry
;
int16_t x
= 0;
int16_t y
= ry
;
lcd_plot
(x0
, y0
+ ry
, mode
);
lcd_plot
(x0
, y0
- ry
, mode
);
lcd_plot
(x0
+ rx
, y0
, mode
);
lcd_plot
(x0
- rx
, y0
, mode
);
// while ( 2*ry2*x < 2*rx2*y ) { we can use ddF_x and ddF_y
while (ddF_x
< ddF_y
)
{
if(F
>= 0)
{
y
-= 1; // south
ddF_y
-= 2 * rx2
;
F
-= ddF_y
;
}
x
+= 1; // east
ddF_x
+= 2 * ry2
;
F
+= ddF_x
+ ry2
;
lcd_plot
(x0
+ x
, y0
+ y
, mode
);
lcd_plot
(x0
+ x
, y0
- y
, mode
);
lcd_plot
(x0
- x
, y0
+ y
, mode
);
lcd_plot
(x0
- x
, y0
- y
, mode
);
}
F
= round
(ry2
* (x
+ 0.5) * (x
+ 0.5) + rx2
* (y
- 1) * (y
- 1) - rx2
* ry2
);
while(y
> 0)
{
if(F
<= 0)
{
x
+= 1; // east
ddF_x
+= 2 * ry2
;
F
+= ddF_x
;
}
y
-= 1; // south
ddF_y
-= 2 * rx2
;
F
+= rx2
- ddF_y
;
lcd_plot
(x0
+ x
, y0
+ y
, mode
);
lcd_plot
(x0
+ x
, y0
- y
, mode
);
lcd_plot
(x0
- x
, y0
+ y
, mode
);
lcd_plot
(x0
- x
, y0
- y
, mode
);
}
}
//-----------------------------------------------------------
//
void lcd_ecircle
(int16_t x0
, int16_t y0
, int16_t radius
, uint8_t mode
)
{
lcd_ellipse
(x0
, y0
, radius
+ 3, radius
, mode
);
}
//-----------------------------------------------------------
//
void lcd_ecirc_line
(uint8_t x
, uint8_t y
, uint8_t r
, uint16_t deg
, uint8_t mode
)
{
lcd_ellipse_line
(x
, y
, r
+ 3, r
, deg
, mode
);
}
//-----------------------------------------------------------
//
void lcd_view_font
(uint8_t page
)
{
int x
;
int y
;
lcd_cls
();
lcd_printp
(PSTR
(" 0123456789ABCDEF\r\n"), 0);
lcd_printpns_at
(0, 7, PSTR
(" \x1a \x1b Exit"), 0);
lcd_ypos
= 2;
for (y
= page
* 4 ; y
< (page
* 4 + 4); y
++)
{
if (y
< 10)
{
lcd_putc
(0, lcd_ypos
, '0' + y
, 0);
}
else
{
lcd_putc
(0, lcd_ypos
, 'A' + y
- 10, 0);
}
lcd_xpos
= 2;
for (x
= 0; x
< 16; x
++)
{
lcd_putc
(lcd_xpos
, lcd_ypos
, y
* 16 + x
, 0);
lcd_xpos
++;
}
lcd_ypos
++;
}
}
//-----------------------------------------------------------
uint8_t hdigit
(uint8_t d
)
{
if (d
< 10)
{
return '0' + d
;
}
else
{
return 'A' + d
- 10;
}
}
//-----------------------------------------------------------
void lcd_print_hex_at
(uint8_t x
, uint8_t y
, uint8_t h
, uint8_t mode
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_putc
(lcd_xpos
++, lcd_ypos
, hdigit
(h
>> 4), mode
);
lcd_putc
(lcd_xpos
, lcd_ypos
, hdigit
(h
& 0x0f), mode
);
}
//-----------------------------------------------------------
void lcd_print_hex
(uint8_t h
, uint8_t mode
)
{
// lcd_xpos = x;
// lcd_ypos = y;
lcd_putc
(lcd_xpos
++, lcd_ypos
, hdigit
(h
>> 4), mode
);
lcd_putc
(lcd_xpos
++, lcd_ypos
, hdigit
(h
& 0x0f), mode
);
lcd_putc
(lcd_xpos
++, lcd_ypos
, ' ', mode
);
}
//##################################################################################################################################
//##################################################################################################################################
//-----------------------------------------------------------
// lcdx_printf_at( x,y, mode, xoffs,yoffs, format, ...)
//
// Ausgabe von n-Parametern via Formattierung
// mit erweitertem xoffs,yoffs (RAM-Version)
//
// Parameter:
// x,y : Position in Char x,y
// mode : MNORMAL, MINVERS, ...
// xoffs,yoffs: Verschiebung in Pixel
// format : String aus RAM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
void lcdx_printf_at
( uint8_t x
, uint8_t y
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
, const char *format
, ...
)
{
va_list ap
;
va_start( ap
, format
);
// _xvsnprintf( int useprogmem, char *buffer, size_t n, const char *format, va_list ap )
_xvsnprintf
( false, printf_buffer
, PRINTF_BUFFER_SIZE
, format
, ap
);
va_end(ap
);
lcdx_print_at
( x
, y
, (unsigned char *)printf_buffer
, mode
, xoffs
, yoffs
);
}
//-----------------------------------------------------------
// lcdx_printf_at_P( x,y, mode, xoffs,yoffs, format, ...)
//
// Ausgabe von n-Parametern via Formattierung
// mit erweitertem xoffs,yoffs (PROGMEN-Version)
//
// Parameter:
// x,y : Position in Char x,y
// mode : MNORMAL, MINVERS, ...
// xoffs,yoffs: Verschiebung in Pixel
// format : String aus PROGMEM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
void lcdx_printf_at_P
( uint8_t x
, uint8_t y
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
, const char *format
, ...
)
{
va_list ap
;
va_start( ap
, format
);
_xvsnprintf
( true, printf_buffer
, PRINTF_BUFFER_SIZE
, format
, ap
);
va_end(ap
);
lcdx_print_at
( x
, y
, (unsigned char *)printf_buffer
, mode
, xoffs
, yoffs
);
}
//-----------------------------------------------------------
// lcdx_printf_at( x,y, mode, xoffs,yoffs, format, ...)
//
// Ausgabe von n-Parametern via Formattierung (RAM-Version)
//
// Parameter:
// x,y : Position in Char x,y
// mode : MNORMAL, MINVERS, ...
// format : String aus RAM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
void lcd_printf_at
( uint8_t x
, uint8_t y
, uint8_t mode
, const char *format
, ...
)
{
va_list ap
;
va_start( ap
, format
);
// _xvsnprintf( int useprogmem, char *buffer, size_t n, const char *format, va_list ap )
_xvsnprintf
( false, printf_buffer
, PRINTF_BUFFER_SIZE
, format
, ap
);
va_end(ap
);
lcdx_print_at
( x
, y
, (unsigned char *)printf_buffer
, mode
, 0,0);
}
//-----------------------------------------------------------
// lcd_printf_at_P( x,y, mode, xoffs,yoffs, format, ...)
//
// Ausgabe von n-Parametern via Formattierung (PROGMEN-Version)
//
// Parameter:
// x,y : Position in Char x,y
// mode : MNORMAL, MINVERS, ...
// format : String aus PROGMEM (siehe: xprintf in utils/xstring.h)
// ... : Parameter fuer 'format'
//-----------------------------------------------------------
void lcd_printf_at_P
( uint8_t x
, uint8_t y
, uint8_t mode
, const char *format
, ...
)
{
va_list ap
;
va_start( ap
, format
);
_xvsnprintf
( true, printf_buffer
, PRINTF_BUFFER_SIZE
, format
, ap
);
va_end(ap
);
lcdx_print_at
( x
, y
, (unsigned char *)printf_buffer
, mode
, 0,0);
}
//##################################################################################################################################
//##################################################################################################################################
//-----------------------------------------------------------
void lcd_write_number_u
(uint8_t number
)
{
uint8_t num
= 100;
uint8_t started
= 0;
while (num
> 0)
{
uint8_t b
= number
/ num
;
if (b
> 0 || started
|| num
== 1)
{
lcd_putc
(lcd_xpos
++, lcd_ypos
, '0' + b
, 0);
started
= 1;
}
number
-= b
* num
;
num
/= 10;
}
}
//-----------------------------------------------------------
void lcd_write_number_u_at
(uint8_t x
, uint8_t y
, uint8_t number
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
lcd_write_number_u
(number
);
}
//-----------------------------------------------------------
// numtype: 'd' oder 'u'
//
// Ergebnis: ein String in format_buffer
// -> "%4d" "%4.2d" "%03.1d" "%4u" usw...
//-----------------------------------------------------------
void make_number_format
( char numtype
, int16_t length
, int16_t decimals
, uint8_t pad
)
{
register char *p
;
register char *psrc
;
p
= format_buffer
;
*p
= '%'; p
++; // start '%'
if(pad
) { *p
= '0'; p
++; } // pad '0'
itoa( length
, s
, 10 );
psrc
= s
; while(*psrc
) *p
++ = *psrc
++; // vorkomma
if( decimals
> 0 )
{
*p
= '.'; p
++; // punkt '.'
itoa( decimals
, s
, 10 );
psrc
= s
; while(*psrc
) *p
++ = *psrc
++; // nachkomma
}
*p
= numtype
; p
++; // 'd' oder 'u'
*p
= 0;
}
//-----------------------------------------------------------
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void writex_ndigit_number_u
(uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
make_number_format
( 'u', length
, 0, pad
); // ergebnis in: format_buffer
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, format_buffer
, number
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void write_ndigit_number_u
(uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
writex_ndigit_number_u
( x
, y
, number
, length
, pad
, mode
, 0,0);
}
//-----------------------------------------------------------
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void writex_ndigit_number_s
(uint8_t x
, uint8_t y
, int16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
make_number_format
( 'd', length
, 0, pad
); // ergebnis in: format_buffer
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, format_buffer
, number
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void write_ndigit_number_s
(uint8_t x
, uint8_t y
, int16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
writex_ndigit_number_s
(x
, y
, number
, length
, pad
, mode
, 0,0);
}
//-----------------------------------------------------------
// Write only some digits of a unsigned <number> at <x>/<y> to MAX7456 display memory
// as /10th of the value
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void writex_ndigit_number_u_10th
( uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
make_number_format
( 'u', length
-1, 1, pad
); // ergebnis in: format_buffer
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, format_buffer
, number
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void write_ndigit_number_u_10th
( uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
writex_ndigit_number_u_10th
( x
, y
, number
, length
, pad
, mode
, 0,0);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void writex_ndigit_number_u_100th
( uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
make_number_format
( 'u', length
-2, 2, pad
); // ergebnis in: format_buffer
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, format_buffer
, number
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void write_ndigit_number_u_100th
( uint8_t x
, uint8_t y
, uint16_t number
, int16_t length
, uint8_t pad
)
{
writex_ndigit_number_u_100th
( x
, y
, number
, length
, pad
, MNORMAL
, 0,0);
}
//-----------------------------------------------------------
// Write only some digits of a signed <number> at <x>/<y> to MAX7456 display memory
// as /10th of the value
// <num> represents the largest multiple of 10 that will still be displayable as
// the first digit, so num = 10 will be 0-99 and so on
// <pad> = 1 will cause blank spaced to be filled up with zeros e.g. 007 instead of 7
//
void writex_ndigit_number_s_10th
(uint8_t x
, uint8_t y
, int16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
make_number_format
( 'd', length
-1, 1, pad
); // ergebnis in: format_buffer
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, format_buffer
, number
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void write_ndigit_number_s_10th
(uint8_t x
, uint8_t y
, int16_t number
, int16_t length
, uint8_t pad
, uint8_t mode
)
{
writex_ndigit_number_s_10th
( x
, y
, number
, length
, pad
, mode
, 0,0);
}
//-----------------------------------------------------------
// write <seconds> as human readable time at <x>/<y> to MAX7456 display mem
//
void writex_time
( uint8_t x
, uint8_t y
, uint16_t seconds
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
uint16_t min
= seconds
/ 60;
seconds
-= min
* 60;
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, "%02u:%02u", min
, seconds
);
/*
writex_ndigit_number_u (x, y, min, 2, 0,mode, xoffs,yoffs);
lcdx_putc (x + 2, y, ':', mode, xoffs,yoffs);
writex_ndigit_number_u (x + 3, y, seconds, 2, 1,mode, xoffs,yoffs);
*/
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void write_time
( uint8_t x
, uint8_t y
, uint16_t seconds
)
{
writex_time
( x
, y
, seconds
, 0, 0,0);
}
//--------------------------------------------------------------
// writex_datetime_time()
//
// Anzeigeformat: 'hh:mm:ss'
//
// datetime : vom Typ PKTdatetime_t
//--------------------------------------------------------------
void writex_datetime_time
( uint8_t x
, uint8_t y
, PKTdatetime_t datetime
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
PKTdatetime_t dtlocal
;
UTCdatetime2local
( &dtlocal
, &datetime
);
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, "%02u:%02u:%02u", (uint8_t)(dtlocal.
seconds/3600), (uint8_t)((dtlocal.
seconds/60)%60), (uint8_t)(dtlocal.
seconds%60));
}
//--------------------------------------------------------------
// writex_datetime_date()
//
// Anzeigeformat: 'dd.mm.yyyy' (keine Unterstuetzung von anderen Formaten aus aller Welt)
//
// datetime : vom Typ PKTdatetime_t
//--------------------------------------------------------------
void writex_datetime_date
( uint8_t x
, uint8_t y
, PKTdatetime_t datetime
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
PKTdatetime_t dtlocal
;
if( datetime.
year > 0 )
{
UTCdatetime2local
( &dtlocal
, &datetime
);
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, "%02u.%02u.%04u", dtlocal.
day, dtlocal.
month, dtlocal.
year);
}
else
{
// keine UTCZeit -> keine Datumsanzeige
lcdx_printp_at
( x
, y
, PSTR
(" . . "), mode
, xoffs
,yoffs
);
}
}
//-----------------------------------------------------------
// writes a single gps-pos
//-----------------------------------------------------------
void writex_gpspos
( uint8_t x
, uint8_t y
, int32_t GPSpos
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
lcdx_printf_at
( x
, y
, mode
, xoffs
, yoffs
, "%3.5ld", GPSpos
/100);
}
//--------------------------------------------------------------
//--------------------------------------------------------------
void Show_PKTError_NoRAM
(void)
{
lcd_cls
();
lcd_rect
( 8, 8, 127-16, 6*8, 1);
// 123456789012345678901
lcd_printp_at
( 2,2 , PSTR
("** OUT OF RAM **"), MINVERS
);
lcd_printp_at
( 2,4 , PSTR
("this function is"), MNORMAL
);
lcd_printp_at
( 2,5 , PSTR
("not available!"), MNORMAL
);
while ( !( (get_key_press
(1 << KEY_ENTER
)) || (get_key_press
(1 << KEY_ESC
)) || (get_key_press
(1 << KEY_PLUS
)) || (get_key_press
(1 << KEY_MINUS
)) ) );
}
//--------------------------------------------------------------
//--------------------------------------------------------------
void ShowTitle_P
( const char *title
, uint8_t clearscreen
)
{
if( clearscreen
)
lcd_cls
();
lcd_frect
( 0, 0, 127, 7, 1); // Titel: Invers
if( strlen_P
(title
) < 17 )
show_Lipo
();
lcd_printp_at
( 1, 0, title
, MINVERS
);
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void Popup_Draw
( uint8_t heigthC
)
{
uint8_t y
, h
;
h
= heigthC
*8;
y
= 63-h
;
//lcd_frect( 0, (hC*8)-6, 127, 63-(hC*8)+6, 1); // Box white
lcd_frect
( 0, y
-8, 127, 3, 0); // Box clear
lcd_frect
( 0, y
-4, 127, h
+4, 1); // Box fill white
lcd_plot
( 0, y
-4, 0); // Ecke links oben 1
lcd_plot
( 127, y
-4, 0); // Ecke rechts oben 1
lcd_line
( 1, y
-4, 0, y
-3, 0); // Ecke links oben 2
lcd_line
( 127-1, y
-4, 127, y
-3, 0); // Ecke rechts oben 2
}
//-----------------------------------------------------------
// lcdx_cls_rowwidth( y, width, mode, xoffs,yoffs )
//
// loescht eine Zeile auf dem Display
// mode ist kompatibel zu MNORMALX, MINVERSX
//
// width: in Zeichen
//-----------------------------------------------------------
void lcdx_cls_rowwidth
( uint8_t y
, uint8_t width
, uint8_t mode
, int8_t xoffs
, int8_t yoffs
)
{
int8_t xadd
= 0;
int8_t yadd
= 0;
if( mode
== MNORMALX
|| mode
== MINVERSX
)
{
if( xoffs
> 0 ) xadd
= 1;
if( (y
*8)+yoffs
> 0 ) yadd
= 1;
if( mode
== MNORMALX
)
mode
= MNORMAL
;
else
mode
= MINVERS
;
}
lcd_frect
( xoffs
-xadd
, (y
*8)+yoffs
-yadd
, (width
*6)+xadd
, 7+yadd
, (mode
== MNORMAL
? 0 : 1) ); // Zeile loeschen
}
//-----------------------------------------------------------
// lcdx_cls_row( y, mode, yoffs )
//
// loescht eine Zeile auf dem Display
// mode ist kompatibel zu MNORMALX, MINVERSX
//-----------------------------------------------------------
void lcdx_cls_row
( uint8_t y
, uint8_t mode
, int8_t yoffs
)
{
lcdx_cls_rowwidth
( y
, 21, mode
, 0, yoffs
);
}
//####################################################################################
//####################################################################################
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcd_setpos
( uint8_t x
, uint8_t y
)
{
lcd_xpos
= x
;
lcd_ypos
= y
;
}
//-----------------------------------------------------------
//-----------------------------------------------------------
void lcd_print_char
( uint8_t c
, uint8_t mode
)
{
switch( c
)
{
case 0x0D: lcd_xpos
= 0;
break;
case 0x0A: new_line
();
break;
default: lcdx_putc
(lcd_xpos
, lcd_ypos
, c
, mode
, 0,0);
lcd_xpos
++;
if( lcd_xpos
> 20 )
{
lcd_xpos
= 0;
new_line
();
}
break;
}
}
//----------------------------------------------------
// gibt einen Linefeed aus (CR+LF)
//----------------------------------------------------
void lcd_print_LF
( void )
{
lcd_print_char
( 0x0D, MNORMAL
);
lcd_print_char
( 0x0A, MNORMAL
);
}