| 
					
				 | 
			
			
				@@ -0,0 +1,101 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   This example code is in the Public Domain (or CC0 licensed, at your option.) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   Unless required by applicable law or agreed to in writing, this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   CONDITIONS OF ANY KIND, either express or implied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+*/ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdio.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <stdlib.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <unistd.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <string.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "freertos/FreeRTOS.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "freertos/task.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "freertos/timers.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "esp_system.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "esp_log.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "driver/gpio.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "led.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define MAX_LED	8 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#define BLOCKTIME	10	// up to portMAX_DELAY 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct led_s { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	gpio_num_t gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	bool on; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int onstate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int ontime, offtime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	int waiton, waitoff; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	TimerHandle_t timer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} leds[MAX_LED]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void vCallbackFunction( TimerHandle_t xTimer ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	struct led_s *led = (struct led_s*) pvTimerGetTimerID (xTimer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!led->timer) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	led->on = !led->on; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	gpio_set_level(led->gpio, led->on ? led->onstate : !led->onstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// was just on for a while 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!led->on && led->offtime == -1) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	// regular blinking 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	xTimerChangePeriod(xTimer, (led->on ? led->ontime : led->offtime) / portTICK_RATE_MS, BLOCKTIME); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool led_blink_core(int idx, int ontime, int offtime, bool wait) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!leds[idx].gpio) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (leds[idx].timer) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		// low priority timers will wait	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (wait && xTimerIsTimerActive(leds[idx].timer)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			leds[idx].waiton = ontime;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			leds[idx].waitoff = offtime;  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		xTimerStop(leds[idx].timer, BLOCKTIME); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	leds[idx].ontime = ontime; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	leds[idx].offtime = offtime;	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (ontime == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		gpio_set_level(leds[idx].gpio, !leds[idx].onstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else if (offtime == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		gpio_set_level(leds[idx].gpio, leds[idx].onstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (!leds[idx].timer) leds[idx].timer = xTimerCreate("ledTimer", ontime / portTICK_RATE_MS, pdFALSE, (void *)&leds[idx], vCallbackFunction); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        leds[idx].on = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		gpio_set_level(leds[idx].gpio, leds[idx].onstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (xTimerStart(leds[idx].timer, BLOCKTIME) == pdFAIL) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool led_release(int idx) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (!leds[idx].gpio) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (leds[idx].waiton) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		led_blink_core(idx, leds[idx].waiton, leds[idx].waitoff, false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		leds[idx].waiton = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		gpio_set_level(leds[idx].gpio, !leds[idx].onstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	}	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+bool led_config(int idx, gpio_num_t gpio, int onstate) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	if (idx >= MAX_LED) return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	leds[idx].gpio = gpio; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	leds[idx].onstate = onstate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	gpio_pad_select_gpio(gpio); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	gpio_set_direction(gpio, GPIO_MODE_OUTPUT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	gpio_set_level(gpio, !onstate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |