+
+ /**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Arduino as depicted below.
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+ void OCLogv(LogLevel level, const prog_char * tag, const char *format, ...)
+ {
+ #ifdef TB_LOG
+ char buffer[LINE_BUFFER_SIZE];
+ va_list ap;
+ va_start(ap, format);
+ strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
+ Serial.print(buffer);
+
+ char c;
+ Serial.print(F(": "));
+
+ while ((c = pgm_read_byte(tag))) {
+ Serial.write(c);
+ tag++;
+ }
+ Serial.print(F(": "));
+
+ vsnprintf(buffer, sizeof(buffer), format, ap);
+ for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
+ {
+ if(*p == '\n')
+ {
+ Serial.write('\r');
+ }
+ Serial.write(*p);
+ }
+ Serial.println();
+ va_end(ap);
+ #endif
+ }
+ /**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Arduino as depicted below.
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+ void OCLogv(LogLevel level, const prog_char * tag, const __FlashStringHelper *format, ...)
+ {
+ #ifdef TB_LOG
+ char buffer[LINE_BUFFER_SIZE];
+ va_list ap;
+ va_start(ap, format);
+ strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
+ Serial.print(buffer);
+
+ char c;
+ Serial.print(F(": "));
+
+ while ((c = pgm_read_byte(tag))) {
+ Serial.write(c);
+ tag++;
+ }
+ Serial.print(F(": "));
+
+ #ifdef __AVR__
+ vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
+ #else
+ vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
+ #endif
+ for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
+ {
+ if(*p == '\n')
+ {
+ Serial.write('\r');
+ }
+ Serial.write(*p);
+ }
+ Serial.println();
+ va_end(ap);
+ #endif
+ }
+
+