From 5afbb4ba17d54a6bec9a213a7ad2ad3bb683782d Mon Sep 17 00:00:00 2001
From: Me No Dev <me-no-dev@vdnsbg.com>
Date: Tue, 26 Jul 2016 13:15:53 +0300
Subject: [PATCH 1/2] digitalWrite and digitalRead cancel analogWrite enabled
 on a pin

related to https://github.com/esp8266/Arduino/issues/2175
---
 cores/esp8266/core_esp8266_timer.c          |  2 +-
 cores/esp8266/core_esp8266_wiring_digital.c | 18 ++++++++++-------
 cores/esp8266/core_esp8266_wiring_pwm.c     | 22 +++++++++++++++++----
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/cores/esp8266/core_esp8266_timer.c b/cores/esp8266/core_esp8266_timer.c
index eb9f5ffff5..a1cbc4e954 100644
--- a/cores/esp8266/core_esp8266_timer.c
+++ b/cores/esp8266/core_esp8266_timer.c
@@ -41,7 +41,7 @@ void ICACHE_RAM_ATTR timer1_isr_handler(void *para){
     }
 }
 
-void timer1_isr_init(){
+void ICACHE_RAM_ATTR timer1_isr_init(){
     ETS_FRC_TIMER1_INTR_ATTACH(timer1_isr_handler, NULL);
 }
 
diff --git a/cores/esp8266/core_esp8266_wiring_digital.c b/cores/esp8266/core_esp8266_wiring_digital.c
index ea573fb7fc..1961b42283 100644
--- a/cores/esp8266/core_esp8266_wiring_digital.c
+++ b/cores/esp8266/core_esp8266_wiring_digital.c
@@ -1,9 +1,9 @@
-/* 
+/*
   digital.c - wiring digital implementation for esp8266
 
   Copyright (c) 2015 Hristo Gochkov. All rights reserved.
   This file is part of the esp8266 core for Arduino environment.
- 
+
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
@@ -25,9 +25,12 @@
 #include "eagle_soc.h"
 #include "ets_sys.h"
 
+extern void pwm_stop_pin(uint8_t pin);
+
 uint8_t esp8266_gpioToFn[16] = {0x34, 0x18, 0x38, 0x14, 0x3C, 0x40, 0x1C, 0x20, 0x24, 0x28, 0x2C, 0x30, 0x04, 0x08, 0x0C, 0x10};
 
 extern void __pinMode(uint8_t pin, uint8_t mode) {
+  pwm_stop_pin(pin);
   if(pin < 16){
     if(mode == SPECIAL){
       GPC(pin) = (GPC(pin) & (0xF << GPCI)); //SOURCE(GPIO) | DRIVER(NORMAL) | INT_TYPE(UNCHANGED) | WAKEUP_ENABLE(DISABLED)
@@ -77,6 +80,7 @@ extern void __pinMode(uint8_t pin, uint8_t mode) {
 }
 
 extern void ICACHE_RAM_ATTR __digitalWrite(uint8_t pin, uint8_t val) {
+  pwm_stop_pin(pin);
   if(pin < 16){
     if(val) GPOS = (1 << pin);
     else GPOC = (1 << pin);
@@ -87,6 +91,7 @@ extern void ICACHE_RAM_ATTR __digitalWrite(uint8_t pin, uint8_t val) {
 }
 
 extern int ICACHE_RAM_ATTR __digitalRead(uint8_t pin) {
+  pwm_stop_pin(pin);
   if(pin < 16){
     return GPIP(pin);
   } else if(pin == 16){
@@ -121,12 +126,12 @@ void ICACHE_RAM_ATTR interrupt_handler(void *arg) {
     while(!(changedbits & (1 << i))) i++;
     changedbits &= ~(1 << i);
     interrupt_handler_t *handler = &interrupt_handlers[i];
-    if (handler->fn && 
-        (handler->mode == CHANGE || 
+    if (handler->fn &&
+        (handler->mode == CHANGE ||
          (handler->mode & 1) == !!(levels & (1 << i)))) {
       // to make ISR compatible to Arduino AVR model where interrupts are disabled
       // we disable them before we call the client ISR
-      uint32_t savedPS = xt_rsil(15); // stop other interrupts 
+      uint32_t savedPS = xt_rsil(15); // stop other interrupts
       handler->fn();
       xt_wsr_ps(savedPS);
     }
@@ -170,7 +175,7 @@ void initPins() {
   for (int i = 12; i <= 16; ++i) {
     pinMode(i, INPUT);
   }
-  
+
   ETS_GPIO_INTR_ATTACH(interrupt_handler, &interrupt_reg);
   ETS_GPIO_INTR_ENABLE();
 }
@@ -180,4 +185,3 @@ extern void digitalWrite(uint8_t pin, uint8_t val) __attribute__ ((weak, alias("
 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")));
-
diff --git a/cores/esp8266/core_esp8266_wiring_pwm.c b/cores/esp8266/core_esp8266_wiring_pwm.c
index 8297e21ee7..90e2dc31bc 100644
--- a/cores/esp8266/core_esp8266_wiring_pwm.c
+++ b/cores/esp8266/core_esp8266_wiring_pwm.c
@@ -126,10 +126,11 @@ void ICACHE_RAM_ATTR pwm_timer_isr() //103-138
     TEIE &= ~TEIE1;//14
     T1I = 0;//9
     if(current_step < table->len) { //20/21
-        if(table->masks[current_step] & 0xFFFF) {
-            GPOC = table->masks[current_step] & 0xFFFF;    //15/21
+        uint32_t mask = table->masks[current_step] & pwm_mask;
+        if(mask & 0xFFFF) {
+            GPOC = mask & 0xFFFF;    //15/21
         }
-        if(table->masks[current_step] & 0x10000) {
+        if(mask & 0x10000) {
             GP16O = 0;    //6/13
         }
         current_step++;//1
@@ -164,6 +165,19 @@ void pwm_start_timer()
     timer1_write(1);
 }
 
+void ICACHE_RAM_ATTR pwm_stop_pin(uint8_t pin)
+{
+    if(pwm_mask){
+        pwm_mask &= ~(1 << pin);
+        if(pwm_mask == 0) {
+            ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
+            T1C = 0;
+            T1I = 0;
+            timer1_isr_init();
+        }
+    }
+}
+
 extern void __analogWrite(uint8_t pin, int value)
 {
     bool start_timer = false;
@@ -183,9 +197,9 @@ extern void __analogWrite(uint8_t pin, int value)
             memset(&_pwm_isr_data, 0, sizeof(struct pwm_isr_data*));
             start_timer = true;
         }
-        pwm_mask |= (1 << pin);
         pinMode(pin, OUTPUT);
         digitalWrite(pin, LOW);
+        pwm_mask |= (1 << pin);
     }
     if((F_CPU / ESP8266_CLOCK) == 1) {
         value = (value+1) / 2;

From ee9795179f02de53a2e79e33933483f72596acea Mon Sep 17 00:00:00 2001
From: Me No Dev <me-no-dev@vdnsbg.com>
Date: Tue, 26 Jul 2016 13:50:48 +0300
Subject: [PATCH 2/2] Optimize methods a bit

---
 cores/esp8266/core_esp8266_timer.c      |  2 +-
 cores/esp8266/core_esp8266_wiring_pwm.c | 11 ++---------
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/cores/esp8266/core_esp8266_timer.c b/cores/esp8266/core_esp8266_timer.c
index a1cbc4e954..d10b7c4ee6 100644
--- a/cores/esp8266/core_esp8266_timer.c
+++ b/cores/esp8266/core_esp8266_timer.c
@@ -66,7 +66,7 @@ void ICACHE_RAM_ATTR timer1_write(uint32_t ticks){
     if ((T1C & (1 << TCIT)) == 0) TEIE |= TEIE1;//edge int enable
 }
 
-void timer1_disable(){
+void ICACHE_RAM_ATTR timer1_disable(){
     T1C = 0;
     T1I = 0;
 }
diff --git a/cores/esp8266/core_esp8266_wiring_pwm.c b/cores/esp8266/core_esp8266_wiring_pwm.c
index 90e2dc31bc..8d1ec15604 100644
--- a/cores/esp8266/core_esp8266_wiring_pwm.c
+++ b/cores/esp8266/core_esp8266_wiring_pwm.c
@@ -171,8 +171,7 @@ void ICACHE_RAM_ATTR pwm_stop_pin(uint8_t pin)
         pwm_mask &= ~(1 << pin);
         if(pwm_mask == 0) {
             ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
-            T1C = 0;
-            T1I = 0;
+            timer1_disable();
             timer1_isr_init();
         }
     }
@@ -182,14 +181,8 @@ extern void __analogWrite(uint8_t pin, int value)
 {
     bool start_timer = false;
     if(value == 0) {
-        pwm_mask &= ~(1 << pin);
-        prep_pwm_steps();
         digitalWrite(pin, LOW);
-        if(pwm_mask == 0) {
-            ETS_FRC_TIMER1_NMI_INTR_ATTACH(NULL);
-            timer1_disable();
-            timer1_isr_init();
-        }
+        prep_pwm_steps();
         return;
     }
     if((pwm_mask & (1 << pin)) == 0) {