Ir esp8266 lib update and code impacts (#235)
* integrate new IRremoteESP8266 lib 2.4.2 and add new protocols IR_RC6 IR_MITSUBISHI IR_GICABLE IR_MITSUBISHI2 IR_LASERTAG IR_CARRIER_AC IR_MIDEA IR_NIKAI IR_SHERWOOD IR_DENON IR_AIWA_RC_T501 IR_JVC
This commit is contained in:
1 parent
9b258723a8
commit
b12ee19979
130 files changed
+16548
-1693
No files matched your search
@@ -1,30 +1,39 @@
|
||||
// Copyright 2017 Jonny Graham
|
||||
// Copyright 2017 Jonny Graham, David Conran
|
||||
#include "ir_Fujitsu.h"
|
||||
#include <algorithm>
|
||||
#ifndef ARDUINO
|
||||
#include <string>
|
||||
#endif
|
||||
#include "IRsend.h"
|
||||
#include "IRutils.h"
|
||||
|
||||
|
||||
// Fujitsu A/C support added by Jonny Graham
|
||||
// Fujitsu A/C support added by Jonny Graham & David Conran
|
||||
|
||||
// Equipment it seems compatible with:
|
||||
// * Fujitsu ASYG30LFCA with remote AR-RAH2E
|
||||
// * Fujitsu AST9RSGCW with remote AR-DB1
|
||||
// * <Add models (A/C & remotes) you've gotten it working with here>
|
||||
|
||||
// Fujitsu A/C
|
||||
// Ref:
|
||||
// These values are based on averages of measurements
|
||||
#define FUJITSU_AC_HDR_MARK 3224U
|
||||
#define FUJITSU_AC_HDR_MARK 3324U
|
||||
#define FUJITSU_AC_HDR_SPACE 1574U
|
||||
#define FUJITSU_AC_BIT_MARK 448U
|
||||
#define FUJITSU_AC_ONE_SPACE 1182U
|
||||
#define FUJITSU_AC_ZERO_SPACE 367U
|
||||
#define FUJITSU_AC_TRL_MARK 448U
|
||||
#define FUJITSU_AC_TRL_SPACE 8100U
|
||||
#define FUJITSU_AC_ZERO_SPACE 390U
|
||||
#define FUJITSU_AC_MIN_GAP 8100U
|
||||
|
||||
#if SEND_FUJITSU_AC
|
||||
// Send a Fujitsu A/C message.
|
||||
//
|
||||
// Args:
|
||||
// data: An array of bytes containing the IR command.
|
||||
// nbytes: Nr. of bytes of data in the array. (typically either
|
||||
// FUJITSU_AC_STATE_LENGTH or FUJITSU_AC_STATE_LENGTH_SHORT)
|
||||
// nbytes: Nr. of bytes of data in the array. Typically one of:
|
||||
// FUJITSU_AC_STATE_LENGTH
|
||||
// FUJITSU_AC_STATE_LENGTH - 1
|
||||
// FUJITSU_AC_STATE_LENGTH_SHORT
|
||||
// FUJITSU_AC_STATE_LENGTH_SHORT - 1
|
||||
// repeat: Nr. of times the message is to be repeated.
|
||||
// (Default = FUJITSU_AC_MIN_REPEAT).
|
||||
//
|
||||
@@ -32,35 +41,36 @@
|
||||
//
|
||||
void IRsend::sendFujitsuAC(unsigned char data[], uint16_t nbytes,
|
||||
uint16_t repeat) {
|
||||
// Set IR carrier frequency
|
||||
enableIROut(38);
|
||||
for (uint16_t r = 0; r <= repeat; ++r) {
|
||||
// Header
|
||||
mark(FUJITSU_AC_HDR_MARK);
|
||||
space(FUJITSU_AC_HDR_SPACE);
|
||||
// Data
|
||||
for (uint16_t i = 0; i < nbytes; i++)
|
||||
sendData(FUJITSU_AC_BIT_MARK, FUJITSU_AC_ONE_SPACE,
|
||||
FUJITSU_AC_BIT_MARK, FUJITSU_AC_ZERO_SPACE,
|
||||
data[i], 8, false);
|
||||
// Footer
|
||||
mark(FUJITSU_AC_TRL_MARK);
|
||||
space(FUJITSU_AC_TRL_SPACE);
|
||||
}
|
||||
sendGeneric(FUJITSU_AC_HDR_MARK, FUJITSU_AC_HDR_SPACE,
|
||||
FUJITSU_AC_BIT_MARK, FUJITSU_AC_ONE_SPACE,
|
||||
FUJITSU_AC_BIT_MARK, FUJITSU_AC_ZERO_SPACE,
|
||||
FUJITSU_AC_BIT_MARK, FUJITSU_AC_MIN_GAP,
|
||||
data, nbytes, 38, false, repeat, 50);
|
||||
}
|
||||
#endif // SEND_FUJITSU_AC
|
||||
|
||||
// Code to emulate Fujitsu A/C IR remote control unit.
|
||||
|
||||
// Warning: Consider this very alpha code. Seems to work, but not validated.
|
||||
//
|
||||
// Equipment it seems compatible with:
|
||||
// * Fujitsu ASYG30LFCA with remote AR-RAH2E
|
||||
// * <Add models (A/C & remotes) you've gotten it working with here>
|
||||
// Initialise the object.
|
||||
IRFujitsuAC::IRFujitsuAC(uint16_t pin) : _irsend(pin) {
|
||||
IRFujitsuAC::IRFujitsuAC(uint16_t pin, fujitsu_ac_remote_model_t model)
|
||||
: _irsend(pin) {
|
||||
setModel(model);
|
||||
stateReset();
|
||||
}
|
||||
|
||||
void IRFujitsuAC::setModel(fujitsu_ac_remote_model_t model) {
|
||||
_model = model;
|
||||
switch (model) {
|
||||
case ARDB1:
|
||||
_state_length = FUJITSU_AC_STATE_LENGTH - 1;
|
||||
_state_length_short = FUJITSU_AC_STATE_LENGTH_SHORT - 1;
|
||||
break;
|
||||
default:
|
||||
_state_length = FUJITSU_AC_STATE_LENGTH;
|
||||
_state_length_short = FUJITSU_AC_STATE_LENGTH_SHORT;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the state of the remote to a known good state/sequence.
|
||||
void IRFujitsuAC::stateReset() {
|
||||
_temp = 24;
|
||||
@@ -68,29 +78,23 @@ void IRFujitsuAC::stateReset() {
|
||||
_mode = FUJITSU_AC_MODE_COOL;
|
||||
_swingMode = FUJITSU_AC_SWING_BOTH;
|
||||
_cmd = FUJITSU_AC_CMD_TURN_ON;
|
||||
buildState();
|
||||
}
|
||||
|
||||
// Configure the pin for output.
|
||||
void IRFujitsuAC::begin() {
|
||||
_irsend.begin();
|
||||
_irsend.begin();
|
||||
}
|
||||
|
||||
#if SEND_FUJITSU_AC
|
||||
// Send the current desired state to the IR LED.
|
||||
void IRFujitsuAC::send() {
|
||||
getRaw();
|
||||
uint8_t len = getCommandLength();
|
||||
_irsend.sendFujitsuAC(remote_state, len);
|
||||
_irsend.sendFujitsuAC(remote_state, getStateLength());
|
||||
}
|
||||
#endif // SEND_FUJITSU_AC
|
||||
|
||||
uint8_t IRFujitsuAC::getCommandLength() {
|
||||
if (remote_state[5] != 0xFE)
|
||||
return FUJITSU_AC_STATE_LENGTH_SHORT;
|
||||
else
|
||||
return FUJITSU_AC_STATE_LENGTH;
|
||||
}
|
||||
|
||||
// Return a pointer to the internal state date of the remote.
|
||||
uint8_t* IRFujitsuAC::getRaw() {
|
||||
void IRFujitsuAC::buildState() {
|
||||
remote_state[0] = 0x14;
|
||||
remote_state[1] = 0x63;
|
||||
remote_state[2] = 0x00;
|
||||
@@ -108,48 +112,130 @@ uint8_t* IRFujitsuAC::getRaw() {
|
||||
remote_state[5] = 0x6C;
|
||||
break;
|
||||
default:
|
||||
remote_state[5] = 0xFE;
|
||||
switch (_model) {
|
||||
case ARRAH2E:
|
||||
remote_state[5] = 0xFE;
|
||||
break;
|
||||
case ARDB1:
|
||||
remote_state[5] = 0xFC;
|
||||
break;
|
||||
}
|
||||
fullCmd = true;
|
||||
break;
|
||||
}
|
||||
if (fullCmd) {
|
||||
remote_state[6] = 0x09;
|
||||
remote_state[7] = 0x30;
|
||||
if (fullCmd) { // long codes
|
||||
uint8_t tempByte = _temp - FUJITSU_AC_MIN_TEMP;
|
||||
// Nr. of bytes in the message after this byte.
|
||||
remote_state[6] = _state_length - 7;
|
||||
|
||||
remote_state[7] = 0x30;
|
||||
remote_state[8] = (_cmd == FUJITSU_AC_CMD_TURN_ON) | (tempByte << 4);
|
||||
remote_state[9] = _mode | 0 << 4; // timer off
|
||||
remote_state[10] = _fanSpeed | _swingMode << 4;
|
||||
remote_state[11] = 0; // timerOff values
|
||||
remote_state[12] = 0; // timerOff/on values
|
||||
remote_state[12] = 0; // timerOff/On values
|
||||
remote_state[13] = 0; // timerOn values
|
||||
remote_state[14] = 0x20;
|
||||
// Checksum is the sum of the 8th to 16th bytes (ie remote_state[7]
|
||||
// thru remote_state[15]).
|
||||
// The checksum itself is stored in the 16th byte (ie remote_state[15]).
|
||||
// So we sum bytes 8th-15th...
|
||||
if (_model == ARRAH2E)
|
||||
remote_state[14] = 0x20;
|
||||
else
|
||||
remote_state[14] = 0x00;
|
||||
|
||||
uint8_t checksum = 0;
|
||||
for (uint8_t i = 7 ; i < 15; ++i) {
|
||||
checksum += remote_state[i];
|
||||
uint8_t checksum_complement = 0;
|
||||
if (_model == ARRAH2E) {
|
||||
checksum = sumBytes(remote_state + _state_length_short,
|
||||
_state_length - _state_length_short - 1);
|
||||
} else if (_model == ARDB1) {
|
||||
checksum = sumBytes(remote_state, _state_length - 1);
|
||||
checksum_complement = 0x9B;
|
||||
}
|
||||
// and then do 0 - sum and store it in 16th.
|
||||
remote_state[15] = 0 - checksum;
|
||||
} else {
|
||||
// For the short codes, byte 7 is the inverse of byte 6
|
||||
remote_state[6] = ~remote_state[5];
|
||||
for (uint8_t i = 7; i < FUJITSU_AC_STATE_LENGTH; ++i) {
|
||||
// and negate the checksum and store it in the last byte.
|
||||
remote_state[_state_length - 1] = checksum_complement - checksum;
|
||||
} else { // short codes
|
||||
if (_model == ARRAH2E)
|
||||
// The last byte is the inverse of penultimate byte
|
||||
remote_state[_state_length_short - 1] = ~remote_state[_state_length_short
|
||||
- 2];
|
||||
// Zero the rest of the state.
|
||||
for (uint8_t i = _state_length_short;
|
||||
i < FUJITSU_AC_STATE_LENGTH;
|
||||
i++)
|
||||
remote_state[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t IRFujitsuAC::getStateLength() {
|
||||
buildState(); // Force an update of the internal state.
|
||||
if ((_model == ARRAH2E && remote_state[5] != 0xFE) ||
|
||||
(_model == ARDB1 && remote_state[5] != 0xFC))
|
||||
return _state_length_short;
|
||||
else
|
||||
return _state_length;
|
||||
}
|
||||
|
||||
// Return a pointer to the internal state date of the remote.
|
||||
uint8_t* IRFujitsuAC::getRaw() {
|
||||
buildState();
|
||||
return remote_state;
|
||||
}
|
||||
|
||||
void IRFujitsuAC::buildFromState(const uint16_t length) {
|
||||
switch (length) {
|
||||
case FUJITSU_AC_STATE_LENGTH - 1:
|
||||
case FUJITSU_AC_STATE_LENGTH_SHORT - 1:
|
||||
setModel(ARDB1);
|
||||
break;
|
||||
default:
|
||||
setModel(ARRAH2E);
|
||||
}
|
||||
switch (remote_state[6]) {
|
||||
case 8:
|
||||
setModel(ARDB1);
|
||||
break;
|
||||
case 9:
|
||||
setModel(ARRAH2E);
|
||||
break;
|
||||
}
|
||||
setTemp((remote_state[8] >> 4) + FUJITSU_AC_MIN_TEMP);
|
||||
if (remote_state[8] & 0x1)
|
||||
setCmd(FUJITSU_AC_CMD_TURN_ON);
|
||||
else
|
||||
setCmd(FUJITSU_AC_CMD_STAY_ON);
|
||||
setMode(remote_state[9] & 0b111);
|
||||
setFanSpeed(remote_state[10] & 0b111);
|
||||
setSwing(remote_state[10] >> 4);
|
||||
switch (remote_state[5]) {
|
||||
case FUJITSU_AC_CMD_TURN_OFF:
|
||||
case FUJITSU_AC_CMD_STEP_HORIZ:
|
||||
case FUJITSU_AC_CMD_STEP_VERT:
|
||||
setCmd(remote_state[5]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool IRFujitsuAC::setRaw(const uint8_t newState[], const uint16_t length) {
|
||||
if (length > FUJITSU_AC_STATE_LENGTH) return false;
|
||||
for (uint16_t i = 0; i < FUJITSU_AC_STATE_LENGTH; i++) {
|
||||
if (i < length)
|
||||
remote_state[i] = newState[i];
|
||||
else
|
||||
remote_state[i] = 0;
|
||||
}
|
||||
buildFromState(length);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set the requested power state of the A/C to off.
|
||||
void IRFujitsuAC::off() {
|
||||
_cmd = FUJITSU_AC_CMD_TURN_OFF;
|
||||
}
|
||||
|
||||
void IRFujitsuAC::stepHoriz() {
|
||||
_cmd = FUJITSU_AC_CMD_STEP_HORIZ;
|
||||
switch (_model) {
|
||||
case ARDB1: break; // This remote doesn't have a horizontal option.
|
||||
default:
|
||||
_cmd = FUJITSU_AC_CMD_STEP_HORIZ;
|
||||
}
|
||||
}
|
||||
|
||||
void IRFujitsuAC::stepVert() {
|
||||
@@ -162,20 +248,26 @@ void IRFujitsuAC::setCmd(uint8_t cmd) {
|
||||
case FUJITSU_AC_CMD_TURN_OFF:
|
||||
case FUJITSU_AC_CMD_TURN_ON:
|
||||
case FUJITSU_AC_CMD_STAY_ON:
|
||||
case FUJITSU_AC_CMD_STEP_HORIZ:
|
||||
case FUJITSU_AC_CMD_STEP_VERT:
|
||||
_cmd = cmd;
|
||||
break;
|
||||
case FUJITSU_AC_CMD_STEP_HORIZ:
|
||||
if (_model != ARDB1) // AR-DB1 remote doesn't have step horizontal.
|
||||
_cmd = cmd;
|
||||
default:
|
||||
cmd = FUJITSU_AC_CMD_STAY_ON;
|
||||
_cmd = FUJITSU_AC_CMD_STAY_ON;
|
||||
break;
|
||||
}
|
||||
_cmd = cmd;
|
||||
}
|
||||
|
||||
uint8_t IRFujitsuAC::getCmd() {
|
||||
return _cmd;
|
||||
}
|
||||
|
||||
bool IRFujitsuAC::getPower() {
|
||||
return _cmd != FUJITSU_AC_CMD_TURN_OFF;
|
||||
}
|
||||
|
||||
// Set the temp. in deg C
|
||||
void IRFujitsuAC::setTemp(uint8_t temp) {
|
||||
temp = std::max((uint8_t) FUJITSU_AC_MIN_TEMP, temp);
|
||||
@@ -209,8 +301,18 @@ uint8_t IRFujitsuAC::getMode() {
|
||||
}
|
||||
// Set the requested swing operation mode of the a/c unit.
|
||||
void IRFujitsuAC::setSwing(uint8_t swingMode) {
|
||||
if (swingMode > FUJITSU_AC_SWING_BOTH)
|
||||
swingMode = FUJITSU_AC_SWING_BOTH; // Set the mode to max if out of range
|
||||
switch (_model) {
|
||||
case ARDB1:
|
||||
// Set the mode to max if out of range
|
||||
if (swingMode > FUJITSU_AC_SWING_VERT)
|
||||
swingMode = FUJITSU_AC_SWING_VERT;
|
||||
break;
|
||||
case ARRAH2E:
|
||||
default:
|
||||
// Set the mode to max if out of range
|
||||
if (swingMode > FUJITSU_AC_SWING_BOTH)
|
||||
swingMode = FUJITSU_AC_SWING_BOTH;
|
||||
}
|
||||
_swingMode = swingMode;
|
||||
}
|
||||
|
||||
@@ -218,4 +320,228 @@ uint8_t IRFujitsuAC::getSwing() {
|
||||
return _swingMode;
|
||||
}
|
||||
|
||||
#endif
|
||||
bool IRFujitsuAC::validChecksum(uint8_t state[], uint16_t length) {
|
||||
uint8_t sum = 0;
|
||||
uint8_t sum_complement = 0;
|
||||
uint8_t checksum = 0;
|
||||
switch (length) {
|
||||
case FUJITSU_AC_STATE_LENGTH_SHORT: // ARRAH2E
|
||||
return state[length - 1] == (uint8_t) ~state[length - 2];
|
||||
case FUJITSU_AC_STATE_LENGTH - 1: // ARDB1
|
||||
sum = sumBytes(state, length - 1);
|
||||
sum_complement = 0x9B;
|
||||
checksum = state[length - 1];
|
||||
break;
|
||||
case FUJITSU_AC_STATE_LENGTH: // ARRAH2E
|
||||
sum = sumBytes(state + FUJITSU_AC_STATE_LENGTH_SHORT,
|
||||
length - 1 - FUJITSU_AC_STATE_LENGTH_SHORT);
|
||||
default: // Includes ARDB1 short.
|
||||
return true; // Assume the checksum is valid for other lengths.
|
||||
}
|
||||
return checksum == (uint8_t) (sum_complement - sum); // Does it match?
|
||||
}
|
||||
|
||||
// Convert the internal state into a human readable string.
|
||||
#ifdef ARDUINO
|
||||
String IRFujitsuAC::toString() {
|
||||
String result = "";
|
||||
#else
|
||||
std::string IRFujitsuAC::toString() {
|
||||
std::string result = "";
|
||||
#endif // ARDUINO
|
||||
result += "Power: ";
|
||||
if (getPower())
|
||||
result += "On";
|
||||
else
|
||||
result += "Off";
|
||||
result += ", Mode: " + uint64ToString(getMode());
|
||||
switch (getMode()) {
|
||||
case FUJITSU_AC_MODE_AUTO:
|
||||
result += " (AUTO)";
|
||||
break;
|
||||
case FUJITSU_AC_MODE_COOL:
|
||||
result += " (COOL)";
|
||||
break;
|
||||
case FUJITSU_AC_MODE_HEAT:
|
||||
result += " (HEAT)";
|
||||
break;
|
||||
case FUJITSU_AC_MODE_DRY:
|
||||
result += " (DRY)";
|
||||
break;
|
||||
case FUJITSU_AC_MODE_FAN:
|
||||
result += " (FAN)";
|
||||
break;
|
||||
default:
|
||||
result += " (UNKNOWN)";
|
||||
}
|
||||
result += ", Temp: " + uint64ToString(getTemp()) + "C";
|
||||
result += ", Fan: " + uint64ToString(getFanSpeed());
|
||||
switch (getFanSpeed()) {
|
||||
case FUJITSU_AC_FAN_AUTO:
|
||||
result += " (AUTO)";
|
||||
break;
|
||||
case FUJITSU_AC_FAN_HIGH:
|
||||
result += " (HIGH)";
|
||||
break;
|
||||
case FUJITSU_AC_FAN_MED:
|
||||
result += " (MED)";
|
||||
break;
|
||||
case FUJITSU_AC_FAN_LOW:
|
||||
result += " (LOW)";
|
||||
break;
|
||||
case FUJITSU_AC_FAN_QUIET:
|
||||
result += " (QUIET)";
|
||||
break;
|
||||
}
|
||||
result += ", Swing: ";
|
||||
switch (getSwing()) {
|
||||
case FUJITSU_AC_SWING_OFF:
|
||||
result += "Off";
|
||||
break;
|
||||
case FUJITSU_AC_SWING_VERT:
|
||||
result += "Vert";
|
||||
break;
|
||||
case FUJITSU_AC_SWING_HORIZ:
|
||||
result += "Horiz";
|
||||
break;
|
||||
case FUJITSU_AC_SWING_BOTH:
|
||||
result += "Vert + Horiz";
|
||||
break;
|
||||
default:
|
||||
result += "UNKNOWN";
|
||||
}
|
||||
result += ", Command: ";
|
||||
switch (getCmd()) {
|
||||
case FUJITSU_AC_CMD_STEP_HORIZ:
|
||||
result += "Step vane horizontally";
|
||||
break;
|
||||
case FUJITSU_AC_CMD_STEP_VERT:
|
||||
result += "Step vane vertically";
|
||||
break;
|
||||
default:
|
||||
result += "N/A";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#if DECODE_FUJITSU_AC
|
||||
// Decode a Fujitsu AC IR message if possible.
|
||||
// Places successful decode information in the results pointer.
|
||||
// Args:
|
||||
// results: Ptr to the data to decode and where to store the decode result.
|
||||
// nbits: The number of data bits to expect. Typically FUJITSU_AC_BITS.
|
||||
// strict: Flag to indicate if we strictly adhere to the specification.
|
||||
// Returns:
|
||||
// boolean: True if it can decode it, false if it can't.
|
||||
//
|
||||
// Status: ALPHA / Untested.
|
||||
//
|
||||
// Ref:
|
||||
//
|
||||
bool IRrecv::decodeFujitsuAC(decode_results *results, uint16_t nbits,
|
||||
bool strict) {
|
||||
uint16_t offset = OFFSET_START;
|
||||
uint16_t dataBitsSoFar = 0;
|
||||
|
||||
// Have we got enough data to successfully decode?
|
||||
if (results->rawlen < (2 * FUJITSU_AC_MIN_BITS) + HEADER + FOOTER - 1)
|
||||
return false; // Can't possibly be a valid message.
|
||||
|
||||
|
||||
// Compliance
|
||||
if (strict) {
|
||||
switch (nbits) {
|
||||
case FUJITSU_AC_BITS:
|
||||
case FUJITSU_AC_BITS - 8:
|
||||
case FUJITSU_AC_MIN_BITS:
|
||||
case FUJITSU_AC_MIN_BITS + 8:
|
||||
break;
|
||||
default:
|
||||
return false; // Must be called with the correct nr. of bits.
|
||||
}
|
||||
}
|
||||
|
||||
// Header
|
||||
if (!matchMark(results->rawbuf[offset++], FUJITSU_AC_HDR_MARK))
|
||||
return false;
|
||||
if (!matchSpace(results->rawbuf[offset++], FUJITSU_AC_HDR_SPACE))
|
||||
return false;
|
||||
|
||||
// Data (Fixed signature)
|
||||
match_result_t data_result = matchData(&(results->rawbuf[offset]),
|
||||
FUJITSU_AC_MIN_BITS - 8,
|
||||
FUJITSU_AC_BIT_MARK,
|
||||
FUJITSU_AC_ONE_SPACE,
|
||||
FUJITSU_AC_BIT_MARK,
|
||||
FUJITSU_AC_ZERO_SPACE);
|
||||
if (data_result.success == false) return false; // Fail
|
||||
if (reverseBits(data_result.data, FUJITSU_AC_MIN_BITS - 8) != 0x1010006314)
|
||||
return false; // Signature failed.
|
||||
dataBitsSoFar += FUJITSU_AC_MIN_BITS - 8;
|
||||
offset += data_result.used;
|
||||
results->state[0] = 0x14;
|
||||
results->state[1] = 0x63;
|
||||
results->state[2] = 0x00;
|
||||
results->state[3] = 0x10;
|
||||
results->state[4] = 0x10;
|
||||
|
||||
// Keep reading bytes until we either run out of message or state to fill.
|
||||
for (uint16_t i = 5;
|
||||
offset <= results->rawlen - 16 && i < FUJITSU_AC_STATE_LENGTH;
|
||||
i++, dataBitsSoFar += 8, offset += data_result.used) {
|
||||
data_result = matchData(&(results->rawbuf[offset]), 8,
|
||||
FUJITSU_AC_BIT_MARK,
|
||||
FUJITSU_AC_ONE_SPACE,
|
||||
FUJITSU_AC_BIT_MARK,
|
||||
FUJITSU_AC_ZERO_SPACE);
|
||||
if (data_result.success == false) break; // Fail
|
||||
results->state[i] = (uint8_t) reverseBits(data_result.data, 8);
|
||||
}
|
||||
|
||||
// Footer
|
||||
if (offset > results->rawlen ||
|
||||
!matchMark(results->rawbuf[offset++], FUJITSU_AC_BIT_MARK)) return false;
|
||||
// The space is optional if we are out of capture.
|
||||
if (offset < results->rawlen &&
|
||||
!matchAtLeast(results->rawbuf[offset], FUJITSU_AC_MIN_GAP)) return false;
|
||||
|
||||
// Compliance
|
||||
if (strict) {
|
||||
if (dataBitsSoFar != nbits) return false;
|
||||
}
|
||||
|
||||
results->decode_type = FUJITSU_AC;
|
||||
results->bits = dataBitsSoFar;
|
||||
|
||||
// Compliance
|
||||
switch (dataBitsSoFar) {
|
||||
case FUJITSU_AC_MIN_BITS:
|
||||
// Check if this values indicate that this should have been a long state
|
||||
// message.
|
||||
if (results->state[5] == 0xFC) return false;
|
||||
return true; // Success
|
||||
case FUJITSU_AC_MIN_BITS + 8:
|
||||
// Check if this values indicate that this should have been a long state
|
||||
// message.
|
||||
if (results->state[5] == 0xFE) return false;
|
||||
// The last byte needs to be the inverse of the penultimate byte.
|
||||
if (results->state[5] != (uint8_t) ~results->state[6]) return false;
|
||||
return true; // Success
|
||||
case FUJITSU_AC_BITS - 8:
|
||||
// Long messages of this size require this byte be correct.
|
||||
if (results->state[5] != 0xFC) return false;
|
||||
break;
|
||||
case FUJITSU_AC_BITS:
|
||||
// Long messages of this size require this byte be correct.
|
||||
if (results->state[5] != 0xFE) return false;
|
||||
break;
|
||||
default:
|
||||
return false; // Unexpected size.
|
||||
}
|
||||
if (!IRFujitsuAC::validChecksum(results->state, dataBitsSoFar / 8))
|
||||
return false;
|
||||
|
||||
// Success
|
||||
return true; // All good.
|
||||
}
|
||||
#endif // DECODE_FUJITSU_AC
|
||||
Reference in new issue
Block a user