/* ------------------------------------------------------- my_printf.cpp Library-Header fuer eine eigene (sehr kleine) printf- sprintf-Funktion. Arduino-Boards: alle fuer | myprintf | muss im Sketch irgendwo ein my_putchar vorhanden sein. Bsp.: void my_putchar(char ch) { txlcd_putchar(ch); } 05.05.2026 R. Seelig ------------------------------------------------------ */ #include "my_printf.h" char printfkomma = 1; char printfoutstream = MYSTREAM; char *printfptr; extern void my_putchar(char ch); /* ------------------------------------------------------------ charout sendet ein Zeichen in Abhaengigkeit von Outstream ent- weder an das Ausgabegeraet oder in ein Chararray ------------------------------------------------------------ */ void charout(char ch) { if (printfoutstream == MYSTREAM) { my_putchar(ch); } else { *printfptr = ch; printfptr++; } } /* ------------------------------------------------------------ putint gibt einen Integer dezimal aus. Ist Uebergabe "komma" != 0 wird ein "Kommapunkt" mit ausgegeben. Bsp.: 12345 wird als 123.45 ausgegeben (bei komma== 2). ------------------------------------------------------------ */ void putint(int32_t i, char komma) { typedef enum boolean { FALSE, TRUE } bool_t; static int32_t zz[] = { 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10 }; bool_t not_first = FALSE; uint8_t zi; komma = 10 - komma; if (!i) { charout('0'); } else { if (i < 0) { charout('-'); i = -i; } int32_t z, b; for (zi = 0; zi < 9; zi++) { z = 0; b = 0; while (z + zz[zi] <= i) { b++; z += zz[zi]; } if (b || not_first) { charout('0' + b); not_first = TRUE; } if (zi + 1 == komma) { if (!not_first) charout('0'); charout('.'); not_first = TRUE; } i -= z; } charout('0' + i); } } /* ------------------------------------------------------------ hexnibbleout gibt die unteren 4 Bits eines chars als Hexaziffer aus. Eine Pruefung ob die oberen vier Bits geloescht sind erfolgt NICHT ! ------------------------------------------------------------- */ void hexnibbleout(uint8_t b) { if (b < 10) b += '0'; else b += 55; charout(b); } /* ------------------------------------------------------------ puthex gibt einen Integer hexadezimal aus. Ist die auszugebende Zahl >= 0xff erfolgt die Ausgabe 2-stellig, ist sie groesser erfolgt die Ausgabe 4-stellig. Ist out16 gesetzt, erfolgt ausgabe immer 4 stellig ------------------------------------------------------------ */ void puthex(uint16_t h, char out16) { uint8_t b; if ((h > 0xff) || out16) // 16 Bit-Wert { b = (h >> 12); hexnibbleout(b); b = (h >> 8) & 0x0f; hexnibbleout(b); } b = (h >> 4) & 0x0f; hexnibbleout(b); b = h & 0x0f; hexnibbleout(b); } /* ------------------------------------------------------------ putstring gibt einen AsciiZ String aus ------------------------------------------------------------- */ void putstring(const char *p) { while (*p) { charout(*p); p++; } } /* ------------------------------------------------------------ my_vprintf Parserkern fuer printf und sprintf Platzhalterfunktionen: %s : Ausgabe Textstring %d : dezimale Ausgabe ( verwendet int, je nach Compiler 16 oder 32 Bit breit) %x : hexadezimale Ausgabe ( verwendet int, je nach Compiler 16 oder 32 Bit breit) ist Wert > 0xff erfolgt 4 oder 8-stellige Ausgabe ist Wert <= 0xff erfolgt 2-stellige Ausgabe ( verwendet int, je nach Compiler 16 oder 32 Bit breit) %k : Integerausgabe als Pseudokommazahl 12345 wird bei printfkomma== 2 als 123.45 ausgegeben ( verwendet int, je nach Compiler 16 oder 32 Bit breit) %D : wie %d nur mit explizter 32-Bit Variable %X : wie %x nur mit explizter 32-Bit Variable %K : wie %K nur mit explizter 32-Bit Variable %c : Ausgabe als Asciizeichen ------------------------------------------------------------ */ static void my_vprintf(const char *s, va_list ap) { int32_t arg1; uint32_t xarg1; const char *arg2; char ch; do { ch = *s; if (ch == 0) return; if (ch == '%') { s++; uint8_t token = *s; switch (token) { case 'd': { arg1 = va_arg(ap, int); putint(arg1, 0); break; } case 'x': { xarg1 = va_arg(ap, unsigned int); if (xarg1 <= 0xFFFF) { puthex(xarg1, 0); } else { puthex(xarg1 >> 16, 0); puthex(xarg1 & 0xffff, 1); } break; } case 'D': { arg1 = va_arg(ap, int32_t); putint(arg1, 0); break; } case 'X': { xarg1 = va_arg(ap, uint32_t); if (xarg1 <= 0xFFFF) { puthex(xarg1, 0); } else { puthex(xarg1 >> 16, 0); puthex(xarg1 & 0xffff, 1); } break; } case 'k': { arg1 = va_arg(ap, int); putint(arg1, printfkomma); break; } case 'K': { arg1 = va_arg(ap, int32_t); putint(arg1, printfkomma); break; } case 'c': { arg1 = va_arg(ap, int); charout(arg1); break; } case '%': { charout('%'); break; } case 's': { arg2 = va_arg(ap, char *); putstring(arg2); break; } } } else { charout(ch); } s++; } while (ch != '\0'); } /* ------------------------------------------------------------ my_printf alternativer Ersatz fuer printf. Aufruf: my_printf("Ergebnis= %d",zahl); Platzhalter siehe my_vprintf ------------------------------------------------------------ */ void my_printf(const char *s, ...) { va_list ap; printfoutstream = MYSTREAM; va_start(ap, s); my_vprintf(s, ap); va_end(ap); } /* ------------------------------------------------------------ my_sprintf alternativer Ersatz fuer sprintf. Aufruf: my_sprintf(strbuffer, "Ergebnis= %d",zahl); Platzhalter siehe my_vprintf ------------------------------------------------------------ */ void my_sprintf(char *buffer, const char *s, ...) { va_list ap; printfoutstream = MYARRAY; printfptr = buffer; va_start(ap, s); my_vprintf(s, ap); va_end(ap); *printfptr = 0; printfoutstream = MYSTREAM; }