IRremote
TinyIR.h
Go to the documentation of this file.
1 /*
2  * TinyIR.h
3  *
4  *
5  * Copyright (C) 2021-2025 Armin Joachimsmeyer
6  * armin.joachimsmeyer@gmail.com
7  *
8  * This file is part of IRMP https://github.com/IRMP-org/IRMP.
9  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
10  *
11  * TinyIRReceiver is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation, either version 3 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
23  *
24  */
25 
26 #ifndef _TINY_IR_H
27 #define _TINY_IR_H
28 
29 #include <Arduino.h>
30 
31 #include "LongUnion.h"
32 
37 #define VERSION_TINYIR "2.2.0"
38 #define VERSION_TINYIR_MAJOR 2
39 #define VERSION_TINYIR_MINOR 2
40 #define VERSION_TINYIR_PATCH 0
41 // The change log is at the bottom of the file
42 
49 #if !defined(NEC_ADDRESS_BITS)
50 #define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address
51 #define NEC_COMMAND_BITS 16 // Command and inverted command
52 #define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS)
53 
54 #define NEC_UNIT 560
55 
56 #define NEC_HEADER_MARK (16 * NEC_UNIT) // 8860
57 #define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4480
58 
59 #define NEC_BIT_MARK NEC_UNIT
60 #define NEC_ONE_SPACE (3 * NEC_UNIT) // 1680
61 #define NEC_ZERO_SPACE NEC_UNIT
62 
63 #define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2240
64 
65 #define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down.
66 #define NEC_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones
67 #define NEC_MAXIMUM_REPEAT_DISTANCE (NEC_REPEAT_PERIOD - NEC_MINIMAL_DURATION + 10000) // 70 ms
68 #endif
69 
79 /*
80  Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first
81  +2100,-1050
82  + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500
83  + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500
84  + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550
85  + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550
86  + 550
87  Sum: 28900
88  */
89 #define FAST_KHZ 38
90 #define FAST_ADDRESS_BITS 0 // No address
91 #define FAST_COMMAND_BITS 16 // Command and inverted command (parity)
92 #define FAST_BITS (FAST_ADDRESS_BITS + FAST_COMMAND_BITS)
93 
94 #define FAST_UNIT 526 // 20 periods of 38 kHz (526.315789)
95 
96 #define FAST_BIT_MARK FAST_UNIT
97 #define FAST_ONE_SPACE (3 * FAST_UNIT) // 1578 -> bit period = 2104
98 #define FAST_ZERO_SPACE FAST_UNIT // 526 -> bit period = 1052
99 
100 #define FAST_HEADER_MARK (4 * FAST_UNIT) // 2104
101 #define FAST_HEADER_SPACE (2 * FAST_UNIT) // 1052
102 
103 #define FAST_REPEAT_PERIOD 50000 // Commands are repeated every 50 ms (measured from start to start) for as long as the key on the remote control is held down.
104 #define FAST_REPEAT_DISTANCE (FAST_REPEAT_PERIOD - (55 * FAST_UNIT)) // 19 ms
105 #define FAST_MAXIMUM_REPEAT_DISTANCE (FAST_REPEAT_DISTANCE + 10000) // 29 ms
106 
107 /*
108  * Definitions to switch between FAST and NEC/ONKYO timing with the same code.
109  */
110 #if defined(USE_FAST_PROTOCOL)
111 #define ENABLE_NEC2_REPEATS // Disables detection of special short frame NEC repeats. Saves 40 bytes program memory.
112 
113 #define TINY_RECEIVER_ADDRESS_BITS FAST_ADDRESS_BITS
114 #define TINY_RECEIVER_COMMAND_BITS FAST_COMMAND_BITS
115 #if !defined(TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY)
116 #define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity
117 //#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity - not tested
118 #endif
119 
120 #define TINY_RECEIVER_BITS FAST_BITS
121 #define TINY_RECEIVER_UNIT FAST_UNIT
122 
123 #define TINY_RECEIVER_HEADER_MARK FAST_HEADER_MARK
124 #define TINY_RECEIVER_HEADER_SPACE FAST_HEADER_SPACE
125 #define TINY_RECEIVER_MARK_TIMEOUT (2 * FAST_HEADER_MARK)
126 
127 #define TINY_RECEIVER_BIT_MARK FAST_BIT_MARK
128 #define TINY_RECEIVER_ONE_SPACE FAST_ONE_SPACE
129 #define TINY_RECEIVER_ZERO_SPACE FAST_ZERO_SPACE
130 #define TINY_RECEIVER_ONE_THRESHOLD (2 * FAST_UNIT) // 1052
131 
132 #define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE FAST_MAXIMUM_REPEAT_DISTANCE // for repeat detection
133 
134 #else
135 
136 #define TINY_RECEIVER_ADDRESS_BITS NEC_ADDRESS_BITS // the address bits + parity
137 # if defined(USE_ONKYO_PROTOCOL)
138 #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity
139 # elif defined(USE_EXTENDED_NEC_PROTOCOL)
140 #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity
141 # else
142 #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity
143 # endif
144 
145 #define TINY_RECEIVER_COMMAND_BITS NEC_COMMAND_BITS // the command bits + parity
146 # if defined(USE_ONKYO_PROTOCOL)
147 #define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity
148 # else
149 #define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity
150 # endif
151 
152 #define TINY_RECEIVER_BITS NEC_BITS
153 #define TINY_RECEIVER_UNIT NEC_UNIT
154 
155 #define TINY_RECEIVER_HEADER_MARK NEC_HEADER_MARK
156 #define TINY_RECEIVER_MARK_TIMEOUT (2 * NEC_HEADER_MARK)
157 #define TINY_RECEIVER_HEADER_SPACE NEC_HEADER_SPACE
158 
159 #define TINY_RECEIVER_BIT_MARK NEC_BIT_MARK
160 #define TINY_RECEIVER_ONE_SPACE NEC_ONE_SPACE
161 #define TINY_RECEIVER_ZERO_SPACE NEC_ZERO_SPACE
162 #define TINY_RECEIVER_ONE_THRESHOLD (2 * NEC_UNIT) // 1120
163 
164 #define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE
165 #endif
166 
167 #if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
168 /*
169  * This function is called, if a complete command was received and must be implemented in the file (user code)
170  * which includes this library if USE_CALLBACK_FOR_TINY_RECEIVER is activated.
171  */
172 extern void handleReceivedTinyIRData();
173 #endif
174 
175 #if !defined(MICROS_IN_ONE_SECOND)
176 #define MICROS_IN_ONE_SECOND 1000000L
177 #endif
178 
179 #if !defined(MICROS_IN_ONE_MILLI)
180 #define MICROS_IN_ONE_MILLI 1000L
181 #endif
182 
183 /*
184  * Macros for comparing timing values
185  */
186 #define lowerValue25Percent(aDuration) (aDuration - (aDuration / 4))
187 #define upperValue25Percent(aDuration) (aDuration + (aDuration / 4))
188 #define lowerValue50Percent(aDuration) (aDuration / 2) // (aDuration - (aDuration / 2))
189 #define upperValue50Percent(aDuration) (aDuration + (aDuration / 2))
190 
191 /*
192  * The states for the state machine
193  */
194 #define IR_RECEIVER_STATE_WAITING_FOR_START_MARK 0
195 #define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE 1
196 #define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK 2
197 #define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE 3
198 #define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4
199 #define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5
200 
204  /*
205  * State machine
206  */
207  uint32_t LastChangeMicros;
208  uint8_t IRReceiverState;
210  /*
211  * Data
212  */
213 #if (TINY_RECEIVER_BITS > 16)
214  uint32_t IRRawDataMask;
216 #else
217  uint16_t IRRawDataMask;
219 #endif
220  uint8_t Flags;
221 };
222 
223 /*
224  * Definitions for member TinyIRReceiverCallbackDataStruct.Flags
225  * This is a copy of flags from IRremoteInt.h
226  */
227 #define IRDATA_FLAGS_EMPTY 0x00
228 #define IRDATA_FLAGS_IS_REPEAT 0x01
229 #define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 // not used for TinyIR
230 #define IRDATA_FLAGS_PARITY_FAILED 0x04
231 
232 
236 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
237 # if (TINY_RECEIVER_ADDRESS_BITS == 16) && !TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
238  uint16_t Address;
239 # else
240  uint8_t Address;
241 # endif
242 #endif
243 
244 # if (TINY_RECEIVER_COMMAND_BITS == 16) && !TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
245  uint16_t Command;
246 #else
247  uint8_t Command;
248 #endif
249  uint8_t Flags; // Bit coded flags. Can contain one of the bits: IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED
250  bool justWritten;
251 };
253 
258 bool isTinyReceiverIdle();
259 bool TinyReceiverDecode();
260 void printTinyReceiverResultMinimal(Print *aSerial);
261 
262 void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0);
263 void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0);
264 void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100
265 void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0)
266  __attribute__ ((deprecated ("Renamed to sendNEC().")));
267 void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false);
268 void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false);
269 
270 #if defined(NO_LED_FEEDBACK_CODE)
271 # if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
272 #define NO_LED_RECEIVE_FEEDBACK_CODE
273 # endif
274 # if !defined(NO_LED_SEND_FEEDBACK_CODE)
275 #define NO_LED_SEND_FEEDBACK_CODE
276 # endif
277 #endif
278 
279 #if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
280 #define IR_FEEDBACK_LED_PIN LED_BUILTIN
281 #endif
282 
283 /*
284  * Version 2.2.0 - 7/2024
285  * - New TinyReceiverDecode() function to be used as drop in for IrReceiver.decode().
286  *
287  * Version 2.1.0 - 2/2024
288  * - New sendExtendedNEC() function and new parameter aSendNEC2Repeats.
289  *
290  * Version 2.0.0 - 10/2023
291  * - New TinyIRReceiverData which is filled with address, command and flags.
292  * - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal().
293  * - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated.
294  *
295  * Version 1.2.0 - 01/2023
296  * - Added ONKYO protocol, NEC with 16 bit address and command, instead of 8 bit + 8 bit parity address and command.
297  * - Renamed functions and macros.
298  *
299  * Version 1.1.0 - 01/2023
300  * - FAST protocol added.
301  */
304 #endif // _TINY_IR_H
LongUnion
Union to specify parts / manifestations of a 32 bit Long without casts and shifts.
Definition: LongUnion.h:59
TinyIRReceiverStruct::IRReceiverState
uint8_t IRReceiverState
The state of the state machine.
Definition: TinyIR.h:208
sendNECMinimal
void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats=0) __attribute__((deprecated("Renamed to sendNEC().")))
Definition: TinyIRSender.hpp:188
TinyIRReceiverCallbackDataStruct::Flags
uint8_t Flags
Definition: TinyIR.h:249
WordUnion
Union to specify parts / manifestations of a 16 bit Word without casts and shifts.
Definition: LongUnion.h:36
TinyIRReceiverStruct
Control and data variables of the state machine for TinyReceiver.
Definition: TinyIR.h:203
TinyIRReceiverStruct::Flags
uint8_t Flags
One of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT, and IRDATA_FLAGS_PARITY_FAILED.
Definition: TinyIR.h:220
enablePCIInterruptForTinyReceiver
bool enablePCIInterruptForTinyReceiver()
Initializes hardware interrupt generation according to IR_RECEIVE_PIN or use attachInterrupt() functi...
Definition: TinyIRReceiver.hpp:578
TinyIRReceiverData
volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData
Definition: TinyIRReceiver.hpp:111
isTinyReceiverIdle
bool isTinyReceiverIdle()
Definition: TinyIRReceiver.hpp:436
handleReceivedTinyIRData
void handleReceivedTinyIRData()
Declaration of the callback function provided by the user application.
disablePCIInterruptForTinyReceiver
void disablePCIInterruptForTinyReceiver()
Definition: TinyIRReceiver.hpp:649
TinyIRReceiverCallbackDataStruct::Address
uint16_t Address
Definition: TinyIR.h:238
TinyReceiverDecode
bool TinyReceiverDecode()
Definition: TinyIRReceiver.hpp:443
TinyIRReceiverCallbackDataStruct::justWritten
bool justWritten
Is set true if new data is available. Used by the main loop / TinyReceiverDecode(),...
Definition: TinyIR.h:250
TinyIRReceiverStruct::LastChangeMicros
uint32_t LastChangeMicros
Microseconds of last Pin Change Interrupt.
Definition: TinyIR.h:207
TinyIRReceiverStruct::IRRawDataMask
uint32_t IRRawDataMask
The corresponding bit mask for IRRawDataBitCounter.
Definition: TinyIR.h:214
TinyIRReceiverCallbackDataStruct
Is filled before calling the user callback to transfer received data to main loop for further process...
Definition: TinyIR.h:235
sendNEC
void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats=0, bool aSendNEC2Repeats=false)
Definition: TinyIRSender.hpp:191
LongUnion.h
TinyIRReceiverCallbackDataStruct::Command
uint16_t Command
Definition: TinyIR.h:245
printTinyReceiverResultMinimal
void printTinyReceiverResultMinimal(Print *aSerial)
Definition: TinyIRReceiver.hpp:478
TinyIRReceiverStruct::IRRawDataBitCounter
uint8_t IRRawDataBitCounter
How many bits are currently contained in raw data.
Definition: TinyIR.h:209
sendFast8BitAndParity
void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats=0)
Definition: TinyIRSender.hpp:344
sendONKYO
void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats=0, bool aSendNEC2Repeats=false)
Definition: TinyIRSender.hpp:120
isIRReceiverAttachedForTinyReceiver
bool isIRReceiverAttachedForTinyReceiver()
Definition: TinyIRReceiver.hpp:455
sendExtendedNEC
void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats=0, bool aSendNEC2Repeats=false)
Definition: TinyIRSender.hpp:274
sendFAST
void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats=0)
Definition: TinyIRSender.hpp:351
TinyIRReceiverStruct::IRRawData
LongUnion IRRawData
The current raw data. LongUnion helps with decoding of address and command.
Definition: TinyIR.h:215
initPCIInterruptForTinyReceiver
bool initPCIInterruptForTinyReceiver()
Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mo...
Definition: TinyIRReceiver.hpp:466