Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -932,7 +932,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 @@ -1123,7 +1123,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
196 changes: 106 additions & 90 deletions src/ir_Argo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const uint16_t kArgoOneSpace = 2200;
const uint16_t kArgoZeroSpace = 900;
const uint32_t kArgoGap = kDefaultMessageGap; // Made up value. Complete guess.

const uint8_t kArgoSensorCheck = 52; // Part of the sensor message check calc.
const uint8_t kArgoSensorFixed = 0b011;

using irutils::addBoolToString;
using irutils::addIntToString;
using irutils::addLabeledString;
Expand All @@ -37,8 +40,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 @@ -66,24 +67,21 @@ void IRArgoAC::send(const uint16_t repeat) {

/// Send current room temperature for the iFeel feature as a silent IR
/// message (no acknowledgement from the device).
/// @param[in] temp The temperature in degrees celsius.
/// @param[in] degrees 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;

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;

_irsend.sendArgo(data.raw, kArgoStateLength, repeat);
void IRArgoAC::sendSensorTemp(const uint8_t degrees, const uint16_t repeat) {
const uint8_t temp = std::max(std::min(degrees, kArgoMaxRoomTemp),
kArgoTempDelta) - kArgoTempDelta;
const uint8_t check = kArgoSensorCheck + temp;

ArgoProtocol data;
_stateReset(&data);
data.SensorT = temp;
data.CheckHi = check >> 5;
data.CheckLo = check;
data.Fixed = kArgoSensorFixed;
_checksum(&data);
_irsend.sendArgo(data.raw, kArgoStateLength, repeat);
}
#endif // SEND_ARGO

Expand All @@ -107,32 +105,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 +148,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 +198,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 +405,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
30 changes: 25 additions & 5 deletions src/ir_Argo.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// Copyright 2017 Schmolders
// Copyright 2022 crankyoldgit
/// @file
/// @brief Support for Argo Ulisse 13 DCI Mobile Split ACs.

Expand All @@ -25,9 +26,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 +58,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 @@ -131,7 +146,7 @@ class IRArgoAC {

#if SEND_ARGO
void send(const uint16_t repeat = kArgoDefaultRepeat);
void sendSensorTemp(const uint8_t temp,
void sendSensorTemp(const uint8_t degrees,
const uint16_t repeat = kArgoDefaultRepeat);
/// Run the calibration to calculate uSec timing offsets for this platform.
/// @return The uSec timing offset needed per modulation of the IR Led.
Expand All @@ -149,6 +164,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 +189,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 +212,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