IRremote
IRProtocol.hpp
Go to the documentation of this file.
1 /*
2  * IRReceive.hpp
3  * This file is exclusively included by IRremote.h to enable easy configuration of library switches
4  *
5  * Contains all protocol functions used by receiver and sender.
6  *
7  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
8  *
9  ************************************************************************************
10  * MIT License
11  *
12  * Copyright (c) 2009-2023 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this software and associated documentation files (the "Software"), to deal
16  * in the Software without restriction, including without limitation the rights
17  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18  * copies of the Software, and to permit persons to whom the Software is furnished
19  * to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in all
22  * copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
25  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
26  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
28  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
29  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  *
31  ************************************************************************************
32  */
33 #ifndef _IR_PROTOCOL_HPP
34 #define _IR_PROTOCOL_HPP
35 
36 #if defined(DEBUG) && !defined(LOCAL_DEBUG)
37 #define LOCAL_DEBUG
38 #else
39 //#define LOCAL_DEBUG // This enables debug output only for this file
40 #endif
41 
46 const char string_Unknown[] PROGMEM = "UNKNOWN";
47 const char string_PulseWidth[] PROGMEM = "PulseWidth";
48 const char string_PulseDistance[] PROGMEM = "PulseDistance";
49 const char string_Apple[] PROGMEM = "Apple";
50 const char string_Denon[] PROGMEM = "Denon";
51 const char string_JVC[] PROGMEM = "JVC";
52 const char string_LG[] PROGMEM = "LG";
53 const char string_LG2[] PROGMEM = "LG2";
54 const char string_NEC[] PROGMEM = "NEC";
55 const char string_NEC2[] PROGMEM = "NEC2";
56 const char string_Onkyo[] PROGMEM = "Onkyo";
57 const char string_Panasonic[] PROGMEM = "Panasonic";
58 const char string_Kaseikyo[] PROGMEM = "Kaseikyo";
59 const char string_Kaseikyo_Denon[] PROGMEM = "Kaseikyo_Denon";
60 const char string_Kaseikyo_Sharp[] PROGMEM = "Kaseikyo_Sharp";
61 const char string_Kaseikyo_JVC[] PROGMEM = "Kaseikyo_JVC";
62 const char string_Kaseikyo_Mitsubishi[] PROGMEM = "Kaseikyo_Mitsubishi";
63 const char string_RC5[] PROGMEM = "RC5";
64 const char string_RC6[] PROGMEM = "RC6";
65 const char string_Samsung[] PROGMEM = "Samsung";
66 const char string_SamsungLG[] PROGMEM = "SamsungLG";
67 const char string_Samsung48[] PROGMEM = "Samsung48";
68 const char string_Sharp[] PROGMEM = "Sharp";
69 const char string_Sony[] PROGMEM = "Sony";
70 const char string_BangOlufsen[] PROGMEM = "Bang&Olufsen";
71 const char string_BoseWave[] PROGMEM = "BoseWave";
72 const char string_Lego[] PROGMEM = "Lego";
73 const char string_MagiQuest[] PROGMEM = "MagiQuest";
74 const char string_Whynter[] PROGMEM = "Whynter";
75 const char string_FAST[] PROGMEM = "FAST";
76 
77 /*
78  * !!Must be the same order as in decode_type_t in IRProtocol.h!!!
79  */
80 const char *const ProtocolNames[]
81 PROGMEM = { string_Unknown, string_PulseWidth, string_PulseDistance, string_Apple, string_Denon, string_JVC, string_LG, string_LG2,
82  string_NEC, string_NEC2, string_Onkyo, string_Panasonic, string_Kaseikyo, string_Kaseikyo_Denon, string_Kaseikyo_Sharp,
83  string_Kaseikyo_JVC, string_Kaseikyo_Mitsubishi, string_RC5, string_RC6, string_Samsung, string_SamsungLG, string_Samsung48,
84  string_Sharp, string_Sony
85 #if !defined(EXCLUDE_EXOTIC_PROTOCOLS)
86  , string_BangOlufsen, string_BoseWave, string_Lego, string_MagiQuest, string_Whynter, string_FAST
87 #endif
88  };
89 
90 #if defined(__AVR__)
91 const __FlashStringHelper* getProtocolString(decode_type_t aProtocol) {
92  const char *tProtocolStringPtr = (char*) pgm_read_word(&ProtocolNames[aProtocol]);
93  return ((__FlashStringHelper*) (tProtocolStringPtr));
94 }
95 #else
96 const char* getProtocolString(decode_type_t aProtocol) {
97  return ProtocolNames[aProtocol];
98 }
99 #endif
100 
101 #if (__INT_WIDTH__ >= 32)
102 # if __has_include(<type_traits>)
103 /*
104  * This code to handle the missing print(unsigned long long...) function of seeduino core was contributed by sklott
105  * https://stackoverflow.com/questions/74622227/avoid-calling-of-function-size-t-printprintunsigned-long-long-n-int-base-if
106  */
107 #include <type_traits>
108 
109 // If you have C++17 you can just use std::void_t, or use this for all versions
110 #if __cpp_lib_void_t >= 201411L
111 template<typename T>
112 using void_t = std::void_t<T>;
113 #else
114 template<typename ... Ts> struct make_void {
115  typedef void type;
116 };
117 template<typename ... Ts> using void_t = typename make_void<Ts...>::type;
118 #endif
119 
120 // Detecting if we have print(unsigned long long value, int base) / print(0ull, 0) overload
121 template<typename T, typename = void>
122 struct has_ull_print: std::false_type {
123 };
124 template<typename T>
125 struct has_ull_print<T, void_t<decltype(std::declval<T>().print(0ull, 0))>> : std::true_type {
126 };
127 
128 // Must be namespace, to avoid public and static declarations for class
129 namespace PrintULL {
130 template<typename PrintImplType, typename std::enable_if<!has_ull_print<PrintImplType>::value, bool>::type = true>
131 size_t print(PrintImplType *p, unsigned long long value, int base) {
132  size_t tLength = p->print(static_cast<uint32_t>(value >> 32), base);
133  tLength += p->print(static_cast<uint32_t>(value), base);
134  return tLength;
135 }
136 
137 template<typename PrintImplType, typename std::enable_if<has_ull_print<PrintImplType>::value, bool>::type = true>
138 size_t print(PrintImplType *p, unsigned long long value, int base) {
139  return p->print(value, base);
140 }
141 }
142 ;
143 # else
144 namespace PrintULL {
145  size_t print(Print *aSerial, unsigned long long n, int base) {
146  return aSerial->print(n, base);
147  }
148 };
149 # endif
150 #endif
151 
162 void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) {
163  if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) {
164  aSerial->println(F("Overflow"));
165  return;
166  }
167  aSerial->print(F("Protocol="));
168  aSerial->print(getProtocolString(aIRDataPtr->protocol));
169  if (aIRDataPtr->protocol == UNKNOWN) {
170 #if defined(DECODE_HASH)
171  aSerial->print(F(" Hash=0x"));
172 #if (__INT_WIDTH__ < 32)
173  aSerial->print(aIRDataPtr->decodedRawData, HEX);
174 #else
175  PrintULL::print(aSerial,aIRDataPtr->decodedRawData, HEX);
176 #endif
177 
178 #endif
179 #if !defined(DISABLE_CODE_FOR_RECEIVER)
180  aSerial->print(' ');
181  aSerial->print((aIRDataPtr->rawlen + 1) / 2, DEC);
182  aSerial->println(F(" bits (incl. gap and start) received"));
183 #endif
184  } else {
185 #if defined(DECODE_DISTANCE_WIDTH)
186  if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) {
187 #endif
188  /*
189  * New decoders have address and command
190  */
191  aSerial->print(F(" Address=0x"));
192  aSerial->print(aIRDataPtr->address, HEX);
193 
194  aSerial->print(F(" Command=0x"));
195  aSerial->print(aIRDataPtr->command, HEX);
196 
197  if (aIRDataPtr->flags & IRDATA_FLAGS_EXTRA_INFO) {
198  aSerial->print(F(" Extra=0x"));
199  aSerial->print(aIRDataPtr->extra, HEX);
200  }
201 
202  if (aIRDataPtr->flags & IRDATA_FLAGS_PARITY_FAILED) {
203  aSerial->print(F(" Parity fail"));
204  }
205 
206  if (aIRDataPtr->flags & IRDATA_FLAGS_TOGGLE_BIT) {
207  aSerial->print(F(" Toggle=1"));
208  }
209 #if defined(DECODE_DISTANCE_WIDTH)
210  }
211 #endif
213  aSerial->print(' ');
214  if (aIRDataPtr->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
215  aSerial->print(F("Auto-"));
216  }
217  aSerial->print(F("Repeat"));
218 #if !defined(DISABLE_CODE_FOR_RECEIVER)
219  if (aPrintRepeatGap) {
220  aSerial->print(F(" gap="));
221  aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK);
222  aSerial->print(F("us"));
223  }
224 #else
225  (void)aPrintRepeatGap;
226 #endif
227  }
228 
229  /*
230  * Print raw data
231  */
232  if (!(aIRDataPtr->flags & IRDATA_FLAGS_IS_REPEAT) || aIRDataPtr->decodedRawData != 0) {
233  aSerial->print(F(" Raw-Data=0x"));
234 #if (__INT_WIDTH__ < 32)
235  aSerial->print(aIRDataPtr->decodedRawData, HEX);
236 #else
237  PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX);
238 #endif
239  /*
240  * Print number of bits processed
241  */
242  aSerial->print(' ');
243  aSerial->print(aIRDataPtr->numberOfBits, DEC);
244  aSerial->print(F(" bits"));
245 
246  if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
247  aSerial->println(F(" MSB first"));
248  } else {
249  aSerial->println(F(" LSB first"));
250  }
251 
252  } else {
253  aSerial->println();
254  }
255  }
256 }
257 
258 /**********************************************************************************************************************
259  * Function to bit reverse OLD MSB values of e.g. NEC.
260  **********************************************************************************************************************/
261 uint8_t bitreverseOneByte(uint8_t aValue) {
262 // uint8_t tReversedValue;
263 // return __builtin_avr_insert_bits(0x01234567, aValue, tReversedValue);
264 // 76543210
265  aValue = (aValue >> 4) | (aValue << 4); // Swap in groups of 4
266 // 32107654
267  aValue = ((aValue & 0xcc) >> 2) | ((aValue & 0x33) << 2); // Swap in groups of 2
268 // 10325476
269  aValue = ((aValue & 0xaa) >> 1) | ((aValue & 0x55) << 1); // Swap bit pairs
270 // 01234567
271  return aValue;
272 }
273 
274 uint32_t bitreverse32Bit(uint32_t aInput) {
275 // __builtin_avr_insert_bits();
276  LongUnion tValue;
277  tValue.UByte.HighByte = bitreverseOneByte(aInput);
278  tValue.UByte.MidHighByte = bitreverseOneByte(aInput >> 8);
279  tValue.UByte.MidLowByte = bitreverseOneByte(aInput >> 16);
280  tValue.UByte.LowByte = bitreverseOneByte(aInput >> 24);
281  return tValue.ULong;
282 }
283 
286 #if defined(LOCAL_DEBUG)
287 #undef LOCAL_DEBUG
288 #endif
289 #endif // _IR_PROTOCOL_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:110
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:250
LongUnion
Union to specify parts / manifestations of a 32 bit Long without casts and shifts.
Definition: LongUnion.h:59
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:119
bitreverse32Bit
uint32_t bitreverse32Bit(uint32_t aInput)
Definition: IRProtocol.hpp:274
LongUnion::UByte
struct LongUnion::@4 UByte
PULSE_WIDTH
@ PULSE_WIDTH
Definition: IRProtocol.h:42
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:92
decode_type_t
decode_type_t
An enum consisting of all supported formats.
Definition: IRProtocol.h:40
LongUnion::LowByte
uint8_t LowByte
Definition: LongUnion.h:61
LongUnion::HighByte
uint8_t HighByte
Definition: LongUnion.h:64
IRDATA_FLAGS_IS_AUTO_REPEAT
#define IRDATA_FLAGS_IS_AUTO_REPEAT
The current repeat frame is a repeat, that is always sent after a regular frame and cannot be avoided...
Definition: IRProtocol.h:93
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:113
PULSE_DISTANCE
@ PULSE_DISTANCE
Definition: IRProtocol.h:43
printIRResultShort
void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap)
Function to print decoded result and flags in one line.
Definition: IRProtocol.hpp:162
IRDATA_FLAGS_PARITY_FAILED
#define IRDATA_FLAGS_PARITY_FAILED
The current (autorepeat) frame violated parity check.
Definition: IRProtocol.h:94
LongUnion::MidLowByte
uint8_t MidLowByte
Definition: LongUnion.h:62
ProtocolNames
const char *const ProtocolNames[]
Definition: IRProtocol.hpp:81
IRData
Data structure for the user application, available as decodedIRData.
Definition: IRProtocol.h:108
IRDATA_FLAGS_EXTRA_INFO
#define IRDATA_FLAGS_EXTRA_INFO
There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID,...
Definition: IRProtocol.h:97
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:120
IRDATA_FLAGS_WAS_OVERFLOW
#define IRDATA_FLAGS_WAS_OVERFLOW
irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag.
Definition: IRProtocol.h:99
bitreverseOneByte
uint8_t bitreverseOneByte(uint8_t aValue)
Definition: IRProtocol.hpp:261
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:111
LongUnion::ULong
uint32_t ULong
Definition: LongUnion.h:95
PROGMEM
const char string_Unknown[] PROGMEM
Definition: IRProtocol.hpp:46
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:100
IRDATA_FLAGS_TOGGLE_BIT
#define IRDATA_FLAGS_TOGGLE_BIT
Is set if RC5 or RC6 toggle bit is set.
Definition: IRProtocol.h:95
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRProtocol.h:112
IRData::rawlen
IRRawlenType rawlen
counter of entries in rawbuf of last received frame.
Definition: IRProtocol.h:128
LongUnion::MidHighByte
uint8_t MidHighByte
Definition: LongUnion.h:63
UNKNOWN
@ UNKNOWN
Definition: IRProtocol.h:41
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:109
IRData::initialGapTicks
uint16_t initialGapTicks
contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
Definition: IRProtocol.h:129
getProtocolString
const char * getProtocolString(decode_type_t aProtocol)
Definition: IRProtocol.hpp:96