Taguchi Yuuki / IRremote

Dependents:   Lilnija_29012017 NucleoF042K6_IRReceiver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ir_RC5_RC6.cpp Source File

ir_RC5_RC6.cpp

00001 #include "IRremote.h"
00002 #include "IRremoteInt.h"
00003 
00004 //+=============================================================================
00005 // Gets one undecoded level at a time from the raw buffer.
00006 // The RC5/6 decoding is easier if the data is broken into time intervals.
00007 // E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,
00008 // successive calls to getRClevel will return MARK, MARK, SPACE.
00009 // offset and used are updated to keep track of the current position.
00010 // t1 is the time interval for a single bit in microseconds.
00011 // Returns -1 for error (measured time interval is not a multiple of t1).
00012 //
00013 #if (DECODE_RC5 || DECODE_RC6)
00014 int  IRrecv::getRClevel (decode_results *results,  int *offset,  int *used,  int t1)
00015 {
00016     int  width;
00017     int  val;
00018     int  correction;
00019     int  avail;
00020 
00021     if (*offset >= results->rawlen)  return SPACE ;  // After end of recorded buffer, assume SPACE.
00022     width      = results->rawbuf[*offset];
00023     val        = ((*offset) % 2) ? MARK : SPACE;
00024     correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
00025 
00026     if      (MATCH(width, (  t1) + correction))  avail = 1 ;
00027     else if (MATCH(width, (2*t1) + correction))  avail = 2 ;
00028     else if (MATCH(width, (3*t1) + correction))  avail = 3 ;
00029     else                                         return -1 ;
00030 
00031     (*used)++;
00032     if (*used >= avail) {
00033         *used = 0;
00034         (*offset)++;
00035     }
00036 
00037     DBG_PRINTLN( (val == MARK) ? "MARK" : "SPACE" );
00038 
00039     return val;
00040 }
00041 #endif
00042 
00043 //==============================================================================
00044 // RRRR    CCCC  55555
00045 // R   R  C      5
00046 // RRRR   C      5555
00047 // R  R   C          5
00048 // R   R   CCCC  5555
00049 //
00050 // NB: First bit must be a one (start bit)
00051 //
00052 #define MIN_RC5_SAMPLES     11
00053 #define RC5_T1             889
00054 #define RC5_RPT_LENGTH   46000
00055 
00056 //+=============================================================================
00057 #if SEND_RC5
00058 void  IRsend::sendRC5 (unsigned long data,  int nbits)
00059 {
00060     // Set IR carrier frequency
00061     enableIROut(36);
00062 
00063     // Start
00064     mark(RC5_T1);
00065     space(RC5_T1);
00066     mark(RC5_T1);
00067 
00068     // Data
00069     for (unsigned long  mask = 1UL << (nbits - 1);  mask;  mask >>= 1) {
00070         if (data & mask) {
00071             space(RC5_T1); // 1 is space, then mark
00072             mark(RC5_T1);
00073         } else {
00074             mark(RC5_T1);
00075             space(RC5_T1);
00076         }
00077     }
00078 
00079     space(0);  // Always end with the LED off
00080 }
00081 #endif
00082 
00083 //+=============================================================================
00084 #if DECODE_RC5
00085 bool  IRrecv::decodeRC5 (decode_results *results)
00086 {
00087     int   nbits;
00088     long  data   = 0;
00089     int   used   = 0;
00090     int   offset = 1;  // Skip gap space
00091 
00092     if (irparams.rawlen < MIN_RC5_SAMPLES + 2)  return false ;
00093 
00094     // Get start bits
00095     if (getRClevel(results, &offset, &used, RC5_T1) != MARK)   return false ;
00096     if (getRClevel(results, &offset, &used, RC5_T1) != SPACE)  return false ;
00097     if (getRClevel(results, &offset, &used, RC5_T1) != MARK)   return false ;
00098 
00099     for (nbits = 0;  offset < irparams.rawlen;  nbits++) {
00100         int  levelA = getRClevel(results, &offset, &used, RC5_T1);
00101         int  levelB = getRClevel(results, &offset, &used, RC5_T1);
00102 
00103         if      ((levelA == SPACE) && (levelB == MARK ))  data = (data << 1) | 1 ;
00104         else if ((levelA == MARK ) && (levelB == SPACE))  data = (data << 1) | 0 ;
00105         else                                              return false ;
00106     }
00107 
00108     // Success
00109     results->bits        = nbits;
00110     results->value       = data;
00111     results->decode_type = RC5;
00112     return true;
00113 }
00114 #endif
00115 
00116 //+=============================================================================
00117 // RRRR    CCCC   6666
00118 // R   R  C      6
00119 // RRRR   C      6666
00120 // R  R   C      6   6
00121 // R   R   CCCC   666
00122 //
00123 // NB : Caller needs to take care of flipping the toggle bit
00124 //
00125 #define MIN_RC6_SAMPLES      1
00126 #define RC6_HDR_MARK      2666
00127 #define RC6_HDR_SPACE      889
00128 #define RC6_T1             444
00129 #define RC6_RPT_LENGTH   46000
00130 
00131 #if SEND_RC6
00132 void  IRsend::sendRC6 (unsigned long data,  int nbits)
00133 {
00134     // Set IR carrier frequency
00135     enableIROut(36);
00136 
00137     // Header
00138     mark(RC6_HDR_MARK);
00139     space(RC6_HDR_SPACE);
00140 
00141     // Start bit
00142     mark(RC6_T1);
00143     space(RC6_T1);
00144 
00145     // Data
00146     for (unsigned long  i = 1, mask = 1UL << (nbits - 1);  mask;  i++, mask >>= 1) {
00147         // The fourth bit we send is a "double width trailer bit"
00148         int  t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1) ;
00149         if (data & mask) {
00150             mark(t);
00151             space(t);
00152         } else {
00153             space(t);
00154             mark(t);
00155         }
00156     }
00157 
00158     space(0);  // Always end with the LED off
00159 }
00160 #endif
00161 
00162 //+=============================================================================
00163 #if DECODE_RC6
00164 bool  IRrecv::decodeRC6 (decode_results *results)
00165 {
00166     int   nbits;
00167     long  data   = 0;
00168     int   used   = 0;
00169     int   offset = 1;  // Skip first space
00170 
00171     if (results->rawlen < MIN_RC6_SAMPLES)  return false ;
00172 
00173     // Initial mark
00174     if (!MATCH_MARK(results->rawbuf[offset++],  RC6_HDR_MARK))   return false ;
00175     if (!MATCH_SPACE(results->rawbuf[offset++], RC6_HDR_SPACE))  return false ;
00176 
00177     // Get start bit (1)
00178     if (getRClevel(results, &offset, &used, RC6_T1) != MARK)   return false ;
00179     if (getRClevel(results, &offset, &used, RC6_T1) != SPACE)  return false ;
00180 
00181     for (nbits = 0;  offset < results->rawlen;  nbits++) {
00182         int  levelA, levelB;  // Next two levels
00183 
00184         levelA = getRClevel(results, &offset, &used, RC6_T1);
00185         if (nbits == 3) {
00186             // T bit is double wide; make sure second half matches
00187             if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return false;
00188         }
00189 
00190         levelB = getRClevel(results, &offset, &used, RC6_T1);
00191         if (nbits == 3) {
00192             // T bit is double wide; make sure second half matches
00193             if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return false;
00194         }
00195 
00196         if      ((levelA == MARK ) && (levelB == SPACE))  data = (data << 1) | 1 ;  // inverted compared to RC5
00197         else if ((levelA == SPACE) && (levelB == MARK ))  data = (data << 1) | 0 ;  // ...
00198         else                                              return false ;            // Error
00199     }
00200 
00201     // Success
00202     results->bits        = nbits;
00203     results->value       = data;
00204     results->decode_type = RC6;
00205     return true;
00206 }
00207 #endif