From 32c6176e249733f584b181c7b93012bbe4322de6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 14 Mar 2016 00:28:09 +0300 Subject: [PATCH] Fix pulseIn (#1072, #1149) - fix return value on timeout - add optimistic_yield to allow WiFi/network tasks to run - use ccount instead of micros (which causes an integer division on every call) --- cores/esp8266/core_esp8266_wiring_pulse.c | 41 +++++++++++++++++------ 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/cores/esp8266/core_esp8266_wiring_pulse.c b/cores/esp8266/core_esp8266_wiring_pulse.c index bb13e31c1..ddcd8b9cd 100644 --- a/cores/esp8266/core_esp8266_wiring_pulse.c +++ b/cores/esp8266/core_esp8266_wiring_pulse.c @@ -1,9 +1,9 @@ -/* +/* pulse.c - wiring pulseIn 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 @@ -18,19 +18,38 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "wiring_private.h" #include "pins_arduino.h" -unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { - pinMode(pin, INPUT); - uint32_t start = micros(); - while(digitalRead(pin) == state && (micros() - start) < timeout); - while(digitalRead(pin) != state && (micros() - start) < timeout); - start = micros(); - while(digitalRead(pin) == state && (micros() - start) < timeout); - return micros() - start; + +extern uint32_t xthal_get_ccount(); + +#define WAIT_FOR_PIN_STATE(state) \ + while (digitalRead(pin) != (state)) { \ + if (xthal_get_ccount() - start_cycle_count > timeout_cycles) { \ + return 0; \ + } \ + optimistic_yield(5000); \ + } + +// max timeout is 27 seconds at 160MHz clock and 54 seconds at 80MHz clock +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) +{ + const uint32_t max_timeout_us = clockCyclesToMicroseconds(UINT_MAX); + if (timeout > max_timeout_us) { + timeout = max_timeout_us; + } + const uint32_t timeout_cycles = microsecondsToClockCycles(timeout); + const uint32_t start_cycle_count = xthal_get_ccount(); + WAIT_FOR_PIN_STATE(!state); + WAIT_FOR_PIN_STATE(state); + const uint32_t pulse_start_cycle_count = xthal_get_ccount(); + WAIT_FOR_PIN_STATE(!state); + return clockCyclesToMicroseconds(xthal_get_ccount() - pulse_start_cycle_count); } -unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) { +unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) +{ return pulseIn(pin, state, timeout); }