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

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

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

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

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

//----------------------------------------------------------------------------------------------------------------------
// Globale Variablen:
//----------------------------------------------------------------------------------------------------------------------
__flash U08 NC_HEX_ARRAY[] = "0123456789ABCDEF"; // alle hexadezimalen Ziffern in der Codierung von ASCII
                                                 // im FLASH-Speicher als Konvertierungs-Vorlage
U08 nc_buffer[16 ];                              // Umwandlungspuffer (8-Bit-Array mit 16 Elementen)
U08 nc_format_buffer[16 ];                       // Formatatierungspuffer (8-Bit-Array mit 16 Elementen)
static U08 nc_int_digits[8];                     // Array fuer Ziffern vor dem Komma einer float-Variablen
static U08 nc_dec_digits[6];                     // Array fuer Ziffern nach dem Komma einer float-Variablen

//----------------------------------------------------------------------------------------------------------------------
//------------------- Es folgen FUNKTIONEN FUER DIE KONVERTIERUNG VERSCHIEDENER DATEN-TYPEN ----------------------------
//----------------------------- (nicht nur fuer das Modul lcd_2wire interessant) ---------------------------------------
//----------------------------------------------------------------------------------------------------------------------

//----------------------------------------------------------------------------------------------------------------------
//--Formatierung des Uebergabe-Strings durch Auffuellen mit Space----------------------------------------------------4.1
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_format(pU08 source_ptr,U08 digits)       // Aufruf: nc_format(Pointer auf das Quell-Array,n-Zeichen);
                                                 // Formatierung des Uebergabe-Strings durch Auffuellen mit
                                                 // vorlaufenden 'Space'. Der Pointer verweist auf die vorderste
                                                 // Ziffer oder das Vorzeichen im Array.
                                                 // n-Zeichen ist die Anzahl auszugebender Zeichen auf dem LCD
{
  U08 len = strlen(source_ptr);                  // Bibliotheks-Funktion ermittelt Laenge des Quell-Arrays ohne NULL
  pU08 dest_ptr = (pU08)&nc_format_buffer;       // Dem Pointer auf das Ziel-Array wird die Adresse
                                                 // des Formatierungspuffers zugewiesen.
  // Schleife zum Auffuellen mit Leerzeichen
  while (digits-- > len)                         // Fuer jede Stelle, die die Laenge len kuerzer ist als
  {                                              // die Anzahl ASCII-Zeichen im Array, wird
    *dest_ptr++ = 32 ;                           // ein ASCII-Zeichen Space in das Ziel-Array eingefuegt
  }
  // Schleife zum Erstellen des Uebergabe-Strings an die LCD-Ausgabe-Funktion
  while (len--)
  {                                              // Nun werden die ASCII-Zeichen vom Quell-Array source_ptr
    *dest_ptr++ = *source_ptr++;                 // in das Ziel-Array dest_ptr uebertragen
  }
  *dest_ptr = 0;                                 // und mit einem NULL-Zeichen (Terminator) abgeschlossen
  return (pU08)&nc_format_buffer;                // Beim Ruecksprung verweist der Pointer auf die erste Adresse
                                                 // des Uebergabe-Strings (Formatierungspuffer)
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 8-Bit-Dual-Zahl in ein ASCII-String um---------------------------------------------------------------4.2
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U08_to_str(U08 value,U08 digits)         // Aufruf: nc_U08_to_str(8-Bit-Dual-Zahl,n-Zeichen);
                                                 // Wandle eine 8-Bit-Dual-Zahl in ein ASCII-String um.
                                                 // Wertebereich: 0 ... 255
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
/*
Abarbeitung der if-Kette:
Der Pointer zeigt zunaechst auf das 1. Element des Arrays, also nc_buffer[0]. Ab hier wird
das Array besetzt. Die folgenden Abfragen entscheiden darueber, mit welcher Dezimal-Stelle die
Besetzung des Arrays beginnt. Die 1. Abfrage beginnt bei der 3. Dezimal-Stelle und wird
fortgesetzt bis zur Einerstelle.
Ist zum Beispiel der Wert value = 123, so wird das Array wie folgt besetzt:

nc_buffer[ 0] = Hunderter-Stelle der 8-Bit-Dual-Zahl        => '1'
nc_buffer[ 1] = Zehner-Stelle der 8-Bit-Dual-Zahl           => '2'
nc_buffer[ 2] = Einer-Stelle der 8-Bit-Dual-Zahl            => '3'
nc_buffer[ 3] = NULL (Terminator)
*/
  if (value >= 100) *pstr++ = ('0' + (value % 1000 / 100));
  if (value >= 10) *pstr++ = ('0' + (value % 100 / 10));
  *pstr++ = ('0' + (value % 10));
  *pstr = 0;                                     // NULL-Zeichen (Terminator) im Array
  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine vorzeichenbehaftete 8-Bit-Dual-Zahl nach ASCII um----------------------------------------------------4.3
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_S08_to_str(S08 signed_value,U08 digits)  // Aufruf: nc_S08_to_str(+/- 8-Bit-Dual-Zahl,n-Zeichen);
                                                 // Wandle eine vorzeichenbehaftete 8-Bit-Dual-Zahl
                                                 // in ein ASCII-String um.
                                                 // Wertebereich: -128 ... +127
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  U08 value;
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  if (signed_value < 0)                          // Wenn Zahl negativ, dann
  {
    *pstr++ = '-';                               // Minus-Zeichen setzen und
    value = -signed_value;                       // mit positivem Wert als Type U08 weiter arbeiten
  }
  else                                           // andernfalls:
  {
    value = signed_value;                        // mit positivem Wert als Type U08 weiter arbeiten
  }
/*
Abarbeitung der if-Kette:
Der Pointer zeigt zunaechst auf das 1. Element des Arrays, also nc_buffer[0], bei positiven Zahlen
oder auf das 2. Element nc_buffer[1] bei negativen Zahlen, da nc_buffer[0]='-' ist. Ab hier wird
das Array besetzt. Die folgenden Abfragen entscheiden darueber, mit welcher Dezimal-Stelle die
Besetzung des Arrays beginnt. Die 1. Abfrage beginnt bei der 3. Dezimal-Stelle (Hunderter) und wird
fortgesetzt bis zur Einerstelle.
Ist zum Beispiel der Wert value = 123, so wird das Array wie folgt besetzt:
nc_buffer[ 0] = Hunderter-Stelle der vorzeichenbehafteten 8-Bit-Dual-Zahl        => '1'
nc_buffer[ 1] = Zehner-Stelle der vorzeichenbehafteten 8-Bit-Dual-Zahl           => '2'
nc_buffer[ 2] = Einer-Stelle der vorzeichenbehafteten 8-Bit-Dual-Zahl            => '3'
nc_buffer[ 3] = NULL (Terminator)
*/
  if (value >= 100) *pstr++ = ('0' + (value % 1000 / 100));
  if (value >= 10) *pstr++ = ('0' + (value % 100 / 10));
  *pstr++ = ('0' + (value % 10));
  *pstr = 0;                                     // NULL-Zeichen (Terminator) in Array
  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
                                                 // oder das Vorzeichen
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 8-Bit-Dual-Zahl in eine Hexadezimal-Zahl um----------------------------------------------------------4.4
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U08_to_hex(U08 value)                    // Aufruf: nc_U08_to_hex(8-Bit-Dual-Zahl);
                                                 // Wandle eine 8-Bit-Dual-Zahl in eine Hexadezimal-Zahl um
                                                 // und lege ihre Ziffern als ASCII-Zeichen in einem Array ab.
                                                 // Wertebereich: 0 ... 255 => 0x00 ... 0xFF

{
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  *pstr++ = NC_HEX_ARRAY[value >> 4];            // nc_buffer[0] = Hexadezimal-Ziffer des oberen Nibbles als ASCII
  *pstr++ = NC_HEX_ARRAY[value & 0x0F];          // nc_buffer[1] = Hexadezimal-Ziffer des unteren Nibbles als ASCII
  *pstr = 0;                                     // nc_buffer[2] = NULL-Zeichen (Terminator) im Array
  return (nc_buffer);                            // Beim Ruecksprung verweist der Pointer auf die
                                                 // hoechstwertige Hexadezimal-Ziffer als ASCII-Zeichen im Array
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 8-Bit-Dual-Zahl in ein Binary-String um--------------------------------------------------------------4.5
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U08_to_bin(U08 value)                    // Aufruf: nc_U08_to_bin(8-Bit-Dual-Zahl);
                                                 // Wandle eine 8-Bit-Dual-Zahl in ein Binary-String um und lege
                                                 // ihre Nullen und Einsen als ASCII-Zeichen in einem Array ab.
                                                 // Wertebereich: 0 ... 255 => 00000000 ... 11111111
{
  U08 n;
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  for (n = 7; n < 8; n--)                        //
  {
    if (value & (1 << n))                        // Abfragen der Bits von Bit7 bis Bit0; wenn Bit gleich 1 dann
    {
      *pstr++ = '1';                             // setze ASCII-Zeichen '1' an die laufende Position im Array
    }
    else                                         // andernfalls
    {
      *pstr++ = '0';                             // setze ASCII-Zeichen '0' an die laufende Position im Array
    }
  }
  *pstr = 0;                                     // nc_buffer[7] = NULL-Zeichen (Terminator) im Array
  return (nc_buffer);                            // Beim Ruecksprung verweist der Pointer auf die
                                                 // hoechstwertige Dual-Ziffer im Array
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 16-Bit-Dual-Zahl in ein ASCII-String um--------------------------------------------------------------4.6
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U16_to_str(U16 value,U08 digits)         // Aufruf: nc_U16_to_str(16-Bit-Dual-Zahl,n-Zeichen);
                                                 // Wandle eine 16-Bit-Dual-Zahl in ein ASCII-String um.
                                                 // Wertebereich: 0 ... 65535
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt

{
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
/*
Abarbeitung der if-Kette:
Der Pointer zeigt zunaechst auf das 1. Element des Arrays, also nc_buffer[0]. Ab hier wird
das Array besetzt. Die folgenden Abfragen entscheiden darueber, mit welcher Dezimal-Stelle die
Besetzung des Arrays beginnt. Die 1. Abfrage beginnt bei der 5. Dezimal-Stelle (Zehntausender)
und wird fortgesetzt bis zur Einerstelle.
Ist zum Beispiel der Wert value = 1234, so wird das Array wie folgt besetzt (Zehntausender-Stelle entfaellt):
nc_buffer[ 0] = Tausender-Stelle der 16-Bit-Dual-Zahl       => '1'
nc_buffer[ 1] = Hunderter-Stelle der 16-Bit-Dual-Zahl       => '2'
nc_buffer[ 2] = Zehner-Stelle der 16-Bit-Dual-Zahl          => '3'
nc_buffer[ 3] = Einer-Stelle der 16-Bit-Dual-Zahl           => '4'
nc_buffer[ 4] = NULL (Terminator)
*/
  if (value >= 10000) *pstr++ = ('0' + (value / 10000));
  if (value >= 1000) *pstr++ = ('0' + (value % 10000 / 1000));
  if (value >= 100) *pstr++ = ('0' + (value % 1000 / 100));
  if (value >= 10)*pstr++ = ('0' + (value % 100 / 10));
  *pstr++ = ('0' + (value % 10));
  *pstr = 0;                                     // NULL-Zeichen (Terminator)
  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine vorzeichenbehaftete 16-Bit-Dual-Zahl nach ASCII------------------------------------------------------4.7
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_S16_to_str(S16 signed_value,U08 digits)  // Aufruf: nc_S16_to_str(+/- 16-Bit-Dual-Zahl,n-Zeichen);
                                                 // Wandle eine vorzeichenbehaftete 16-Bit-Dual-Zahl
                                                 // in ein ASCII-String um.
                                                 // Wertebereich: -32768 ... 32767
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  U16 value;
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  if (signed_value < 0)                          // Wenn Zahl negativ, dann
  {
    *pstr++ = '-';                               // Minus-Zeichen setzen und
    value = -signed_value;                       // mit positivem Wert als Type U16 weiter arbeiten
  }
  else                                           // andernfalls:
  {
    value = signed_value;                        // mit positivem Wert als Type U16 weiter arbeiten
  }
/*
Abarbeitung der if-Kette:
Der Pointer zeigt zunaechst auf das 1. Element des Arrays, also nc_buffer[0], bei positiven Zahlen
oder auf das 2. Element nc_buffer[1] bei negativen Zahlen, da nc_buffer[0]='-' ist. Ab hier wird
das Array besetzt. Die folgenden Abfragen entscheiden darueber, mit welcher Dezimal-Stelle die
Besetzung des Arrays beginnt. Die 1. Abfrage beginnt bei der 5. Dezimal-Stelle (Zehntausender)und wird
fortgesetzt bis zur Einerstelle.
Ist zum Beispiel der Wert value = 1234, so wird das Array wie folgt besetzt (Zehntausender-Stelle entfaellt):
nc_buffer[ 0] = Tausender-Stelle der vorzeichenbehafteten 16-Bit-Dual-Zahl       => '1'
nc_buffer[ 1] = Hunderter-Stelle der vorzeichenbehafteten 16-Bit-Dual-Zahl       => '2'
nc_buffer[ 2] = Zehner-Stelle der vorzeichenbehafteten 16-Bit-Dual-Zahl          => '3'
nc_buffer[ 3] = Einer-Stelle der vorzeichenbehafteten 16-Bit-Dual-Zahl           => '4'
nc_buffer[ 4] = NULL (Terminator)
*/
  if (value >= 10000) *pstr++ = ('0' + (value / 10000));
  if (value >= 1000) *pstr++ = ('0' + (value % 10000 / 1000));
  if (value >= 100) *pstr++ = ('0' + (value % 1000 / 100));
  if (value >= 10) *pstr++ = ('0' + (value % 100 / 10));
  *pstr++ = ('0' + (value % 10));
  *pstr = 0;                                     // NULL-Zeichen (Terminator)
  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
                                                 // oder das Vorzeichen
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 16-Bit-Dual-Zahl in eine Hexadezimal-Zahl um---------------------------------------------------------4.8
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U16_to_hex(U16 value)                    // Aufruf: nc_U16_to_hex(16-Bit-Dual-Zahl);
                                                 // Wandle eine 16-Bit-Dual-Zahl in eine Hexadezimal-Zahl um
                                                 // und lege ihre Ziffern als ASCII-Zeichen in einem Array ab.
                                                 // Wertebereich: 0 ... 65535 => 0x0000 ... 0xFFFF
{
  tMEM16 data;                                   // data ist die Variable einer UNION
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  data.word = value;                             // word ist das Mitglied der UNION-Variablen data
  *pstr++ = NC_HEX_ARRAY[(data.byte[1]) >> 4];   // nc_buffer[0] = Hexadezimal-Ziffer des oberen Nibbles
                                                 //                als ASCII-Zeichen vom hoeherwertigen Byte
  *pstr++ = NC_HEX_ARRAY[(data.byte[1]) & 0x0F]; // nc_buffer[1] = Hexadezimal-Ziffer des unteren Nibbles
                                                 //                als ASCII-Zeichen vom hoeherwertigen Byte
  *pstr++ = NC_HEX_ARRAY[(data.byte[0]) >> 4];   // nc_buffer[2] = Hexadezimal-Ziffer des oberen Nibbles
                                                 //                als ASCII-Zeichen vom niederwertigen Byte
  *pstr++ = NC_HEX_ARRAY[(data.byte[0]) & 0x0F]; // nc_buffer[3] = Hexadezimal-Ziffer des unteren Nibbles
                                                 //                als ASCII-Zeichen vom niederwertigen Byte
  *pstr = 0;                                     // nc_buffer[4] = NULL-Zeichen (Terminator)
  return (nc_buffer);                            // Beim Ruecksprung verweist der Pointer auf die
                                                 // hoechstwertige Hexadezimal-Ziffer als ASCII-Zeichen im Array
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 32-Bit-Dual-Zahl in ein ASCII-String um--------------------------------------------------------------4.9
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U32_to_str(U32 value,U08 digits)         // Aufruf: nc_U32_to_str(32-Bit-Dual-Zahl,n-Zeichen);
                                                 // Wandle eine 32-Bit-Dual-Zahl in ein ASCII-String um.
                                                 // Wertebereich: 0 ... 4294967295
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
/*
Abarbeitung der if-Kette:
Der Pointer zeigt zunaechst auf das 1. Element des Arrays, also nc_buffer[0]. Ab hier
wird das Array besetzt. Die folgenden Abfragen entscheiden darueber, mit welcher Dezimal-Stelle
die Besetzung des Arrays beginnt. Die 1. Abfrage beginnt bei der 10. Dezimal-Stelle und wird
fortgesetzt bis zur Einerstelle.
Ist zum Beispiel der Wert value = 123456, so wird das Array wie folgt besetzt:

nc_buffer[ 0] = Hundertausender-Stelle der 32-Bit-Dual-Zahl => '1'
nc_buffer[ 1] = Zehntausender-Stelle der 32-Bit-Dual-Zahl   => '2'
nc_buffer[ 2] = Tausender-Stelle der 32-Bit-Dual-Zahl       => '3'
nc_buffer[ 3] = Hunderter-Stelle der 32-Bit-Dual-Zahl       => '4'
nc_buffer[ 4] = Zehner-Stelle der 32-Bit-Dual-Zahl          => '5'
nc_buffer[ 5] = Einer-Stelle der 32-Bit-Dual-Zahl           => '6'
nc_buffer[ 6] = NULL (Terminator)
*/
  if (value >= 1000000000) *pstr++ = ('0' + (value / 1000000000));
  if (value >= 100000000) *pstr++ = ('0' + (value % 1000000000 / 100000000));
  if (value >= 10000000) *pstr++ = ('0' + (value % 100000000 / 10000000));
  if (value >= 1000000) *pstr++ = ('0' + (value % 10000000 / 1000000));
  if (value >= 100000) *pstr++ = ('0' + (value % 1000000 / 100000));
  if (value >= 10000) *pstr++ = ('0' + (value % 100000 / 10000));
  if (value >= 1000) *pstr++ = ('0' + (value % 10000 / 1000));
  if (value >= 100) *pstr++ = ('0' + (value % 1000 / 100));
  if (value >= 10) *pstr++ = ('0' + (value % 100 / 10));
  *pstr++ = ('0' + (value % 10));
  *pstr = 0;                                     // NULL-Zeichen (Terminator)
  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine vorzeichenbehaftete 32-Bit-Dual-Zahl nach ASCII-----------------------------------------------------4.10
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_S32_to_str(S32 signed_value,U08 digits)  // Aufruf: nc_S32_to_str(+/- 32-Bit-Dual-Zahl,n-Zeichen);
                                                 // Wandle eine vorzeichenbehaftete 32-Bit-Dual-Zahl
                                                 // in ein ASCII-String um.
                                                 // Wertebereich: -2147483648 ... 2147483647
                                                 // n-Zeichen: Anzahl darzustellender Stellen insgesamt
{
  U32 value;
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  if (signed_value < 0)                          // Wenn Zahl negativ, dann
  {
    *pstr++ = '-';                               // Minus-Zeichen setzen und
    value = -signed_value;                       // mit positivem Wert als Type U16 weiter arbeiten
  }
  else                                           // Andernfalls:
  {
    value = signed_value;                        // mit positivem Wert als Type U16 weiter arbeiten
  }
/*
Abarbeitung der if-Kette:
Der Pointer zeigt zunaechst auf das 1. Element des Arrays, also nc_buffer[0], bei positiven Zahlen
oder auf das 2. Element nc_buffer[1] bei negativen Zahlen, da nc_buffer[0]='-' ist. Ab hier wird
das Array besetzt. Die folgenden Abfragen entscheiden darueber, mit welcher Dezimal-Stelle die
Besetzung des Arrays beginnt. Die 1. Abfrage beginnt bei der 10. Dezimal-Stelle und wird
fortgesetzt bis zur Einerstelle.
Ist zum Beispiel der Wert value = 123456, so wird das Array wie folgt besetzt:

nc_buffer[ 0] = Hundertausender-Stelle der vorzeichenbehafteten 32-Bit-Dual-Zahl => '1'
nc_buffer[ 1] = Zehntausender-Stelle der vorzeichenbehafteten 32-Bit-Dual-Zahl   => '2'
nc_buffer[ 2] = Tausender-Stelle der vorzeichenbehafteten 32-Bit-Dual-Zahl       => '3'
nc_buffer[ 3] = Hunderter-Stelle der vorzeichenbehafteten 32-Bit-Dual-Zahl       => '4'
nc_buffer[ 4] = Zehner-Stelle der vorzeichenbehafteten 32-Bit-Dual-Zahl          => '5'
nc_buffer[ 5] = Einer-Stelle der vorzeichenbehafteten 32-Bit-Dual-Zahl           => '6'
nc_buffer[ 6] = NULL (Terminator)
*/
  if (value >= 1000000000) *pstr++ = ('0' + (value / 1000000000));
  if (value >= 100000000) *pstr++ = ('0' + (value % 1000000000 / 100000000));
  if (value >= 10000000) *pstr++ = ('0' + (value % 100000000 / 10000000));
  if (value >= 1000000) *pstr++ = ('0' + (value % 10000000 / 1000000));
  if (value >= 100000) *pstr++ = ('0' + (value % 1000000 / 100000));
  if (value >= 10000) *pstr++ = ('0' + (value % 100000 / 10000));
  if (value >= 1000) *pstr++ = ('0' + (value % 10000 / 1000));
  if (value >= 100) *pstr++ = ('0' + (value % 1000 / 100));
  if (value >= 10) *pstr++ = ('0' + (value % 100 / 10));
  *pstr++ = ('0' + (value % 10));
  *pstr = 0;                                     // NULL-Zeichen (Terminator)
  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
                                                 // oder das Vorzeichen
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 32-Bit-Dual-Zahl in eine Hexadezimal-Zahl um--------------------------------------------------------4.11
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_U32_to_hex(U32 value)                    // Aufruf: nc_U32_to_hex(32-Bit-Dual-Zahl);
                                                 // Wandle eine 32-Bit-Dual-Zahl in eine Hexadezimal-Zahl um
                                                 // und lege ihre Ziffern als ASCII-Zeichen in einem Array ab.
                                                 // Wertebereich: 0 ... 4294967295 => 0x00000000 ... 0xFFFFFFFF
{
  tMEM32 data;                                   // data ist die Variable einer UNION
  pU08 pstr = nc_buffer;                         // Weise dem Pointer pstr die Adresse des 1. Elementes vom
                                                 // Array nc_buffer zu => identisch mit *pstr = &nc_buffer[0]
  data.dword = value;                             // word ist das Mitglied der UNION-Variablen data
  *pstr++ = NC_HEX_ARRAY[(data.byte[3]) >> 4];   // nc_buffer[0] = Hexadezimal-Ziffer des oberen Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit
  *pstr++ = NC_HEX_ARRAY[(data.byte[3]) & 0x0F]; // nc_buffer[1] = Hexadezimal-Ziffer des unteren Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit
  *pstr++ = NC_HEX_ARRAY[(data.byte[2]) >> 4];   // nc_buffer[2] = Hexadezimal-Ziffer des oberen Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit-1
  *pstr++ = NC_HEX_ARRAY[(data.byte[2]) & 0x0F]; // nc_buffer[3] = Hexadezimal-Ziffer des unteren Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit-1
  *pstr++ = NC_HEX_ARRAY[(data.byte[1]) >> 4];   // nc_buffer[4] = Hexadezimal-Ziffer des oberen Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit-2
  *pstr++ = NC_HEX_ARRAY[(data.byte[1]) & 0x0F]; // nc_buffer[5] = Hexadezimal-Ziffer des unteren Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit-2
  *pstr++ = NC_HEX_ARRAY[(data.byte[0]) >> 4];   // nc_buffer[6] = Hexadezimal-Ziffer des oberen Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit-3
  *pstr++ = NC_HEX_ARRAY[(data.byte[0]) & 0x0F]; // nc_buffer[7] = Hexadezimal-Ziffer des unteren Nibbles
                                                 //                als ASCII-Zeichen vom Byte hoechster Wertgkeit-3
  *pstr = 0;                                     // nc_buffer[8] = NULL-Zeichen (Terminator)
  return (nc_buffer);                            // Beim Ruecksprung verweist der Pointer auf die
                                                 // hoechstwertige Hexadezimal-Ziffer als ASCII-Zeichen im Array
}

//----------------------------------------------------------------------------------------------------------------------
//--Wandle eine 32-Bit-Gleitkomma-Zahl in ein ASCII-String um-------------------------------------------------------4.12
//----------------------------------------------------------------------------------------------------------------------
pU08 nc_float_to_str(float value,U08 decimals,U08 digits)
                                                 // Aufruf: nc_float_to_str(Gleitkomma-Zahl,d-Bruchstellen,n-Zeichen);
                                                 // Wandle eine 32-Bit-Gleitkomma-Zahl in ein ASCII-String um
                                                 // 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
{
  S08 n;                                         // Allgemeiner Zaehler
  U08 int_count;                                 // Zaehler fuer vorhandene Anzahl Ziffern vor dem Komma
  U08 dec_count;                                 // Zaehler fuer vorhandene Anzahl Ziffern nach dem Komma
  float dec_part;                                // Werte-Teil der Zahl nach dem Komma
  U32 int_part;                                  // Werte-Teil der Zahl vor dem Komma
  pU08 pstr = nc_buffer;                         // Pointer pstr erhaelt die Adresse des 1. Elementes vom
                                                 // Array nc_buffer => identisch mit *pstr = &nc_buffer[0]
  if (decimals > 5)                              // Anzahl darzustellender Stellen nach dem Komma werden
  {
    decimals = 5;                                // auf max. 5 Bruchstellen beschraenkt
  }
  if (value < 0.0)                               // Wenn Gleitkomma-Zahl negativ, dann
  {
    *pstr++ = '-';                               // Minus-Zeichen setzen und
    value = -value;                              // mit positivem Wert weiter arbeiten
  }
  int_part = value;                              // Umwandlung der Gleitpunkt-Zahl in eine 32-Bit-Dual-Zahl (Integer)
                                                 // d.h. es wird nur der Teil vor dem Komma nach int_part abgelegt.
  dec_part = value - int_part;                   // Der Bruchteil nach dem Komma wird nach dec_part abgelegt.
  int_count = 0;                                 // Zaehler-INT fuer Anzahl Ziffern vor dem Komma auf 0
  dec_count = 0;                                 // Zaehler-DEC fuer Anzahl Ziffern nach dem Komma auf 0
  if (int_part == 0)                             // Wenn der Wert vor dem Komma 0 ist,
  {
    *pstr++ = '0';                               // dann ASCII-Ziffer 0 an die 1. Stelle bei positiver Zahl,
                                                 //                     an die 2. Stelle bei negativer Zahl
  }
  while (int_part > 0)                           // 1. Schleife zur Bearbeitung der ganzen Zahl; solange groesser 0
  {                                              // Beginn bei der Einerstelle:
    nc_int_digits[int_count] = int_part % 10;    // Der Restwert der Division durch 10 ergibt
                                                 // eine Dezimalstelle; Ziffer nach Array nc_int_digits[]
    int_part = int_part - nc_int_digits[int_count]; // bearbeitete Dezimalstelle mit 0 besetzen
    if (int_part > 0)                            // Solange Rest der ganzen Zahl groesser 0,
    {                                            // Fortsetzung der 1. Schleife
      int_part = int_part / 10;                  // bearbeitete Dezimalstelle abtrennen (Division durch 10)
    }                                            // Nach letzter Ziffer ist hier int_part = 0
    int_count++;                                 // Anzahl Ziffern vor dem Komma hochzaehlen.
  }                                              // Ende der 1. Schleife
  while (dec_count < decimals)                   // 2. Schleife zur Bearbeitung der Bruchstellen; solange bis
  {                                              // die Anzahl Ziffern nach dem Komma < als anzuzeigende Anzahl ist
    dec_part = dec_part * 10.0;                  // Naechste Bruchstelle vor das Komma schieben (Multipl. mit 10.0)
    nc_dec_digits[dec_count] = dec_part;         // implizite Typwandlung nach U08 => die Ziffer vor dem Komma
                                                 // nach Array nc_dec_digits[] ablegen.
    if (nc_dec_digits[dec_count] > 0)            // Wenn diese Ziffer groesser 0 ist (1, 2, ...oder 9),
    {                                            // dann soll diese entfernt werden:
      dec_part = dec_part - nc_dec_digits[dec_count]; // bearbeitete Dezimalstelle mit 0 besetzen
    }                                            // Nach letzter Ziffer ist hier dec_count = decimals-1
    dec_count++;                                 // Anzahl Ziffern nach dem Komma hochzaehlen: dec_count = decimals
  }                                              // Ende der 2. Schleife

  for (n = int_count - 1; n > -1; n--)           // 3. Schleife fuer die Uebertragung der Ziffern vor dem Punkt
  {
    *pstr++ = 48 + nc_int_digits[n];             // Ziffer (unteres Nibble) + 48 ergibt Code fuer ASCII-Zeichen
  }
  *pstr++ = '.';                                 // Dezimal-Punkt als ASCII-Zeichen
  for (n = 0; n < dec_count; n++)                // 4. Schleife fuer die Uebertragung der Ziffern nach dem Punkt
  {
    *pstr++ = 48 + nc_dec_digits[n];             // Ziffer (unteres Nibble) + 48 ergibt Code fuer ASCII-Zeichen
  }
  *pstr = 0;                                     // NULL-Zeichen (Terminator)

  if (!digits)                                   // Wenn n-Ziffer = 0 ist, dann ist der Ausdruck TRUE
  {                                              // und es erfolgt der
    return nc_buffer;                            // Ruecksprung mit dem Pointer auf nc_buffer[0]
  }                                              // das ist die vorderste Ziffer der Gleitkomma-Zahl
                                                 // oder das Vorzeichen
  else                                           // Andernfalls: Formatierte Ausgabe
  {
    return nc_format(nc_buffer,digits);          // Formatierung (Auffuellen mit fuehrenden Leerstellen)
                                                 // Beim Ruecksprung verweist der Pointer auf die erste Adresse
  }                                              // des Strings; digits ist die Anzahl Zeichen = n-Zeichen
}
//----------------------------------------------------------------------------------------------------------------------

