32 #ifndef _IR_RC5_RC6_HPP
33 #define _IR_RC5_RC6_HPP
92 #define RC5_ADDRESS_BITS 5
93 #define RC5_COMMAND_BITS 6
94 #define RC5_COMMAND_FIELD_BIT 1
95 #define RC5_TOGGLE_BIT 1
97 #define RC5_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS) // 13
99 #define RC5_UNIT 889 // 32 periods of 36 kHz (888.8888)
101 #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
103 #define RC5_DURATION (26 * RC5_UNIT) // 23114
104 #define RC5_REPEAT_PERIOD (128L * RC5_UNIT) // 113792
105 #define RC5_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - RC5_DURATION) // 90 ms
106 #define RC5_MAXIMUM_REPEAT_DISTANCE (RC5_REPEAT_DISTANCE + (RC5_REPEAT_DISTANCE / 4)) // Just a guess
108 #define MARANTZ_COMMAND_EXTENSION_BITS 6
109 #define MARANTZ_BITS (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS + RC5_COMMAND_BITS + MARANTZ_COMMAND_EXTENSION_BITS) // 19
110 #define MARANTZ_PAUSE_BIT_INDEX (RC5_COMMAND_FIELD_BIT + RC5_TOGGLE_BIT + RC5_ADDRESS_BITS) // 7
111 #define MARANTZ_PAUSE_DURATION (4 * RC5_UNIT) // 3556
113 #define MARANTZ_DURATION (42L * RC5_UNIT) // RC5 + 6 Extension bits + 4 pause units = 37338
114 #define MARANTZ_REPEAT_DISTANCE (RC5_REPEAT_PERIOD - MARANTZ_DURATION) // 100 ms
131 bool aEnableAutomaticToggle) {
136 uint16_t tIRData = (aAddress & 0x1F);
153 tIRExtData |= (aMarantzExtension & 0x3F);
155 if (aEnableAutomaticToggle) {
166 while (tNumberOfCommands > 0) {
177 if (tNumberOfCommands > 0) {
189 void IRsend::sendRC5(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats,
bool aEnableAutomaticToggle) {
209 if (aEnableAutomaticToggle) {
220 while (tNumberOfCommands > 0) {
227 if (tNumberOfCommands > 0) {
234 #if defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6)
235 void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) {
236 irparams.RawbuffOffsetForNextBiphaseLevel = aRCDecodeRawbuffOffset;
237 irparams.BiphaseTimeUnit = aBiphaseTimeUnit;
238 irparams.AlreadyUsedTimingIntervalsOfCurrentInterval = 0;
244 uint8_t IRrecv::getNumberOfUnitsInInterval(uint16_t aCurrentInterval, uint16_t aTimeUnit) {
245 return (aCurrentInterval + (aTimeUnit / 2)) / aTimeUnit;
265 uint_fast8_t IRrecv::getBiphaselevel() {
266 uint_fast8_t tLevelOfCurrentInterval;
272 tLevelOfCurrentInterval = (
irparams.RawbuffOffsetForNextBiphaseLevel) & 1;
278 if (
irparams.AlreadyUsedTimingIntervalsOfCurrentInterval == 0) {
281 irparams.NumberOfTimingIntervalsInCurrentInterval = getNumberOfUnitsInInterval(
282 tCurrentIntervalWithMicros + tMarkExcessCorrectionMicros,
irparams.BiphaseTimeUnit);
286 TRACE_PRINT(tCurrentIntervalWithMicros + tMarkExcessCorrectionMicros);
290 if (
irparams.NumberOfTimingIntervalsInCurrentInterval == 0) {
295 irparams.AlreadyUsedTimingIntervalsOfCurrentInterval++;
297 if (
irparams.AlreadyUsedTimingIntervalsOfCurrentInterval >=
irparams.NumberOfTimingIntervalsInCurrentInterval) {
301 irparams.AlreadyUsedTimingIntervalsOfCurrentInterval = 0;
302 irparams.RawbuffOffsetForNextBiphaseLevel++;
306 return tLevelOfCurrentInterval;
308 # endif // defined(DECODE_RC5) || defined(DECODE_MARANTZ) || defined(DECODE_RC6)
310 #if defined(DECODE_RC5) || defined(DECODE_MARANTZ)
326 bool IRrecv::decodeRC5() {
328 uint32_t tDecodedRawData = 0;
349 if (getBiphaselevel() !=
MARK) {
350 DEBUG_PRINTLN(F(
"RC5: first getBiphaselevel() is not MARK"));
357 #if defined(DECODE_MARANTZ)
358 bool RC5Marantz =
false;
362 uint8_t tStartLevel = getBiphaselevel();
363 uint8_t tEndLevel = getBiphaselevel();
365 if ((tStartLevel ==
SPACE) && (tEndLevel ==
MARK)) {
367 tDecodedRawData = (tDecodedRawData << 1) | 1;
368 }
else if ((tStartLevel ==
MARK) && (tEndLevel ==
SPACE)) {
370 tDecodedRawData = (tDecodedRawData << 1) | 0;
371 #if defined(DECODE_MARANTZ)
389 irparams.AlreadyUsedTimingIntervalsOfCurrentInterval += 2;
390 if (
irparams.AlreadyUsedTimingIntervalsOfCurrentInterval >=
irparams.NumberOfTimingIntervalsInCurrentInterval){
391 irparams.RawbuffOffsetForNextBiphaseLevel++;
396 DEBUG_PRINT(F(
"RC5: no transition found, decode failed, BitIndex="));
405 tValue.
ULong = tDecodedRawData;
408 #if defined(DECODE_MARANTZ)
446 #if defined(DECODE_MARANTZ)
454 #endif // defined(DECODE_RC5) || defined(DECODE_MARANTZ)
493 #define MIN_RC6_SAMPLES 1
495 #define RC6_RPT_LENGTH 46000
497 #define RC6_LEADING_BIT 1
498 #define RC6_MODE_BITS 3 // never seen others than all 0 for Philips TV
499 #define RC6_TOGGLE_BIT 1 // toggles at every key press. Can be used to distinguish repeats from 2 key presses and has another timing :-(.
500 #define RC6_TOGGLE_BIT_INDEX RC6_MODE_BITS // fourth position, index = 3
501 #define RC6_ADDRESS_BITS 8
502 #define RC6_COMMAND_BITS 8
503 #define RC6_CUSTOMER_BITS 14
505 #define RC6_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 21
506 #define RC6A_BITS (RC6_LEADING_BIT + RC6_MODE_BITS + RC6_TOGGLE_BIT + 1 + RC6_CUSTOMER_BITS + RC6_ADDRESS_BITS + RC6_COMMAND_BITS) // 36
508 #define RC6_UNIT 444 // 16 periods of 36 kHz (444.4444)
510 #define RC6_HEADER_MARK (6 * RC6_UNIT) // 2666
511 #define RC6_HEADER_SPACE (2 * RC6_UNIT) // 889
513 #define RC6_TRAILING_SPACE (6 * RC6_UNIT) // 2666
514 #define MIN_RC6_MARKS 4 + ((RC6_ADDRESS_BITS + RC6_COMMAND_BITS) / 2) // 12, 4 are for preamble
516 #define RC6_REPEAT_DISTANCE 107000 // just a guess but > 2.666ms
517 #define RC6_MAXIMUM_REPEAT_DISTANCE (RC6_REPEAT_DISTANCE + (RC6_REPEAT_DISTANCE / 4)) // Just a guess
538 uint32_t mask = 1UL << (aNumberOfBitsToSend - 1);
539 for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
542 if (aRawData & mask) {
572 uint64_t mask = 1ULL << (aNumberOfBitsToSend - 1);
573 for (uint_fast8_t i = 1; mask; i++, mask >>= 1) {
576 if (aRawData & mask) {
591 void IRsend::sendRC6(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats,
bool aEnableAutomaticToggle) {
598 if (aEnableAutomaticToggle) {
614 while (tNumberOfCommands > 0) {
621 if (tNumberOfCommands > 0) {
633 void IRsend::sendRC6A(uint8_t aAddress, uint8_t aCommand, int_fast8_t aNumberOfRepeats, uint16_t aCustomer,
634 bool aEnableAutomaticToggle) {
642 if (aEnableAutomaticToggle) {
653 uint64_t tRawData = tIRRawData.
ULong + 0x0600000000;
661 while (tNumberOfCommands > 0) {
668 if (tNumberOfCommands > 0) {
675 #if defined(DECODE_RC6)
692 bool IRrecv::decodeRC6() {
694 uint32_t tDecodedRawData = 0;
707 DEBUG_PRINTLN(F(
"RC6: Header mark or space length is wrong"));
715 if (getBiphaselevel() !=
MARK) {
716 DEBUG_PRINTLN(F(
"RC6: first getBiphaselevel() is not MARK"));
720 if (getBiphaselevel() !=
SPACE) {
721 DEBUG_PRINTLN(F(
"RC6: second getBiphaselevel() is not SPACE"));
729 tStartLevel = getBiphaselevel();
730 tEndLevel = getBiphaselevel();
736 if (tStartLevel != tEndLevel) {
737 DEBUG_PRINTLN(F(
"RC6: Toggle mark or space length is wrong"));
740 tEndLevel = getBiphaselevel();
741 if (tEndLevel != getBiphaselevel()) {
742 DEBUG_PRINTLN(F(
"RC6: Toggle mark or space length is wrong"));
750 if ((tStartLevel ==
MARK) && (tEndLevel ==
SPACE)) {
752 tDecodedRawData = (tDecodedRawData << 1) | 1;
753 }
else if ((tStartLevel ==
SPACE) && (tEndLevel ==
MARK)) {
755 tDecodedRawData = (tDecodedRawData << 1) | 0;
767 tValue.
ULong = tDecodedRawData;
770 if (tBitIndex < 35) {
779 if (tBitIndex > 20) {
801 #endif // #if defined(DECODE_RC6)
820 for (uint32_t mask = 1UL << (nbits - 1); mask; mask >>= 1) {
838 uint8_t addressBits = 5;
839 uint8_t commandBits = 7;
846 uint8_t cmdBit6 = (1UL << (commandBits - 1)) & cmd;
858 static int toggleBit = 1;
860 if (toggleBit == 0) {
875 for (uint_fast8_t mask = 1UL << (addressBits - 1); mask; mask >>= 1) {
886 for (uint_fast8_t mask = 1UL << (commandBits - 1); mask; mask >>= 1) {
900 #endif // _IR_RC5_RC6_HPP