IRremote
ir_RC5_RC6.hpp
Go to the documentation of this file.
1 /*
2  * ir_RC5_RC6.hpp
3  *
4  * Contains functions for receiving and sending RC5, RC5X, RC6 protocols
5  *
6  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
7  *
8  ************************************************************************************
9  * MIT License
10  *
11  * Copyright (c) 2020-2025 Armin Joachimsmeyer
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is furnished
18  * to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in all
21  * copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
24  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
25  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
28  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  *
30  ************************************************************************************
31  */
32 #ifndef _IR_RC5_RC6_HPP
33 #define _IR_RC5_RC6_HPP
34 
35 #if defined(DEBUG)
36 #define LOCAL_DEBUG
37 #else
38 //#define LOCAL_DEBUG // This enables debug output only for this file
39 #endif
40 
44 uint8_t sLastSendToggleValue = 1; // To start first command with toggle 0
45 //uint8_t sLastReceiveToggleValue = 3; // 3 -> start value
46 
47 //==============================================================================
48 // RRRR CCCC 55555
49 // R R C 5
50 // RRRR C 5555
51 // R R C 5
52 // R R CCCC 5555
53 //==============================================================================
54 /*
55  Protocol=RC5 Address=0x11 Command=0x36 Raw-Data=0x1476 13 bits MSB first
56  + 900,- 900
57  +1800,-1750 +1800,- 850 + 900,- 850 + 900,-1750
58  + 950,- 850 + 900,- 850 +1800,-1750 + 950,- 850
59  +1800
60  Sum: 23100
61 
62  RC5X with 7.th MSB of command set
63  Protocol=RC5 Address=0x11 Command=0x76 Toggle=1 Raw-Data=0xC76 13 bits MSB first
64  +1800,-1750
65  + 850,- 900 +1800,- 850 + 950,- 850 + 900,-1750
66  + 900,- 850 + 950,- 850 +1800,-1750 + 900,- 850
67  +1800
68  Sum: 23050
69  */
70 //
71 // see: https://www.sbprojects.net/knowledge/ir/rc5.php
72 // https://en.wikipedia.org/wiki/Manchester_code
73 // https://en.wikipedia.org/wiki/RC-5
74 // https://forum.arduino.cc/t/sending-rc-5-extended-code-using-irsender/1045841/10 - Protocol Maranz Extended
75 // mark->space => 0
76 // space->mark => 1
77 // MSB first 1 start bit, 1 field bit, 1 toggle bit + 5 bit address + 6 bit command, no stop bit
78 // Field bit is 1 for RC5 and inverted 7. command bit for RC5X. That way the first 64 commands of RC5X remain compatible with the original RC5.
79 // SF TAAA AACC CCCC
80 // IR duty factor is 25%,
81 //
82 #define RC5_ADDRESS_BITS 5
83 #define RC5_COMMAND_BITS 6
84 #define RC5_EXTENSION_BITS 6
85 #define RC5_COMMAND_FIELD_BIT 1
86 #define RC5_TOGGLE_BIT 1
87 
88 #define RC5_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS) // 13
89 
90 #define RC5_UNIT 889 // 32 periods of 36 kHz (888.8888)
91 
92 #define MIN_RC5_MARKS ((RC5_BITS + 1) / 2) // 7 - Divided by 2 to handle the bit sequence of 01010101 which gives one mark and space for each 2 bits
93 
94 #define RC5_DURATION (15L * RC5_UNIT) // 13335
95 #define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792
96 #define RC5_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - RC5_DURATION) // 100 ms
97 #define RC5_MAXIMUM_REPEAT_DISTANCE (RC5_REPEAT_DISTANCE + (RC5_REPEAT_DISTANCE / 4)) // Just a guess
98 
99 /************************************
100  * Start of send and decode functions
101  ************************************/
102 
108 void IRsend::sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats,
109  bool aEnableAutomaticToggle) {
110 
111  // Set IR carrier frequency
113 
114  uint16_t tIRData = (aAddress & 0x1F);
115 
116  if (aCommand < 0x40) {
117  // Auto discovery of RC5X, set field bit to 1
118  tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS);
119  } else {
120  // Mask bit 7 of command and let field bit 0
121  aCommand &= 0x3F;
122  }
123  // Set the command to the 2nd part of data to be sent after the pause
124  uint16_t tIRExtData = (aCommand << RC5_EXTENSION_BITS);
125  // Set the Marantz command extension bits
126  tIRExtData |= (aMarantzExtension & 0x3F);
127 
128  if (aEnableAutomaticToggle) {
129  if (sLastSendToggleValue == 0) {
131  // set toggled bit
132  tIRData |= 1 << (RC5_ADDRESS_BITS);
133  } else {
135  }
136  }
137 
138  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
139  while (tNumberOfCommands > 0) {
140 
141  // start bit is sent by sendBiphaseData followed by the field bit and toggle bit and address
143  // pause before the bits of command and command extension to indicate that it's Marantz-RC5x
144  space(4 * RC5_UNIT); // Marantz-RC5x has a pause before the bits of command and command extension
145  // send command and command extension
147 
148  tNumberOfCommands--;
149  // skip last delay!
150  if (tNumberOfCommands > 0) {
151  // send repeated command in a fixed raster
153  }
154  }
155 }
156 
161 void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
162 
163  // Set IR carrier frequency
165 
166  uint16_t tIRData = ((aAddress & 0x1F) << (RC5_COMMAND_BITS));
167 
168  if (aCommand < 0x40) {
169  // Auto discovery of RC5X, set field bit to 1
170  tIRData |= 1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
171  } else {
172  // Mask bit 7 of command and let field bit 0
173  aCommand &= 0x3F;
174  }
175  tIRData |= aCommand;
176 
177  if (aEnableAutomaticToggle) {
178  if (sLastSendToggleValue == 0) {
180  // set toggled bit
181  tIRData |= 1 << (RC5_ADDRESS_BITS + RC5_COMMAND_BITS);
182  } else {
184  }
185  }
186 
187  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
188  while (tNumberOfCommands > 0) {
189 
190  // start bit is sent by sendBiphaseData
191  sendBiphaseData(RC5_UNIT, tIRData, RC5_BITS);
192 
193  tNumberOfCommands--;
194  // skip last delay!
195  if (tNumberOfCommands > 0) {
196  // send repeated command in a fixed raster
198  }
199  }
200 }
201 
215  uint8_t tBitIndex;
216  uint32_t tDecodedRawData = 0;
217 
218  // Set Biphase decoding start values
219  initBiphaselevel(1, RC5_UNIT); // Skip gap space
220 
221  // Check we have the right amount of data (11 to 26). The +2 is for initial gap and start bit mark.
222  if (decodedIRData.rawlen < ((RC5_BITS + 1) / 2) + 2 && (RC5_BITS + 2) < decodedIRData.rawlen) {
223  // no debug output, since this check is mainly to determine the received protocol
224  IR_DEBUG_PRINT(F("RC5: "));
225  IR_DEBUG_PRINT(F("Data length="));
227  IR_DEBUG_PRINTLN(F(" is not between 9 and 15"));
228  return false;
229  }
230 
231 // Check start bit, the first space is included in the gap
232  if (getBiphaselevel() != MARK) {
233  IR_DEBUG_PRINT(F("RC5: "));
234  IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK"));
235  return false;
236  }
237 
238  /*
239  * Get data bits - MSB first
240  */
241  for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) {
242  // get next 2 levels and check for transition
243  uint8_t tStartLevel = getBiphaselevel();
244  uint8_t tEndLevel = getBiphaselevel();
245 
246  if ((tStartLevel == SPACE) && (tEndLevel == MARK)) {
247  // we have a space to mark transition here
248  tDecodedRawData = (tDecodedRawData << 1) | 1;
249  } else if ((tStartLevel == MARK) && (tEndLevel == SPACE)) {
250  // we have a mark to space transition here
251  tDecodedRawData = (tDecodedRawData << 1) | 0;
252  } else {
253 #if defined(LOCAL_DEBUG)
254  Serial.print(F("RC5: "));
255  Serial.println(F("no transition found, decode failed"));
256 #endif
257  return false;
258  }
259  }
260 
261  // Success
262  decodedIRData.numberOfBits = tBitIndex; // must be RC5_BITS
263 
264  LongUnion tValue;
265  tValue.ULong = tDecodedRawData;
266  decodedIRData.decodedRawData = tDecodedRawData;
267  decodedIRData.command = tValue.UByte.LowByte & 0x3F;
268  decodedIRData.address = (tValue.UWord.LowWord >> RC5_COMMAND_BITS) & 0x1F;
269 
270  // Get the inverted 7. command bit for RC5X, the inverted value is always 1 for RC5 and serves as a second start bit.
271  if ((tValue.UWord.LowWord & (1 << (RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS))) == 0) {
272  decodedIRData.command += 0x40;
273  }
274 
276  if (tValue.UByte.MidLowByte & 0x8) {
278  }
280 
281  // check for repeat
283 
284  return true;
285 }
286 
287 //+=============================================================================
288 // RRRR CCCC 6666
289 // R R C 6
290 // RRRR C 6666
291 // R R C 6 6
292 // R R CCCC 666
293 //+=============================================================================
294 //
295 /*
296  Protocol=RC6 Address=0xF1 Command=0x76 Raw-Data=0xF176 20 bits MSB first
297  +2650,- 850
298  + 500,- 850 + 500,- 400 + 450,- 450 + 450,- 850
299  +1400,- 400 + 450,- 450 + 450,- 450 + 450,- 900
300  + 450,- 450 + 450,- 400 + 950,- 850 + 900,- 450
301  + 450,- 450 + 450,- 850 + 950,- 400 + 450,- 900
302  + 450
303  Sum: 23150
304  */
305 // Frame RC6: 1 start bit + 1 Bit "1" + 3 mode bits (000) + 1 toggle bit + 8 address + 8 command bits + 2666us pause - 22 bits incl. start bit
306 // Frame RC6A: 1 start bit + 1 Bit "1" + 3 mode bits (110) + 1 toggle bit + "1" + 14 customer bits + 8 system bits + 8 command bits + 2666us pause - 37 bits incl. start bit
307 // !!! toggle bit has another timing :-( !!!
308 // mark->space => 1
309 // space->mark => 0
310 // https://www.sbprojects.net/knowledge/ir/rc6.php
311 // https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A
312 // https://en.wikipedia.org/wiki/Manchester_code
313 #define MIN_RC6_SAMPLES 1
314 
315 #define RC6_RPT_LENGTH 46000
316 
317 #define RC6_LEADING_BIT 1
318 #define RC6_MODE_BITS 3 // never seen others than all 0 for Philips TV
319 #define RC6_TOGGLE_BIT 1 // toggles at every key press. Can be used to distinguish repeats from 2 key presses and has another timing :-(.
320 #define RC6_TOGGLE_BIT_INDEX RC6_MODE_BITS // fourth position, index = 3
321 #define RC6_ADDRESS_BITS 8
322 #define RC6_COMMAND_BITS 8
323 #define RC6_CUSTOMER_BITS 14
324 
325 #define RC6_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 21
326 #define RC6A_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + 1 + RC6_CUSTOMER_BITS + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 36
327 
328 #define RC6_UNIT 444 // 16 periods of 36 kHz (444.4444)
329 
330 #define RC6_HEADER_MARK (6 * RC6_UNIT) // 2666
331 #define RC6_HEADER_SPACE (2 * RC6_UNIT) // 889
332 
333 #define RC6_TRAILING_SPACE (6 * RC6_UNIT) // 2666
334 #define MIN_RC6_MARKS 4 + ((RC6_ADDRESS_BITS + RC6_COMMAND_BITS) / 2) // 12, 4 are for preamble
335 
336 #define RC6_REPEAT_DISTANCE 107000 // just a guess but > 2.666ms
337 #define RC6_MAXIMUM_REPEAT_DISTANCE (RC6_REPEAT_DISTANCE + (RC6_REPEAT_DISTANCE / 4)) // Just a guess
338 
342 void IRsend::sendRC6(uint32_t aRawData, uint8_t aNumberOfBitsToSend) {
343  sendRC6Raw(aRawData, aNumberOfBitsToSend);
344 }
345 void IRsend::sendRC6Raw(uint32_t aRawData, uint8_t aNumberOfBitsToSend) {
346 // Set IR carrier frequency
348 
349 // Header
352 
353 // Start bit
354  mark(RC6_UNIT);
355  space(RC6_UNIT);
356 
357 // Data MSB first
358  uint32_t mask = 1UL << (aNumberOfBitsToSend - 1);
359  for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
360  // The fourth bit we send is the "double width toggle bit"
361  unsigned int t = (i == (RC6_TOGGLE_BIT_INDEX + 1)) ? (RC6_UNIT * 2) : (RC6_UNIT);
362  if (aRawData & mask) {
363  mark(t);
364  space(t);
365  } else {
366  space(t);
367  mark(t);
368  }
369  }
370 }
371 
376 void IRsend::sendRC6(uint64_t aRawData, uint8_t aNumberOfBitsToSend) {
377  sendRC6Raw(aRawData, aNumberOfBitsToSend);
378 }
379 void IRsend::sendRC6Raw(uint64_t aRawData, uint8_t aNumberOfBitsToSend) {
380 // Set IR carrier frequency
382 
383 // Header
386 
387 // Start bit
388  mark(RC6_UNIT);
389  space(RC6_UNIT);
390 
391 // Data MSB first
392  uint64_t mask = 1ULL << (aNumberOfBitsToSend - 1);
393  for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
394  // The fourth bit we send is the "double width toggle bit"
395  unsigned int t = (i == (RC6_TOGGLE_BIT_INDEX + 1)) ? (RC6_UNIT * 2) : (RC6_UNIT);
396  if (aRawData & mask) {
397  mark(t);
398  space(t);
399  } else {
400  space(t);
401  mark(t);
402  }
403  }
404 }
405 
411 void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) {
412 
413  LongUnion tIRRawData;
414  tIRRawData.UByte.LowByte = aCommand;
415  tIRRawData.UByte.MidLowByte = aAddress;
416 
417  tIRRawData.UWord.HighWord = 0; // must clear high word
418  if (aEnableAutomaticToggle) {
419  if (sLastSendToggleValue == 0) {
421  // set toggled bit
422  IR_DEBUG_PRINT(F("Set Toggle "));
423  tIRRawData.UByte.MidHighByte = 1; // 3 Mode bits are 0
424  } else {
426  }
427  }
428 
429 #if defined(LOCAL_DEBUG)
430  Serial.print(F("RC6: "));
431  Serial.print(F("sLastSendToggleValue="));
432  Serial.print (sLastSendToggleValue);
433  Serial.print(F(" RawData="));
434  Serial.println(tIRRawData.ULong, HEX);
435 #endif
436 
437  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
438  while (tNumberOfCommands > 0) {
439 
440  // start and leading bits are sent by sendRC6
441  sendRC6Raw(tIRRawData.ULong, RC6_BITS - 1); // -1 since the leading bit is additionally sent by sendRC6
442 
443  tNumberOfCommands--;
444  // skip last delay!
445  if (tNumberOfCommands > 0) {
446  // send repeated command in a fixed raster
448  }
449  }
450 }
451 
457 void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aCustomer,
458  bool aEnableAutomaticToggle) {
459 
460  LongUnion tIRRawData;
461  tIRRawData.UByte.LowByte = aCommand;
462  tIRRawData.UByte.MidLowByte = aAddress;
463 
464  tIRRawData.UWord.HighWord = aCustomer | 0x400; // bit 31 is always 1
465 
466  if (aEnableAutomaticToggle) {
467  if (sLastSendToggleValue == 0) {
469  // set toggled bit
470  IR_DEBUG_PRINT(F("Set Toggle "));
471  tIRRawData.UByte.HighByte |= 0x80; // toggle bit is bit 32
472  } else {
474  }
475  }
476 
477  // Set mode bits
478  uint64_t tRawData = tIRRawData.ULong + 0x0600000000;
479 
480 #if defined(LOCAL_DEBUG)
481  Serial.print(F("RC6A: "));
482  Serial.print(F("sLastSendToggleValue="));
483  Serial.print (sLastSendToggleValue);
484  Serial.print(F(" RawData="));
485  Serial.println(tIRRawData.ULong, HEX);
486 #endif
487 
488  uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1;
489  while (tNumberOfCommands > 0) {
490 
491  // start and leading bits are sent by sendRC6
492  sendRC6Raw(tRawData, RC6A_BITS - 1); // -1 since the leading bit is additionally sent by sendRC6
493 
494  tNumberOfCommands--;
495  // skip last delay!
496  if (tNumberOfCommands > 0) {
497  // send repeated command in a fixed raster
499  }
500  }
501 }
502 
507  uint8_t tBitIndex;
508  uint32_t tDecodedRawData = 0;
509 
510  // Check we have the right amount of data (). The +3 for initial gap, start bit mark and space
512  IR_DEBUG_PRINT(F("RC6: "));
513  IR_DEBUG_PRINT(F("Data length="));
515  IR_DEBUG_PRINTLN(F(" is not between 15 and 25"));
516  return false;
517  }
518 
519  // Check header "mark" and "space", this must be done for repeat and data
522  // no debug output, since this check is mainly to determine the received protocol
523  IR_DEBUG_PRINT(F("RC6: "));
524  IR_DEBUG_PRINTLN(F("Header mark or space length is wrong"));
525  return false;
526  }
527 
528  // Set Biphase decoding start values
529  initBiphaselevel(3, RC6_UNIT); // Skip gap-space and start-bit mark + space
530 
531 // Process first bit, which is known to be a 1 (mark->space)
532  if (getBiphaselevel() != MARK) {
533  IR_DEBUG_PRINT(F("RC6: "));
534  IR_DEBUG_PRINTLN(F("first getBiphaselevel() is not MARK"));
535  return false;
536  }
537  if (getBiphaselevel() != SPACE) {
538  IR_DEBUG_PRINT(F("RC6: "));
539  IR_DEBUG_PRINTLN(F("second getBiphaselevel() is not SPACE"));
540  return false;
541  }
542 
543  for (tBitIndex = 0; sBiphaseDecodeRawbuffOffset < decodedIRData.rawlen; tBitIndex++) {
544  uint8_t tStartLevel; // start level of coded bit
545  uint8_t tEndLevel; // end level of coded bit
546 
547  tStartLevel = getBiphaselevel();
548  if (tBitIndex == RC6_TOGGLE_BIT_INDEX) {
549  // Toggle bit is double wide; make sure second half is equal first half
550  if (tStartLevel != getBiphaselevel()) {
551 #if defined(LOCAL_DEBUG)
552  Serial.print(F("RC6: "));
553  Serial.println(F("Toggle mark or space length is wrong"));
554 #endif
555  return false;
556  }
557  }
558 
559  tEndLevel = getBiphaselevel();
560  if (tBitIndex == RC6_TOGGLE_BIT_INDEX) {
561  // Toggle bit is double wide; make sure second half matches
562  if (tEndLevel != getBiphaselevel()) {
563 #if defined(LOCAL_DEBUG)
564  Serial.print(F("RC6: "));
565  Serial.println(F("Toggle mark or space length is wrong"));
566 #endif
567  return false;
568  }
569  }
570 
571  /*
572  * Determine tDecodedRawData bit value by checking the transition type
573  */
574  if ((tStartLevel == MARK) && (tEndLevel == SPACE)) {
575  // we have a mark to space transition here
576  tDecodedRawData = (tDecodedRawData << 1) | 1; // inverted compared to RC5
577  } else if ((tStartLevel == SPACE) && (tEndLevel == MARK)) {
578  // we have a space to mark transition here
579  tDecodedRawData = (tDecodedRawData << 1) | 0;
580  } else {
581 #if defined(LOCAL_DEBUG)
582  Serial.print(F("RC6: "));
583  Serial.println(F("Decode failed"));
584 #endif
585  // we have no transition here or one level is -1 -> error
586  return false; // Error
587  }
588  }
589 
590 // Success
591  decodedIRData.numberOfBits = tBitIndex;
592 
593  LongUnion tValue;
594  tValue.ULong = tDecodedRawData;
595  decodedIRData.decodedRawData = tDecodedRawData;
596 
597  if (tBitIndex < 35) {
598  // RC6 8 address bits, 8 command bits
602  // Check for toggle flag
603  if ((tValue.UByte.MidHighByte & 1) != 0) {
605  }
606  if (tBitIndex > 20) {
608  }
610 
611  } else {
612  // RC6A
616  decodedIRData.extra = tValue.UWord.HighWord & 0x3FFF; // Mask to 14 bits, remove toggle and constant 1
617  if ((tValue.UByte.HighByte & 0x80) != 0) {
619  }
621  }
622 
623  // check for repeat, do not check toggle bit yet
625 
626  return true;
627 }
628 
629 /*********************************************************************************
630  * Old deprecated functions, kept for backward compatibility to old 2.0 tutorials
631  *********************************************************************************/
632 
636 void IRsend::sendRC5(uint32_t data, uint8_t nbits) {
637  // Set IR carrier frequency
639 
640  // Start
641  mark(RC5_UNIT);
642  space(RC5_UNIT);
643  mark(RC5_UNIT);
644 
645  // Data - Biphase code MSB first
646  for (uint32_t mask = 1UL << (nbits - 1); mask; mask >>= 1) {
647  if (data & mask) {
648  space(RC5_UNIT); // 1 is space, then mark
649  mark(RC5_UNIT);
650  } else {
651  mark(RC5_UNIT);
652  space(RC5_UNIT);
653  }
654  }
655 }
656 
657 /*
658  * Not longer required, use sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle) instead
659  */
660 void IRsend::sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle) {
661 // Set IR carrier frequency
663 
664  uint8_t addressBits = 5;
665  uint8_t commandBits = 7;
666 // unsigned long nbits = addressBits + commandBits;
667 
668 // Start
669  mark(RC5_UNIT);
670 
671 // Bit #6 of the command part, but inverted!
672  uint8_t cmdBit6 = (1UL << (commandBits - 1)) & cmd;
673  if (cmdBit6) {
674  // Inverted (1 -> 0 = mark-to-space)
675  mark(RC5_UNIT);
676  space(RC5_UNIT);
677  } else {
678  space(RC5_UNIT);
679  mark(RC5_UNIT);
680  }
681  commandBits--;
682 
683 // Toggle bit
684  static int toggleBit = 1;
685  if (toggle) {
686  if (toggleBit == 0) {
687  toggleBit = 1;
688  } else {
689  toggleBit = 0;
690  }
691  }
692  if (toggleBit) {
693  space(RC5_UNIT);
694  mark(RC5_UNIT);
695  } else {
696  mark(RC5_UNIT);
697  space(RC5_UNIT);
698  }
699 
700 // Address
701  for (uint_fast8_t mask = 1UL << (addressBits - 1); mask; mask >>= 1) {
702  if (addr & mask) {
703  space(RC5_UNIT); // 1 is space, then mark
704  mark(RC5_UNIT);
705  } else {
706  mark(RC5_UNIT);
707  space(RC5_UNIT);
708  }
709  }
710 
711 // Command
712  for (uint_fast8_t mask = 1UL << (commandBits - 1); mask; mask >>= 1) {
713  if (cmd & mask) {
714  space(RC5_UNIT); // 1 is space, then mark
715  mark(RC5_UNIT);
716  } else {
717  mark(RC5_UNIT);
718  space(RC5_UNIT);
719  }
720  }
721 }
722 
724 #if defined(LOCAL_DEBUG)
725 #undef LOCAL_DEBUG
726 #endif
727 #endif // _IR_RC5_RC6_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRremoteInt.h:152
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:207
LongUnion
Union to specify parts / manifestations of a 32 bit Long without casts and shifts.
Definition: LongUnion.h:59
RC5_RC6_KHZ
#define RC5_RC6_KHZ
Definition: IRProtocol.h:196
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRremoteInt.h:161
IRsend::aNumberOfRepeats
void int_fast8_t aNumberOfRepeats
Definition: IRremoteInt.h:538
MICROS_IN_ONE_MILLI
#define MICROS_IN_ONE_MILLI
Definition: IRremote.hpp:212
LongUnion::UByte
struct LongUnion::@4 UByte
IRsend::sendRC6Raw
void sendRC6Raw(uint32_t data, uint8_t nbits)
Definition: ir_RC5_RC6.hpp:345
IRsend::mark
void mark(uint16_t aMarkMicros)
Sends an IR mark for the specified number of microseconds.
Definition: IRSend.hpp:1271
IRsend::sendRC6
void sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle=true)
Assemble raw data for RC6 from parameters and toggle state and send We do not wait for the minimal tr...
Definition: ir_RC5_RC6.hpp:411
sLastSendToggleValue
uint8_t sLastSendToggleValue
Definition: ir_RC5_RC6.hpp:44
sBiphaseDecodeRawbuffOffset
uint_fast8_t sBiphaseDecodeRawbuffOffset
Definition: IRReceive.hpp:1129
RC5_UNIT
#define RC5_UNIT
Definition: ir_RC5_RC6.hpp:90
LongUnion::LowByte
uint8_t LowByte
Definition: LongUnion.h:61
RC6_BITS
#define RC6_BITS
Definition: ir_RC5_RC6.hpp:325
LongUnion::HighByte
uint8_t HighByte
Definition: LongUnion.h:64
RC5_REPEAT_DISTANCE
#define RC5_REPEAT_DISTANCE
Definition: ir_RC5_RC6.hpp:96
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send<protocol>Raw functions.
Definition: IRremoteInt.h:155
IRrecv::checkForRepeatSpaceTicksAndSetFlag
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks)
Definition: IRReceive.hpp:1333
IR_DEBUG_PRINT
#define IR_DEBUG_PRINT(...)
If DEBUG, print the arguments, otherwise do nothing.
Definition: IRremoteInt.h:186
LongUnion::LowWord
uint16_t LowWord
Definition: LongUnion.h:80
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1459
IRrecv::getBiphaselevel
uint_fast8_t getBiphaselevel()
Gets the level of one time interval (aBiphaseTimeUnit) at a time from the raw buffer.
Definition: IRReceive.hpp:1156
RC5_ADDRESS_BITS
#define RC5_ADDRESS_BITS
Definition: ir_RC5_RC6.hpp:82
RC6_HEADER_SPACE
#define RC6_HEADER_SPACE
Definition: ir_RC5_RC6.hpp:331
LongUnion::MidLowByte
uint8_t MidLowByte
Definition: LongUnion.h:62
MIN_RC6_MARKS
#define MIN_RC6_MARKS
Definition: ir_RC5_RC6.hpp:334
LongUnion::HighWord
uint16_t HighWord
Definition: LongUnion.h:81
IRsend::sendRC5Marantz
void sendRC5Marantz(uint8_t aAddress, uint8_t aCommand, uint8_t aMarantzExtension, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle=true)
Definition: ir_RC5_RC6.hpp:108
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:409
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:152
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRremoteInt.h:162
IRsend::sendRC5ext
void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle)
Definition: ir_RC5_RC6.hpp:660
RC5_COMMAND_BITS
#define RC5_COMMAND_BITS
Definition: ir_RC5_RC6.hpp:83
RC6_HEADER_MARK
#define RC6_HEADER_MARK
Definition: ir_RC5_RC6.hpp:330
RC5_BITS
#define RC5_BITS
Definition: ir_RC5_RC6.hpp:88
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRremoteInt.h:153
RC6_MAXIMUM_REPEAT_DISTANCE
#define RC6_MAXIMUM_REPEAT_DISTANCE
Definition: ir_RC5_RC6.hpp:337
IRsend::sendBiphaseData
void sendBiphaseData(uint16_t aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits, bool aSendStartBit=true)
Sends Biphase (Manchester) coded data MSB first This function concatenates two marks to one longer ma...
Definition: IRSend.hpp:1193
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1411
RC5_COMMAND_FIELD_BIT
#define RC5_COMMAND_FIELD_BIT
Definition: ir_RC5_RC6.hpp:85
RC5_TOGGLE_BIT
#define RC5_TOGGLE_BIT
Definition: ir_RC5_RC6.hpp:86
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:140
LongUnion::ULong
uint32_t ULong
Definition: LongUnion.h:95
IRrecv::irparams
irparams_struct irparams
Definition: IRremoteInt.h:408
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:155
IRrecv::decodeRC5
bool decodeRC5()
Try to decode data as RC5 protocol.
Definition: ir_RC5_RC6.hpp:214
RC6A
@ RC6A
Definition: IRProtocol.h:113
RC6_REPEAT_DISTANCE
#define RC6_REPEAT_DISTANCE
Definition: ir_RC5_RC6.hpp:336
IRDATA_FLAGS_TOGGLE_BIT
#define IRDATA_FLAGS_TOGGLE_BIT
Is set if RC5 or RC6 toggle bit is set.
Definition: IRProtocol.h:150
RC5
@ RC5
Definition: IRProtocol.h:111
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRremoteInt.h:154
RC6_TOGGLE_BIT_INDEX
#define RC6_TOGGLE_BIT_INDEX
Definition: ir_RC5_RC6.hpp:320
IRsend::space
static void space(uint16_t aSpaceMicros)
Sends an IR space for the specified number of microseconds.
Definition: IRSend.hpp:1482
IRsend::sendRC5
void sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle=true)
Definition: ir_RC5_RC6.hpp:161
RC5_EXTENSION_BITS
#define RC5_EXTENSION_BITS
Definition: ir_RC5_RC6.hpp:84
IRrecv::initBiphaselevel
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit)
Definition: IRReceive.hpp:1134
SPACE
#define SPACE
Definition: IRremoteInt.h:39
IRData::rawlen
IRRawlenType rawlen
Counter of entries in rawbuf of last received frame.
Definition: IRremoteInt.h:170
LongUnion::MidHighByte
uint8_t MidHighByte
Definition: LongUnion.h:63
RC6
@ RC6
Definition: IRProtocol.h:112
LongUnion::UWord
struct LongUnion::@6 UWord
RC6_UNIT
#define RC6_UNIT
Definition: ir_RC5_RC6.hpp:328
IRsend::sendRC6A
void sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aCustomer, bool aEnableAutomaticToggle=true)
Assemble raw data for RC6 from parameters and toggle state and send We do not wait for the minimal tr...
Definition: ir_RC5_RC6.hpp:457
IR_DEBUG_PRINTLN
#define IR_DEBUG_PRINTLN(...)
If DEBUG, print the arguments as a line, otherwise do nothing.
Definition: IRremoteInt.h:190
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRremoteInt.h:151
IRrecv::decodeRC6
bool decodeRC6()
Try to decode data as RC6 protocol.
Definition: ir_RC5_RC6.hpp:506
MARK
#define MARK
Definition: IRremoteInt.h:38
IRsend::aCommand
void aCommand
Definition: IRremoteInt.h:627
RC5_MAXIMUM_REPEAT_DISTANCE
#define RC5_MAXIMUM_REPEAT_DISTANCE
Definition: ir_RC5_RC6.hpp:97
IRsend::enableIROut
void enableIROut(uint_fast8_t aFrequencyKHz)
Enables IR output.
Definition: IRSend.hpp:1522
RC6A_BITS
#define RC6A_BITS
Definition: ir_RC5_RC6.hpp:326