From 64523cd45c768a71f3cf8d7dcfd802ef82b34e65 Mon Sep 17 00:00:00 2001
From: Phillip Johnston <phillip@embeddedartistry.com>
Date: Wed, 27 May 2020 08:57:40 -0700
Subject: [PATCH 1/5] Update ArduinoLogger to address usage on ESP8266, which
 defines printf

We'll use the ESP built-in support instead of the printf library. Some lambda trickery is required to get the library working with the built-in ets_vprintf, since they only provide a callback and no private data.
---
 src/ArduinoLogger.h   | 34 +++++++++++++++++++++++--
 src/internal/lambda.h | 59 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 91 insertions(+), 2 deletions(-)
 create mode 100644 src/internal/lambda.h

diff --git a/src/ArduinoLogger.h b/src/ArduinoLogger.h
index 56e3a36..1a61629 100644
--- a/src/ArduinoLogger.h
+++ b/src/ArduinoLogger.h
@@ -1,11 +1,20 @@
 #ifndef ARDUINO_LOGGER_H_
 #define ARDUINO_LOGGER_H_
 
+#ifdef ESP8266
+#include <ets_sys.h>
+#include <internal/lambda.h>
+#else
 #include <LibPrintf.h>
+#endif
 #if !defined(__AVR__)
 #include <utility>
 #endif
 
+#ifdef ESP8266
+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,11 +279,31 @@ class LoggerBase
 #endif
 	}
 
+#ifdef ESP8266
+	/// 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
 	{
-		fctprintf(&LoggerBase::log_putc_bounce, this, args...);
+		fctprintf(&LoggerBase::log_putc_bounce, this, format, args...);
 
 		if(echo_)
 		{
@@ -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/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_

From 5431f6e4b5016ce80d5f7d34c352c8b49c3a45cd Mon Sep 17 00:00:00 2001
From: Phillip Johnston <phillip@embeddedartistry.com>
Date: Wed, 27 May 2020 08:59:36 -0700
Subject: [PATCH 2/5] Add notes mentioning support for ESP8266 with native
 printf support

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 7bb1f08..0b4d122 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 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, 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.
 

From 989d09684f86074c82d106a050e9d90fcf212ee5 Mon Sep 17 00:00:00 2001
From: Phillip Johnston <phillip@embeddedartistry.com>
Date: Wed, 27 May 2020 09:08:52 -0700
Subject: [PATCH 3/5] Generalize support beyond ESP8266

---
 README.md           | 4 ++--
 src/ArduinoLogger.h | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 0b4d122..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 if you are using a non-ESP8266 setup:
+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. If you are using the ESP8266, we use the built-in `printf` support instead of the external 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 1a61629..4d0bf2f 100644
--- a/src/ArduinoLogger.h
+++ b/src/ArduinoLogger.h
@@ -1,7 +1,7 @@
 #ifndef ARDUINO_LOGGER_H_
 #define ARDUINO_LOGGER_H_
 
-#ifdef ESP8266
+#ifdef __XTENSA__
 #include <ets_sys.h>
 #include <internal/lambda.h>
 #else
@@ -11,7 +11,7 @@
 #include <utility>
 #endif
 
-#ifdef ESP8266
+#ifdef __XTENSA__
 void _putchar(char c);
 #endif
 
@@ -279,7 +279,7 @@ class LoggerBase
 #endif
 	}
 
-#ifdef ESP8266
+#ifdef __XTENSA__
 	/// Prints directly to the log with no extra characters added to the message.
 	void print(const char* format, ...) noexcept
 	{

From 8d847a395cc98acfe4870e74b2126b1f3af17920 Mon Sep 17 00:00:00 2001
From: Phillip Johnston <phillip@embeddedartistry.com>
Date: Wed, 27 May 2020 09:09:10 -0700
Subject: [PATCH 4/5] Resolve compilation failure in CircularBufferLogger.h
 with ESP8266

---
 src/CircularBufferLogger.h | 4 ++++
 1 file changed, 4 insertions(+)

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
 		}
 	}
 

From 6892dc7e9cd95eda030b7ff276ce53b375a603ff Mon Sep 17 00:00:00 2001
From: Phillip Johnston <phillip@embeddedartistry.com>
Date: Wed, 27 May 2020 09:11:25 -0700
Subject: [PATCH 5/5] Address compilation error in non-ESP8266 case

---
 src/ArduinoLogger.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/ArduinoLogger.h b/src/ArduinoLogger.h
index 4d0bf2f..cb0c70a 100644
--- a/src/ArduinoLogger.h
+++ b/src/ArduinoLogger.h
@@ -303,7 +303,7 @@ class LoggerBase
 	template<typename... Args>
 	void print(const Args&... args) noexcept
 	{
-		fctprintf(&LoggerBase::log_putc_bounce, this, format, args...);
+		fctprintf(&LoggerBase::log_putc_bounce, this, args...);
 
 		if(echo_)
 		{