116 lines
4.1 KiB
C++
116 lines
4.1 KiB
C++
// Copyright 2020 David Conran
|
|
|
|
/// @file
|
|
/// @brief Support for Multibrackets protocols.
|
|
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1103
|
|
/// @see http://info.multibrackets.com/data/common/manuals/4500_code.pdf
|
|
|
|
// Supports:
|
|
// Brand: Multibrackets, Model: Motorized Swing mount large - 4500
|
|
|
|
#include "IRrecv.h"
|
|
#include "IRsend.h"
|
|
|
|
const uint16_t kMultibracketsTick = 5000; // uSeconds
|
|
const uint16_t kMultibracketsHdrMark = 3 * kMultibracketsTick; // uSeconds
|
|
const uint16_t kMultibracketsFooterSpace = 6 * kMultibracketsTick; // uSeconds
|
|
const uint8_t kMultibracketsTolerance = 5; // Percent
|
|
const uint16_t kMultibracketsFreq = 38000; // Hertz
|
|
|
|
#if SEND_MULTIBRACKETS
|
|
/// Send a Multibrackets formatted message.
|
|
/// Status: BETA / Appears to be working.
|
|
/// @param[in] data The message to be sent.
|
|
/// @param[in] nbits The number of bits of message to be sent.
|
|
/// @param[in] repeat The number of times the command is to be repeated.
|
|
void IRsend::sendMultibrackets(uint64_t data, uint16_t nbits, uint16_t repeat) {
|
|
enableIROut(kMultibracketsFreq);
|
|
for (uint16_t r = 0; r <= repeat; r++) {
|
|
uint16_t bits = nbits;
|
|
// Header
|
|
mark(kMultibracketsHdrMark);
|
|
// Data
|
|
// Send 0's until we get down to a bit size we can actually manage.
|
|
while (bits > sizeof(data) * 8) {
|
|
space(kMultibracketsTick);
|
|
bits--;
|
|
}
|
|
// Send the supplied data.
|
|
for (uint64_t mask = 1ULL << (bits - 1); mask; mask >>= 1)
|
|
if (data & mask) // Send a 1
|
|
mark(kMultibracketsTick);
|
|
else // Send a 0
|
|
space(kMultibracketsTick);
|
|
// Footer
|
|
space(kMultibracketsFooterSpace);
|
|
}
|
|
}
|
|
#endif // SEND_MULTIBRACKETS
|
|
|
|
#if DECODE_MULTIBRACKETS
|
|
/// Decode the Multibrackets message.
|
|
/// Status: BETA / Appears to be working.
|
|
/// @param[in,out] results Ptr to the data to decode & where to store the result
|
|
/// @param[in] offset The starting index to use when attempting to decode the
|
|
/// raw data. Typically/Defaults to kStartOffset.
|
|
/// @param[in] nbits The number of data bits to expect.
|
|
/// @param[in] strict Flag indicating if we should perform strict matching.
|
|
/// @return True if it can decode it, false if it can't.
|
|
bool IRrecv::decodeMultibrackets(decode_results *results, uint16_t offset,
|
|
const uint16_t nbits, const bool strict) {
|
|
// Compliance
|
|
if (strict && nbits != kMultibracketsBits)
|
|
return false; // Doesn't match our protocol defn.
|
|
|
|
// Check there is enough unprocessed buffer left.
|
|
if (results->rawlen < offset) return false;
|
|
|
|
// Header
|
|
int32_t remaining = *(results->rawbuf + offset);
|
|
if (!matchAtLeast(remaining, kMultibracketsHdrMark, kMultibracketsTolerance))
|
|
return false;
|
|
remaining -= (kMultibracketsHdrMark / kRawTick); // Remove the header.
|
|
|
|
// We are done with the header. Onto the data.
|
|
bool bit = true;
|
|
uint16_t bitsSoFar = 0;
|
|
uint64_t data = 0;
|
|
// Keep going till we run out of message or expected bits.
|
|
while (offset <= results->rawlen && bitsSoFar < nbits) {
|
|
// Have we finished processing this rawbuf value yet?
|
|
if (remaining <= 0) { // No more possible "bits" left in this value.
|
|
// Invert the bit for next time, and move along the rawbuf.
|
|
bit = !bit;
|
|
offset++;
|
|
// Load the next data point if there is one.
|
|
if (offset <= results->rawlen) remaining = *(results->rawbuf + offset);
|
|
} else { // Look for more bits in this entry.
|
|
if (matchAtLeast(remaining, kMultibracketsTick,
|
|
kMultibracketsTolerance)) { // There is!
|
|
data <<= 1;
|
|
data += bit;
|
|
bitsSoFar++;
|
|
}
|
|
remaining -= (kMultibracketsTick / kRawTick); // Remove the "bit".
|
|
}
|
|
}
|
|
|
|
// Compliance
|
|
if (bitsSoFar != nbits) return false;
|
|
|
|
// Footer
|
|
if (results->rawlen <= offset && !matchAtLeast(*(results->rawbuf + offset),
|
|
kMultibracketsFooterSpace,
|
|
kMultibracketsTolerance))
|
|
return false;
|
|
|
|
// Success
|
|
results->decode_type = decode_type_t::MULTIBRACKETS;
|
|
results->value = data;
|
|
results->bits = nbits;
|
|
results->address = 0;
|
|
results->command = 0;
|
|
return true;
|
|
}
|
|
#endif // DECODE_MULTIBRACKETS
|