PDA

View Full Version : printf() support in Print class



bperrybap
11-22-2013, 02:45 AM
Paul,
Do you think that there is any chance in getting the Arduino guys
to add printf() support to the Print() class
so that all device libraries that use Print can pick up printf() support?

If not, would you have any interest in adding it into Teensyduino?

BTW, this is a great example of the somewhat broken Arduino build methodology
in that there are core independent library headers and code that is being stuck
into the core directories.

I updated the Arduino Printf Playground page to show how to manually add this
and how to use it.
http://playground.arduino.cc/Main/Printf
It is as simple as dropping this code into the public section of the Print class definition.

#include <stdarg.h>
#define PRINTF_BUF 80 // define the tmp buffer size (change if desired)
void printf(const char *format, ...)
{
char buf[PRINTF_BUF];
va_list ap;
va_start(ap, format);
vsnprintf(buf, sizeof(buf), format, ap);
for(char *p = &buf[0]; *p; p++) // emulate cooked mode for newlines
{
if(*p == '\n')
write('\r');
write(*p);
}
va_end(ap);
}
#ifdef F // check to see if F() macro is available
void printf(const __FlashStringHelper *format, ...)
{
char buf[PRINTF_BUF];
va_list ap;
va_start(ap, format);
#ifdef __AVR__
vsnprintf_P(buf, sizeof(buf), (const char *)format, ap); // progmem for AVR
#else
vsnprintf(buf, sizeof(buf), (const char *)format, ap); // for the rest of the world
#endif
for(char *p = &buf[0]; *p; p++) // emulate cooked mode for newlines
{
if(*p == '\n')
write('\r');
write(*p);
}
va_end(ap);
}
#endif

PaulStoffregen
11-22-2013, 05:54 AM
Paul,
Do you think that there is any chance in getting the Arduino guys
to add printf() support to the Print() class


Would a snowball's chance in hell still count as "any" chance?



If not, would you have any interest in adding it into Teensyduino?


Yes, actually. But I'm not so excited about this particular implementation with a fixed size, stack-allocated buffer.

bperrybap
11-22-2013, 09:08 PM
I know what you mean about the fixed sized buffer.
I know how to use the internal stdio (FDEV) stuff for the AVR libC to avoid it,
and how to use the _mon_putc() routine for the pic32 (chipKIT) printf() function,
which won't work for an internal printf() device class function, but
I have no idea how to tap into the stdio output stream for the arm tools used on Teensy3.
So unfortunately, at this point in time, I don't know of any other way to make the code portable.



--- bill

bperrybap
12-14-2013, 08:27 PM
In looking at the newlib libC ARM implementation for vdprintf(), there will be a 512 byte local buffer
used down in vdprintf_r(). And then if there is a need for more than 512 bytes, the lower level stdio routines will use malloc() to get more memory
using some sort of sizing algorithm. and then if that allocated buffer eventually fills, it will free() and malloc() a bigger buffer continually as needed
again using the re-sizing algorithm.
So while it doesn't use a fixed sized buffer, users may need to know that it will consume 512 bytes of ram, and potentially
much more if the output string is larger than 512 bytes since the original 512 byte local buffer on the stack
can't be freed when the additional buffer is allocated which must be larger than the original 512 byte buffer
since it must hold the original 512 bytes of data.

--- bill

PaulStoffregen
12-14-2013, 09:39 PM
Eventually I'm planning to implement printf() for ARM in the core library. The code will be designed more efficiently that newlib's version!