Skip to content

Commit

Permalink
ARGO: Improve code & add support for decoding 32bit sensor msgs.
Browse files Browse the repository at this point in the history
* Add `getSensorTemp()`.
* deduplicate code used.
* Support decoding 32bit `ARGO` messages.

For crankyoldgit#1859
  • Loading branch information
crankyoldgit authored and mbronk committed Oct 16, 2022
1 parent 71cd956 commit d3b27ed
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 106 deletions.
13 changes: 10 additions & 3 deletions src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3797,7 +3797,7 @@ namespace IRAcUtils {
#if DECODE_ARGO
case decode_type_t::ARGO: {
IRArgoAC ac(kGpioUnused);
ac.setRaw(result->state);
ac.setRaw(result->state, result->bits / 8);
return ac.toString();
}
#endif // DECODE_ARGO
Expand Down Expand Up @@ -4259,8 +4259,15 @@ namespace IRAcUtils {
#if DECODE_ARGO
case decode_type_t::ARGO: {
IRArgoAC ac(kGpioUnused);
ac.setRaw(decode->state);
*result = ac.toCommon();
const uint16_t length = decode->bits / 8;
switch (length) {
case kArgoStateLength:
ac.setRaw(decode->state, length);
*result = ac.toCommon();
break;
default:
return false;
}
break;
}
#endif // DECODE_ARGO
Expand Down
3 changes: 2 additions & 1 deletion src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,8 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
#endif
#if DECODE_ARGO
DPRINTLN("Attempting Argo decode");
if (decodeArgo(results, offset)) return true;
if (decodeArgo(results, offset) ||
decodeArgo(results, offset, kArgoShortBits, false)) return true;
#endif // DECODE_ARGO
#if DECODE_SHARP_AC
DPRINTLN("Attempting SHARP_AC decode");
Expand Down
2 changes: 2 additions & 0 deletions src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -1131,7 +1131,9 @@ const uint16_t kAmcorStateLength = 8;
const uint16_t kAmcorBits = kAmcorStateLength * 8;
const uint16_t kAmcorDefaultRepeat = kSingleRepeat;
const uint16_t kArgoStateLength = 12;
const uint16_t kArgoShortStateLength = 4;
const uint16_t kArgoBits = kArgoStateLength * 8;
const uint16_t kArgoShortBits = kArgoShortStateLength * 8;
const uint16_t kArgoDefaultRepeat = kNoRepeat;
const uint16_t kArrisBits = 32;
const uint16_t kBosch144StateLength = 18;
Expand Down
185 changes: 100 additions & 85 deletions src/ir_Argo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ using irutils::addTempToString;
/// @param[in] repeat The number of times the command is to be repeated.
void IRsend::sendArgo(const unsigned char data[], const uint16_t nbytes,
const uint16_t repeat) {
// Check if we have enough bytes to send a proper message.
if (nbytes < kArgoStateLength) return;
// TODO(kaschmo): validate
sendGeneric(kArgoHdrMark, kArgoHdrSpace, kArgoBitMark, kArgoOneSpace,
kArgoBitMark, kArgoZeroSpace, 0, 0, // No Footer.
Expand Down Expand Up @@ -69,20 +67,19 @@ void IRArgoAC::send(const uint16_t repeat) {
/// @param[in] temp The temperature in degrees celsius.
/// @param[in] repeat Nr. of times the message will be repeated.
void IRArgoAC::sendSensorTemp(const uint8_t temp, const uint16_t repeat) {
uint8_t tempc = temp - kArgoTempDelta;
uint8_t check = 52 + tempc;
uint8_t end = 0b011;
const uint8_t tempc = temp - kArgoTempDelta;
const uint8_t check = 52 + tempc;
const uint8_t end = 0b011;

ArgoProtocol data;
data.raw[0] = 0b10101100;
data.raw[1] = 0b11110101;
data.raw[2] = (tempc << 3) | (check >> 5);
data.raw[3] = (check << 3) | end;
for (uint8_t i = 4; i < kArgoStateLength; i++) data.raw[i] = 0x0;
uint8_t sum = IRArgoAC::calcChecksum(data.raw, kArgoStateLength);
data.raw[10] = 0b00000010;
data.Sum = sum;

_stateReset(&data);
// data.raw[2] = (tempc << 3) | (check >> 5);
data.SensorT = tempc;
data.CheckHi = check >> 5;
// data.raw[3] = (check << 3) | end;
data.CheckLo = check;
data.Fixed = end;
_checksum(&data);
_irsend.sendArgo(data.raw, kArgoStateLength, repeat);
}
#endif // SEND_ARGO
Expand All @@ -107,32 +104,37 @@ bool IRArgoAC::validChecksum(const uint8_t state[], const uint16_t length) {
IRArgoAC::calcChecksum(state, length);
}

/// Update the checksum for the internal state.
void IRArgoAC::checksum(void) {
uint8_t sum = IRArgoAC::calcChecksum(_.raw, kArgoStateLength);
/// Update the checksum for a given state.
/// @param[in,out] state Pointer to a binary representation of the A/C state.
void IRArgoAC::_checksum(ArgoProtocol *state) {
uint8_t sum = IRArgoAC::calcChecksum(state->raw, kArgoStateLength);
// Append sum to end of array
// Set const part of checksum bit 10
_.raw[10] = 0b00000010;
_.Sum = sum;
state->Post = kArgoPost;
state->Sum = sum;
}

/// Update the checksum for the internal state.
void IRArgoAC::checksum(void) { _checksum(&_); }

/// Reset the given state to a known good state.
/// @param[in,out] state Pointer to a binary representation of the A/C state.
void IRArgoAC::_stateReset(ArgoProtocol *state) {
for (uint8_t i = 2; i < kArgoStateLength; i++) state->raw[i] = 0x0;
state->Pre1 = kArgoPreamble1; // LSB first (as sent) 0b00110101;
state->Pre2 = kArgoPreamble2; // LSB first: 0b10101111; //const preamble
state->Post = kArgoPost;
}

/// Reset the internals of the object to a known good state.
void IRArgoAC::stateReset(void) {
for (uint8_t i = 0; i < kArgoStateLength; i++) _.raw[i] = 0x0;

// Argo Message. Store MSB left.
// Default message:
_.raw[0] = 0b10101100; // LSB first (as sent) 0b00110101; //const preamble
_.raw[1] = 0b11110101; // LSB first: 0b10101111; //const preamble
// Keep payload 2-9 at zero
_.raw[10] = 0b00000010; // Const 01
_.Sum = 0;

_stateReset(&_);
off();
setTemp(20);
setRoomTemp(25);
setMode(kArgoAuto);
setFan(kArgoFanAuto);
_length = kArgoStateLength;
}

/// Get the raw state of the object, suitable to be sent with the appropriate
Expand All @@ -145,8 +147,10 @@ uint8_t* IRArgoAC::getRaw(void) {

/// Set the raw state of the object.
/// @param[in] state The raw state from the native IR message.
void IRArgoAC::setRaw(const uint8_t state[]) {
std::memcpy(_.raw, state, kArgoStateLength);
/// @param[in] length The length of raw state in bytes.
void IRArgoAC::setRaw(const uint8_t state[], const uint16_t length) {
std::memcpy(_.raw, state, length);
_length = length;
}

/// Set the internal state to have the power on.
Expand Down Expand Up @@ -193,6 +197,12 @@ uint8_t IRArgoAC::getTemp(void) const {
return _.Temp + kArgoTempDelta;
}

/// Get the current sensor temperature setting.
/// @return The current setting for the sensor. in degrees celsius.
uint8_t IRArgoAC::getSensorTemp(void) const {
return (_length == kArgoShortStateLength) ? _.SensorT + kArgoTempDelta : 0;
}

/// Set the speed of the fan.
/// @param[in] fan The desired setting.
void IRArgoAC::setFan(const uint8_t fan) {
Expand Down Expand Up @@ -394,61 +404,66 @@ stdAc::state_t IRArgoAC::toCommon(void) const {
String IRArgoAC::toString(void) const {
String result = "";
result.reserve(100); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(_.Power, kPowerStr, false);
result += addIntToString(_.Mode, kModeStr);
result += kSpaceLBraceStr;
switch (_.Mode) {
case kArgoAuto:
result += kAutoStr;
break;
case kArgoCool:
result += kCoolStr;
break;
case kArgoHeat:
result += kHeatStr;
break;
case kArgoDry:
result += kDryStr;
break;
case kArgoHeatAuto:
result += kHeatStr;
result += ' ';
result += kAutoStr;
break;
case kArgoOff:
result += kOffStr;
break;
default:
result += kUnknownStr;
}
result += ')';
result += addIntToString(_.Fan, kFanStr);
result += kSpaceLBraceStr;
switch (_.Fan) {
case kArgoFanAuto:
result += kAutoStr;
break;
case kArgoFan3:
result += kMaxStr;
break;
case kArgoFan1:
result += kMinStr;
break;
case kArgoFan2:
result += kMedStr;
break;
default:
result += kUnknownStr;
if (_length == kArgoShortStateLength) {
result += addIntToString(getSensorTemp(), kSensorTempStr, false);
result += 'C';
} else {
result += addBoolToString(_.Power, kPowerStr, false);
result += addIntToString(_.Mode, kModeStr);
result += kSpaceLBraceStr;
switch (_.Mode) {
case kArgoAuto:
result += kAutoStr;
break;
case kArgoCool:
result += kCoolStr;
break;
case kArgoHeat:
result += kHeatStr;
break;
case kArgoDry:
result += kDryStr;
break;
case kArgoHeatAuto:
result += kHeatStr;
result += ' ';
result += kAutoStr;
break;
case kArgoOff:
result += kOffStr;
break;
default:
result += kUnknownStr;
}
result += ')';
result += addIntToString(_.Fan, kFanStr);
result += kSpaceLBraceStr;
switch (_.Fan) {
case kArgoFanAuto:
result += kAutoStr;
break;
case kArgoFan3:
result += kMaxStr;
break;
case kArgoFan1:
result += kMinStr;
break;
case kArgoFan2:
result += kMedStr;
break;
default:
result += kUnknownStr;
}
result += ')';
result += addTempToString(getTemp());
result += kCommaSpaceStr;
result += kRoomStr;
result += ' ';
result += addTempToString(getRoomTemp(), true, false);
result += addBoolToString(_.Max, kMaxStr);
result += addBoolToString(_.iFeel, kIFeelStr);
result += addBoolToString(_.Night, kNightStr);
}
result += ')';
result += addTempToString(getTemp());
result += kCommaSpaceStr;
result += kRoomStr;
result += ' ';
result += addTempToString(getRoomTemp(), true, false);
result += addBoolToString(_.Max, kMaxStr);
result += addBoolToString(_.iFeel, kIFeelStr);
result += addBoolToString(_.Night, kNightStr);
return result;
}

Expand Down
27 changes: 23 additions & 4 deletions src/ir_Argo.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ union ArgoProtocol {
uint8_t raw[kArgoStateLength]; ///< The state in native IR code form
struct {
// Byte 0
uint64_t :8; // Typically 0b00110101
uint64_t Pre1 :8; // Typically 0b00110101
// Byte 1
uint64_t :8; // Typically 0b10101111
uint64_t Pre2 :8; // Typically 0b10101111
// Byte 2~4
uint64_t :3;
uint64_t Mode :3;
Expand Down Expand Up @@ -57,16 +57,30 @@ union ArgoProtocol {
uint32_t :1; // const 0
uint32_t iFeel :1;
// Byte 10~11
uint32_t :2; // const 01
uint32_t Post :2;
uint32_t Sum :8; // straddle byte 10 and 11
uint32_t :6;
};
struct {
// Byte 0-1
uint8_t :8;
uint8_t :8;
// Byte 2-3
uint8_t CheckHi :3;
uint8_t SensorT :5;
uint8_t Fixed :3; // Typically 0b011
uint8_t CheckLo :5;
};
};

// Constants. Store MSB left.

const uint8_t kArgoHeatBit = 0b00100000;

const uint8_t kArgoPreamble1 = 0b10101100;
const uint8_t kArgoPreamble2 = 0b11110101;
const uint8_t kArgoPost = 0b00000010;

// Mode 0b00111000
const uint8_t kArgoCool = 0b000;
const uint8_t kArgoDry = 0b001;
Expand Down Expand Up @@ -149,6 +163,8 @@ class IRArgoAC {
void setTemp(const uint8_t degrees);
uint8_t getTemp(void) const;

uint8_t getSensorTemp(void) const;

void setFan(const uint8_t fan);
uint8_t getFan(void) const;

Expand All @@ -172,7 +188,7 @@ class IRArgoAC {
uint8_t getRoomTemp(void) const;

uint8_t* getRaw(void);
void setRaw(const uint8_t state[]);
void setRaw(const uint8_t state[], const uint16_t length = kArgoStateLength);
static uint8_t calcChecksum(const uint8_t state[],
const uint16_t length = kArgoStateLength);
static bool validChecksum(const uint8_t state[],
Expand All @@ -195,13 +211,16 @@ class IRArgoAC {
#endif
// # of bytes per command
ArgoProtocol _;
void _stateReset(ArgoProtocol *state);
void stateReset(void);
void _checksum(ArgoProtocol *state);
void checksum(void);

// Attributes
uint8_t flap_mode;
uint8_t heat_mode;
uint8_t cool_mode;
uint16_t _length = kArgoStateLength;
};

#endif // IR_ARGO_H_
Loading

0 comments on commit d3b27ed

Please sign in to comment.