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_