Infrared remote library for Arduino: send and receive infrared signals with multiple protocols Port from Arduino-IRremote https://github.com/z3t0/Arduino-IRremote
Diff: ir_RC5_RC6.cpp
- Revision:
- 0:70c8e56bac45
diff -r 000000000000 -r 70c8e56bac45 ir_RC5_RC6.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ir_RC5_RC6.cpp Sat Jan 23 06:16:48 2016 +0000 @@ -0,0 +1,207 @@ +#include "IRremote.h" +#include "IRremoteInt.h" + +//+============================================================================= +// Gets one undecoded level at a time from the raw buffer. +// The RC5/6 decoding is easier if the data is broken into time intervals. +// E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, +// successive calls to getRClevel will return MARK, MARK, SPACE. +// offset and used are updated to keep track of the current position. +// t1 is the time interval for a single bit in microseconds. +// Returns -1 for error (measured time interval is not a multiple of t1). +// +#if (DECODE_RC5 || DECODE_RC6) +int IRrecv::getRClevel (decode_results *results, int *offset, int *used, int t1) +{ + int width; + int val; + int correction; + int avail; + + if (*offset >= results->rawlen) return SPACE ; // After end of recorded buffer, assume SPACE. + width = results->rawbuf[*offset]; + val = ((*offset) % 2) ? MARK : SPACE; + correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS; + + if (MATCH(width, ( t1) + correction)) avail = 1 ; + else if (MATCH(width, (2*t1) + correction)) avail = 2 ; + else if (MATCH(width, (3*t1) + correction)) avail = 3 ; + else return -1 ; + + (*used)++; + if (*used >= avail) { + *used = 0; + (*offset)++; + } + + DBG_PRINTLN( (val == MARK) ? "MARK" : "SPACE" ); + + return val; +} +#endif + +//============================================================================== +// RRRR CCCC 55555 +// R R C 5 +// RRRR C 5555 +// R R C 5 +// R R CCCC 5555 +// +// NB: First bit must be a one (start bit) +// +#define MIN_RC5_SAMPLES 11 +#define RC5_T1 889 +#define RC5_RPT_LENGTH 46000 + +//+============================================================================= +#if SEND_RC5 +void IRsend::sendRC5 (unsigned long data, int nbits) +{ + // Set IR carrier frequency + enableIROut(36); + + // Start + mark(RC5_T1); + space(RC5_T1); + mark(RC5_T1); + + // Data + for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { + if (data & mask) { + space(RC5_T1); // 1 is space, then mark + mark(RC5_T1); + } else { + mark(RC5_T1); + space(RC5_T1); + } + } + + space(0); // Always end with the LED off +} +#endif + +//+============================================================================= +#if DECODE_RC5 +bool IRrecv::decodeRC5 (decode_results *results) +{ + int nbits; + long data = 0; + int used = 0; + int offset = 1; // Skip gap space + + if (irparams.rawlen < MIN_RC5_SAMPLES + 2) return false ; + + // Get start bits + if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ; + if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return false ; + if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ; + + for (nbits = 0; offset < irparams.rawlen; nbits++) { + int levelA = getRClevel(results, &offset, &used, RC5_T1); + int levelB = getRClevel(results, &offset, &used, RC5_T1); + + if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 1 ; + else if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 0 ; + else return false ; + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = RC5; + return true; +} +#endif + +//+============================================================================= +// RRRR CCCC 6666 +// R R C 6 +// RRRR C 6666 +// R R C 6 6 +// R R CCCC 666 +// +// NB : Caller needs to take care of flipping the toggle bit +// +#define MIN_RC6_SAMPLES 1 +#define RC6_HDR_MARK 2666 +#define RC6_HDR_SPACE 889 +#define RC6_T1 444 +#define RC6_RPT_LENGTH 46000 + +#if SEND_RC6 +void IRsend::sendRC6 (unsigned long data, int nbits) +{ + // Set IR carrier frequency + enableIROut(36); + + // Header + mark(RC6_HDR_MARK); + space(RC6_HDR_SPACE); + + // Start bit + mark(RC6_T1); + space(RC6_T1); + + // Data + for (unsigned long i = 1, mask = 1UL << (nbits - 1); mask; i++, mask >>= 1) { + // The fourth bit we send is a "double width trailer bit" + int t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1) ; + if (data & mask) { + mark(t); + space(t); + } else { + space(t); + mark(t); + } + } + + space(0); // Always end with the LED off +} +#endif + +//+============================================================================= +#if DECODE_RC6 +bool IRrecv::decodeRC6 (decode_results *results) +{ + int nbits; + long data = 0; + int used = 0; + int offset = 1; // Skip first space + + if (results->rawlen < MIN_RC6_SAMPLES) return false ; + + // Initial mark + if (!MATCH_MARK(results->rawbuf[offset++], RC6_HDR_MARK)) return false ; + if (!MATCH_SPACE(results->rawbuf[offset++], RC6_HDR_SPACE)) return false ; + + // Get start bit (1) + if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return false ; + if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return false ; + + for (nbits = 0; offset < results->rawlen; nbits++) { + int levelA, levelB; // Next two levels + + levelA = getRClevel(results, &offset, &used, RC6_T1); + if (nbits == 3) { + // T bit is double wide; make sure second half matches + if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return false; + } + + levelB = getRClevel(results, &offset, &used, RC6_T1); + if (nbits == 3) { + // T bit is double wide; make sure second half matches + if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return false; + } + + if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 1 ; // inverted compared to RC5 + else if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 0 ; // ... + else return false ; // Error + } + + // Success + results->bits = nbits; + results->value = data; + results->decode_type = RC6; + return true; +} +#endif