Infrared remote library for Arduino: send and receive infrared signals with multiple protocols Port from Arduino-IRremote https://github.com/z3t0/Arduino-IRremote
ir_RC5_RC6.cpp@8:629ef37f2853, 2019-09-25 (annotated)
- Committer:
- JRM1986
- Date:
- Wed Sep 25 13:20:19 2019 +0000
- Revision:
- 8:629ef37f2853
- Parent:
- 0:70c8e56bac45
Remote Control Decoded - recieving codes from module;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
yuhki50 | 0:70c8e56bac45 | 1 | #include "IRremote.h" |
yuhki50 | 0:70c8e56bac45 | 2 | #include "IRremoteInt.h" |
yuhki50 | 0:70c8e56bac45 | 3 | |
yuhki50 | 0:70c8e56bac45 | 4 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 5 | // Gets one undecoded level at a time from the raw buffer. |
yuhki50 | 0:70c8e56bac45 | 6 | // The RC5/6 decoding is easier if the data is broken into time intervals. |
yuhki50 | 0:70c8e56bac45 | 7 | // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1, |
yuhki50 | 0:70c8e56bac45 | 8 | // successive calls to getRClevel will return MARK, MARK, SPACE. |
yuhki50 | 0:70c8e56bac45 | 9 | // offset and used are updated to keep track of the current position. |
yuhki50 | 0:70c8e56bac45 | 10 | // t1 is the time interval for a single bit in microseconds. |
yuhki50 | 0:70c8e56bac45 | 11 | // Returns -1 for error (measured time interval is not a multiple of t1). |
yuhki50 | 0:70c8e56bac45 | 12 | // |
yuhki50 | 0:70c8e56bac45 | 13 | #if (DECODE_RC5 || DECODE_RC6) |
yuhki50 | 0:70c8e56bac45 | 14 | int IRrecv::getRClevel (decode_results *results, int *offset, int *used, int t1) |
yuhki50 | 0:70c8e56bac45 | 15 | { |
yuhki50 | 0:70c8e56bac45 | 16 | int width; |
yuhki50 | 0:70c8e56bac45 | 17 | int val; |
yuhki50 | 0:70c8e56bac45 | 18 | int correction; |
yuhki50 | 0:70c8e56bac45 | 19 | int avail; |
yuhki50 | 0:70c8e56bac45 | 20 | |
yuhki50 | 0:70c8e56bac45 | 21 | if (*offset >= results->rawlen) return SPACE ; // After end of recorded buffer, assume SPACE. |
yuhki50 | 0:70c8e56bac45 | 22 | width = results->rawbuf[*offset]; |
yuhki50 | 0:70c8e56bac45 | 23 | val = ((*offset) % 2) ? MARK : SPACE; |
yuhki50 | 0:70c8e56bac45 | 24 | correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS; |
yuhki50 | 0:70c8e56bac45 | 25 | |
yuhki50 | 0:70c8e56bac45 | 26 | if (MATCH(width, ( t1) + correction)) avail = 1 ; |
yuhki50 | 0:70c8e56bac45 | 27 | else if (MATCH(width, (2*t1) + correction)) avail = 2 ; |
yuhki50 | 0:70c8e56bac45 | 28 | else if (MATCH(width, (3*t1) + correction)) avail = 3 ; |
yuhki50 | 0:70c8e56bac45 | 29 | else return -1 ; |
yuhki50 | 0:70c8e56bac45 | 30 | |
yuhki50 | 0:70c8e56bac45 | 31 | (*used)++; |
yuhki50 | 0:70c8e56bac45 | 32 | if (*used >= avail) { |
yuhki50 | 0:70c8e56bac45 | 33 | *used = 0; |
yuhki50 | 0:70c8e56bac45 | 34 | (*offset)++; |
yuhki50 | 0:70c8e56bac45 | 35 | } |
yuhki50 | 0:70c8e56bac45 | 36 | |
yuhki50 | 0:70c8e56bac45 | 37 | DBG_PRINTLN( (val == MARK) ? "MARK" : "SPACE" ); |
yuhki50 | 0:70c8e56bac45 | 38 | |
yuhki50 | 0:70c8e56bac45 | 39 | return val; |
yuhki50 | 0:70c8e56bac45 | 40 | } |
yuhki50 | 0:70c8e56bac45 | 41 | #endif |
yuhki50 | 0:70c8e56bac45 | 42 | |
yuhki50 | 0:70c8e56bac45 | 43 | //============================================================================== |
yuhki50 | 0:70c8e56bac45 | 44 | // RRRR CCCC 55555 |
yuhki50 | 0:70c8e56bac45 | 45 | // R R C 5 |
yuhki50 | 0:70c8e56bac45 | 46 | // RRRR C 5555 |
yuhki50 | 0:70c8e56bac45 | 47 | // R R C 5 |
yuhki50 | 0:70c8e56bac45 | 48 | // R R CCCC 5555 |
yuhki50 | 0:70c8e56bac45 | 49 | // |
yuhki50 | 0:70c8e56bac45 | 50 | // NB: First bit must be a one (start bit) |
yuhki50 | 0:70c8e56bac45 | 51 | // |
yuhki50 | 0:70c8e56bac45 | 52 | #define MIN_RC5_SAMPLES 11 |
yuhki50 | 0:70c8e56bac45 | 53 | #define RC5_T1 889 |
yuhki50 | 0:70c8e56bac45 | 54 | #define RC5_RPT_LENGTH 46000 |
yuhki50 | 0:70c8e56bac45 | 55 | |
yuhki50 | 0:70c8e56bac45 | 56 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 57 | #if SEND_RC5 |
yuhki50 | 0:70c8e56bac45 | 58 | void IRsend::sendRC5 (unsigned long data, int nbits) |
yuhki50 | 0:70c8e56bac45 | 59 | { |
yuhki50 | 0:70c8e56bac45 | 60 | // Set IR carrier frequency |
yuhki50 | 0:70c8e56bac45 | 61 | enableIROut(36); |
yuhki50 | 0:70c8e56bac45 | 62 | |
yuhki50 | 0:70c8e56bac45 | 63 | // Start |
yuhki50 | 0:70c8e56bac45 | 64 | mark(RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 65 | space(RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 66 | mark(RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 67 | |
yuhki50 | 0:70c8e56bac45 | 68 | // Data |
yuhki50 | 0:70c8e56bac45 | 69 | for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) { |
yuhki50 | 0:70c8e56bac45 | 70 | if (data & mask) { |
yuhki50 | 0:70c8e56bac45 | 71 | space(RC5_T1); // 1 is space, then mark |
yuhki50 | 0:70c8e56bac45 | 72 | mark(RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 73 | } else { |
yuhki50 | 0:70c8e56bac45 | 74 | mark(RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 75 | space(RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 76 | } |
yuhki50 | 0:70c8e56bac45 | 77 | } |
yuhki50 | 0:70c8e56bac45 | 78 | |
yuhki50 | 0:70c8e56bac45 | 79 | space(0); // Always end with the LED off |
yuhki50 | 0:70c8e56bac45 | 80 | } |
yuhki50 | 0:70c8e56bac45 | 81 | #endif |
yuhki50 | 0:70c8e56bac45 | 82 | |
yuhki50 | 0:70c8e56bac45 | 83 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 84 | #if DECODE_RC5 |
yuhki50 | 0:70c8e56bac45 | 85 | bool IRrecv::decodeRC5 (decode_results *results) |
yuhki50 | 0:70c8e56bac45 | 86 | { |
yuhki50 | 0:70c8e56bac45 | 87 | int nbits; |
yuhki50 | 0:70c8e56bac45 | 88 | long data = 0; |
yuhki50 | 0:70c8e56bac45 | 89 | int used = 0; |
yuhki50 | 0:70c8e56bac45 | 90 | int offset = 1; // Skip gap space |
yuhki50 | 0:70c8e56bac45 | 91 | |
yuhki50 | 0:70c8e56bac45 | 92 | if (irparams.rawlen < MIN_RC5_SAMPLES + 2) return false ; |
yuhki50 | 0:70c8e56bac45 | 93 | |
yuhki50 | 0:70c8e56bac45 | 94 | // Get start bits |
yuhki50 | 0:70c8e56bac45 | 95 | if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ; |
yuhki50 | 0:70c8e56bac45 | 96 | if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return false ; |
yuhki50 | 0:70c8e56bac45 | 97 | if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ; |
yuhki50 | 0:70c8e56bac45 | 98 | |
yuhki50 | 0:70c8e56bac45 | 99 | for (nbits = 0; offset < irparams.rawlen; nbits++) { |
yuhki50 | 0:70c8e56bac45 | 100 | int levelA = getRClevel(results, &offset, &used, RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 101 | int levelB = getRClevel(results, &offset, &used, RC5_T1); |
yuhki50 | 0:70c8e56bac45 | 102 | |
yuhki50 | 0:70c8e56bac45 | 103 | if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 1 ; |
yuhki50 | 0:70c8e56bac45 | 104 | else if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 0 ; |
yuhki50 | 0:70c8e56bac45 | 105 | else return false ; |
yuhki50 | 0:70c8e56bac45 | 106 | } |
yuhki50 | 0:70c8e56bac45 | 107 | |
yuhki50 | 0:70c8e56bac45 | 108 | // Success |
yuhki50 | 0:70c8e56bac45 | 109 | results->bits = nbits; |
yuhki50 | 0:70c8e56bac45 | 110 | results->value = data; |
yuhki50 | 0:70c8e56bac45 | 111 | results->decode_type = RC5; |
yuhki50 | 0:70c8e56bac45 | 112 | return true; |
yuhki50 | 0:70c8e56bac45 | 113 | } |
yuhki50 | 0:70c8e56bac45 | 114 | #endif |
yuhki50 | 0:70c8e56bac45 | 115 | |
yuhki50 | 0:70c8e56bac45 | 116 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 117 | // RRRR CCCC 6666 |
yuhki50 | 0:70c8e56bac45 | 118 | // R R C 6 |
yuhki50 | 0:70c8e56bac45 | 119 | // RRRR C 6666 |
yuhki50 | 0:70c8e56bac45 | 120 | // R R C 6 6 |
yuhki50 | 0:70c8e56bac45 | 121 | // R R CCCC 666 |
yuhki50 | 0:70c8e56bac45 | 122 | // |
yuhki50 | 0:70c8e56bac45 | 123 | // NB : Caller needs to take care of flipping the toggle bit |
yuhki50 | 0:70c8e56bac45 | 124 | // |
yuhki50 | 0:70c8e56bac45 | 125 | #define MIN_RC6_SAMPLES 1 |
yuhki50 | 0:70c8e56bac45 | 126 | #define RC6_HDR_MARK 2666 |
yuhki50 | 0:70c8e56bac45 | 127 | #define RC6_HDR_SPACE 889 |
yuhki50 | 0:70c8e56bac45 | 128 | #define RC6_T1 444 |
yuhki50 | 0:70c8e56bac45 | 129 | #define RC6_RPT_LENGTH 46000 |
yuhki50 | 0:70c8e56bac45 | 130 | |
yuhki50 | 0:70c8e56bac45 | 131 | #if SEND_RC6 |
yuhki50 | 0:70c8e56bac45 | 132 | void IRsend::sendRC6 (unsigned long data, int nbits) |
yuhki50 | 0:70c8e56bac45 | 133 | { |
yuhki50 | 0:70c8e56bac45 | 134 | // Set IR carrier frequency |
yuhki50 | 0:70c8e56bac45 | 135 | enableIROut(36); |
yuhki50 | 0:70c8e56bac45 | 136 | |
yuhki50 | 0:70c8e56bac45 | 137 | // Header |
yuhki50 | 0:70c8e56bac45 | 138 | mark(RC6_HDR_MARK); |
yuhki50 | 0:70c8e56bac45 | 139 | space(RC6_HDR_SPACE); |
yuhki50 | 0:70c8e56bac45 | 140 | |
yuhki50 | 0:70c8e56bac45 | 141 | // Start bit |
yuhki50 | 0:70c8e56bac45 | 142 | mark(RC6_T1); |
yuhki50 | 0:70c8e56bac45 | 143 | space(RC6_T1); |
yuhki50 | 0:70c8e56bac45 | 144 | |
yuhki50 | 0:70c8e56bac45 | 145 | // Data |
yuhki50 | 0:70c8e56bac45 | 146 | for (unsigned long i = 1, mask = 1UL << (nbits - 1); mask; i++, mask >>= 1) { |
yuhki50 | 0:70c8e56bac45 | 147 | // The fourth bit we send is a "double width trailer bit" |
yuhki50 | 0:70c8e56bac45 | 148 | int t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1) ; |
yuhki50 | 0:70c8e56bac45 | 149 | if (data & mask) { |
yuhki50 | 0:70c8e56bac45 | 150 | mark(t); |
yuhki50 | 0:70c8e56bac45 | 151 | space(t); |
yuhki50 | 0:70c8e56bac45 | 152 | } else { |
yuhki50 | 0:70c8e56bac45 | 153 | space(t); |
yuhki50 | 0:70c8e56bac45 | 154 | mark(t); |
yuhki50 | 0:70c8e56bac45 | 155 | } |
yuhki50 | 0:70c8e56bac45 | 156 | } |
yuhki50 | 0:70c8e56bac45 | 157 | |
yuhki50 | 0:70c8e56bac45 | 158 | space(0); // Always end with the LED off |
yuhki50 | 0:70c8e56bac45 | 159 | } |
yuhki50 | 0:70c8e56bac45 | 160 | #endif |
yuhki50 | 0:70c8e56bac45 | 161 | |
yuhki50 | 0:70c8e56bac45 | 162 | //+============================================================================= |
yuhki50 | 0:70c8e56bac45 | 163 | #if DECODE_RC6 |
yuhki50 | 0:70c8e56bac45 | 164 | bool IRrecv::decodeRC6 (decode_results *results) |
yuhki50 | 0:70c8e56bac45 | 165 | { |
yuhki50 | 0:70c8e56bac45 | 166 | int nbits; |
yuhki50 | 0:70c8e56bac45 | 167 | long data = 0; |
yuhki50 | 0:70c8e56bac45 | 168 | int used = 0; |
yuhki50 | 0:70c8e56bac45 | 169 | int offset = 1; // Skip first space |
yuhki50 | 0:70c8e56bac45 | 170 | |
yuhki50 | 0:70c8e56bac45 | 171 | if (results->rawlen < MIN_RC6_SAMPLES) return false ; |
yuhki50 | 0:70c8e56bac45 | 172 | |
yuhki50 | 0:70c8e56bac45 | 173 | // Initial mark |
yuhki50 | 0:70c8e56bac45 | 174 | if (!MATCH_MARK(results->rawbuf[offset++], RC6_HDR_MARK)) return false ; |
yuhki50 | 0:70c8e56bac45 | 175 | if (!MATCH_SPACE(results->rawbuf[offset++], RC6_HDR_SPACE)) return false ; |
yuhki50 | 0:70c8e56bac45 | 176 | |
yuhki50 | 0:70c8e56bac45 | 177 | // Get start bit (1) |
yuhki50 | 0:70c8e56bac45 | 178 | if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return false ; |
yuhki50 | 0:70c8e56bac45 | 179 | if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return false ; |
yuhki50 | 0:70c8e56bac45 | 180 | |
yuhki50 | 0:70c8e56bac45 | 181 | for (nbits = 0; offset < results->rawlen; nbits++) { |
yuhki50 | 0:70c8e56bac45 | 182 | int levelA, levelB; // Next two levels |
yuhki50 | 0:70c8e56bac45 | 183 | |
yuhki50 | 0:70c8e56bac45 | 184 | levelA = getRClevel(results, &offset, &used, RC6_T1); |
yuhki50 | 0:70c8e56bac45 | 185 | if (nbits == 3) { |
yuhki50 | 0:70c8e56bac45 | 186 | // T bit is double wide; make sure second half matches |
yuhki50 | 0:70c8e56bac45 | 187 | if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return false; |
yuhki50 | 0:70c8e56bac45 | 188 | } |
yuhki50 | 0:70c8e56bac45 | 189 | |
yuhki50 | 0:70c8e56bac45 | 190 | levelB = getRClevel(results, &offset, &used, RC6_T1); |
yuhki50 | 0:70c8e56bac45 | 191 | if (nbits == 3) { |
yuhki50 | 0:70c8e56bac45 | 192 | // T bit is double wide; make sure second half matches |
yuhki50 | 0:70c8e56bac45 | 193 | if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return false; |
yuhki50 | 0:70c8e56bac45 | 194 | } |
yuhki50 | 0:70c8e56bac45 | 195 | |
yuhki50 | 0:70c8e56bac45 | 196 | if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 1 ; // inverted compared to RC5 |
yuhki50 | 0:70c8e56bac45 | 197 | else if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 0 ; // ... |
yuhki50 | 0:70c8e56bac45 | 198 | else return false ; // Error |
yuhki50 | 0:70c8e56bac45 | 199 | } |
yuhki50 | 0:70c8e56bac45 | 200 | |
yuhki50 | 0:70c8e56bac45 | 201 | // Success |
yuhki50 | 0:70c8e56bac45 | 202 | results->bits = nbits; |
yuhki50 | 0:70c8e56bac45 | 203 | results->value = data; |
yuhki50 | 0:70c8e56bac45 | 204 | results->decode_type = RC6; |
yuhki50 | 0:70c8e56bac45 | 205 | return true; |
yuhki50 | 0:70c8e56bac45 | 206 | } |
yuhki50 | 0:70c8e56bac45 | 207 | #endif |