ir_Whynter.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright 2009 Ken Shirriff
  2. // Copyright 2017 David Conran
  3. #include <algorithm>
  4. #include "IRrecv.h"
  5. #include "IRsend.h"
  6. #include "IRutils.h"
  7. // W W H H Y Y N N TTTTT EEEEE RRRRR
  8. // W W H H Y Y NN N T E R R
  9. // W W W HHHHH Y N N N T EEE RRRR
  10. // W W W H H Y N NN T E R R
  11. // WWW H H Y N N T EEEEE R R
  12. // Whynter A/C ARC-110WD added by Francesco Meschia
  13. // Whynter originally added from https://github.com/shirriff/Arduino-IRremote/
  14. // Constants
  15. const uint16_t kWhynterTick = 50;
  16. const uint16_t kWhynterHdrMarkTicks = 57;
  17. const uint16_t kWhynterHdrMark = kWhynterHdrMarkTicks * kWhynterTick;
  18. const uint16_t kWhynterHdrSpaceTicks = 57;
  19. const uint16_t kWhynterHdrSpace = kWhynterHdrSpaceTicks * kWhynterTick;
  20. const uint16_t kWhynterBitMarkTicks = 15;
  21. const uint16_t kWhynterBitMark = kWhynterBitMarkTicks * kWhynterTick;
  22. const uint16_t kWhynterOneSpaceTicks = 43;
  23. const uint16_t kWhynterOneSpace = kWhynterOneSpaceTicks * kWhynterTick;
  24. const uint16_t kWhynterZeroSpaceTicks = 15;
  25. const uint16_t kWhynterZeroSpace = kWhynterZeroSpaceTicks * kWhynterTick;
  26. const uint16_t kWhynterMinCommandLengthTicks = 2160; // Totally made up value.
  27. const uint32_t kWhynterMinCommandLength =
  28. kWhynterMinCommandLengthTicks * kWhynterTick;
  29. const uint16_t kWhynterMinGapTicks =
  30. kWhynterMinCommandLengthTicks -
  31. (2 * (kWhynterBitMarkTicks + kWhynterZeroSpaceTicks) +
  32. kWhynterBits * (kWhynterBitMarkTicks + kWhynterOneSpaceTicks));
  33. const uint16_t kWhynterMinGap = kWhynterMinGapTicks * kWhynterTick;
  34. #if SEND_WHYNTER
  35. // Send a Whynter message.
  36. //
  37. // Args:
  38. // data: message to be sent.
  39. // nbits: Nr. of bits of the message to be sent.
  40. // repeat: Nr. of additional times the message is to be sent.
  41. //
  42. // Status: STABLE
  43. //
  44. // Ref:
  45. // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp
  46. void IRsend::sendWhynter(uint64_t data, uint16_t nbits, uint16_t repeat) {
  47. // Set IR carrier frequency
  48. enableIROut(38);
  49. for (uint16_t i = 0; i <= repeat; i++) {
  50. // (Pre-)Header
  51. mark(kWhynterBitMark);
  52. space(kWhynterZeroSpace);
  53. sendGeneric(
  54. kWhynterHdrMark, kWhynterHdrSpace, kWhynterBitMark, kWhynterOneSpace,
  55. kWhynterBitMark, kWhynterZeroSpace, kWhynterBitMark, kWhynterMinGap,
  56. kWhynterMinCommandLength - (kWhynterBitMark + kWhynterZeroSpace), data,
  57. nbits, 38, true, 0, // Repeats are already handled.
  58. 50);
  59. }
  60. }
  61. #endif
  62. #if DECODE_WHYNTER
  63. // Decode the supplied Whynter message.
  64. //
  65. // Args:
  66. // results: Ptr to the data to decode and where to store the decode result.
  67. // nbits: Nr. of data bits to expect.
  68. // strict: Flag indicating if we should perform strict matching.
  69. // Returns:
  70. // boolean: True if it can decode it, false if it can't.
  71. //
  72. // Status: BETA Strict mode is ALPHA.
  73. //
  74. // Ref:
  75. // https://github.com/z3t0/Arduino-IRremote/blob/master/ir_Whynter.cpp
  76. bool IRrecv::decodeWhynter(decode_results *results, uint16_t nbits,
  77. bool strict) {
  78. if (results->rawlen < 2 * nbits + 2 * kHeader + kFooter - 1)
  79. return false; // We don't have enough entries to possibly match.
  80. // Compliance
  81. if (strict && nbits != kWhynterBits)
  82. return false; // Incorrect nr. of bits per spec.
  83. uint16_t offset = kStartOffset;
  84. // Header
  85. // Sequence begins with a bit mark and a zero space.
  86. // These are typically small, so we'll prefer to do the calibration
  87. // on the much larger header mark & space that are next.
  88. if (!matchMark(results->rawbuf[offset++], kWhynterBitMark)) return false;
  89. if (!matchSpace(results->rawbuf[offset++], kWhynterZeroSpace)) return false;
  90. // Main header mark and space
  91. if (!matchMark(results->rawbuf[offset], kWhynterHdrMark)) return false;
  92. // Calculate how long the common tick time is based on the header mark.
  93. uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kWhynterHdrMarkTicks;
  94. if (!matchSpace(results->rawbuf[offset], kWhynterHdrSpace)) return false;
  95. // Calculate how long the common tick time is based on the header space.
  96. uint32_t s_tick =
  97. results->rawbuf[offset++] * kRawTick / kWhynterHdrSpaceTicks;
  98. // Data
  99. uint64_t data = 0;
  100. match_result_t data_result =
  101. matchData(&(results->rawbuf[offset]), nbits,
  102. kWhynterBitMarkTicks * m_tick, kWhynterOneSpaceTicks * s_tick,
  103. kWhynterBitMarkTicks * m_tick, kWhynterZeroSpaceTicks * s_tick);
  104. if (data_result.success == false) return false;
  105. data = data_result.data;
  106. offset += data_result.used;
  107. // Footer
  108. if (!matchMark(results->rawbuf[offset++], kWhynterBitMarkTicks * m_tick))
  109. return false;
  110. if (offset < results->rawlen &&
  111. !matchAtLeast(results->rawbuf[offset], kWhynterMinGapTicks * s_tick))
  112. return false;
  113. // Success
  114. results->decode_type = WHYNTER;
  115. results->bits = nbits;
  116. results->value = data;
  117. results->address = 0;
  118. results->command = 0;
  119. return true;
  120. }
  121. #endif