PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

208 lines
5.9KB

  1. #include "IRremote.h"
  2. #include "IRremoteInt.h"
  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, int *offset, int *used, int t1)
  14. {
  15. int width;
  16. int val;
  17. int correction;
  18. int avail;
  19. if (*offset >= results->rawlen) return SPACE ; // After end of recorded buffer, assume SPACE.
  20. width = results->rawbuf[*offset];
  21. val = ((*offset) % 2) ? MARK : SPACE;
  22. correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;
  23. if (MATCH(width, ( t1) + correction)) avail = 1 ;
  24. else if (MATCH(width, (2*t1) + correction)) avail = 2 ;
  25. else if (MATCH(width, (3*t1) + correction)) avail = 3 ;
  26. else return -1 ;
  27. (*used)++;
  28. if (*used >= avail) {
  29. *used = 0;
  30. (*offset)++;
  31. }
  32. DBG_PRINTLN( (val == MARK) ? "MARK" : "SPACE" );
  33. return val;
  34. }
  35. #endif
  36. //==============================================================================
  37. // RRRR CCCC 55555
  38. // R R C 5
  39. // RRRR C 5555
  40. // R R C 5
  41. // R R CCCC 5555
  42. //
  43. // NB: First bit must be a one (start bit)
  44. //
  45. #define MIN_RC5_SAMPLES 11
  46. #define RC5_T1 889
  47. #define RC5_RPT_LENGTH 46000
  48. //+=============================================================================
  49. #if SEND_RC5
  50. void IRsend::sendRC5 (unsigned long data, int nbits)
  51. {
  52. // Set IR carrier frequency
  53. enableIROut(36);
  54. // Start
  55. mark(RC5_T1);
  56. space(RC5_T1);
  57. mark(RC5_T1);
  58. // Data
  59. for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) {
  60. if (data & mask) {
  61. space(RC5_T1); // 1 is space, then mark
  62. mark(RC5_T1);
  63. } else {
  64. mark(RC5_T1);
  65. space(RC5_T1);
  66. }
  67. }
  68. space(0); // Always end with the LED off
  69. }
  70. #endif
  71. //+=============================================================================
  72. #if DECODE_RC5
  73. bool IRrecv::decodeRC5 (decode_results *results)
  74. {
  75. int nbits;
  76. long data = 0;
  77. int used = 0;
  78. int offset = 1; // Skip gap space
  79. if (irparams.rawlen < MIN_RC5_SAMPLES + 2) return false ;
  80. // Get start bits
  81. if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ;
  82. if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return false ;
  83. if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return false ;
  84. for (nbits = 0; offset < irparams.rawlen; nbits++) {
  85. int levelA = getRClevel(results, &offset, &used, RC5_T1);
  86. int levelB = getRClevel(results, &offset, &used, RC5_T1);
  87. if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 1 ;
  88. else if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 0 ;
  89. else return false ;
  90. }
  91. // Success
  92. results->bits = nbits;
  93. results->value = data;
  94. results->decode_type = RC5;
  95. return true;
  96. }
  97. #endif
  98. //+=============================================================================
  99. // RRRR CCCC 6666
  100. // R R C 6
  101. // RRRR C 6666
  102. // R R C 6 6
  103. // R R CCCC 666
  104. //
  105. // NB : Caller needs to take care of flipping the toggle bit
  106. //
  107. #define MIN_RC6_SAMPLES 1
  108. #define RC6_HDR_MARK 2666
  109. #define RC6_HDR_SPACE 889
  110. #define RC6_T1 444
  111. #define RC6_RPT_LENGTH 46000
  112. #if SEND_RC6
  113. void IRsend::sendRC6 (unsigned long data, int nbits)
  114. {
  115. // Set IR carrier frequency
  116. enableIROut(36);
  117. // Header
  118. mark(RC6_HDR_MARK);
  119. space(RC6_HDR_SPACE);
  120. // Start bit
  121. mark(RC6_T1);
  122. space(RC6_T1);
  123. // Data
  124. for (unsigned long i = 1, mask = 1UL << (nbits - 1); mask; i++, mask >>= 1) {
  125. // The fourth bit we send is a "double width trailer bit"
  126. int t = (i == 4) ? (RC6_T1 * 2) : (RC6_T1) ;
  127. if (data & mask) {
  128. mark(t);
  129. space(t);
  130. } else {
  131. space(t);
  132. mark(t);
  133. }
  134. }
  135. space(0); // Always end with the LED off
  136. }
  137. #endif
  138. //+=============================================================================
  139. #if DECODE_RC6
  140. bool IRrecv::decodeRC6 (decode_results *results)
  141. {
  142. int nbits;
  143. long data = 0;
  144. int used = 0;
  145. int offset = 1; // Skip first space
  146. if (results->rawlen < MIN_RC6_SAMPLES) return false ;
  147. // Initial mark
  148. if (!MATCH_MARK(results->rawbuf[offset++], RC6_HDR_MARK)) return false ;
  149. if (!MATCH_SPACE(results->rawbuf[offset++], RC6_HDR_SPACE)) return false ;
  150. // Get start bit (1)
  151. if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return false ;
  152. if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return false ;
  153. for (nbits = 0; offset < results->rawlen; nbits++) {
  154. int levelA, levelB; // Next two levels
  155. levelA = getRClevel(results, &offset, &used, RC6_T1);
  156. if (nbits == 3) {
  157. // T bit is double wide; make sure second half matches
  158. if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return false;
  159. }
  160. levelB = getRClevel(results, &offset, &used, RC6_T1);
  161. if (nbits == 3) {
  162. // T bit is double wide; make sure second half matches
  163. if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return false;
  164. }
  165. if ((levelA == MARK ) && (levelB == SPACE)) data = (data << 1) | 1 ; // inverted compared to RC5
  166. else if ((levelA == SPACE) && (levelB == MARK )) data = (data << 1) | 0 ; // ...
  167. else return false ; // Error
  168. }
  169. // Success
  170. results->bits = nbits;
  171. results->value = data;
  172. results->decode_type = RC6;
  173. return true;
  174. }
  175. #endif