diff --git a/examples/IRrecvDumpV2/IRrecvDumpV2.ino b/examples/IRrecvDumpV2/IRrecvDumpV2.ino index 0ef680d40..a34aab2a1 100644 --- a/examples/IRrecvDumpV2/IRrecvDumpV2.ino +++ b/examples/IRrecvDumpV2/IRrecvDumpV2.ino @@ -24,7 +24,14 @@ uint16_t RECV_PIN = 14; // than normal buffer so we can handle Air Conditioner remote codes. uint16_t CAPTURE_BUFFER_SIZE = 1024; -IRrecv irrecv(RECV_PIN, CAPTURE_BUFFER_SIZE); +// Nr. of milli-Seconds of no-more-data before we consider a message ended. +// NOTE: Don't exceed MAX_TIMEOUT_MS. Typically 130ms. +#define TIMEOUT 15U // Suits most messages, while not swallowing repeats. +// #define TIMEOUT 90U // Suits messages with big gaps like XMP-1 & some aircon + // units, but can accidently swallow repeated messages + // in the rawData[] output. + +IRrecv irrecv(RECV_PIN, CAPTURE_BUFFER_SIZE, TIMEOUT); decode_results results; // Somewhere to store the results irparams_t save; // A place to copy the interrupt state while decoding. diff --git a/src/IRrecv.cpp b/src/IRrecv.cpp index e6642b77a..5451cdcc2 100644 --- a/src/IRrecv.cpp +++ b/src/IRrecv.cpp @@ -75,7 +75,7 @@ static void ICACHE_RAM_ATTR gpio_intr() { start = now; #define ONCE 0 - os_timer_arm(&timer, TIMEOUT_MS, ONCE); + os_timer_arm(&timer, irparams.timeout, ONCE); } #endif // UNIT_TEST @@ -85,11 +85,16 @@ static void ICACHE_RAM_ATTR gpio_intr() { // Args: // recvpin: GPIO pin the IR receiver module's data pin is connected to. // bufsize: Nr. of entries to have in the capture buffer. (Default: RAWBUF) +// timeout: Nr. of milli-Seconds of no signal before we stop capturing data. +// (Default: TIMEOUT_MS) // Returns: // A IRrecv class object. -IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize) { +IRrecv::IRrecv(uint16_t recvpin, uint16_t bufsize, uint8_t timeout) { irparams.recvpin = recvpin; irparams.bufsize = bufsize; + // Ensure we are going to be able to store all possible values in the + // capture buffer. + irparams.timeout = std::min(timeout, (uint8_t) MAX_TIMEOUT_MS); irparams.rawbuf = new uint16_t[bufsize]; if (irparams.rawbuf == NULL) { #ifndef UNIT_TEST @@ -427,16 +432,16 @@ bool IRrecv::matchAtLeast(uint32_t measured, uint32_t desired, DPRINT(". Matching: "); DPRINT(measured); DPRINT(" >= "); - DPRINT(ticksLow(std::min(desired, TIMEOUT_MS * 1000), tolerance)); + DPRINT(ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance)); DPRINT(" [min("); DPRINT(ticksLow(desired, tolerance)); DPRINT(", "); - DPRINT(ticksLow(TIMEOUT_MS * 1000, tolerance)); + DPRINT(ticksLow(MS_TO_USEC(irparams.timeout), tolerance)); DPRINTLN(")]"); // We really should never get a value of 0, except as the last value // in the buffer. If that is the case, then assume infinity and return true. if (measured == 0) return true; - return measured >= ticksLow(std::min(desired, TIMEOUT_MS * 1000), + return measured >= ticksLow(std::min(desired, MS_TO_USEC(irparams.timeout)), tolerance); } diff --git a/src/IRrecv.h b/src/IRrecv.h index ad4ee45d7..5847dade3 100644 --- a/src/IRrecv.h +++ b/src/IRrecv.h @@ -18,6 +18,7 @@ #define HEADER 2U // Usual nr. of header entries. #define FOOTER 2U // Usual nr. of footer (stop bits) entries. #define OFFSET_START 1U // Usual rawbuf entry to start processing from. +#define MS_TO_USEC(x) (x * 1000U) // Convert milli-Seconds to micro-Seconds. // Marks tend to be 100us too long, and spaces 100us too short // when received due to sensor lag. #define MARK_EXCESS 50U @@ -31,12 +32,15 @@ #define TOLERANCE 25U // default percent tolerance in measurements #define RAWTICK 2U // Capture tick to uSec factor. // How long (ms) before we give up wait for more data? -// Don't exceed 130ms (RAWTICK * UINT16_MAX uSeconds) without a good reason. +// Don't exceed MAX_TIMEOUT_MS without a good reason. // That is the capture buffers maximum value size. (UINT16_MAX / RAWTICK) // Typically messages/protocols tend to repeat around the 100ms timeframe, // thus we should timeout before that to give us some time to try to decode // before we need to start capturing a possible new message. -#define TIMEOUT_MS 90U // In MilliSeconds. (Historic default was 15ms) +// Typically 15ms suits most applications. However, some protocols demand a +// higher value. e.g. 90ms for XMP-1 and some aircon units. +#define TIMEOUT_MS 15U // In MilliSeconds. +#define MAX_TIMEOUT_MS (RAWTICK * UINT16_MAX / MS_TO_USEC(1)) // Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param #define FNV_PRIME_32 16777619UL @@ -54,6 +58,7 @@ typedef struct { // handler. Don't ask why, I don't know. It just does. uint16_t rawlen; // counter of entries in rawbuf. uint8_t overflow; // Buffer overflow indicator. + uint8_t timeout; // Nr. of milliSeconds before we give up. } irparams_t; // results from a data match @@ -82,7 +87,8 @@ class decode_results { // main class for receiving IR class IRrecv { public: - explicit IRrecv(uint16_t recvpin, uint16_t bufsize = RAWBUF); // Constructor + explicit IRrecv(uint16_t recvpin, uint16_t bufsize = RAWBUF, + uint8_t timeout = TIMEOUT_MS); // Constructor ~IRrecv(); // Destructor bool decode(decode_results *results, irparams_t *save = NULL); void enableIRIn();