@@ -154,6 +154,12 @@ int IRrecv::decode(decode_results *results) {
154
154
if (irparams.rcvstate != STATE_STOP) {
155
155
return ERR;
156
156
}
157
+ #ifdef DEBUG
158
+ Serial.println (" Attempting SPACE_ENC decode" );
159
+ #endif
160
+ if (decodeSpaceEnc (results)) {
161
+ return DECODED;
162
+ }
157
163
#ifdef DEBUG
158
164
Serial.println (" Attempting NEC decode" );
159
165
#endif
@@ -189,6 +195,191 @@ int IRrecv::decode(decode_results *results) {
189
195
return ERR;
190
196
}
191
197
198
+ // Decoding a generic space encoded signal is a bit tricky.
199
+ // We assume one of two cases:
200
+ // a) a 0 is a mark and a short space, and a 1 is a mark and a long space (spaceVaries), or
201
+ // b) a 0 is a short mark and a space, and a 1 is a long mark and a space (markVaries)
202
+ // The NEC code is an example of varying space, and the Sony code is an example of varying mark.
203
+ //
204
+ // We assume that if the space varies, there is a trailing mark (so you can tell when the last space ends),
205
+ // but if the mark varies then the last mark is part of the last bit, but the last space is very long.
206
+ //
207
+ // To decode, the first step is to find the shortest and longest marks and spaces (excluding headers and trailers).
208
+ // Then see if the marks or spaces vary. (If both, probably RC5/6 so quit.)
209
+ // Loop through all the mark/space pairs to see if it is a 1 or a 0.
210
+ // Finally, fill in the results.
211
+ //
212
+ // The code is somewhat long and confusing because it is generic and handles both cases.
213
+ //
214
+ long IRrecv::decodeSpaceEnc (decode_results *results) {
215
+ if (irparams.rawlen < 10 ) {
216
+ // Don't have a reasonable number of bits to decode.
217
+ return ERR;
218
+ }
219
+ unsigned int minMark = 999999 ;
220
+ unsigned int maxMark = 0 ;
221
+ unsigned int minSpace = 999999 ;
222
+ unsigned int maxSpace = 0 ;
223
+ // Compute the minimum and maximum mark and space durations, ignoring
224
+ // header and trailer.
225
+ // start with entry 3, skipping first space and two header elements
226
+ // skip the last space and mark in case they are a trailer
227
+ for (int i = 3 ; i < irparams.rawlen -2 ; i += 2 ) {
228
+ if (results->rawbuf [i] < minMark) {
229
+ minMark = results->rawbuf [i];
230
+ } else if (results->rawbuf [i] > maxMark) {
231
+ maxMark = results->rawbuf [i];
232
+ }
233
+ if (results->rawbuf [i+1 ] < minSpace) {
234
+ minSpace = results->rawbuf [i+1 ];
235
+ } else if (results->rawbuf [i+1 ] > maxSpace) {
236
+ maxSpace = results->rawbuf [i+1 ];
237
+ }
238
+ }
239
+ maxMark *= USECPERTICK;
240
+ maxSpace *= USECPERTICK;
241
+ // The second argument is us, the first is ticks, so need to multiply the second
242
+ // markVaries is true if there are two different mark values
243
+ // spaceVaries is true if there are two different space values
244
+ int markVaries = !MATCH (minMark, maxMark);
245
+ int spaceVaries = !MATCH (minSpace, maxSpace);
246
+ minMark *= USECPERTICK;
247
+ minSpace *= USECPERTICK;
248
+ #ifdef DEBUG
249
+ Serial.print (" min mark: " );
250
+ Serial.println (minMark, DEC);
251
+ Serial.print (" max mark: " );
252
+ Serial.println (maxMark, DEC);
253
+ Serial.print (" min space: " );
254
+ Serial.println (minSpace, DEC);
255
+ Serial.print (" max space: " );
256
+ Serial.println (maxSpace, DEC);
257
+ #endif
258
+ // Only one of these can vary for SPACE_ENC
259
+ if (markVaries == spaceVaries) {
260
+ return ERR;
261
+ }
262
+ // Subtract 4 entries: space, 2 for header, 1 for trailer
263
+ int nbits = (irparams.rawlen -4 ) / 2 ;
264
+ // Clean up the non-varying value by averaging the min and max
265
+ // They will probably be slightly different due to random fluctuations
266
+ // so the average is probably best to use.
267
+ if (markVaries) {
268
+ minSpace = (minSpace + maxSpace) / 2 ;
269
+ maxSpace = minSpace;
270
+ nbits += 1 ; // Last mark is a bit, not a trailer
271
+ results->spaceEncData .trailer = 0 ;
272
+ } else {
273
+ minMark = (minMark + maxMark) / 2 ;
274
+ maxMark = minMark;
275
+ // If space varies, need a trailer to delimit the last space
276
+ results->spaceEncData .trailer = results->rawbuf [irparams.rawlen -1 ] * USECPERTICK;
277
+ }
278
+ #ifdef DEBUG
279
+ Serial.print (" nbits: " );
280
+ Serial.println (nbits);
281
+ Serial.print (" markVaries: " );
282
+ Serial.println (markVaries);
283
+ Serial.print (" spaceVaries: " );
284
+ Serial.println (spaceVaries);
285
+ Serial.print (" rawlen: " );
286
+ Serial.println (irparams.rawlen );
287
+ #endif
288
+
289
+ // Now loop through the data and determine the bit values.
290
+
291
+ long data = 0 ;
292
+ int offset = 3 ; // Offset into rawbuf; skip the header
293
+ if (markVaries) {
294
+ // The decode loop where the mark width determines the bit value
295
+ for (int i=0 ; i < nbits-1 ; i++) {
296
+ data <<= 1 ;
297
+ // Check the mark and determine the bit
298
+ unsigned int markVal = results->rawbuf [offset++];
299
+ if (MATCH (markVal, minMark)) {
300
+ // 0 bit
301
+ } else if (MATCH (markVal, maxMark)) {
302
+ data |= 1 ; // 1 bit
303
+ } else {
304
+ // The mark is no good.
305
+ return ERR;
306
+ }
307
+ // Check that the space is okay
308
+ unsigned int spaceVal = results->rawbuf [offset++];
309
+ if (!MATCH (spaceVal, minSpace)) {
310
+ // The space is no good
311
+ return ERR;
312
+ }
313
+ }
314
+ // Process the last bit specially because it's just a mark without a space
315
+ // (because the transmission has to end with a mark).
316
+ // If it makes sense as a bit, treat it as a bit, otherwise treat it as a
317
+ // trailer.
318
+ unsigned int markVal = results->rawbuf [offset++];
319
+ if (MATCH (markVal, minMark)) {
320
+ // 0 bit
321
+ data <<= 1 ;
322
+ } else if (MATCH (markVal, maxMark)) {
323
+ data <<= 1 ;
324
+ data |= 1 ; // 1 bit
325
+ } else {
326
+ // Guess the last mark was just a trailer after all
327
+ nbits--;
328
+ results->spaceEncData .trailer = results->rawbuf [irparams.rawlen -1 ] * USECPERTICK;
329
+ }
330
+ } else {
331
+
332
+ // The decode loop where the space width determines the bit value
333
+ for (int i=0 ; i &
F438
lt; nbits; i++) {
334
+ data <<= 1 ; // Shift the data over for the next bit
335
+ // Check that the mark is okay
336
+ unsigned int markVal = results->rawbuf [offset++];
337
+ if (!MATCH (markVal, minMark)) {
338
+ return ERR;
339
+ }
340
+ // Check the space and determine the bit
341
+ unsigned int spaceVal = results->rawbuf [offset++];
342
+ if (MATCH (spaceVal, minSpace)) {
343
+ // 0 bit
344
+ } else if (MATCH (spaceVal, maxSpace)) {
345
+ data |= 1 ; // 1 bit
346
+ } else {
347
+ return ERR;
348
+ }
349
+ }
350
+ }
351
+
352
+ // Finally, save the results
353
+
354
+ results->spaceEncData .headerMark = results->rawbuf [1 ] * USECPERTICK;
355
+ results->spaceEncData .headerSpace = results->rawbuf [2 ] * USECPERTICK;
356
+ results->spaceEncData .mark0 = minMark;
357
+ results->spaceEncData .space0 = minSpace;
358
+ results->spaceEncData .mark1 = maxMark;
359
+ results->spaceEncData .space1 = maxSpace;
360
+ results->spaceEncData .frequency = 0 ; // Don't know
361
+ results->bits = nbits;
362
+ results->value = data;
363
+ results->decode_type = SPACE_ENC;
364
+ #ifdef DEBUG
365
+ Serial.print (" headerMark: " );
366
+ Serial.println (results->spaceEncData .headerMark , DEC);
367
+ Serial.print (" headerSpace: " );
368
+ Serial.println (results->spaceEncData .headerSpace , DEC);
369
+ Serial.print (" mark0: " );
370
+ Serial.println (results->spaceEncData .mark0 , DEC);
371
+ Serial.print (" space0: " );
372
+ Serial.println (results->spaceEncData .space0 , DEC);
373
+ Serial.print (" mark1: " );
374
+ Serial.println (results->spaceEncData .mark1 , DEC);
375
+ Serial.print (" space1: " );
376
+ Serial.println (results->spaceEncData .space1 , DEC);
377
+ Serial.print (" trailer: " );
378
+ Serial.println (results->spaceEncData .trailer , DEC);
379
+ #endif
380
+ return SPACE_ENC;
381
+ }
382
+
192
383
long IRrecv::decodeNEC (decode_results *results) {
193
384
long data = 0 ;
194
385
int offset = 1 ; // Skip first space
0 commit comments