From 18f77964b4d00a2afcbede1aaa117c06b82181dd Mon Sep 17 00:00:00 2001
From: frank eden <frank.eden@gmail.com>
Date: Mon, 14 May 2018 21:57:15 +1000
Subject: [PATCH 1/3] Make sample show more examples of std::function and
 std::bind

---
 Sming/SmingCore/Timer.cpp                   |  32 +++++
 Sming/SmingCore/Timer.h                     |  34 ++++-
 samples/Basic_Delegates/app/application.cpp | 138 ++++++++++++++++----
 3 files changed, 169 insertions(+), 35 deletions(-)

diff --git a/Sming/SmingCore/Timer.cpp b/Sming/SmingCore/Timer.cpp
index 2e6ac3690b..5fd2041a2b 100644
--- a/Sming/SmingCore/Timer.cpp
+++ b/Sming/SmingCore/Timer.cpp
@@ -44,6 +44,20 @@ Timer& Timer::initializeUs(uint32_t microseconds, TimerDelegate delegateFunction
 	return *this;
 }
 
+Timer& Timer::initializeMs(uint32_t milliseconds, TimerDelegateStdFunction delegateFunction)
+{
+	setCallback(delegateFunction);
+	setIntervalMs(milliseconds);
+	return *this;
+}
+
+Timer& Timer::initializeUs(uint32_t microseconds, TimerDelegateStdFunction delegateFunction)
+{
+	setCallback(delegateFunction);
+	setIntervalUs(microseconds);
+	return *this;
+}
+
 void Timer::start(bool repeating/* = true*/)
 {
 	this->repeating = repeating;
@@ -135,6 +149,7 @@ void Timer::setCallback(InterruptCallback interrupt/* = NULL*/)
 	ETS_INTR_LOCK();
 	callback = interrupt;
 	delegate_func = nullptr;
+	delegate_stdfunc = nullptr;
 	ETS_INTR_UNLOCK();
 
 	if (!interrupt)
@@ -146,6 +161,19 @@ void Timer::setCallback(TimerDelegate delegateFunction)
 	ETS_INTR_LOCK();
 	callback = nullptr;
 	delegate_func = delegateFunction;
+	delegate_stdfunc = nullptr;
+	ETS_INTR_UNLOCK();
+
+	if (!delegateFunction)
+		stop();
+}
+
+void Timer::setCallback(const TimerDelegateStdFunction& delegateFunction)
+{
+	ETS_INTR_LOCK();
+	callback = nullptr;
+	delegate_func = nullptr;
+	delegate_stdfunc = delegateFunction;
 	ETS_INTR_UNLOCK();
 
 	if (!delegateFunction)
@@ -197,6 +225,10 @@ void Timer::tick()
 	{
 		delegate_func();
 	}
+	else if (delegate_stdfunc)
+	{
+		delegate_stdfunc();
+	}
 	else{
 		stop();
 	}
diff --git a/Sming/SmingCore/Timer.h b/Sming/SmingCore/Timer.h
index 247c5ef6cb..7504f4a37a 100644
--- a/Sming/SmingCore/Timer.h
+++ b/Sming/SmingCore/Timer.h
@@ -11,7 +11,7 @@
 #ifndef _SMING_CORE_Timer_H_
 #define _SMING_CORE_Timer_H_
 
-
+#include <functional>
 #include "../SmingCore/Interrupts.h"
 #include "../SmingCore/Delegate.h"
 #include "../Wiring/WiringFrameworkDependencies.h"
@@ -25,6 +25,7 @@
 #define MAX_OS_TIMER_INTERVAL_US 268435000
 
 typedef Delegate<void()> TimerDelegate;
+typedef std::function<void()> TimerDelegateStdFunction;
 
 class Timer
 {
@@ -59,6 +60,7 @@ class Timer
      *  @param  milliseconds Duration of timer in milliseconds
      *  @param  delegateFunction Function to call when timer triggers
      *  @note   Delegate callback method
+     *  @deprecated Use initializeMs(xx, TimerDelegateStdFunction); instead.
      */
 	Timer& IRAM_ATTR initializeMs(uint32_t milliseconds, TimerDelegate delegateFunction = NULL); // Init in Milliseconds.
 
@@ -66,9 +68,23 @@ class Timer
      *  @param  microseconds Duration of timer in milliseconds
      *  @param  delegateFunction Function to call when timer triggers
      *  @note   Delegate callback method
+     *  @deprecated Use initializeMs(xx, TimerDelegateStdFunction); instead.
      */
 	Timer& IRAM_ATTR initializeUs(uint32_t microseconds, TimerDelegate delegateFunction = NULL); // Init in Microseconds.
 
+    /** @brief  Initialise millisecond timer
+     *  @param  milliseconds Duration of timer in milliseconds
+     *  @param  delegateFunction Function to call when timer triggers
+     *  @note   Delegate callback method
+     */
+	Timer& IRAM_ATTR initializeMs(uint32_t milliseconds, TimerDelegateStdFunction delegateFunction = nullptr); // Init in Milliseconds.
+
+    /** @brief  Initialise microsecond timer
+     *  @param  microseconds Duration of timer in milliseconds
+     *  @param  delegateFunction Function to call when timer triggers
+     *  @note   Delegate callback method
+     */
+	Timer& IRAM_ATTR initializeUs(uint32_t microseconds, TimerDelegateStdFunction delegateFunction = nullptr); // Init in Microseconds.
     /** @brief  Start timer running
      *  @param  repeating Set to true for repeating timer. Set to false for one-shot.
      */
@@ -120,11 +136,16 @@ class Timer
      */
     void IRAM_ATTR setCallback(InterruptCallback interrupt = NULL);
 
-    /** @brief  Set timer trigger function
-     *  @param  delegateFunction Function to be called on timer trigger
-     *  @note   Delegate callback method
-     */
-    void IRAM_ATTR setCallback(TimerDelegate delegateFunction);
+	/** @brief  Set timer trigger function
+	*  @param  delegateFunction Function to be called on timer trigger
+	*  @note   Delegate callback method
+	*/
+	void IRAM_ATTR setCallback(TimerDelegate delegateFunction);
+	/** @brief  Set timer trigger function
+	*  @param  delegateFunction Function to be called on timer trigger
+	*  @note   Delegate callback method
+	*/
+	void IRAM_ATTR setCallback(const TimerDelegateStdFunction& delegateFunction);
 
 
 protected:
@@ -142,6 +163,7 @@ class Timer
     uint64_t interval = 0;
     InterruptCallback callback = nullptr;
     TimerDelegate delegate_func = nullptr;
+    TimerDelegateStdFunction delegate_stdfunc = nullptr;
     bool repeating = false;
     bool started = false;
 
diff --git a/samples/Basic_Delegates/app/application.cpp b/samples/Basic_Delegates/app/application.cpp
index 95f494c427..ac0869b48a 100644
--- a/samples/Basic_Delegates/app/application.cpp
+++ b/samples/Basic_Delegates/app/application.cpp
@@ -1,45 +1,125 @@
 #include <user_config.h>
 #include <SmingCore.h>
 
-class LedBlinker
+void plainOldOrdinaryFunction()
 {
+	debugf("plainOldOrdinaryFunction");
+}
+
+
+void functionWithMoreComlicatedSignature(int a, String b)
+{
+	debugf("functionWithMoreComlicatedSignature %d %s", a, b.c_str());
+}
 
-public :
-	LedBlinker(int reqPin) : ledPin(reqPin) {
-		pinMode(ledPin, OUTPUT);
-	};
+
+class Task
+{
+
+public:
+	Task() {};
 	bool setTimer(int reqInterval) {
-		if (reqInterval <= 0) return false;
-		ledInterval = reqInterval;
+		if (reqInterval <= 0) {
+			return false;
+		}
+		taskInterval = reqInterval;
 		return true;
 	}
-	void blink(bool reqRun) {
-		if (reqRun) {
-			ledTimer.initializeMs(ledInterval, TimerDelegate(&LedBlinker::ledBlink,this)).start();
-		}
-		else {
-			ledTimer.stop();
-		}
+
+	// This example show the way delegates have been used in Sming in the past.
+	void blinkOldDelegate() {
+		taskTimer.initializeMs(taskInterval, TimerDelegate(&Task::doOldDelegate, this)).start();
 	}
-	void ledBlink () { ledState = !ledState ; digitalWrite(ledPin, ledState);}
 
-private :
-	int ledPin = 2;
-	Timer ledTimer;
-	int ledInterval = 1000;
-	bool ledState = true;
-};
+	// This example shows how to use a plain old ordinary function as a callback
+	void callPlainOldOrdinaryFunction() {
+		taskTimer.initializeMs(taskInterval, TimerDelegateStdFunction(plainOldOrdinaryFunction)).start();
+		// or just
+		// taskTimer.initializeMs(taskInterval, plainOldOrdinaryFunction).start();
+	}
+
+
+	// This example shows how to use std::bind to make us of a function that has more parameters than our signature has
+	void showHowToUseBind() {
+		auto b = std::bind(functionWithMoreComlicatedSignature, 2, "parameters");
+		taskTimer.initializeMs(taskInterval, b).start();
+	}
+
+	// Sming now allows the use of std::function
+	// This example shows how to use a lamda expression as a callback
+	void callLamda() {
+		int foo = 123;
+		taskTimer.initializeMs(taskInterval,
+			[foo]		// capture just foo by value (Note it would be bad to pass by reference as foo would be out of scope when the lamda function runs later)
+		()			// No parameters to the callback
+			-> void		// Returns nothing
+		{
+			if (foo == 123) {
+				debugf("lamda Callback foo is 123");
+			}
+			else
+			{
+				debugf("lamda Callback foo is not 123, crikey!");
+			}
+		})
+			.start();
+	}
 
-#define LEDPIN_1  2 // GPIO2
-#define LEDPIN_2  4 // GPIO4
 
-LedBlinker myLed1 = LedBlinker(LEDPIN_1);
-LedBlinker myLed2 = LedBlinker(LEDPIN_2);
+
+	// This example shows how to use a member function as a callback
+	void callMemberFunction() {
+
+		// A non-static member function must be called with an object. 
+		// That is, it always implicitly passes "this" pointer as its argument.
+		// But because our callback specifies that we don't take any arguments (<void(void)>), 
+		// you must use std::bind to bind the first (and the only) argument.
+
+		TimerDelegateStdFunction b = std::bind(&Task::callbackMemberFunction, this);
+		taskTimer.initializeMs(taskInterval, b).start();
+	}
+
+	void doOldDelegate()
+	{
+		debugf("doOldDelegate");
+	}
+	void callbackMemberFunction()
+	{
+		debugf("callMemberFunction");
+	}
+
+
+private:
+	Timer taskTimer;
+	int taskInterval = 1000;
+
+};
+
+Task task1;
+Task task2;
+Task task3;
+Task task4;
+Task task5;
 
 void init()
 {
-	myLed1.setTimer(1000);
-	myLed1.blink(true);
-	myLed2.setTimer(500);
-	myLed2.blink(true);
+	WifiStation.enable(false);
+	WifiAccessPoint.enable(false);
+	Serial.begin(115200);
+
+	task1.setTimer(1500);
+	task1.blinkOldDelegate();
+
+	task2.setTimer(1600);
+	task2.callPlainOldOrdinaryFunction();
+
+	task3.setTimer(1900);
+	task3.showHowToUseBind();
+
+	task4.setTimer(1700);
+	task4.callMemberFunction();
+
+	task5.setTimer(1800);
+	task5.callLamda();
+
 }

From d27c56821a44d83be696ec01ae4ed9635bbf2e46 Mon Sep 17 00:00:00 2001
From: frank eden <frank.eden@gmail.com>
Date: Mon, 14 May 2018 22:34:14 +1000
Subject: [PATCH 2/3] Tidy up sample

---
 samples/Basic_Delegates/app/application.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/samples/Basic_Delegates/app/application.cpp b/samples/Basic_Delegates/app/application.cpp
index ac0869b48a..d832ee3bf7 100644
--- a/samples/Basic_Delegates/app/application.cpp
+++ b/samples/Basic_Delegates/app/application.cpp
@@ -27,7 +27,7 @@ class Task
 	}
 
 	// This example show the way delegates have been used in Sming in the past.
-	void blinkOldDelegate() {
+	void callOldDelegate() {
 		taskTimer.initializeMs(taskInterval, TimerDelegate(&Task::doOldDelegate, this)).start();
 	}
 
@@ -103,12 +103,10 @@ Task task5;
 
 void init()
 {
-	WifiStation.enable(false);
-	WifiAccessPoint.enable(false);
 	Serial.begin(115200);
 
 	task1.setTimer(1500);
-	task1.blinkOldDelegate();
+	task1.callOldDelegate();
 
 	task2.setTimer(1600);
 	task2.callPlainOldOrdinaryFunction();

From 82628637ca24e54936fbda0e1e7e71ebd5f7257e Mon Sep 17 00:00:00 2001
From: frank eden <frank.eden@gmail.com>
Date: Tue, 15 May 2018 17:27:33 +1000
Subject: [PATCH 3/3] Apply coding standards

---
 samples/Basic_Delegates/app/application.cpp | 52 ++++++++++-----------
 1 file changed, 24 insertions(+), 28 deletions(-)

diff --git a/samples/Basic_Delegates/app/application.cpp b/samples/Basic_Delegates/app/application.cpp
index d832ee3bf7..e163b22194 100644
--- a/samples/Basic_Delegates/app/application.cpp
+++ b/samples/Basic_Delegates/app/application.cpp
@@ -6,19 +6,17 @@ void plainOldOrdinaryFunction()
 	debugf("plainOldOrdinaryFunction");
 }
 
-
 void functionWithMoreComlicatedSignature(int a, String b)
 {
 	debugf("functionWithMoreComlicatedSignature %d %s", a, b.c_str());
 }
 
-
 class Task
 {
-
 public:
 	Task() {};
-	bool setTimer(int reqInterval) {
+	bool setTimer(int reqInterval) 
+	{
 		if (reqInterval <= 0) {
 			return false;
 		}
@@ -27,49 +25,50 @@ class Task
 	}
 
 	// This example show the way delegates have been used in Sming in the past.
-	void callOldDelegate() {
+	void callOldDelegate() 
+	{
 		taskTimer.initializeMs(taskInterval, TimerDelegate(&Task::doOldDelegate, this)).start();
 	}
 
 	// This example shows how to use a plain old ordinary function as a callback
-	void callPlainOldOrdinaryFunction() {
+	void callPlainOldOrdinaryFunction() 
+	{
 		taskTimer.initializeMs(taskInterval, TimerDelegateStdFunction(plainOldOrdinaryFunction)).start();
 		// or just
 		// taskTimer.initializeMs(taskInterval, plainOldOrdinaryFunction).start();
 	}
-
-
+	
 	// This example shows how to use std::bind to make us of a function that has more parameters than our signature has
-	void showHowToUseBind() {
+	void showHowToUseBind() 
+	{
 		auto b = std::bind(functionWithMoreComlicatedSignature, 2, "parameters");
 		taskTimer.initializeMs(taskInterval, b).start();
 	}
 
 	// Sming now allows the use of std::function
 	// This example shows how to use a lamda expression as a callback
-	void callLamda() {
+	void callLamda() 
+	{
 		int foo = 123;
 		taskTimer.initializeMs(taskInterval,
 			[foo]		// capture just foo by value (Note it would be bad to pass by reference as foo would be out of scope when the lamda function runs later)
-		()			// No parameters to the callback
+			()			// No parameters to the callback
 			-> void		// Returns nothing
-		{
-			if (foo == 123) {
-				debugf("lamda Callback foo is 123");
-			}
-			else
 			{
-				debugf("lamda Callback foo is not 123, crikey!");
+				if (foo == 123) {
+					debugf("lamda Callback foo is 123");
+				}
+				else
+				{
+					debugf("lamda Callback foo is not 123, crikey!");
+				}
 			}
-		})
-			.start();
+			).start();
 	}
-
-
-
+	
 	// This example shows how to use a member function as a callback
-	void callMemberFunction() {
-
+	void callMemberFunction() 
+	{
 		// A non-static member function must be called with an object. 
 		// That is, it always implicitly passes "this" pointer as its argument.
 		// But because our callback specifies that we don't take any arguments (<void(void)>), 
@@ -87,12 +86,10 @@ class Task
 	{
 		debugf("callMemberFunction");
 	}
-
-
+	
 private:
 	Timer taskTimer;
 	int taskInterval = 1000;
-
 };
 
 Task task1;
@@ -119,5 +116,4 @@ void init()
 
 	task5.setTimer(1800);
 	task5.callLamda();
-
 }