diff --git a/README.md b/README.md
index 7bb1f08..b530407 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Flexible logging library for the Arduino SDK. This library allows the same loggi
## Dependencies
-This library requires the following Arduino library to be installed on your system:
+This library requires the following Arduino library to be installed on your system if you are using a non-ESP8266/ESP32 setup:
* [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf)
@@ -280,7 +280,7 @@ These settings can be changed in the build system, but it is easiest to define t
By default, the logging library does not echo logging calls to the serial console. You can change the default setting at compile-time using the `LOG_ECHO_EN_DEFAULT` definition.
-The logging library will print the output using the `printf` function. To change that output, see the instructions in the [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) library.
+The logging library will print the output using the `printf` function. To change that output, see the instructions in the [embeddedartistry/arduino-printf](https://github.com/embeddedartistry/arduino-printf) library. If you are using the ESP8266 or ESP32, we use the built-in `printf` support instead of the external library.
The setting can be changed in your build system or by defining the desired value in `platform_logger.h` before including the necessary logging library header.
diff --git a/src/ArduinoLogger.h b/src/ArduinoLogger.h
index 56e3a36..cb0c70a 100644
--- a/src/ArduinoLogger.h
+++ b/src/ArduinoLogger.h
@@ -1,11 +1,20 @@
#ifndef ARDUINO_LOGGER_H_
#define ARDUINO_LOGGER_H_
+#ifdef __XTENSA__
+#include <ets_sys.h>
+#include <internal/lambda.h>
+#else
#include <LibPrintf.h>
+#endif
#if !defined(__AVR__)
#include <utility>
#endif
+#ifdef __XTENSA__
+void _putchar(char c);
+#endif
+
/// Logging is disabled
#define LOG_LEVEL_OFF 0
/// Indicates the system is unusable, or an error that is unrecoverable
@@ -270,6 +279,26 @@ class LoggerBase
#endif
}
+#ifdef __XTENSA__
+ /// Prints directly to the log with no extra characters added to the message.
+ void print(const char* format, ...) noexcept
+ {
+ // We need to capture this with a lambda to call log_putc,
+ // Then decay that into a function pointer for a callback
+ auto f = [this](char c) { log_putc(c); };
+ void (*callback)(char) = Lambda::ptr(f);
+
+ va_list va;
+ va_start(va, format);
+ ets_vprintf(callback, format, va);
+ va_end(va);
+
+ if(echo_)
+ {
+ ets_vprintf(ets_putc, format, va);
+ }
+ }
+#else
/// Prints directly to the log with no extra characters added to the message.
template<typename... Args>
void print(const Args&... args) noexcept
@@ -282,6 +311,7 @@ class LoggerBase
printf(args...);
}
}
+#endif
/** Add data to the log buffer
*
@@ -301,7 +331,7 @@ class LoggerBase
log_customprefix();
- // Send the primary log statement
+ // Send the primary log statementets_vprintf
print(fmt, args...);
}
}
diff --git a/src/CircularBufferLogger.h b/src/CircularBufferLogger.h
index b88edca..75b8473 100644
--- a/src/CircularBufferLogger.h
+++ b/src/CircularBufferLogger.h
@@ -61,7 +61,11 @@ class CircularLogBufferLogger final : public LoggerBase
{
while(!log_buffer_.empty())
{
+#ifdef __XTENSA__
+ ets_putc(log_buffer_.pop_front());
+#else
_putchar(log_buffer_.pop_front());
+#endif
}
}
diff --git a/src/internal/lambda.h b/src/internal/lambda.h
new file mode 100644
index 0000000..1d4657a
--- /dev/null
+++ b/src/internal/lambda.h
@@ -0,0 +1,59 @@
+#ifndef LAMBDA_HELPERS_H_
+#define LAMBDA_HELPERS_H_
+
+/** Lambda Helper: Decay to Function Pointer
+ *
+ * When you need to convert a lambda with captures to a C pointer,
+ * such as when a callback interface doesn't provide a variable for private data
+ * which can store a `this` pointer, use this helper.
+ *
+ * @code
+ * int a = 100;
+ * auto b = [&](void*) {return ++a;};
+ *
+ * // Converting lambda with captures to a C pointer
+ * void (*f1)(void*) = Lambda::ptr(b);
+ * f1(nullptr);
+ * printf("%d\n", a); // 101
+ *
+ * // In case return value should be used
+ * int (*f3)(void*) = Lambda::ptr<int>(b);
+ * printf("%d\n", f3(nullptr)); // 103
+ *
+ * // In case data is used
+ * auto b2 = [&](void* data) {return *(int*)(data) + a;};
+ * int (*f4)(void*) = Lambda::ptr<int>(b2);
+ * int data = 5;
+ * printf("%d\n", f4(&data)); // 108
+ * @endcode
+ *
+ * Source: https://stackoverflow.com/questions/7852101/c-lambda-with-captures-as-a-function-pointer
+ */
+struct Lambda
+{
+ template<typename Tret, typename T>
+ static Tret lambda_ptr_exec(char data)
+ {
+ return (Tret)(*(T*)fn<T>())(data);
+ }
+
+ template<typename Tret = void, typename Tfp = Tret (*)(char), typename T>
+ static Tfp ptr(T& t)
+ {
+ fn<T>(&t);
+ return (Tfp)lambda_ptr_exec<Tret, T>;
+ }
+
+ template<typename T>
+ static void* fn(void* new_fn = nullptr)
+ {
+ static void* fn;
+ if(new_fn != nullptr)
+ {
+ fn = new_fn;
+ }
+ return fn;
+ }
+};
+
+#endif // LAMBDA_HELPERS_H_