/* * File: xprintf.c * * Snafu (Gast) * Created on 5. Februar 2019, 10:16 https://www.mikrocontroller.net/topic/497784#new * * Updated and corrected by Manni on 6. June 2022 * * Tested with Atmel Studio 7 and ATmega8 controller. * * The original software by Snafu (Gast) had 3 errors: * - in function xprintDEC() The line: while (x < dv[i++]) continue; changed to: while (x < dv[i]) {i++;}; - in function xprintf() The line: if (c == 'i' && (signed)i.u16 < 0) i.u16 = -i.u16, PUTC('-'); changed to: if (c == 'd' && (signed)i.u16 < 0) i.u16 = -i.u16, PUTC('-'); - in function main() The line: xprintf("multiple args %s %c %d %u %l %n %f %X \n", s, c, d, u, l, n, x); changed to: xprintf("multiple args %s %c %d %u %l %n %X \n", s, c, d, u, l, n, x); */ #include #include #include "RS232.h" #include "my_xprintf.h" //****************************************************************************** //****************************************************************************** void xprintDEC(xprintf_t x) { #ifdef XPRINTF_32 const uint32_t dv[] = {1000000000UL, 100000000UL, 10000000UL, 1000000UL, 100000UL, 10000UL, 1000UL, 100UL, 10UL, 1UL}; #else const uint16_t dv[] = {10000U, 1000U, 100U, 10U, 1U}; #endif char c; uint8_t i = 0; xprintf_t d; if (x) { while (x < dv[i]) {i++;}; // code corrected do { d = dv[i++]; c = '0'; while (x >= d) { ++c; x = x - d; } PUTC ( c); } while (!(d & 1)); } else { PUTC ('0'); } return; } //****************************************************************************** //****************************************************************************** void xprintHex(const uint8_t data) { // if (value > 9) return value + 'A'-'0'; // else return value + '0'; const char hexChar[] = "0123456789ABCDEF"; PUTC (hexChar[data>>4]); PUTC (hexChar[data&0x0F]); return; } //****************************************************************************** //****************************************************************************** void xprintf(char *format, ...) { uint8_t c; #ifdef XPRINTF_32 union {uint32_t u32; uint16_t u16; struct {uint8_t lsb, msb;};} i; #else union {uint16_t u16; struct {uint8_t lsb, msb;};} i; #endif va_list a; va_start (a, format); while (c = *format++, c) { if (c == '%') { switch (c = *format++, c) { case 's': // string PUTS (va_arg (a, char*)); break; case 'c': // char PUTC (va_arg (a, int)); break; case 'd': // integer (int16_t) case 'u': // unsigned integer (uint16_t) i.u16 = va_arg (a, int16_t); if (c == 'd' && (signed)i.u16 < 0) i.u16 = -i.u16, PUTC ('-'); // code corrected xprintDEC (i.u16); break; #ifdef XPRINTF_32 case 'l': // long (int32_t) case 'n': // unsigned long (uint32_t) i.u32 = va_arg (a, xprintf_t); if(c == 'l' && (signed)i.u32 < 0) i.u32 = -i.u32, PUTC ('-'); xprintDEC (i.u32); break; #endif case 'X': // max 16bit heXadecimal i.u16 = va_arg (a, uint16_t); xprintHex (i.msb); xprintHex (i.lsb); break; case 0: return; default: goto noFormat; } } else { noFormat: PUTC (c); } } va_end(a); return; } /* The below test program main() will result in the following printout: string test char X integer -12345 unsigned int 12345 long -1234567890 unsigned long 1234567890 hex ABCD multiple args test X -12345 12345 -1234567890 1234567890 ABCD Dec: 42 Hex: 2A */ int main () { RS232_Init (); // will init the ATmegaX UART with the correct baud rate volatile uint8_t *s = (uint8_t[]){"test"}, c = 'X'; volatile uint16_t x = 0xABCD; volatile int16_t d = -12345; volatile int16_t u = 12345; volatile int32_t l = -1234567890; volatile int32_t n = 1234567890; xprintf ("string %s\n", s); xprintf ("char %c\n", c); xprintf ("integer %d\n", d); xprintf ("unsigned int %u\n", u); xprintf ("long %l\n", l); xprintf ("unsigned long %n\n", n); xprintf ("hex %X\n", x); xprintf ("multiple args %s %c %d %u %l %n %X \n", s, c, d, u, l, n, x); // code corrected xprintf ("Dec: "); xprintDEC (42); xprintf ("\n"); xprintf ("Hex: "); xprintHex (42); xprintf ("\n"); while (1) {}; }