| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "esp32-hal-gpio.h"
 | 
					
						
							|  |  |  | #include "freertos/FreeRTOS.h"
 | 
					
						
							|  |  |  | #include "freertos/task.h"
 | 
					
						
							|  |  |  | #include "rom/ets_sys.h"
 | 
					
						
							|  |  |  | #include "esp_attr.h"
 | 
					
						
							|  |  |  | #include "esp_intr.h"
 | 
					
						
							|  |  |  | #include "rom/gpio.h"
 | 
					
						
							|  |  |  | #include "soc/gpio_reg.h"
 | 
					
						
							|  |  |  | #include "soc/io_mux_reg.h"
 | 
					
						
							|  |  |  | #include "soc/gpio_struct.h"
 | 
					
						
							| 
									
										
										
										
											2016-12-02 13:03:48 +02:00
										 |  |  | #include "soc/rtc_io_reg.h"
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-10 05:27:00 -06:00
										 |  |  | const int8_t esp32_adc2gpio[20] = {36, 37, 38, 39, 32, 33, 34, 35, -1, -1, 4, 0, 2, 15, 13, 12, 14, 27, 25, 26}; | 
					
						
							| 
									
										
										
										
											2016-12-12 02:12:13 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 13:03:48 +02:00
										 |  |  | const DRAM_ATTR esp32_gpioMux_t esp32_gpioMux[GPIO_PIN_COUNT]={ | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     {0x44, 11, 11, 1}, | 
					
						
							|  |  |  |     {0x88, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x40, 12, 12, 2}, | 
					
						
							|  |  |  |     {0x84, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x48, 10, 10, 0}, | 
					
						
							|  |  |  |     {0x6c, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x60, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x64, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x68, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x54, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x58, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x5c, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x34, 15, 15, 5}, | 
					
						
							|  |  |  |     {0x38, 14, 14, 4}, | 
					
						
							|  |  |  |     {0x30, 16, 16, 6}, | 
					
						
							|  |  |  |     {0x3c, 13, 13, 3}, | 
					
						
							|  |  |  |     {0x4c, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x50, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x70, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x74, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x78, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x7c, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x80, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x8c, -1, -1, -1}, | 
					
						
							|  |  |  |     {0, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x24, 6, 18, -1}, //DAC1
 | 
					
						
							|  |  |  |     {0x28, 7, 19, -1}, //DAC2
 | 
					
						
							|  |  |  |     {0x2c, 17, 17, 7}, | 
					
						
							|  |  |  |     {0, -1, -1, -1}, | 
					
						
							|  |  |  |     {0, -1, -1, -1}, | 
					
						
							|  |  |  |     {0, -1, -1, -1}, | 
					
						
							|  |  |  |     {0, -1, -1, -1}, | 
					
						
							|  |  |  |     {0x1c, 9, 4, 9}, | 
					
						
							|  |  |  |     {0x20, 8, 5, 8}, | 
					
						
							|  |  |  |     {0x14, 4, 6, -1}, | 
					
						
							|  |  |  |     {0x18, 5, 7, -1}, | 
					
						
							|  |  |  |     {0x04, 0, 0, -1}, | 
					
						
							| 
									
										
										
										
											2017-11-10 05:27:00 -06:00
										 |  |  |     {0x08, 1, 1, -1}, | 
					
						
							|  |  |  |     {0x0c, 2, 2, -1}, | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     {0x10, 3, 3, -1} | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef void (*voidFuncPtr)(void); | 
					
						
							|  |  |  | static voidFuncPtr __pinInterruptHandlers[GPIO_PIN_COUNT] = {0,}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  | #include "driver/rtc_io.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | extern void IRAM_ATTR __pinMode(uint8_t pin, uint8_t mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     if(!digitalPinIsValid(pin)) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     uint32_t rtc_reg = rtc_gpio_desc[pin].reg; | 
					
						
							|  |  |  |     if(mode == ANALOG) { | 
					
						
							|  |  |  |         if(!rtc_reg) { | 
					
						
							|  |  |  |             return;//not rtc pin
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         //lock rtc
 | 
					
						
							|  |  |  |         uint32_t reg_val = ESP_REG(rtc_reg); | 
					
						
							|  |  |  |         if(reg_val & rtc_gpio_desc[pin].mux){ | 
					
						
							|  |  |  |             return;//already in adc mode
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         reg_val &= ~( | 
					
						
							|  |  |  |                 (RTC_IO_TOUCH_PAD1_FUN_SEL_V << rtc_gpio_desc[pin].func) | 
					
						
							|  |  |  |                 |rtc_gpio_desc[pin].ie | 
					
						
							|  |  |  |                 |rtc_gpio_desc[pin].pullup | 
					
						
							|  |  |  |                 |rtc_gpio_desc[pin].pulldown); | 
					
						
							|  |  |  |         ESP_REG(RTC_GPIO_ENABLE_W1TC_REG) = (1 << (rtc_gpio_desc[pin].rtc_num + RTC_GPIO_ENABLE_W1TC_S)); | 
					
						
							|  |  |  |         ESP_REG(rtc_reg) = reg_val | rtc_gpio_desc[pin].mux; | 
					
						
							|  |  |  |         //unlock rtc
 | 
					
						
							|  |  |  |         ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = ((uint32_t)2 << MCU_SEL_S) | ((uint32_t)2 << FUN_DRV_S) | FUN_IE; | 
					
						
							|  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2016-12-14 13:11:10 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //RTC pins PULL settings
 | 
					
						
							|  |  |  |     if(rtc_reg) { | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |         //lock rtc
 | 
					
						
							|  |  |  |         ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); | 
					
						
							|  |  |  |         if(mode & PULLUP) { | 
					
						
							|  |  |  |             ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pullup) & ~(rtc_gpio_desc[pin].pulldown); | 
					
						
							|  |  |  |         } else if(mode & PULLDOWN) { | 
					
						
							|  |  |  |             ESP_REG(rtc_reg) = (ESP_REG(rtc_reg) | rtc_gpio_desc[pin].pulldown) & ~(rtc_gpio_desc[pin].pullup); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         //unlock rtc
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 13:03:48 +02:00
										 |  |  |     uint32_t pinFunction = 0, pinControl = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     //lock gpio
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     if(mode & INPUT) { | 
					
						
							|  |  |  |         if(pin < 32) { | 
					
						
							|  |  |  |             GPIO.enable_w1tc = ((uint32_t)1 << pin); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if(mode & OUTPUT) { | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |         if(pin > 33){ | 
					
						
							|  |  |  |             //unlock gpio
 | 
					
						
							|  |  |  |             return;//pins above 33 can be only inputs
 | 
					
						
							|  |  |  |         } else if(pin < 32) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             GPIO.enable_w1ts = ((uint32_t)1 << pin); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-14 13:11:10 +02:00
										 |  |  |     if(mode & PULLUP) { | 
					
						
							|  |  |  |         pinFunction |= FUN_PU; | 
					
						
							|  |  |  |     } else if(mode & PULLDOWN) { | 
					
						
							|  |  |  |         pinFunction |= FUN_PD; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     pinFunction |= ((uint32_t)2 << FUN_DRV_S);//what are the drivers?
 | 
					
						
							|  |  |  |     pinFunction |= FUN_IE;//input enable but required for output as well?
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if(mode & (INPUT | OUTPUT)) { | 
					
						
							|  |  |  |         pinFunction |= ((uint32_t)2 << MCU_SEL_S); | 
					
						
							|  |  |  |     } else if(mode == SPECIAL) { | 
					
						
							|  |  |  |         pinFunction |= ((uint32_t)(((pin)==1||(pin)==3)?0:1) << MCU_SEL_S); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         pinFunction |= ((uint32_t)(mode >> 5) << MCU_SEL_S); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; | 
					
						
							| 
									
										
										
										
											2016-11-26 12:04:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     if(mode & OPEN_DRAIN) { | 
					
						
							|  |  |  |         pinControl = (1 << GPIO_PIN0_PAD_DRIVER_S); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GPIO.pin[pin].val = pinControl; | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     //unlock gpio
 | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void IRAM_ATTR __digitalWrite(uint8_t pin, uint8_t val) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(val) { | 
					
						
							|  |  |  |         if(pin < 32) { | 
					
						
							|  |  |  |             GPIO.out_w1ts = ((uint32_t)1 << pin); | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |         } else if(pin < 34) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         if(pin < 32) { | 
					
						
							|  |  |  |             GPIO.out_w1tc = ((uint32_t)1 << pin); | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |         } else if(pin < 34) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |             GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern int IRAM_ATTR __digitalRead(uint8_t pin) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if(pin < 32) { | 
					
						
							|  |  |  |         return (GPIO.in >> pin) & 0x1; | 
					
						
							| 
									
										
										
										
											2016-12-02 13:03:48 +02:00
										 |  |  |     } else if(pin < 40) { | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |         return (GPIO.in1.val >> (pin - 32)) & 0x1; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-12-02 13:03:48 +02:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-28 12:27:10 +08:00
										 |  |  | static intr_handle_t gpio_intr_handle = NULL; | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void IRAM_ATTR __onPinInterrupt(void *arg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t gpio_intr_status_l=0; | 
					
						
							|  |  |  |     uint32_t gpio_intr_status_h=0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     gpio_intr_status_l = GPIO.status; | 
					
						
							|  |  |  |     gpio_intr_status_h = GPIO.status1.val; | 
					
						
							|  |  |  |     GPIO.status_w1tc = gpio_intr_status_l;//Clear intr for gpio0-gpio31
 | 
					
						
							|  |  |  |     GPIO.status1_w1tc.val = gpio_intr_status_h;//Clear intr for gpio32-39
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     uint8_t pin=0; | 
					
						
							|  |  |  |     if(gpio_intr_status_l) { | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             if(gpio_intr_status_l & ((uint32_t)1 << pin)) { | 
					
						
							|  |  |  |                 if(__pinInterruptHandlers[pin]) { | 
					
						
							|  |  |  |                     __pinInterruptHandlers[pin](); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } while(++pin<32); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if(gpio_intr_status_h) { | 
					
						
							|  |  |  |         pin=32; | 
					
						
							|  |  |  |         do { | 
					
						
							|  |  |  |             if(gpio_intr_status_h & ((uint32_t)1 << (pin - 32))) { | 
					
						
							|  |  |  |                 if(__pinInterruptHandlers[pin]) { | 
					
						
							|  |  |  |                     __pinInterruptHandlers[pin](); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } while(++pin<GPIO_PIN_COUNT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void __attachInterrupt(uint8_t pin, voidFuncPtr userFunc, int intr_type) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     static bool interrupt_initialized = false; | 
					
						
							| 
									
										
										
										
											2016-10-11 12:29:06 +03:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     if(!interrupt_initialized) { | 
					
						
							|  |  |  |         interrupt_initialized = true; | 
					
						
							| 
									
										
										
										
											2017-09-28 12:27:10 +08:00
										 |  |  |         esp_intr_alloc(ETS_GPIO_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, __onPinInterrupt, NULL, &gpio_intr_handle); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  |     } | 
					
						
							|  |  |  |     __pinInterruptHandlers[pin] = userFunc; | 
					
						
							| 
									
										
										
										
											2017-09-28 12:27:10 +08:00
										 |  |  |     esp_intr_disable(gpio_intr_handle); | 
					
						
							|  |  |  |     if(esp_intr_get_cpu(gpio_intr_handle)) { //APP_CPU
 | 
					
						
							| 
									
										
										
										
											2016-10-11 12:29:06 +03:00
										 |  |  |         GPIO.pin[pin].int_ena = 1; | 
					
						
							|  |  |  |     } else { //PRO_CPU
 | 
					
						
							|  |  |  |         GPIO.pin[pin].int_ena = 4; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-10-11 12:07:18 +03:00
										 |  |  |     GPIO.pin[pin].int_type = intr_type; | 
					
						
							| 
									
										
										
										
											2017-09-28 12:27:10 +08:00
										 |  |  |     esp_intr_enable(gpio_intr_handle); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void __detachInterrupt(uint8_t pin) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-09-28 12:27:10 +08:00
										 |  |  |     esp_intr_disable(gpio_intr_handle); | 
					
						
							| 
									
										
										
										
											2016-12-08 23:43:41 +02:00
										 |  |  |     __pinInterruptHandlers[pin] = NULL; | 
					
						
							| 
									
										
										
										
											2016-10-11 12:07:18 +03:00
										 |  |  |     GPIO.pin[pin].int_ena = 0; | 
					
						
							|  |  |  |     GPIO.pin[pin].int_type = 0; | 
					
						
							| 
									
										
										
										
											2017-09-28 12:27:10 +08:00
										 |  |  |     esp_intr_enable(gpio_intr_handle); | 
					
						
							| 
									
										
										
										
											2016-10-06 14:21:30 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode"))); | 
					
						
							|  |  |  | extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("__digitalWrite"))); | 
					
						
							|  |  |  | extern int digitalRead(uint8_t pin) __attribute__ ((weak, alias("__digitalRead"))); | 
					
						
							|  |  |  | extern void attachInterrupt(uint8_t pin, voidFuncPtr handler, int mode) __attribute__ ((weak, alias("__attachInterrupt"))); | 
					
						
							|  |  |  | extern void detachInterrupt(uint8_t pin) __attribute__ ((weak, alias("__detachInterrupt"))); | 
					
						
							|  |  |  | 
 |