IRremote
ir_DistanceWidthProtocol.hpp
Go to the documentation of this file.
1 /*
2  * ir_DistanceWidthProtocol.hpp
3  *
4  * Contains only the decoder functions for universal pulse width or pulse distance protocols!
5  * The send functions are used by almost all protocols and are therefore located in IRSend.hpp.
6  *
7  * If RAM is not more than 2k, the decoder only accepts mark or space durations up to 50 * 50 (MICROS_PER_TICK) = 2500 microseconds
8  * to save RAM space, otherwise it accepts durations up to 10 ms.
9  *
10  * This decoder tries to decode the protocols:
11  * - Pulse distance with constant pulse length
12  * - Pulse distance width with constant period length
13  * - Pulse width with constant pause length - not enabled yet
14  *
15  * 1. Analyze all space and mark length
16  * 2. Decide which protocol we have
17  * 3. Try to decode with the mark and space data found in step 1
18  * 4. Assume one start bit / header and one stop bit, since pulse distance data must have a stop bit!
19  * No data and address decoding, only raw data as result.
20  *
21  * Pulse distance data can be sent with the generic function as in SendDemo example line 155:
22  * https://github.com/Arduino-IRremote/Arduino-IRremote/blob/d51b540cb2ddf1424888d2d9e6b62fe1ef46859d/examples/SendDemo/SendDemo.ino#L155
23  * void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
24  * unsigned int aZeroSpaceMicros, uint32_t aData, uint8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit = false)
25  * The header must be sent manually with:
26  * IrSender.mark(MarkMicros)
27  * IrSender.space(SpaceMicros);
28  *
29  * Or send it by filling a DecodedRawDataArray and with the sendPulseDistanceWidthFromArray() function as in SendDemo example line 175:
30  * https://github.com/Arduino-IRremote/Arduino-IRremote/blob/d51b540cb2ddf1424888d2d9e6b62fe1ef46859d/examples/SendDemo/SendDemo.ino#L175
31  * sendPulseDistanceWidthFromArray(uint_fast8_t aFrequencyKHz, unsigned int aHeaderMarkMicros,
32  * unsigned int aHeaderSpaceMicros, unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
33  * unsigned int aZeroSpaceMicros, uint32_t *aDecodedRawDataArray, unsigned int aNumberOfBits, uint8_t aFlags,
34  * unsigned int aRepeatPeriodMillis, int_fast8_t aNumberOfRepeats)
35  *
36  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
37  *
38  ************************************************************************************
39  * MIT License
40  *
41  * Copyright (c) 2022-2025 Armin Joachimsmeyer
42  *
43  * Permission is hereby granted, free of charge, to any person obtaining a copy
44  * of this software and associated documentation files (the "Software"), to deal
45  * in the Software without restriction, including without limitation the rights
46  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
47  * copies of the Software, and to permit persons to whom the Software is furnished
48  * to do so, subject to the following conditions:
49  *
50  * The above copyright notice and this permission notice shall be included in all
51  * copies or substantial portions of the Software.
52  *
53  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
54  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
55  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
56  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
57  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
58  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
59  *
60  ************************************************************************************
61  */
62 #ifndef _IR_DISTANCE_WIDTH_HPP
63 #define _IR_DISTANCE_WIDTH_HPP
64 
65 // This block must be located after the includes of other *.hpp files
66 //#define LOCAL_DEBUG // This enables debug output only for this file - only for development
67 #include "LocalDebugLevelStart.h"
68 
73 #if !defined(DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS)
74 #define DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS 100000 // 100 ms, bit it is just a guess
75 #endif
76 
77 //#define SHOW_DISTANCE_WIDTH_DECODER_ERRORS // Prints errors which prevents data to be decoded as distance width data
78 
79 #if !defined(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE)
80 # if (defined(RAMEND) && RAMEND <= 0x8FF) || (defined(RAMSIZE) && RAMSIZE < 0x8FF)
81 #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 50 // To save program space, the decoder only accepts mark or space durations up to 50 * 50 (MICROS_PER_TICK) = 2500 microseconds
82 # else
83 #define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE 200 // The decoder accepts mark or space durations up to 200 * 50 (MICROS_PER_TICK) = 10 milliseconds
84 # endif
85 #endif
86 
87 // Switch the decoding according to your needs
88 //#define USE_MSB_DECODING_FOR_DISTANCE_DECODER // If active, it resembles LG, otherwise LSB first as most other protocols e.g. NEC and Kaseikyo/Panasonic
89 
90 //=====================================================================================
91 // DDD III SSS TTTTTT AA N N CCC EEEE W W III DDD TTTTTT H H
92 // D D I S TT A A NN N C E W W I D D TT H H
93 // D D I SSS TT AAAA N N N C EEE W W W I D D TT HHHH
94 // D D I S TT A A N NN C E W W W I D D TT H H
95 // DDD III SSSS TT A A N N CCC EEEE W W III DDD TT H H
96 //=====================================================================================
97 // see: https://www.mikrocontroller.net/articles/IRMP_-_english#Codings
98 /*
99  Example output of UnitTest.ino for PulseWidth protocol:
100  Protocol=PulseWidth Raw-Data=0x87654321 32 bits LSB first
101  Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 950, 550, 600, 300, 300, 300, 0x87654321, 32, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
102  rawData[66]:
103  -1088600
104  + 950,- 550
105  + 600,- 300 + 300,- 300 + 350,- 250 + 350,- 250
106  + 350,- 300 + 600,- 300 + 300,- 300 + 300,- 300
107  + 650,- 250 + 650,- 250 + 300,- 300 + 350,- 250
108  + 350,- 300 + 300,- 300 + 600,- 300 + 300,- 300
109  + 600,- 300 + 350,- 250 + 600,- 300 + 350,- 250
110  + 350,- 300 + 600,- 300 + 600,- 300 + 300,- 300
111  + 600,- 300 + 600,- 300 + 600,- 300 + 300,- 300
112  + 300,- 300 + 300,- 300 + 350,- 250 + 650
113  Sum: 24500
114 
115  Example output of UnitTest.ino for PulseDistanceWidth protocol:
116  Protocol=PulseDistance Raw-Data=0x76 7 bits LSB first
117  Send on a 8 bit platform with: IrSender.sendPulseDistanceWidth(38, 5950, 500, 550, 1450, 1550, 500, 0x76, 7, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
118  rawData[18]:
119  -1092450
120  +5950,- 500
121  +1500,- 500 + 500,-1450 + 550,-1450 +1550,- 450
122  + 550,-1450 + 550,-1450 + 550,-1450 + 550
123  Sum: 20950
124  */
125 
126 #if defined(LOCAL_DEBUG)
127 void printDurations(uint8_t aArray[], uint8_t aMaxIndex) {
128  for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
129  //Print index at the beginning of a new line
130  if (i % 10 == 0) {
131  if (i == 0) {
132  Serial.print(' '); // indentation for the first index 0
133  } else {
134  Serial.println(); // new line for next indexes 10, 20 etc.
135  }
136  Serial.print(i);
137  Serial.print(F(": "));
138  }
139  // Print number of values in array and duration if != 0
140  Serial.print(aArray[i]);
141  if (aArray[i] != 0) {
142  Serial.print('x');
143  Serial.print(i * (uint16_t) MICROS_PER_TICK);
144  }
145  Serial.print(F(" | "));
146  }
147  Serial.println();
148 }
149 #endif
150 
151 /*
152  * We count all consecutive (allow only one gap between) durations and compute the average.
153  * @return false if more than 2 distinct duration values found
154  */
155 bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIndex, uint8_t *aLongIndex) {
156  uint8_t tSum = 0;
157  uint16_t tWeightedSum = 0;
158  uint8_t tGapCount = 0;
159  for (uint_fast8_t i = 0; i <= aMaxIndex; i++) {
160  uint8_t tCurrentDurations = aArray[i];
161  if (tCurrentDurations != 0) {
162  // Add it to sum and remove array content
163  tSum += tCurrentDurations;
164  tWeightedSum += (tCurrentDurations * i);
165  aArray[i] = 0;
166  tGapCount = 0;
167  } else {
168  tGapCount++;
169  }
170  if (tSum != 0 && (i == aMaxIndex || tGapCount > 1)) {
171  /*
172  * Here we have a sum AND last element OR more than 1 consecutive gap
173  */
174  uint8_t tAggregateIndex = (tWeightedSum + (tSum / 2)) / tSum; // with rounding
175  aArray[tAggregateIndex] = tSum; // disabling this line increases code size by 2 - unbelievable!
176  // store aggregate for later decoding
177  if (*aShortIndex == 0) {
178  *aShortIndex = tAggregateIndex;
179  } else if (*aLongIndex == 0) {
180  *aLongIndex = tAggregateIndex;
181  } else {
182  // we have 3 bins => this is likely no pulse width or distance protocol. e.g. it can be RC5.
183  return false;
184  }
185  // initialize for next aggregation
186  tSum = 0;
187  tWeightedSum = 0;
188  }
189  }
190  return true;
191 }
192 
193 /*
194  * Try to decode a pulse distance or pulse width protocol.
195  * 1. Analyze all space and mark length
196  * 2. Decide if we have an pulse width or distance protocol
197  * 3. Try to decode with the mark and space data found in step 1
198  * No data and address decoding, only raw data as result.
199  *
200  * Restrictions:
201  * Only protocols with at least 7 bits (+ start and trailing stop bit) are accepted.
202  * Pulse or pause duration must be below 2500 us (depends on DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE).
203  *
204  * calloc() version is 700 bytes larger :-(
205  */
207  /*
208  * Array for up to 49 ticks / 2500 us (or 199 ticks / 10 ms us if RAM > 2k)
209  * tick array index 0 covers mark or space durations from 0 to 49 us, and index 49 from 2450 to 2499 us
210  */
211  uint8_t tDurationArray[DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE];
212 
213  /*
214  * Only protocols with at least 7 bits are accepted
215  */
216  if (decodedIRData.rawlen < (2 * 7) + 4) {
217 #if defined(DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
218  Serial.print(F("PULSE_DISTANCE_WIDTH: "));
219  Serial.print(F("Data length="));
220  Serial.print(decodedIRData.rawlen);
221  Serial.println(F(" is less than 18"));
222 #endif
223  return false;
224  }
225 
226  // Reset duration array
227  memset(tDurationArray, 0, DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE);
228 
229  uint8_t tIndexOfMaxDuration = 0;
230  /*
231  * Count number of mark durations. Skip leading start and trailing stop bit.
232  */
233  for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) {
234 #if(DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE > 0xFF)
235  uint16_t tDurationTicks = irparams.rawbuf[i];
236 #else
237  auto tDurationTicks = irparams.rawbuf[i];
238 #endif
239  if (tDurationTicks < DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) {
240  tDurationArray[tDurationTicks]++; // count duration if less than DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE
241  if (tIndexOfMaxDuration < tDurationTicks) {
242  tIndexOfMaxDuration = tDurationTicks;
243  }
244  } else {
245 #if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
246  Serial.print(F("PULSE_DISTANCE_WIDTH: Mark "));
247  Serial.print(tDurationTicks * MICROS_PER_TICK);
248  Serial.print(F(" is longer than maximum "));
250  Serial.print(F(" us. Index="));
251  Serial.println(i);
252 #endif
253  return false;
254  }
255  }
256 
257  /*
258  * Aggregate mark counts to one duration bin
259  */
260  uint8_t tMarkTicksShort = 0;
261  uint8_t tMarkTicksLong = 0;
262  bool tSuccess = aggregateArrayCounts(tDurationArray, tIndexOfMaxDuration, &tMarkTicksShort, &tMarkTicksLong);
263 #if defined(LOCAL_DEBUG)
264  Serial.println(F("Mark:"));
265  printDurations(tDurationArray, tIndexOfMaxDuration);
266 #endif
267 
268  if (!tSuccess) {
269 #if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
270  Serial.println(F("PULSE_DISTANCE_WIDTH: Mark aggregation failed, more than 2 distinct mark duration values found"));
271 #endif
272  return false;
273  }
274 
275  // Reset duration array
276  memset(tDurationArray, 0, DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE);
277 
278  /*
279  * Count number of space durations. Skip leading start and trailing stop bit.
280  */
281  tIndexOfMaxDuration = 0;
282  for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) {
283  auto tDurationTicks = irparams.rawbuf[i];
284  if (tDurationTicks < DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE) {
285  tDurationArray[tDurationTicks]++;
286  if (tIndexOfMaxDuration < tDurationTicks) {
287  tIndexOfMaxDuration = tDurationTicks;
288  }
289  } else {
290 #if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
291  Serial.print(F("PULSE_DISTANCE_WIDTH: Space "));
292  Serial.print(tDurationTicks * MICROS_PER_TICK);
293  Serial.print(F(" is longer than maximum "));
295  Serial.print(F(" us. Index="));
296  Serial.println(i);
297 #endif
298  return false;
299  }
300  }
301 
302  /*
303  * Aggregate space counts to one duration bin
304  */
305  uint8_t tSpaceTicksShort = 0;
306  uint8_t tSpaceTicksLong = 0;
307  tSuccess = aggregateArrayCounts(tDurationArray, tIndexOfMaxDuration, &tSpaceTicksShort, &tSpaceTicksLong);
308 #if defined(LOCAL_DEBUG)
309  Serial.println(F("Space:"));
310  printDurations(tDurationArray, tIndexOfMaxDuration);
311 #endif
312 
313  if (!tSuccess) {
314 #if defined(LOCAL_DEBUG) || defined(SHOW_DISTANCE_WIDTH_DECODER_ERRORS)
315  Serial.println(F("PULSE_DISTANCE_WIDTH: Space aggregation failed, more than 2 distinct space duration values found"));
316 #endif
317  return false;
318  }
319 
320 #if RAW_BUFFER_LENGTH <= (512 -4)
321  uint_fast8_t tNumberOfBits;
322 #else
323  uint16_t tNumberOfBits;
324 #endif
325  tNumberOfBits = (decodedIRData.rawlen / 2) - 1;
326  if (tSpaceTicksLong > 0) {
327  // For PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- a stop bit is mandatory, for PULSE_WIDTH it is not required!
328  tNumberOfBits--; // Correct for PULSE_DISTANCE stop bit
329  }
330  decodedIRData.numberOfBits = tNumberOfBits;
331 
332  /*
333  * Print characteristics of this protocol. Durations are in (50 us) ticks.
334  * Number of bits, start bit, start pause, long mark, long space, short mark, short space
335  *
336  * NEC: 32, 180, 90, 11, 34, 11, 11
337  * Samsung32: 32, 90, 90, 11, 34, 11, 11
338  * LG: 28, 180, 84, 10, 32, 10, 11
339  * JVC: 16, 168, 84, 10, 32, 10, 10
340  * Kaseikyo: 48. 69, 35, 9, 26, 9, 9
341  * Sony: 12|15|20, 48, 12, 24, 12, 12, 12 // the only known pulse width protocol
342  * Disney monorail
343  * model: 7, 120, 10, 30, 30, 10, 10 // PulseDistanceWidth. Can be seen as direct conversion of a 7 bit serial timing at 250 baud with a 6 ms start bit.
344  */
345 #if defined(LOCAL_DEBUG)
346  Serial.print(F("DistanceWidthTimingInfoStruct: "));
347  Serial.print(tNumberOfBits);
348  Serial.print(F(", "));
349  Serial.print(irparams.rawbuf[1] * MICROS_PER_TICK);
350  Serial.print(F(", "));
351  Serial.print(irparams.rawbuf[2] * MICROS_PER_TICK);
352  Serial.print(F(", "));
353  if(tMarkTicksLong == 0) {
354  Serial.print(tMarkTicksShort * MICROS_PER_TICK);
355  } else {
356  Serial.print(tMarkTicksLong * MICROS_PER_TICK);
357  }
358  Serial.print(F(", "));
359  if(tSpaceTicksLong == 0) {
360  Serial.print(tSpaceTicksShort * MICROS_PER_TICK);
361  } else {
362  Serial.print(tSpaceTicksLong * MICROS_PER_TICK);
363  }
364  Serial.print(F(", "));
365  Serial.print(tMarkTicksShort * MICROS_PER_TICK);
366  Serial.print(F(", "));
367  Serial.println(tSpaceTicksShort * MICROS_PER_TICK);
368 #endif
369 
370  uint8_t tNumberOfAdditionalArrayValues = (tNumberOfBits - 1) / BITS_IN_DECODED_RAW_DATA_TYPE;
371 
372  /*
373  * We can have the following protocol timings
374  * PULSE_DISTANCE: Pause/spaces have different length and determine the bit value, longer space is 1. Pulses/marks can be constant, like NEC.
375  * PULSE_WIDTH: Pulses/marks have different length and determine the bit value, longer mark is 1. Pause/spaces can be constant, like Sony.
376  * PULSE_DISTANCE_WIDTH: Pulses/marks and pause/spaces have different length, often the bit length is constant, like MagiQuest. Can be decoded by PULSE_DISTANCE approach.
377  */
378 
379  if (tMarkTicksLong == 0 && tSpaceTicksLong == 0) {
381  F("PULSE_DISTANCE: Cannot decode, because there is only one distinct duration value for each space and mark"));
382  return false;
383  }
384  unsigned int tSpaceMicrosShort;
385 #if defined(LOCAL_DEBUG)
386  if(tMarkTicksLong > 0 && tSpaceTicksLong > 0) {
387  Serial.println(F("PULSE_DISTANCE_WIDTH signal found"));
388  }
389 #endif
390  tSpaceMicrosShort = tSpaceTicksShort * MICROS_PER_TICK;
391  unsigned int tMarkMicrosShort = tMarkTicksShort * MICROS_PER_TICK;
392  unsigned int tMarkMicrosLong = tMarkTicksLong * MICROS_PER_TICK;
393  unsigned int tSpaceMicrosLong = tSpaceTicksLong * MICROS_PER_TICK;
394  IRRawlenType tStartIndex = 3; // skip leading start bit for decoding.
395 
396  for (uint_fast8_t i = 0; i <= tNumberOfAdditionalArrayValues; ++i) {
397  uint8_t tNumberOfBitsForOneDecode = tNumberOfBits;
398  /*
399  * Decode in 32/64 bit chunks. Only the last chunk can contain less than 32/64 bits
400  */
401  if (tNumberOfBitsForOneDecode > BITS_IN_DECODED_RAW_DATA_TYPE) {
402  tNumberOfBitsForOneDecode = BITS_IN_DECODED_RAW_DATA_TYPE;
403  }
404  if (tSpaceTicksLong > 0) {
405  /*
406  * Here short and long space durations found. So we have PULSE_DISTANCE or PULSE_DISTANCE_WIDTH.
407  * PULSE_DISTANCE_WIDTH can be successfully decoded by only using the timings of space :-).
408  */
409  decodedIRData.protocol = PULSE_DISTANCE; // NEC etc. + PULSE_DISTANCE_WIDTH
410 #if defined(USE_THRESHOLD_DECODER)
411  decodeWithThresholdPulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex,
412  ((tSpaceMicrosLong + tSpaceMicrosShort) / 2) + MARK_EXCESS_MICROS, // MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
413 #else
414  decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tSpaceMicrosLong,
415 #endif
417 #if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
419 #else
421 #endif
422  );
423 
424  } else {
425  /*
426  * Here no long space duration but short and long mark durations found. So we have PULSE_WIDTH.
427  * Use timing of marks for decoding here.
428  * This else case will most likely never be used, but it only requires 12 bytes additional programming space :-)
429  */
431 #if defined(USE_THRESHOLD_DECODER)
432  decodeWithThresholdPulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex,
433  ((tMarkMicrosLong+ tMarkMicrosShort) / 2) - MARK_EXCESS_MICROS, // MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
434 #else
435  decodePulseDistanceWidthData(tNumberOfBitsForOneDecode, tStartIndex, tMarkMicrosLong,
436 #endif
438 #if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
440 #else
442 #endif
443  );
444 
445  }
446  DEBUG_PRINT(F("PULSE_WIDTH: decodedRawData=0x"));
447 #if defined(LOCAL_DEBUG)
448 # if (__INT_WIDTH__ < 32)
449  Serial.println(decodedIRData.decodedRawData, HEX);
450 # else
451  PrintULL::println(&Serial, decodedIRData.decodedRawData, HEX);
452 # endif
453 #endif
454 
455  // fill array with decoded data
456  decodedIRData.decodedRawDataArray[i] = decodedIRData.decodedRawData;
457  tStartIndex += (2 * BITS_IN_DECODED_RAW_DATA_TYPE);
458  tNumberOfBits -= BITS_IN_DECODED_RAW_DATA_TYPE;
459  }
460 
461 #if defined(USE_MSB_DECODING_FOR_DISTANCE_DECODER)
463 #endif
464 
465  // Check for repeat. Check also for equality of last DecodedRawData.
467  && decodedIRData.decodedRawDataArray[tNumberOfAdditionalArrayValues] == lastDecodedRawData) {
469  }
470  lastDecodedRawData = decodedIRData.decodedRawData;
471 
472  /*
473  * Store timing data to reproduce frame for sending
474  */
475  decodedIRData.DistanceWidthTimingInfo.HeaderMarkMicros = (irparams.rawbuf[1] * MICROS_PER_TICK);
476  decodedIRData.DistanceWidthTimingInfo.HeaderSpaceMicros = (irparams.rawbuf[2] * MICROS_PER_TICK);
477  decodedIRData.DistanceWidthTimingInfo.ZeroMarkMicros = tMarkMicrosShort;
478  decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosShort;
479  if (tMarkMicrosLong != 0) {
480  if (tSpaceMicrosLong == 0) {
481  // PULSE_DISTANCE, Sony
482  decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosLong;
483  decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosShort;
484  } else {
485  // PULSE_DISTANCE_WIDTH, we have 4 distinct values here
486  // Assume long space for a one when we have PulseDistanceWidth like for RS232, where a long inactive period (high) is a 1
487  decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosLong;
488  decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosShort;
489  decodedIRData.DistanceWidthTimingInfo.ZeroMarkMicros = tMarkMicrosLong;
490 // // Assume long mark for a one when we have PulseDistanceWidth
491 // decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosShort;
492 // decodedIRData.DistanceWidthTimingInfo.ZeroSpaceMicros = tSpaceMicrosLong;
493 // decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosLong;
494  }
495  } else {
496  // PULSE_WIDTH, NEC etc.
497  // Here tMarkMicrosLong is 0 => tSpaceMicrosLong != 0
498  decodedIRData.DistanceWidthTimingInfo.OneMarkMicros = tMarkMicrosShort;
499  decodedIRData.DistanceWidthTimingInfo.OneSpaceMicros = tSpaceMicrosLong;
500  }
501 
502 #if defined(LOCAL_DEBUG)
503  Serial.print(F("DistanceWidthTimingInfo="));
504  IrReceiver.printDistanceWidthTimingInfo(&Serial, &decodedIRData.DistanceWidthTimingInfo);
505  Serial.println();
506 #endif
507  return true;
508 }
509 
511 #include "LocalDebugLevelEnd.h"
512 
513 #endif // _IR_DISTANCE_WIDTH_HPP
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:133
IRrecv::decodePulseDistanceWidthData
void decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset=3)
Decode pulse distance protocols for PulseDistanceWidthProtocolConstants.
Definition: IRReceive.hpp:1076
PROTOCOL_IS_MSB_FIRST
#define PROTOCOL_IS_MSB_FIRST
Definition: IRProtocol.h:156
PROTOCOL_IS_PULSE_WIDTH
#define PROTOCOL_IS_PULSE_WIDTH
Definition: IRProtocol.h:153
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRremoteInt.h:173
DEBUG_PRINT
#define DEBUG_PRINT(...)
Definition: LocalDebugLevelStart.h:79
IRrecv::printDistanceWidthTimingInfo
void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo)
Definition: IRReceive.hpp:1822
IRRawlenType
unsigned int IRRawlenType
Definition: IRremoteInt.h:88
aggregateArrayCounts
bool aggregateArrayCounts(uint8_t aArray[], uint8_t aMaxIndex, uint8_t *aShortIndex, uint8_t *aLongIndex)
Definition: ir_DistanceWidthProtocol.hpp:155
MARK_EXCESS_MICROS
#define MARK_EXCESS_MICROS
MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,...
Definition: IRremote.hpp:111
PROTOCOL_IS_PULSE_DISTANCE
#define PROTOCOL_IS_PULSE_DISTANCE
Definition: IRProtocol.h:151
IRrecv::decodeDistanceWidth
bool decodeDistanceWidth()
Definition: ir_DistanceWidthProtocol.hpp:206
PULSE_WIDTH
@ PULSE_WIDTH
Definition: IRProtocol.h:98
IRDATA_FLAGS_IS_REPEAT
#define IRDATA_FLAGS_IS_REPEAT
The gap between the preceding frame is as smaller than the maximum gap expected for a repeat....
Definition: IRProtocol.h:125
DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE
#define DISTANCE_WIDTH_DECODER_DURATION_ARRAY_SIZE
Definition: ir_DistanceWidthProtocol.hpp:83
PULSE_DISTANCE
@ PULSE_DISTANCE
Definition: IRProtocol.h:98
LocalDebugLevelStart.h
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:401
DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS
#define DISTANCE_WIDTH_MAXIMUM_REPEAT_DISTANCE_MICROS
Definition: ir_DistanceWidthProtocol.hpp:74
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRremoteInt.h:174
PROTOCOL_IS_LSB_FIRST
#define PROTOCOL_IS_LSB_FIRST
Definition: IRProtocol.h:157
IRData::decodedRawData
IRDecodedRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send<protocol>Raw functions.
Definition: IRremoteInt.h:167
irparams_struct::rawbuf
IRRawbufType rawbuf[RAW_BUFFER_LENGTH]
raw data / tick counts per mark/space. With 8 bit we can only store up to 12.7 ms....
Definition: IRremoteInt.h:147
IRrecv::irparams
irparams_struct irparams
Definition: IRremoteInt.h:400
DEBUG_PRINTLN
#define DEBUG_PRINTLN(...)
Definition: LocalDebugLevelStart.h:80
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:133
IRData::rawlen
IRRawlenType rawlen
Counter of entries in rawbuf of last received frame.
Definition: IRremoteInt.h:182
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRremoteInt.h:163
BITS_IN_DECODED_RAW_DATA_TYPE
#define BITS_IN_DECODED_RAW_DATA_TYPE
Definition: IRremoteInt.h:152
IrReceiver
IRrecv IrReceiver
The receiver instance.
Definition: IRReceive.hpp:57
IRData::initialGapTicks
uint16_t initialGapTicks
Contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
Definition: IRremoteInt.h:183
LocalDebugLevelEnd.h
IRrecv::decodeWithThresholdPulseDistanceWidthData
void decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, bool aMSBfirst)
New threshold decoder to be activated by USE_THRESHOLD_DECODER Assumes a 0 for shorter and a 1 for lo...
Definition: IRReceive.hpp:833