diff --git a/api/Print.cpp b/api/Print.cpp index 8c3e1930..23f2a6de 100644 --- a/api/Print.cpp +++ b/api/Print.cpp @@ -16,6 +16,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include #include #include @@ -235,6 +236,53 @@ size_t Print::println(const Printable& x) return n; } +size_t Print::printf(const char *format, ...) { + va_list arg; + va_start(arg, format); + char temp[64]; + char* buffer = temp; + size_t len = vsnprintf(temp, sizeof(temp), format, arg); + va_end(arg); + if (len > sizeof(temp) - 1) { + buffer = new char[len + 1]; + if (!buffer) { + return 0; + } + va_start(arg, format); + vsnprintf(buffer, len + 1, format, arg); + va_end(arg); + } + len = write((const uint8_t*) buffer, len); + if (buffer != temp) { + delete[] buffer; + } + return len; +} + +// TODO - must be better way than cut-n-paste! +size_t Print::printf_P(const char *format, ...) { + va_list arg; + va_start(arg, format); + char temp[64]; + char* buffer = temp; + size_t len = vsnprintf(temp, sizeof(temp), format, arg); + va_end(arg); + if (len > sizeof(temp) - 1) { + buffer = new char[len + 1]; + if (!buffer) { + return 0; + } + va_start(arg, format); + vsnprintf(buffer, len + 1, format, arg); + va_end(arg); + } + len = write((const uint8_t*) buffer, len); + if (buffer != temp) { + delete[] buffer; + } + return len; +} + // Private Methods ///////////////////////////////////////////////////////////// size_t Print::printNumber(unsigned long n, uint8_t base) diff --git a/api/Print.h b/api/Print.h index 5a19fe78..09b0c2bc 100644 --- a/api/Print.h +++ b/api/Print.h @@ -88,9 +88,11 @@ class Print size_t println(double, int = 2); size_t println(const Printable&); size_t println(void); + size_t printf(const char *format, ...); + size_t printf_P(const char *format, ...); virtual void flush() { /* Empty implementation for backward compatibility */ } }; } -using arduino::Print; \ No newline at end of file +using arduino::Print; diff --git a/api/deprecated-avr-comp/avr/pgmspace.h b/api/deprecated-avr-comp/avr/pgmspace.h index 95897d75..e9f59aac 100644 --- a/api/deprecated-avr-comp/avr/pgmspace.h +++ b/api/deprecated-avr-comp/avr/pgmspace.h @@ -98,12 +98,48 @@ typedef const void* uint_farptr_t; #define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__) #define snprintf_P(s, f, ...) snprintf((s), (f), __VA_ARGS__) +#define vsprintf_P(s, f, ...) vsprintf((s), (f), __VA_ARGS__) +#define vsnprintf_P(s, f, ...) vsnprintf((s), (f), __VA_ARGS__) +#if 0 +// Requires natural aligned addresses #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) #define pgm_read_word(addr) (*(const unsigned short *)(addr)) #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) #define pgm_read_float(addr) (*(const float *)(addr)) #define pgm_read_ptr(addr) (*(void *const *)(addr)) +#else +// Supports misaligned addresses +#ifdef __cplusplus +extern "C"{ +#endif +static inline unsigned char pgm_read_byte(const void *addr) { + return *(const unsigned char *)(addr); +} +static inline unsigned short pgm_read_word(const void *addr) { + const unsigned char *a = (const unsigned char *)addr; + return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ); +} +static inline unsigned long pgm_read_dword(const void *addr) { + const unsigned char *a = (const unsigned char *)addr; + return pgm_read_byte(a) | ( pgm_read_byte(a + 1) << 8 ) | ( pgm_read_byte(a + 2) << 16 ) | ( pgm_read_byte(a + 3) << 24 ); +} +static inline void *pgm_read_ptr(const void *addr) { + return (void*) pgm_read_dword(addr); +} +static inline float pgm_read_float(const void *addr) { + union { + void *p; + float f; + } x; + x.p = pgm_read_ptr(addr); + return x.f; +} +#ifdef __cplusplus +} +#endif + +#endif #define pgm_read_byte_near(addr) pgm_read_byte(addr) #define pgm_read_word_near(addr) pgm_read_word(addr)