/*
------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------- MODUL = Teil C ----------------------------------------------------
************************************************** lcd_2wire.c ** V1.2 *************************************************
------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------
 Beteiligtes Modul....: num_conversion
 Header...............: lcd_2wire.h
 Version..............: 1.2
 Compiler.............: CodeVisionAVR
 Chip.................: ATmega88
 Datum................: Juni 2009
 Autor................: Alwin Lenck (ALE23) basierend auf dem Modul lcd_2wire von Udo Juerss
------------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
//Aufrufbare Funktionen (die Funktions-Prototypen befinden sich in der Header-Datei lcd_2wire.h):
//----------------------------------------------------------------------------------------------------------------------

Das Modul lcd_2wire arbeitet eng mit dem Modul num_conversion zusammen! Das bedeutet, dass viele der hier 
aufgefuehrten Funktionen wiederum Funktionen des Moduls num_conversion aufrufen.

FUNKTIONEN ZUR INITIALISIERUNG DES LCD UND AUSGABE VON KOMMANDOS UND ASCII-DATEN AN DAS LCD

void lcd_init(void)                              // Initialisierung des LC-Displays                                  1.1
void lcd_delay(void)                             // Verzoegerung in Abhaengigkeit der System-Takt-Frequenz           1.2
void lcd_shift_byte(U08 data,U08 mode)           // Schreibe LED-Kommando oder Daten-Byte in das LC-Display          1.3
void lcd_init_shift_reg(U08 mode)                // Loesche Shift-Register, setze E- und ggf. RS-Bit                 1.4
void lcd_shift_nibble(U08 data)                  // Schiebe 4 Bits (ein Nibble) in das Shift-Register                1.5
void lcd_write_command(U08 command)              // Uebertrage ein vollstaendiges LCD-Kommando zum LCD               1.6
void lcd_write_data(U08 data)                    // Uebertrage ein vollstaendiges Daten-Byte zum LCD                 1.7

------------------------------------------------------------------------------------------------------------------------
FUNKTIONEN ZUM ERZEUGEN VON DISPLAY-KOMMANDOS

void lcd_clear(void)                             // CLEAR DISPLAY:                   Bit0 gesetzt                    2.1
void lcd_home(void)                              // RETURN HOME:                     Bit1 gesetzt                    2.2
void lcd_entry_mode(U08 entry_mode)              // SET ENTRY MODE:                  Bit2 gesetzt                    2.3
void lcd_display_mode(U08 display_mode)          // DISPLAY ON/OFF:                  Bit3 gesetzt                    2.4
void lcd_function_mode(U08 function_mode)        // SET FUNCTION:                    Bit5 gesetzt                    2.5
void lcd_download_char_from_rom(U08 char_index,fpU08 byte_ptr) // SET CGRAM ADDRESS: Bit6 gesetzt                    2.6
void lcd_goto_xy(U08 xpos,U08 ypos)              // Setze Cursor-Koordinaten (x/y)   Bit7 gesetzt                    2.7
------------------------------------------------------------------------------------------------------------------------
FUNKTIONEN ZUM ERZEUGEN VON ASCII-DATEN-STRINGS AUS VERSCHIEDENEN ZEICHEN UND ZEICHEN-GRUPPEN

Hierbei verwendete Uebergabe-Variablen:
chr                                              // auszugebendes ASCII-Zeichen (unsigned char)
sp                                               // Pointer auf char-String (Array mit ASCCI-Zeichen)
value                                            // auszugebender Zahlen-Wert (8-Bit- oder 16-Bit-Dual-Zahl)
digits                                           // Anzahl auszugebender Zeichen; ggf. Auffuellen mit
                                                 // vorlaufenden Leerstellen (Spaces ' ')
und verwendete Typen:
U08                                              // unsigned char
pU08                                             // Pointer auf eine char-Variable
fpU08                                            // Pointer auf eine char-Variable im FLASH-Speicher

void lcd_write_char(U08 chr)                     // Schreibe einzelnes ASCII-Zeichen (unsigned char)                 3.1
void lcd_write_char_xy(U08 x,U08 y,U08 chr)      // Schreibe ASCII-Zeichen auf vorbestimmte Position im LCD          3.2
void lcd_write_str(pU08 sp)                      // Schreibe ASCII-String (Array mit ASCCI-Zeichen)                  3.3
void lcd_write_str_xy(U08 x,U08 y,pU08 sp)       // Schreibe ASCII-String auf vorbestimmte Position im LCD           3.4
void lcd_write_flash_str(fpU08 sp)               // Schreibe ASCII-String aus dem Array im FLASH-Speicher            3.5
void lcd_write_flash_str_xy(U08 x,U08 y,fpU08 sp) // Schreibe ASCII-String vom FLASH auf feste Cursor-Position       3.6
void lcd_write_U08(U08 value,U08 digits)         // Schreibe 8-Bit-Dual-Zahl als Dezimal-Zahl                        3.7
void lcd_write_S08(S08 value,U08 digits)         // Schreibe +/- 8-Bit-Dual-Zahl als Dezimal-Zahl                    3.8
void lcd_write_U08_hex(U08 value)                // Schreibe 8-Bit-Dual-Zahl als 2-ziffrige Hexadezimal-Zahl         3.9
void lcd_write_U08_bin(U08 value)                // Schreibe 8-bit-Dual-Zahl in binaerer Schreibweise               3.10
void lcd_write_U16(U16 value,U08 digits)         // Schreibe 16-Bit-Dual-Zahl als Dezimal-Zahl                      3.11
void lcd_write_S16(S16 value,U08 digits)         // Schreibe +/- 16-Bit-Dual-Zahl als Dezimal-Zahl                  3.12
void lcd_write_U16_hex(U16 value)                // Schreibe 16-Bit-Dual-Zahl als 4-ziffrige Hexadezimal-Zahl       3.13
void lcd_write_U32(U32 value,U08 digits)         // Schreibe 32-Bit-Dual-Zahl als Dezimal-Zahl                      3.14
void lcd_write_S32(S32 value,U08 digits)         // Schreibe +/- 32-Bit-Dual-Zahl als Dezimal-Zahl                  3.15
void lcd_write_float(float value,U08 decimals,U08 digits) // Schreibe +/- Gleitkomma-Zahl als Dezimalbruch-Zahl     3.16

------------------------------------------------------------------------------------------------------------------------
Nur zur Uebersicht: FUNKTIONEN FUER DIE KONVERTIERUNG VERSCHIEDENER DATEN-TYPEN
Diese Funktionen befinden sich im Modul num_conversion und werden im Bedarfsfalle vom Modul lcd_2wire aufgerufen!

pU08 nc_format(pU08 source_ptr,U08 digits)       // Formatierung des Uebergabe-Strings durch Auffuellen mit Space    4.1
pU08 nc_U08_to_str(U08 value,U08 digits)         // Wandle eine 8-Bit-Dual-Zahl in ein ASCII-String um               4.2
pU08 nc_S08_to_str(S08 signed_value,U08 digits)  // Wandle eine vorzeichenbehaftete 8-Bit-Dual-Zahl nach ASCII um    4.3
pU08 nc_U08_to_hex(U08 value)                    // Wandle eine 8-Bit-Dual-Zahl in eine Hexadezimal-Zahl um          4.4
pU08 nc_U08_to_bin(U08 value)                    // Wandle eine 8-Bit-Dual-Zahl in ein Binary-String um              4.5
pU08 nc_U16_to_str(U16 value,U08 digits)         // Wandle eine 16-Bit-Dual-Zahl in ein ASCII-String um              4.6
pU08 nc_S16_to_str(S16 signed_value,U08 digits)  // Wandle eine vorzeichenbehaftete 16-Bit-Dual-Zahl nach ASCII      4.7
pU08 nc_U16_to_hex(U16 value)                    // Wandle eine 16-Bit-Dual-Zahl in eine Hexadezimal-Zahl um         4.8
pU08 nc_U32_to_str(U32 value,U08 digits)         // Wandle eine 32-Bit-Dual-Zahl in ein ASCII-String um              4.9
pU08 nc_S32_to_str(S32 signed_value,U08 digits)  // Wandle eine vorzeichenbehaftete 32-Bit-Dual-Zahl nach ASCII     4.10
pU08 nc_U32_to_hex(U32 value)                    // Wandle eine 32-Bit-Dual-Zahl in eine Hexadezimal-Zahl um        4.11
pU08 nc_float_to_str(float value,U08 decimals)   // Wandle eine 32-Bit-Gleitkomma-Zahl in ein ASCII-String um       4.12

------------------------------------------------------------------------------------------------------------------------
*/

//----------------------------------------------------------------------------------------------------------------------
// Header-Datei einfuegen:
//----------------------------------------------------------------------------------------------------------------------
#include "lcd_2wire.h"                           // Initialisierung der Anwendung

//----------------------------------------------------------------------------------------------------------------------
// Globale Variablen:
//----------------------------------------------------------------------------------------------------------------------
__flash U08 LCD_ROW_TABLE[4] =                   // Array mit den Anfangsadressen der Display-Zeilen
                                                 // im DDRAM des LCD, abgespeichert im FLASH-Speicher
                                                 // Das Array wird in der Funktion lcd_goto_xy(x,y) benutzt
                                                 // Zusaetzlich ist das Bit7=1 gesetzt, um aus diesen Konstanten
                                                 // das LCD-Kommando 'SET DDRAM ADDRESS' bilden zu koennen:
{
  0x80,                                          // LCD_ROW_TABLE[0] = 10000000 => Zeile 0 von/bis-Adr.:  0 .... 19
  0xC0,                                          // LCD_ROW_TABLE[1] = 11000000 => Zeile 1 von/bis-Adr.: 64 .... 83
  0x80 + LCD_COLS,                               // LCD_ROW_TABLE[2] = 10010100 => Zeile 2 von/bis-Adr.: 20 .... 39
  0xC0 + LCD_COLS                                // LCD_ROW_TABLE[3] = 11010100 => Zeile 3 von/bis-Adr.: 84 ... 103
                                                 // Die Adressen 40 bis 63 sind nicht ansprechbar !!
};

//----------------------------------------------------------------------------------------------------------------------
//--Initialisierungs-Funktion----------------------------------------------------------------------------------------1.1
//----------------------------------------------------------------------------------------------------------------------
void lcd_init(void)                              // Initialisierung des LC-Displays
{
  // Setze CLK-Pin (PB1) und DATA-Pin (PB2) auf LOW-Level
  LCD_CLOCK_PRT &= ~LCD_CLOCK_BIT;               // PORTB = 00000000 -> negative Impuls-Flanke auf CLK (PB1 = 0)
  LCD_DATA_PRT &= ~LCD_DATA_BIT;                 // PORTB = 00000000 -> Loesche DATA-Signal auf DATA   (PB2 = 0)

  // CLK-Pin und DATA-Pin sind Output-Pins
  LCD_CLOCK_DDR |= LCD_CLOCK_BIT;                // DDRB  = 00000000 | 00000010 = 00000010 (DDRB  |= 0x02)
  LCD_DATA_DDR |= LCD_DATA_BIT;                  // DDRB  = 00000010 | 00000100 = 00000110 (DDRB  |= 0x04)
  delay_ms(LCD_POWER_UP_DELAY_MS);               // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(50 ))

  // Start Initialisierung
  // Nur das hohe Nibble wird im LCD-Initialisierungs-Modus 2 uebertragen !
  lcd_shift_byte(LCD_FUNCTION_8BIT_1LINE,LCD_INIT_MODE);  // 00110000 - LCD-Interface auf 8-Bit-Mode setzen
                                                          // identisch mit lcd_shift_byte(0x30,2)
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))
  lcd_shift_byte(LCD_FUNCTION_8BIT_1LINE,LCD_INIT_MODE);  // 00110000 - LCD-Interface auf 8-Bit-Mode setzen
                                                          // identisch mit lcd_shift_byte(0x30,2)
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))
  lcd_shift_byte(LCD_FUNCTION_8BIT_1LINE,LCD_INIT_MODE);  // 00110000 - LCD-Interface auf 8-Bit-Mode setzen
                                                          // identisch mit lcd_shift_byte(0x30,2)
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))
  lcd_shift_byte(LCD_FUNCTION_4BIT_1LINE,LCD_INIT_MODE);  // 00110000 - LCD-Interface auf 4-Bit-Mode setzen
                                                          // identisch mit lcd_shift_byte(0x20,2)
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))

  // Jetzt wird das Display im 4-Bit-Mode betrieben; die beiden Nibbles werden automatisch vom LCD zusammengesetzt
#if (LCD_ROWS > 1)
  lcd_write_command(LCD_FUNCTION_4BIT_2LINES);   // 00101000 - 4-Bit-Mode, 2-zeilig und 5x7-Punkt-Darstellung
                                                 // identisch mit lcd_write_command(0x28)
#else
  lcd_write_command(LCD_FUNCTION_4BIT_1LINE);    // 00100000 - 4-Bit-Mode, 1-zeilig und 5x7-Punkt-Darstellung
                                                 // identisch mit lcd_write_command(0x20)
#endif
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))
  lcd_write_command(LCD_DISP_ON);                // 00001100 - Display ein, Cursor-Anzeige aus
                                                 // identisch mit lcd_write_command(0x0C)
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))
  lcd_write_command(LCD_CLR);                    // 00000001 - Display (Textpuffer) loeschen
                                                 // identisch mit lcd_write_command(1)
  lcd_write_command(LCD_HOME);                   // 00000010 - Cursor auf 1. Zeichen (Adresse 0)
                                                 // identisch mit lcd_write_command(2)
  delay_ms(LCD_INIT_DELAY_MS);                   // Verzoegerung beim Einschalt- und Reset-Vorgang (delay_ms(5 ))
}

//----------------------------------------------------------------------------------------------------------------------
//--Verzoegerungs-Funktion-------------------------------------------------------------------------------------------1.2
//----------------------------------------------------------------------------------------------------------------------
void lcd_delay(void)                             // Verzoegerung in Abhaengigkeit der System-Takt-Frequenz
{
  // Definition und Laden des von der Takt-Frequenz abhaengigen Verzoegerungswertes
  U08 delay = F_CPU_MHZ;                         // Uebernahme aus dem bei der Projekt-Konfiguration
                                                 // identisch mit U08 delay = (((16000000) / 1000) / 1000)
                                                 // vordefinierten Macro _MCU_CLOCK_FREQUENCY_ (16 MHz)
  while (delay--)                                // Verzoegerung durch Herabzaehlen von delay in der Schleife auf 0
  {
  }
}

//----------------------------------------------------------------------------------------------------------------------
//--Shift-Byte-Funktion----------------------------------------------------------------------------------------------1.3
//----------------------------------------------------------------------------------------------------------------------
void lcd_shift_byte(U08 data,U08 mode)           // Schreibe LED-Kommando oder Daten-Byte in das LC-Display
{
  // Hier beginnt die Uebertragungsprozedur fuer das obere Nibble
  lcd_init_shift_reg(mode);                      // Loesche Shift-Register, setze E-Bit und ggf. RS-Bit
                                                 // Stand im Shift-Register:                Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // Wenn Modus 0 (es folgt LCD-Kommando)     0   0   0   0   0   1   0
                                                 // Wenn Modus 1 (es folgen 4 Daten-Bits)    0   0   0   0   0   1   1
                                                 // Wenn Modus 2 (es folgt LCD-Ini-Kommando) 0   0   0   0   0   1   0

  lcd_shift_nibble(data >> 4);                   // Schiebe oberes Nibble (4 Bits) zuerst in das Shift-Register
                                                 // Endgueltiger Stand im Shift-Register:   Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // entspricht am LCD:                     E/2  RS DB7 DB6 DB5 DB4   -
                                                 // Wenn Modus 0 (LCD-Kommando xxxx)         1   0   x   x   x   x   0
                                                 // Wenn Modus 1 (4 Daten-Bits dddd)         1   1   d   d   d   d   0
                                                 // Wenn Modus 2 (LCD-Ini-Kommando xxxx)     1   0   x   x   x   x   0

  // Nun stehen 6 gueltige Bits des oberen Nibbles im Shift-Register zur Uebertragung zum LCD bereit:
  // Q2 bis Q5 als oberes Daten- bzw. LCD-Kommando-Nibble, Q6 (0 oder 1) fuer RS und Q7 = 1 am UND-Gatter-Eingang
  // Q7 = HIGH und das naechste HIGH auf der Leitung DATA erzeugen in logischer UND-Verknuepfung das HIGH fuer
  // das Enable-Signal an E:
  LCD_SET_DATA();                                // PORTB = 00000100 - Setze DATA-Signal (PB2 = 1)
                                                 // identisch mit {PORTB  |= 0x04 ;}
                                                 // positive Flanke an E => RS-Signal einlesen
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung

  // Hier beginnt die Uebertragungsprozedur fuer das untere Nibble
  // Im LCD-Initialisierungsmodus der Funktion lcd_init() wird dieser Funktions-Zweig uebersprungen, da das LCD-
  // Interface zunaechst im 8-Bit-Mode arbeitet und das untere Nibble (alle Bits=0) nicht uebertragen werden kann!
  if (mode != LCD_INIT_MODE)                     // Sprung, wenn Modus 2 (Initialisierungsmodus)
                                                 // identisch mit if (mode != 2)
  {
    lcd_init_shift_reg(mode);                    // Loesche Shift-Register, setze ggf. RS-Bit und negative Flanke an E
                                                 // Stand im Shift-Register:                Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // Wenn Modus 0 (es folgt LCD-Kommando)     0   0   0   0   0   1   0
                                                 // Wenn Modus 1 (es folgen 4 Daten-Bits)    0   0   0   0   0   1   1
                                                 // Modus 2 entfaellt !

    lcd_shift_nibble(data);                      // Schiebe unteres Nibble (4 Bits) zuletzt in das Shift-Register
                                                 // Endgueltiger Stand im Shift-Register:   Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // entspricht am LCD:                     E/2  RS DB7 DB6 DB5 DB4   -
                                                 // Wenn Modus 0 (LCD-Kommando xxxx)         1   0   x   x   x   x   0
                                                 // Wenn Modus 1 (4 Daten-Bits dddd)         1   1   d   d   d   d   0
                                                 // Modus 2 entfaellt !

  // Nun stehen 6 gueltige Bits des unteren Nibbles im Shift-Register zur Uebertragung zum LCD bereit:
  // Q2 bis Q5 als unteres Daten- bzw. LCD-Kommando-Nibble, Q6 (0 oder 1) fuer RS und Q7 = 1 am UND-Gatter-Eingang
  // Q7 = HIGH und das naechste HIGH auf der Leitung DATA erzeugen in logischer UND-Verknuepfung das HIGH fuer
  // das Enable-Signal an E:
    LCD_SET_DATA();                              // PORTB = 00000100 - Setze DATA-Signal (PB2 = 1)
                                                 // identisch mit {PORTB  |= 0x04 ;}
                                                 // positive Flanke an E => RS-Signal einlesen
    lcd_delay();                                 // Takt-Frequenzabhaengige Verzoegerung
  }
  LCD_CLR_DATA();                                // PORTB = 00000000 - Loesche DATA-Signal (PB2 = 0)
                                                 // identisch mit {PORTB  &= ~0x04 ;}
                                                 // negative Flanke an E => Nibble in LCD uebertragen
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
}

//----------------------------------------------------------------------------------------------------------------------
//--Loesch-Funktion fuer Shift-Register------------------------------------------------------------------------------1.4
//----------------------------------------------------------------------------------------------------------------------
void lcd_init_shift_reg(U08 mode)                // Loesche Shift-Register, setze ggf. RS-Bit und negative Flanke an E
{
  U08 n;
  LCD_CLR_DATA();                                // PORTB = 00000000 - Loesche DATA-Signal (PB2 = 0)
                                                 // identisch mit {PORTB  &= ~0x04 ;}
                                                 // ggf. negative Flanke an E => oberes Nibble in LCD uebertragen
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
  // Loesche alle Ausgabe-Pins des Shift-Registers durch Shift von LOW am Pin Serial-IN     Q7  Q6  Q5  Q4  Q3  Q2  Q1
  for (n = 7; n; n--)                            // durch 7 CLK-Impulse (positive Flanke)    0   0   0   0   0   0   0
  {
    LCD_SET_CLK();                               // PORTB = 00000010 positive Impuls-Flanke auf CLK (PB1 = 1)
                                                 // identisch mit {PORTB  |= 0x02 ;}
    lcd_delay();                                 // Takt-Frequenzabhaengige Verzoegerung
    LCD_CLR_CLK();                               // PORTB = 00000000 negative Impuls-Flanke auf CLK (PB1 = 0)
                                                 // identisch mit {PORTB  &= ~0x02 ;}
  }
  // HIGH-Bit in das Shift-Register fuer das Enable-Signal E des LCD (landet letztlich durch Shift auf Q7)
  LCD_SET_DATA();                                // PORTB = 00000100 - Setze DATA-Signal (PB2 = 1)
                                                 // identisch mit {PORTB  |= 0x04 ;}
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
  LCD_SET_CLK();                                 // PORTB = 00000010 positive Impuls-Flanke CLK (PB1 = 1)
                                                 // identisch mit {PORTB  |= 0x02 ;}
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
  LCD_CLR_CLK();                                 // PORTB = 00000000 negative Impuls-Flanke auf CLK (PB1 = 0)
                                                 // identisch mit {PORTB  &= ~0x02 ;}
                                                 // Neuer Stand im Shift-Register:          Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 //                                          0   0   0   0   0   0   1
  if (mode == LCD_DATA_MODE)                     // Wenn Modus 1 (nur beim Daten-Transfer), dann RS=1
  {                                              // identisch mit if (mode == 1)
    LCD_SET_DATA();                              // PORTB = 00000100 - Setze DATA fuer RS auf HIGH (PB2 = 1)
                                                 // identisch mit {PORTB  |= 0x04 ;}
  }
  else                                           // andernfalls (wenn Modus 0 oder Modus 2) RS=0
  {
    LCD_CLR_DATA();                              // PORTB = 00000000 - Setze DATA fuer RS auf LOW (PB2 = 0)
                                                 // identisch mit {PORTB  &= ~0x04 ;}
  }
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
  LCD_SET_CLK();                                 // PORTB = 00000010 positive Impuls-Flanke auf CLK (PB1 = 1)
                                                 // identisch mit {PORTB  |= 0x02 ;}
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
  LCD_CLR_CLK();                                 // PORTB = 00000000 negative Impuls-Flanke auf CLK (PB1 = 0)
                                                 // identisch mit {PORTB  &= ~0x02 ;}
                                                 // Stand im Shift-Register:                Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // Wenn Modus 0 (es folgt LCD-Kommando)     0   0   0   0   0   1   0
                                                 // Wenn Modus 1 (es folgen 4 Daten-Bits)    0   0   0   0   0   1   1
                                                 // Wenn Modus 2 (es folgt LCD-Ini-Kommando) 0   0   0   0   0   1   0
}

//----------------------------------------------------------------------------------------------------------------------
//--Shift-Nibble-Funktion--------------------------------------------------------------------------------------------1.5
//----------------------------------------------------------------------------------------------------------------------
void lcd_shift_nibble(U08 data)                  // Schiebe 4 Bits (ein Nibble) in das Shift-Register
{
  U08 n, mask = 0x08;                            // mask = 00001000 - zunaechst HIGH auf Bit3
  for (n = 4; n; n--)                            // Schleife fuer 4 Bits
  {
    if (data & mask)                             // Wenn data-Bit & mask-Bit = 1 (TRUE),
                                                 // dann shifte HIGH ins Shift-Register
    {
      LCD_SET_DATA();                            // PORTB = 00000100 - Setze DATA-Signal (PB2 = 1)
                                                 // identisch mit {PORTB  |= 0x04 ;}
    }
    else                                         // andernfalls shifte LOW ins Shift-Register
    {
      LCD_CLR_DATA();                            // PORTB = 00000000 - Loesche DATA-Signal (PB2 = 0)
                                                 // identisch mit  {PORTB  &= ~0x04 ;}
    }
                                                 // Naechster Schritt: Fuehre Shift aus
    LCD_SET_CLK();                               // PORTB = 00000010 positive Impuls-Flanke auf CLK (PB1 = 1)
                                                 // identisch mit {PORTB  |= 0x02 ;}
    lcd_delay();                                 // Takt-Frequenzabhaengige Verzoegerung
    LCD_CLR_CLK();                               // PORTB = 00000000 negative Impuls-Flanke auf CLK (PB1 = 0)
                                                 // identisch mit {PORTB  &= ~0x02 ;}
    mask >>= 1;                                  // Verschiebe HIGH-Bit der MASKE um eine Stelle nach rechts
  }
                                                 // Zwischen-Stand im Shift-Register:       Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // entspricht am LCD:                     E/2  RS DB7 DB6 DB5 DB4   -
                                                 // Wenn Modus 0 (LCD-Kommando xxxx)         0   1   0   x   x   x   x
                                                 // Wenn Modus 1 (4 Daten-Bits dddd)         0   1   1   d   d   d   d
                                                 // Wenn Modus 2 (LCD-Ini-Kommando xxxx)     0   1   0   x   x   x   x
  // Bringe die Bits im Shift-Register an die endgueltige Position:
  LCD_CLR_DATA();                                // PORTB = 00000000 - Loesche DATA-Signal (PB2 = 0)
                                                 // identisch mit {PORTB  &= ~0x04 ;}
  LCD_SET_CLK();                                 // PORTB = 00000010 positive Impuls-Flanke auf CLK (PB1 = 1)
                                                 // identisch mit  {PORTB  |= 0x02 ;}
  lcd_delay();                                   // Takt-Frequenzabhaengige Verzoegerung
  LCD_CLR_CLK();                                 // PORTB = 00000000 negative Impuls-Flanke auf CLK (PB1 = 0)
                                                 // identisch mit {PORTB  &= ~0x02 ;}
}
                                                 // Endgueltiger Stand im Shift-Register:   Q7  Q6  Q5  Q4  Q3  Q2  Q1
                                                 // entspricht am LCD:                     E/2  RS DB7 DB6 DB5 DB4   -
                                                 // Wenn Modus 0 (LCD-Kommando xxxx)         1   0   x   x   x   x   0
                                                 // Wenn Modus 1 (4 Daten-Bits dddd)         1   1   d   d   d   d   0
                                                 // Wenn Modus 2 (LCD-Ini-Kommando xxxx)     1   0   x   x   x   x   0

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer Kommando-----------------------------------------------------------------------------------1.6
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_command(U08 command)              // Uebertrage ein vollstaendiges LCD-Kommando zum LCD
{
  lcd_shift_byte(command,LCD_CMD_MODE);          // Modus 0 (Kommando-Uebertragung)
                                                 // identisch mit lcd_shift_byte(command,0)
}

//----------------------------------------------------------------------------------------------------------------------
//--Initialisierungs-Funktion----------------------------------------------------------------------------------------1.7
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_data(U08 data)                    // Uebertrage ein vollstaendiges Daten-Byte zum LCD
{
  lcd_shift_byte(data,LCD_DATA_MODE);            // Modus 1 (LCD-Daten-Uebertragung)
                                                 // identisch mit lcd_shift_byte(data,1)
}
//----------------------------------------------------------------------------------------------------------------------
//---------------------------Es folgen FUNKTIONEN ZUM ERZEUGEN VON DISPLAY-KOMMANDOS -----------------------------------
//---------------------------(diese stehen auch fuer Projekte zur freien Verfuegung) -----------------------------------
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
//--DISPLAY CLEAR (Bit0 gesetzt)-------------------------------------------------------------------------------------2.1
//----------------------------------------------------------------------------------------------------------------------
void lcd_clear(void)                             // Aufruf: lcd_clear();
{
  lcd_write_command(LCD_CLR);                    // 00000001 - Display (Textpuffer) wird geloescht)
                                                 // identisch mit lcd_write_command(1)
  delay_ms(4);
}

//----------------------------------------------------------------------------------------------------------------------
//--RETURN HOME (Bit1 gesetzt)---------------------------------------------------------------------------------------2.2
//----------------------------------------------------------------------------------------------------------------------
void lcd_home(void)                              // Aufruf: lcd_home();
{
  lcd_write_command(LCD_HOME);                   // 00000010 - Cursor an den Anfang des Textpuffers setzen
                                                 // identisch mit lcd_write_command(2)
}

//----------------------------------------------------------------------------------------------------------------------
//--SET ENTRY MODE (Bit2 gesetzt)------------------------------------------------------------------------------------2.3
//----------------------------------------------------------------------------------------------------------------------
void lcd_entry_mode(U08 entry_mode)              // Aufruf: lc_entry_mode(x);
                                                 // x=0 => Display-Shift AUS, Decrease (links)
                                                 // x=1 => Display-Shift EIN, Decrease (links)
                                                 // x=2 => Display-Shift AUS, Increase (rechts)
                                                 // x=3 => Display-Shift EIN, Increase (rechts)
{
  entry_mode = (entry_mode & 3) + 0x04;          // 000001xx - Bit2 zwangsweise setzen
  lcd_write_command(entry_mode);
}

//----------------------------------------------------------------------------------------------------------------------
//--DISPLAY ON/OFF (Bit3 gesetzt)------------------------------------------------------------------------------------2.4
//----------------------------------------------------------------------------------------------------------------------
void lcd_display_mode(U08 display_mode)          // Aufruf: lcd_display_mode(x);
                                                 // x=0 => Blink-Cursor AUS, Cursor AUS, Display AUS
                                                 // x=1 => Blink-Cursor EIN, Cursor AUS, Display AUS
                                                 // x=2 => Blink-Cursor AUS, Cursor EIN, Display AUS
                                                 // x=3 => Blink-Cursor EIN, Cursor EIN, Display AUS
                                                 // x=4 => Blink-Cursor AUS, Cursor AUS, Display EIN
                                                 // x=5 => Blink-Cursor EIN, Cursor AUS, Display EIN
                                                 // x=6 => Blink-Cursor AUS, Cursor EIN, Display EIN
                                                 // x=7 => Blink-Cursor EIN, Cursor EIN, Display EIN
{
  display_mode = (display_mode & 7) + 0x08;      // 00001xxx - Bit3 zwangsweise setzen
  lcd_write_command(display_mode);
}

//----------------------------------------------------------------------------------------------------------------------
//--SET FUNCTION (Bit5 gesetzt)--------------------------------------------------------------------------------------2.5
//----------------------------------------------------------------------------------------------------------------------
void lcd_function_mode(U08 function_mode)        // Aufruf: lcd_function_mode(x);
                                                 // Bit0 und Bit1 sind undefiniert
                                                 // x=0 =>  5x7 Dots, 1-zeilig, 4-Bit-Interface
                                                 // x=1 => 5x10 Dots, 1-zeilig, 4-Bit-Interface
                                                 // x=2 =>  5x7 Dots, 2-zeilig, 4-Bit-Interface
                                                 // x=3 => 5x10 Dots, 2-zeilig, 4-Bit-Interface
                                                 // x=4 =>  5x7 Dots, 1-zeilig, 8-Bit-Interface
                                                 // x=5 => 5x10 Dots, 1-zeilig, 8-Bit-Interface
                                                 // x=6 =>  5x7 Dots, 2-zeilig, 8-Bit-Interface
                                                 // x=7 => 5x10 Dots, 2-zeilig, 8-Bit-Interface
{
  function_mode = ((function_mode & 7) << 2) + 0x20; // 001xxx00 - Uebergabe-Wert 2 Stellen nach links, Bit5 setzen
  lcd_write_command(function_mode);
}

//----------------------------------------------------------------------------------------------------------------------
//--SET CGRAM ADDRESS (Bit6 gesetzt zum Schreiben in das CGRAM)------------------------------------------------------2.6
//----------------------------------------------------------------------------------------------------------------------
void lcd_download_char_from_rom(U08 char_index,fpU08 byte_ptr)
                                                 // Aufruf: lcd_download_char_from_rom(x,FlashPointer);
                                                 // x => 3 Bits fuer CGRAM-Adressteil des Sonder-Zeichens
                                                 // x = 0 ... 7 ist gleichzeitig die Ansteuerungs-Nummer des
                                                 // Sonder-Zeichens (statt ASCII) mit dem Kommando WRITE DATA
                                                 // (Es koennen bis zu 8 Sonder-Zeichen moduliert werden)
                                                 // FlashPointer => Pointer auf Punkt-Matrix des Zeichens(8 Byte)
{
  U08 n;                                         // Zaehler
  char_index &= 0x07;                            // Fuer Adr-Teil des Sonder-Zeichens werden nur Bit0 ... Bit2
  char_index <<= 0x03;                           // Links-Shift um 3 Bits => 00xxx000 fuer CGRAM-Adresse
  char_index |= LCD_SET_CGRAM_ADDR;              // Bit6 fuer SET CGRAM ADDRESS setzen
                                                 // identisch mit char_index |= 0x40
  lcd_write_command(char_index);                 // Schreibe das Kommando SET CGRAM ADDRESS: 01xxx000
  for (n = 0; n < 8; n++)                        // 8 Datenbytes zur Belegung der Bildpunkte in den 8 Matrix-Zeilen
  {                                              // So entsteht ein selbst codiertes Sonder-Zeichen:
    lcd_write_data(*byte_ptr++);                 // Besetzte die Punkt-Matrix aus dem Array, auf das der
  }                                              // FlashPointer verweist (es muessen 8 Bytes gesendet werden)
}

//----------------------------------------------------------------------------------------------------------------------
//--SET CURSOR POSITION / SET DDRAM ADDRESS (Bit7 wird in der LCD_ROW_TABLE gesetzt)---------------------------------2.7
//----------------------------------------------------------------------------------------------------------------------
void lcd_goto_xy(U08 xpos,U08 ypos)              // Aufruf: lcd_goto_xy(x,y);
                                                 // x von 0 bis 19
                                                 // y von 0 bis 3
{
  if (xpos < LCD_COLS && ypos < LCD_ROWS)        // Entsprechend der x/y-Position (x-Spalte, y-Zeile) werden
  {                                              // die Koordinaten 'linearisiert', d.h. 2-zeilig mit dem
                                                 // Array LCD_ROW_TABLE umgeschluesselt
                                                 // identisch mit if (xpos < 20  && ypos < 4 )
    lcd_write_command(LCD_ROW_TABLE[ypos] + xpos); // Der Klammerwert ist eine 'lineare' DDRAM-Adresse im LCD
  }
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//---- Es folgen FUNKTIONEN ZUM ERZEUGEN VON ASCII-DATEN-STRINGS AUS VERSCHIEDENEN ZEICHEN UND ZEICHEN-GRUPPEN ---------
//---------------------------- (diese stehen fuer Projekte zur freien Verfuegung) --------------------------------------
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer ASCII-Zeichen auf die laufende Position im LCD---------------------------------------------3.1
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_char(U08 chr)                     // Aufruf: lcd_write_char(ASCII-Zeichen);
                                                 // Schreibe einzelnes ASCII-Zeichen (unsigned char)
                                                 // auf die laufende Position im LCD
{
  lcd_write_data(chr);                           // Uebertrage ein ASCII-Zeichen (unsigned char) als
                                                 // vollstaendiges Daten-Byte zum LCD
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer ASCII-Zeichen mit LCD-Positionsangabe------------------------------------------------------3.2
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_char_xy(U08 x,U08 y,U08 chr)      // Aufruf: lcd_write_char_xy(Spalte,Zeile,ASCII-Zeichen);
                                                 // Schreibe einzelnes ASCII-Zeichen auf vorbestimmte Position im LCD
{                                                //
  lcd_goto_xy(x,y);                              // Setze den Cursor auf die vorbestimmte Position im Display
  lcd_write_data(chr);                           // Uebertrage ein ASCII-Zeichen (unsigned char) als
                                                 // vollstaendiges Daten-Byte zum LCD
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer ein ASCII-String-Array (Zeichen fuer Zeichen)----------------------------------------------3.3
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_str(pU08 sp)                      // Aufruf: lcd_write_str(Pointer auf ASCII-String);
                                                 // Schreibe ASCII-String (Array mit ASCII-Zeichen)
{
  while (*sp)                                    // Zeichen fuer Zeichen bis NULL-Zeichen erreicht ist
  {
    lcd_write_data(*sp++);                       // Uebertrage ein ASCII-Zeichen (unsigned char) als
                                                 // vollstaendiges Daten-Byte zum LCD
  }
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer ein ASCII-String-Array (mit LCD-Positionsangabe)-------------------------------------------3.4
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_str_xy(U08 x,U08 y,pU08 sp)       // Aufruf: lcd_write_str_xy(Spalte,Zeile,Pointer auf ASCII-String);
                                                 // Schreibe ASCII-String auf vorbestimmte Position im LCD
{
  lcd_goto_xy(x,y);                              // Setze den Cursor auf die vorbestimmte Position im Display
  lcd_write_str(sp);                             // Schreibe ASCII-String (Array mit ASCII-Zeichen)
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer ein Array im FLASH-Speicher (Zeichen fuer Zeichen)-----------------------------------------3.5
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_flash_str(fpU08 sp)               // Aufruf: lcd_write_flash_str(Pointer auf String im FLASH-Speicher);
                                                 // Schreibe ASCII-String aus dem Array im FLASH-Speicher
{
  while (*sp)                                    // Zeichen fuer Zeichen bis NULL-Zeichen erreicht ist
  {
    lcd_write_data(*sp++);                       // Uebertrage ein ASCII-Zeichen (unsigned char) als
                                                 // vollstaendiges Daten-Byte zum LCD
  }
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer ein Array im FLASH-Speicher (mit LCD-Positionsangabe)--------------------------------------3.6
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_flash_str_xy(U08 x,U08 y,fpU08 sp) // Aufruf: lcd_write_flash_str_xy(Spalte,Zeile,Pointer auf FLASH);
                                                 // (Der Pointer zeigt auf ein Array im FLASH-Speicher)
                                                 // Schreibe ASCII-String aus dem Array im FLASH-Speicher
                                                 // auf die bestimmte Position im Display
{
  lcd_goto_xy(x,y);                              // Setze den Cursor auf die vorbestimmte Position im Display
  lcd_write_flash_str(sp);                       // Schreibe ASCII-String aus dem Array im FLASH-Speicher
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 8-Bit-Dual-Zahl ohne Vorzeichen als Dezimal-Zahl-------------------------------------------3.7
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_U08(U08 value,U08 digits)         // Aufruf: lcd_write_U08(8-Bit-Dual-Zahl,n-Zeichen);
                                                 // Schreibe 8-Bit-Dual-Zahl als n-ziffrige Dezimal-Zahl
                                                 // Wertebereich: 0 ... 255
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_U08_to_str(value,digits));    //  als vollstaendige Daten-Bytes zum LCD
}                                                // (vorher Konvertierung der Zahl in ein ASCII-Array)

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 8-Bit-Dual-Zahl mit Vorzeichen als Dezimal-Zahl--------------------------------------------3.8
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_S08(S08 value,U08 digits)         // Aufruf: lcd_write_S08(+/- 8-Bit-Dual-Zahl,n-Zeichen);
                                                 // Schreibe +/- 8-Bit-Dual-Zahl als n-ziffrige Dezimal-Zahl
                                                 // Wertebereich: -128 ... +127
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_S08_to_str(value,digits));    // Uebertrage ASCII-String
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 8-Bit-Dual-Zahl als 2-ziffrige Hexadezimal-Zahl--------------------------------------------3.9
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_U08_hex(U08 value)                // Aufruf: lcd_write_U08_hex(8-Bit-Dual-Zahl);
                                                 // Schreibe 8-Bit-Dual-Zahl als 2-ziffrige Hexadezimal-Zahl
                                                 // Wertebereich: 0 ... 255 => 0x00 ... 0xFF
{
  lcd_write_str(nc_U08_to_hex(value));           // Uebertrage 2 ASCII-Zeichen (Hex-Ziffern) als Daten-Bytes zum LCD
}                                                // (vorher wird noch eine Konvertierung nach Hex und
                                                 // eine Konvertierung der Zahl in ein ASCII-Array vorgenommen)

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 8-Bit-Dual-Zahl in binaerer Schreibweise--------------------------------------------------3.10
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_U08_bin(U08 value)                // Aufruf: lcd_write_U08_bin(U08 value);
                                                 // Schreibe 8-bit-Dual-Zahl in binaerer Schreibweise
                                                 // Wertebereich: 0 ... 255 => 0b00000000 ... 0b11111111
{
  lcd_write_str(nc_U08_to_bin(value));           // Uebertrage ASCII-String
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 16-Bit-Dual-Zahl ohne Vorzeichen als Dezimal-Zahl-----------------------------------------3.11
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_U16(U16 value,U08 digits)         // Aufruf: lcd_write_U16(16-Bit-Dual-Zahl,n-Zeichen);
                                                 // Schreibe 16-Bit-Dual-Zahl als n-ziffrige Dezimal-Zahl
                                                 // Wertebereich: 0 ... 65535
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_U16_to_str(value,digits));    // Uebertrage ASCII-String als vollstaendige Daten-Bytes zum LCD
}                                                // (vorher Konvertierung der Zahl in ein ASCII-Array)

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 16-Bit-Dual-Zahl mit Vorzeichen als Dezimal-Zahl------------------------------------------3.12
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_S16(S16 value,U08 digits)         // Aufruf: lcd_write_S16(+/- 16-Bit-Dual-Zahl,n-Zeichen);
                                                 // Schreibe +/- 16-Bit-Dual-Zahl als n-ziffrige Dezimal-Zahl
                                                 // Wertebereich: -32768 ... +32767
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_S16_to_str(value,digits));    //
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 16-Bit-Dual-Zahl als 4-ziffrige Hexadezimal-Zahl------------------------------------------3.13
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_U16_hex(U16 value)                // Aufruf: lcd_write_U16_hex(16-Bit-Dual-Zahl);
                                                 // Schreibe 16-Bit-Dual-Zahl als 4-ziffrige Hexadezimal-Zahl
                                                 // Wertebereich: 0 ... 65535 => 0x0000 ... 0xFFFF
{                                                //
  lcd_write_str(nc_U16_to_hex(value));           // Uebertrage 4 ASCII-Zeichen (Hex-Ziffern) als Daten-Bytes zum LCD
}                                                // (vorher wird noch eine Konvertierung nach Hex und
                                                 // eine Konvertierung der Zahl in ein ASCII-Array vorgenommen)

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 32-Bit-Dual-Zahl ohne Vorzeichen als Dezimal-Zahl-----------------------------------------3.14
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_U32(U32 value,U08 digits)         // Aufruf: lcd_write_U32(U32 value,U08 digits);
                                                 // Schreibe 32-Bit-Dual-Zahl als n-ziffrige Dezimal-Zahl
                                                 // Wertebereich: 0 ... 4294967295
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_U32_to_str(value,digits));    // Uebertrage ASCII-String als vollstaendige Daten-Bytes zum LCD
}                                                // (vorher Konvertierung der Zahl in ein ASCII-Array)

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer 32-Bit-Dual-Zahl mit Vorzeichen als Dezimal-Zahl------------------------------------------3.15
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_S32(S32 value,U08 digits)         // Aufruf: lcd_write_S32(+/- 32-Bit-Dual-Zahl,n-Zeichen);
                                                 // Schreibe +/- 32-Bit-Dual-Zahl als n-ziffrige Dezimal-Zahl
                                                 // Wertebereich: -2147483648 ... +2147483647
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_S32_to_str(value,digits));    // Uebertrage ASCII-String
}

//----------------------------------------------------------------------------------------------------------------------
//--Schreib-Funktion fuer Gleitkomma-Zahl als Dezimal-Bruch---------------------------------------------------------3.16
//----------------------------------------------------------------------------------------------------------------------
void lcd_write_float(float value,U08 decimals,U08 digits) // Aufruf: lcd_write_float
                                                 //             (Gleitkomma-Zahl,d-Bruchstellen,n-Zeichen);
                                                 // Wertebereich: +/- 1.175e-35 ... +/- 3.402e38
                                                 // ABER nur 7 Stellen aufeinanderfolgender Ziffern sind garantiert.
                                                 // d-Bruchstellen: maximal 5 darzustellende Stellen nach dem Komma
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  lcd_write_str(nc_float_to_str(value,decimals,digits));  // Uebertrage ASCII-String
}
//----------------------------------------------------------------------------------------------------------------------


