IRremote
ir_RC5_RC6.cpp
Go to the documentation of this file.
1 #include "IRremote.h"
2 
3 //+=============================================================================
4 // Gets one undecoded level at a time from the raw buffer.
5 // The RC5/6 decoding is easier if the data is broken into time intervals.
6 // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
7 // successive calls to getRClevel will return MARK, MARK, SPACE.
8 // offset and used are updated to keep track of the current position.
9 // t1 is the time interval for a single bit in microseconds.
10 // Returns -1 for error (measured time interval is not a multiple of t1).
11 //
12 #if (DECODE_RC5 || DECODE_RC6)
13 int IRrecv::getRClevel(decode_results *results, unsigned int *offset, int *used, int t1) {
14  int width;
15  int val;
16  int correction;
17  int avail;
18 
19  if (*offset >= results->rawlen) {
20  return SPACE; // After end of recorded buffer, assume SPACE.
21  }
22  width = results->rawbuf[*offset];
23  val = ((*offset) % 2) ? MARK : SPACE;
24  correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
25 
26  if (MATCH(width, (t1) + correction)) {
27  avail = 1;
28  } else if (MATCH(width, (2 * t1) + correction)) {
29  avail = 2;
30  } else if (MATCH(width, (3 * t1) + correction)) {
31  avail = 3;
32  } else {
33  return -1;
34  }
35 
36  (*used)++;
37  if (*used >= avail) {
38  *used = 0;
39  (*offset)++;
40  }
41 
42  DBG_PRINTLN((val == MARK) ? "MARK" : "SPACE");
43 
44  return val;
45 }
46 #endif
47 
48 //==============================================================================
49 // RRRR CCCC 55555
50 // R R C 5
51 // RRRR C 5555
52 // R R C 5
53 // R R CCCC 5555
54 //
55 // NB: First bit must be a one (start bit)
56 //
57 #define MIN_RC5_SAMPLES 11
58 #define RC5_T1 889
59 #define RC5_RPT_LENGTH 46000
60 
61 //+=============================================================================
62 #if SEND_RC5
63 void IRsend::sendRC5(unsigned long data, int nbits) {
64  // Set IR carrier frequency
65  enableIROut(36);
66 
67  // Start
68  mark(RC5_T1);
69  space(RC5_T1);
70  mark(RC5_T1);
71 
72  // Data
73  for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) {
74  if (data & mask) {
75  space(RC5_T1); // 1 is space, then mark
76  mark(RC5_T1);
77  } else {
78  mark(RC5_T1);
79  space(RC5_T1);
80  }
81  }
82 
83  space(0); // Always end with the LED off
84 }
85 
86 void IRsend::sendRC5ext(unsigned long addr, unsigned long cmd, boolean toggle) {
87  // Set IR carrier frequency
88  enableIROut(36);
89 
90  unsigned long addressBits = 5;
91  unsigned long commandBits = 7;
92 // unsigned long nbits = addressBits + commandBits;
93 
94  // Start
95  mark(RC5_T1);
96 
97  // Bit #6 of the command part, but inverted!
98  unsigned long cmdBit6 = (1UL << (commandBits - 1)) & cmd;
99  if (cmdBit6) {
100  // Inverted (1 -> 0 = mark-to-space)
101  mark(RC5_T1);
102  space(RC5_T1);
103  } else {
104  space(RC5_T1);
105  mark(RC5_T1);
106  }
107  commandBits--;
108 
109  // Toggle bit
110  static int toggleBit = 1;
111  if (toggle) {
112  if (toggleBit == 0) {
113  toggleBit = 1;
114  } else {
115  toggleBit = 0;
116  }
117  }
118  if (toggleBit) {
119  space(RC5_T1);
120  mark(RC5_T1);
121  } else {
122  mark(RC5_T1);
123  space(RC5_T1);
124  }
125 
126  // Address
127  for (unsigned long mask = 1UL << (addressBits - 1); mask; mask >>= 1) {
128  if (addr & mask) {
129  space(RC5_T1); // 1 is space, then mark
130  mark(RC5_T1);
131  } else {
132  mark(RC5_T1);
133  space(RC5_T1);
134  }
135  }
136 
137  // Command
138  for (unsigned long mask = 1UL << (commandBits - 1); mask; mask >>= 1) {
139  if (cmd & mask) {
140  space(RC5_T1); // 1 is space, then mark
141  mark(RC5_T1);
142  } else {
143  mark(RC5_T1);
144  space(RC5_T1);
145  }
146  }
147 
148  space(0); // Always end with the LED off
149 }
150 
151 #endif
152 
153 //+=============================================================================
154 #if DECODE_RC5
155 bool IRrecv::decodeRC5(decode_results *results) {
156  int nbits;
157  long data = 0;
158  int used = 0;
159  unsigned int offset = 1; // Skip gap space
160 
161  if (irparams.rawlen < MIN_RC5_SAMPLES + 2) {
162  return false;
163  }
164 
165  // Get start bits
166  if (getRClevel(results, &offset, &used, RC5_T1) != MARK) {
167  return false;
168  }
169  if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) {
170  return false;
171  }
172  if (getRClevel(results, &offset, &used, RC5_T1) != MARK) {
173  return false;
174  }
175 
176  for (nbits = 0; offset < irparams.rawlen; nbits++) {
177  int levelA = getRClevel(results, &offset, &used, RC5_T1);
178  int levelB = getRClevel(results, &offset, &used, RC5_T1);
179 
180  if ((levelA == SPACE) && (levelB == MARK)) {
181  data = (data << 1) | 1;
182  } else if ((levelA == MARK) && (levelB == SPACE)) {
183  data = (data << 1) | 0;
184  } else {
185  return false;
186  }
187  }
188 
189  // Success
190  results->bits = nbits;
191  results->value = data;
192  results->decode_type = RC5;
193  return true;
194 }
195 #endif
196 
197 //+=============================================================================
198 // RRRR CCCC 6666
199 // R R C 6
200 // RRRR C 6666
201 // R R C 6 6
202 // R R CCCC 666
203 //
204 // NB : Caller needs to take care of flipping the toggle bit
205 //
206 #define MIN_RC6_SAMPLES 1
207 #define RC6_HDR_MARK 2666
208 #define RC6_HDR_SPACE 889
209 #define RC6_T1 444
210 #define RC6_RPT_LENGTH 46000
211 
212 #if SEND_RC6
213 void IRsend::sendRC6(unsigned long data, int nbits) {
214  // Set IR carrier frequency
215  enableIROut(36);
216 
217  // Header
220 
221  // Start bit
222  mark(RC6_T1);
223  space(RC6_T1);
224 
225  // Data
226  for (unsigned long i = 1, mask = 1UL << (nbits - 1); mask; i++, mask >>= 1) {
227  // The fourth bit we send is a "double width trailer bit"
228  int t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1);
229  if (data & mask) {
230  mark(t);
231  space(t);
232  } else {
233  space(t);
234  mark(t);
235  }
236  }
237 
238  space(0); // Always end with the LED off
239 }
240 #endif
241 
242 //+=============================================================================
243 #if DECODE_RC6
244 bool IRrecv::decodeRC6(decode_results *results) {
245  int nbits;
246  long data = 0;
247  int used = 0;
248  unsigned int offset = 1; // Skip first space
249 
250  if (results->rawlen < MIN_RC6_SAMPLES) {
251  return false;
252  }
253 
254 // Initial mark
255  if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) {
256  return false;
257  }
258  offset++;
259 
260  if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) {
261  return false;
262  }
263  offset++;
264 
265 // Get start bit (1)
266  if (getRClevel(results, &offset, &used, RC6_T1) != MARK) {
267  return false;
268  }
269  if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) {
270  return false;
271  }
272 
273  for (nbits = 0; offset < results->rawlen; nbits++) {
274  int levelA, levelB; // Next two levels
275 
276  levelA = getRClevel(results, &offset, &used, RC6_T1);
277  if (nbits == 3) {
278  // T bit is double wide; make sure second half matches
279  if (levelA != getRClevel(results, &offset, &used, RC6_T1)) {
280  return false;
281  }
282  }
283 
284  levelB = getRClevel(results, &offset, &used, RC6_T1);
285  if (nbits == 3) {
286  // T bit is double wide; make sure second half matches
287  if (levelB != getRClevel(results, &offset, &used, RC6_T1)) {
288  return false;
289  }
290  }
291 
292  if ((levelA == MARK) && (levelB == SPACE)) {
293  data = (data << 1) | 1; // inverted compared to RC5
294  } else if ((levelA == SPACE) && (levelB == MARK)) {
295  data = (data << 1) | 0;
296  } else {
297  return false; // Error
298  }
299  }
300 
301  // Success
302  results->bits = nbits;
303  results->value = data;
304  results->decode_type = RC6;
305  return true;
306 }
307 #endif
RC5
@ RC5
Definition: IRremote.h:115
decode_results
Results returned from the decoder.
Definition: IRremote.h:174
decode_results::bits
int bits
Number of bits in decoded value.
Definition: IRremote.h:179
IRsend::sendRC5ext
void sendRC5ext(unsigned long addr, unsigned long cmd, boolean toggle)
Definition: ir_RC5_RC6.cpp:86
MARK_EXCESS
#define MARK_EXCESS
When received, marks tend to be too long and spaces tend to be too short.
Definition: IRremoteInt.h:92
DBG_PRINTLN
#define DBG_PRINTLN(...)
If DEBUG, print the arguments as a line, otherwise do nothing.
Definition: IRremote.h:155
decode_results::rawbuf
volatile unsigned int * rawbuf
Raw intervals in 50uS ticks.
Definition: IRremote.h:180
IRsend::mark
void mark(unsigned int usec)
Definition: irSend.cpp:69
IRsend::enableIROut
void enableIROut(int khz)
Definition: irSend.cpp:127
IRsend::sendRC5
void sendRC5(unsigned long data, int nbits)
Definition: ir_RC5_RC6.cpp:63
decode_results::decode_type
decode_type_t decode_type
UNKNOWN, NEC, SONY, RC5, ...
Definition: IRremote.h:176
MATCH_SPACE
int MATCH_SPACE(int measured_ticks, int desired_us)
Definition: IRremote.cpp:89
MATCH
int MATCH(int measured, int desired)
Definition: IRremote.cpp:43
irparams
volatile irparams_t irparams
Allow all parts of the code access to the ISR data NB.
IRsend::sendRC6
void sendRC6(unsigned long data, int nbits)
Definition: ir_RC5_RC6.cpp:213
MIN_RC6_SAMPLES
#define MIN_RC6_SAMPLES
Definition: ir_RC5_RC6.cpp:206
RC6
@ RC6
Definition: IRremote.h:116
RC6_HDR_SPACE
#define RC6_HDR_SPACE
Definition: ir_RC5_RC6.cpp:208
RC6_HDR_MARK
#define RC6_HDR_MARK
Definition: ir_RC5_RC6.cpp:207
IRremote.h
Public API to the library.
IRsend::space
void space(unsigned int usec)
Definition: irSend.cpp:103
RC6_T1
#define RC6_T1
Definition: ir_RC5_RC6.cpp:209
RC5_T1
#define RC5_T1
Definition: ir_RC5_RC6.cpp:58
decode_results::value
unsigned long value
Decoded value [max 32-bits].
Definition: IRremote.h:178
SPACE
#define SPACE
Sensor output for a space ("gap")
Definition: IRremoteInt.h:124
MATCH_MARK
int MATCH_MARK(int measured_ticks, int desired_us)
Definition: IRremote.cpp:63
MIN_RC5_SAMPLES
#define MIN_RC5_SAMPLES
Definition: ir_RC5_RC6.cpp:57
MARK
#define MARK
Sensor output for a mark ("flash")
Definition: IRremoteInt.h:123
decode_results::rawlen
unsigned int rawlen
Number of records in rawbuf.
Definition: IRremote.h:181
irparams_t::rawlen
unsigned int rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:45