Skip to content
Open
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
10 changes: 6 additions & 4 deletions src/IRac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,13 +644,14 @@ void IRac::argoWrem3_SetTimer(IRArgoAC_WREM3 *ac, bool on,
/// @param[in] on The power setting.
/// @param[in] mode The operation mode setting.
/// @param[in] degrees The temperature setting in degrees.
/// @param[in] celsius Temperature units. True is Celsius, False is Fahrenheit.
/// @param[in] fan The speed setting for the fan.
/// @param[in] quiet Run the device in quiet/silent mode.
/// @note -1 is Off, >= 0 is on.
void IRac::bosch144(IRBosch144AC *ac,
const bool on, const stdAc::opmode_t mode,
const float degrees, const stdAc::fanspeed_t fan,
const bool quiet) {
const float degrees, const bool celsius,
const stdAc::fanspeed_t fan, const bool quiet) {
ac->begin();
ac->setPower(on);
if (!on) {
Expand All @@ -659,7 +660,7 @@ void IRac::bosch144(IRBosch144AC *ac,
ac->send();
return;
}
ac->setTemp(degrees);
ac->setTemp(degrees, !celsius);
ac->setFan(ac->convertFan(fan));
ac->setMode(ac->convertMode(mode));
ac->setQuiet(quiet);
Expand Down Expand Up @@ -3107,7 +3108,8 @@ bool IRac::sendAc(const stdAc::state_t desired, const stdAc::state_t *prev) {
case BOSCH144:
{
IRBosch144AC ac(_pin, _inverted, _modulation);
bosch144(&ac, send.power, send.mode, degC, send.fanspeed, send.quiet);
bosch144(&ac, send.power, send.mode, send.degrees, send.celsius,
send.fanspeed, send.quiet);
break;
}
#endif // SEND_BOSCH144
Expand Down
2 changes: 1 addition & 1 deletion src/IRac.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class IRac {
#if SEND_BOSCH144
void bosch144(IRBosch144AC *ac,
const bool on, const stdAc::opmode_t mode, const float degrees,
const stdAc::fanspeed_t fan,
const bool celsius, const stdAc::fanspeed_t fan,
const bool quiet);
#endif // SEND_BOSCH144
#if SEND_CARRIER_AC64
Expand Down
60 changes: 44 additions & 16 deletions src/ir_Bosch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,27 +95,55 @@ bool IRBosch144AC::getPower(void) const {
}

void IRBosch144AC::setTempRaw(const uint8_t code) {
_.TempS1 = _.TempS2 = code >> 1; // save 4 bits in S1 and S2
_.TempS3 = code & 1; // save 1 bit in Section3
_.TempS1 = _.TempS2 = code >> 2; // save bits 3-6 in S1 and S2
_.TempS3 = code >> 1; // save bit 2 in Section3
_.TempS4 = code; // save bit 1 in Section3
}

/// Set the temperature.
/// @param[in] degrees The temperature in degrees celsius.
void IRBosch144AC::setTemp(const uint8_t degrees) {
uint8_t temp = max(kBosch144TempMin, degrees);
temp = min(kBosch144TempMax, temp);
setTempRaw(kBosch144TempMap[temp - kBosch144TempMin]);
/// Set the temp. in degrees
/// @param[in] temp Desired temperature in Degrees.
/// @param[in] fahrenheit Use units of Fahrenheit and set that as units used.
/// false is Celsius (Default), true is Fahrenheit.
void IRBosch144AC::setTemp(const uint8_t temp, const bool fahrenheit) {
if (fahrenheit) {
uint8_t constrainedTemp = max(kBosch144FahrenheitMin, temp);
constrainedTemp = min(kBosch144FahrenheitMax, constrainedTemp);
setTempRaw(
kBosch144FahrenheitMap[constrainedTemp - kBosch144FahrenheitMin]);
setUseFahrenheit(true);
} else {
uint8_t constrainedTemp = max(kBosch144CelsiusMin, temp);
constrainedTemp = min(kBosch144CelsiusMax, constrainedTemp);
setTempRaw(kBosch144CelsiusMap[constrainedTemp - kBosch144CelsiusMin]);
setUseFahrenheit(false);
}
}

uint8_t IRBosch144AC::getTemp(void) const {
uint8_t temp = (_.TempS1 << 1) + _.TempS3;
uint8_t retemp = 25;
for (uint8_t i = 0; i < kBosch144TempRange; i++) {
if (temp == kBosch144TempMap[i]) {
retemp = kBosch144TempMin + i;
uint8_t temp = (_.TempS1 << 2) + (_.TempS3 << 1) + _.TempS4;
if (getUseFahrenheit()) {
for (uint8_t i = 0; i < sizeof(kBosch144FahrenheitMap); i++) {
if (temp == kBosch144FahrenheitMap[i]) {
return kBosch144FahrenheitMin + i;
}
}
return 77;
} else {
for (uint8_t i = 0; i < sizeof(kBosch144CelsiusMap); i++) {
if (temp == kBosch144CelsiusMap[i]) {
return kBosch144CelsiusMin + i;
}
}
return 25;
}
return retemp;
}

void IRBosch144AC::setUseFahrenheit(const bool on) {
_.UseFahrenheit = on;
}

bool IRBosch144AC::getUseFahrenheit(void) const {
return _.UseFahrenheit;
}

/// Set the speed of the fan.
Expand Down Expand Up @@ -227,7 +255,7 @@ stdAc::state_t IRBosch144AC::toCommon(void) const {
result.protocol = decode_type_t::BOSCH144;
result.power = getPower();
result.mode = toCommonMode(getMode());
result.celsius = true;
result.celsius = !getUseFahrenheit();
result.degrees = getTemp();
result.fanspeed = toCommonFanSpeed(getFan());
result.quiet = getQuiet();
Expand Down Expand Up @@ -261,7 +289,7 @@ String IRBosch144AC::toString(void) const {
static_cast<int>(stdAc::fanspeed_t::kAuto),
static_cast<int>(stdAc::fanspeed_t::kAuto),
static_cast<int>(stdAc::fanspeed_t::kMedium));
result += addTempToString(getTemp());
result += addTempToString(getTemp(), !getUseFahrenheit());
result += addBoolToString(_.Quiet, kQuietStr);
return result;
}
Expand Down
145 changes: 94 additions & 51 deletions src/ir_Bosch.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// Supports:
// Brand: Bosch, Model: CL3000i-Set 26 E A/C
// Brand: Bosch, Model: RG10A(G2S)BGEF remote
// Brand: Durastar, Model: RG10R(M2S)/BGEFU1 remote


#ifndef IR_BOSCH_H_
Expand Down Expand Up @@ -66,25 +67,62 @@ const uint16_t kBosch144FanAuto = 0b101110011;
const uint16_t kBosch144FanAuto0 = 0b000110011;

// Temperature
const uint8_t kBosch144TempMin = 16; // Celsius
const uint8_t kBosch144TempMax = 30; // Celsius
const uint8_t kBosch144TempRange = kBosch144TempMax - kBosch144TempMin + 1;
const uint8_t kBosch144TempMap[kBosch144TempRange] = {
0b00001, // 16C // Bit[0] to Section 3 Bit[1-4] to Section 1
0b00000, // 17C // TempS3 TempS1
0b00010, // 18c
0b00110, // 19C
0b00100, // 20C
0b01100, // 21C
0b01110, // 22C
0b01010, // 23C
0b01000, // 24C
0b11000, // 25C
0b11010, // 26C
0b10010, // 27C
0b10000, // 28C
0b10100, // 29C
0b10110 // 30C
const uint8_t kBosch144CelsiusMin = 16;
const uint8_t kBosch144CelsiusMax = 30;
const uint8_t kBosch144CelsiusMap[] = {
// Bit[0] to Section 3: TempS4 (the "half-degree" bit)
// Bit[1] to Section 3: TempS3
// Bit[1-4] to Section 1: TempS1
0b000010, // 16C
0b000000, // 17C
0b000100, // 18C
0b001100, // 19C
0b001000, // 20C
0b011000, // 21C
0b011100, // 22C
0b010100, // 23C
0b010000, // 24C
0b110000, // 25C
0b110100, // 26C
0b100100, // 27C
0b100000, // 28C
0b101000, // 29C
0b101100 // 30C
};

const uint8_t kBosch144FahrenheitMin = 60;
const uint8_t kBosch144FahrenheitMax = 86;
const uint8_t kBosch144FahrenheitMap[] = {
// Bit[0] to Section 3: TempS4
// Bit[1] to Section 3: TempS3
// Bit[1-4] to Section 1: TempS1
0b000010, // 60F
0b000011, // 61F
0b000000, // 62F
0b000001, // 63F
0b000100, // 64F
0b000101, // 65F
0b001100, // 66F
0b001101, // 67F
0b001000, // 68F
0b001001, // 69F
0b011000, // 70F
0b011001, // 71F
0b011100, // 72F
0b010100, // 73F
0b010101, // 74F
0b010000, // 75F
0b010001, // 76F
0b110000, // 77F
0b110001, // 78F
0b110100, // 79F
0b110101, // 80F
0b100100, // 81F
0b100000, // 82F
0b100001, // 83F
0b101000, // 84F
0b101001, // 85F
0b101100 // 86F
};

// "OFF" is a 96bit-message the same as Coolix protocol
Expand All @@ -100,37 +138,40 @@ const uint8_t kBosch144DefaultState[kBosch144StateLength] = {
union Bosch144Protocol {
uint8_t raw[kBosch144StateLength]; ///< The state in IR code form.
struct {
uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############
uint8_t InnvertS1_1:8; // Invert byte 0b01001101 / 0x4D #
uint8_t :5; // not used (without timer use) #
uint8_t FanS1 :3; // Fan speed bits in Section 1 #
uint8_t InnvertS1_2:8; // Invert byte # Section 1 =
uint8_t :2; // not used (without timer use) # Sektion 2
uint8_t ModeS1 :2; // Operation mode bits S1 #
uint8_t TempS1 :4; // Desired temperature (Celsius) S2 #
uint8_t InnvertS1_3:8; // Invert byte (without timer use) ############

uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############
uint8_t InnvertS2_1:8; // Invert byte 0b01001101 / 0x4D #
uint8_t :5; // not used (without timer use) #
uint8_t FanS2 :3; // Fan speed bits in Section 2 #
uint8_t InnvertS2_2:8; // Invert byte # Section 2 =
uint8_t :2; // not used (without timer use) # Sektion 1
uint8_t ModeS2 :2; // Operation mode bits S2 #
uint8_t TempS2 :4; // Desired temperature (Celsius) S2 #
uint8_t InnvertS2_3:8; // Invert byte (without timer use) ###########

uint8_t :8; // Fixed value 0b11010101 / 0xD5 ###########
uint8_t ModeS3 :1; // ModeBit in Section 3 #
uint8_t FanS3 :6; // Fan speed bits in Section 3 #
uint8_t :1; // Unknown #
uint8_t :7; // Unknown #
uint8_t Quiet :1; // Silent-Mode # Section 3
uint8_t :4; // Unknown #
uint8_t TempS3 :1; // Desired temp. Bit in Section3 #
uint8_t :3; // Unknown #
uint8_t :8; // Unknown #
uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ###########
uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############
uint8_t InnvertS1_1 :8; // Invert byte 0b01001101 / 0x4D #
uint8_t :5; // not used (without timer use) #
uint8_t FanS1 :3; // Fan speed bits in Section 1 #
uint8_t InnvertS1_2 :8; // Invert byte # Section 1
uint8_t :2; // not used (without timer use) # =
uint8_t ModeS1 :2; // Operation mode bits S1 # Section 2
uint8_t TempS1 :4; // Desired temperature (Celsius) S2 #
uint8_t InnvertS1_3 :8; // Invert byte (without timer use) ############

uint8_t :8; // Fixed value 0b10110010 / 0xB2. ############
uint8_t InnvertS2_1 :8; // Invert byte 0b01001101 / 0x4D #
uint8_t :5; // not used (without timer use) #
uint8_t FanS2 :3; // Fan speed bits in Section 2 #
uint8_t InnvertS2_2 :8; // Invert byte # Section 2
uint8_t :2; // not used (without timer use) # =
uint8_t ModeS2 :2; // Operation mode bits S2 # Section 1
uint8_t TempS2 :4; // Desired temperature (Celsius) S2 #
uint8_t InnvertS2_3 :8; // Invert byte (without timer use) ###########

uint8_t :8; // Fixed value 0b11010101 / 0xD5 ###########
uint8_t ModeS3 :1; // ModeBit in Section 3 #
uint8_t FanS3 :6; // Fan speed bits in Section 3 #
uint8_t :1; // Unknown #
uint8_t :5; // Unknown #
uint8_t TempS4 :1; // Desired temp #
uint8_t :1; // Unknown #
uint8_t Quiet :1; // Silent-Mode # Section 3
uint8_t UseFahrenheit :1; // Fahrenheit or Celcius #
uint8_t :3; // Unknown #
uint8_t TempS3 :1; // Desired temp. Bit in Section3 #
uint8_t :3; // Unknown #
uint8_t :8; // Unknown #
uint8_t ChecksumS3 :8; // Checksum from byte 13-17 ###########
};
};

Expand All @@ -153,8 +194,10 @@ class IRBosch144AC {
void begin();
void setPower(const bool state);
bool getPower(void) const;
void setTemp(const uint8_t temp);
void setTemp(const uint8_t temp, const bool fahrenheit = false);
uint8_t getTemp(void) const;
void setUseFahrenheit(const bool on);
bool getUseFahrenheit(void) const;
void setFan(const uint16_t speed);
uint16_t getFan(void) const;
void setMode(const uint8_t mode);
Expand Down
51 changes: 51 additions & 0 deletions test/ir_Bosch_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,57 @@ TEST(TestDecodeBosch144, RealExample) {
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}

TEST(TestDecodeBosch144, DurastarExample) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);

// Mode: Heat; Fan: auto ; Temp: 73°F
uint16_t rawData[299] = {
4382, 4414, 522, 1630, 522, 552, 550, 1600, 538, 1616, 540, 532, 548,
526, 550, 1602, 548, 528, 548, 528, 550, 1604, 522, 552, 548, 528, 548,
1604, 522, 1630, 546, 528, 548, 1604, 522, 1628, 524, 552, 548, 1604,
546, 1606, 548, 1604, 522, 1630, 520, 1632, 546, 1604, 522, 554, 522,
1630, 520, 554, 522, 552, 522, 552, 524, 552, 546, 530, 546, 528, 548,
528, 548, 1604, 546, 528, 522, 1630, 522, 1630, 522, 1630, 546, 528, 524,
552, 522, 1630, 524, 552, 524, 1630, 520, 554, 522, 554, 522, 554, 548,
1606, 520, 1630, 522, 5224, 4404, 4390, 522, 1630, 522, 554, 520, 1632,
520, 1632, 520, 554, 520, 556, 520, 1632, 520, 556, 520, 556, 520, 1632,
518, 558, 518, 556, 518, 1634, 518, 1634, 518, 558, 518, 1634, 518, 1634,
518, 558, 516, 1636, 516, 1636, 516, 1636, 514, 1638, 514, 1638, 514,
1638, 514, 582, 494, 1658, 492, 582, 492, 584, 492, 584, 490, 584, 492,
584, 490, 586, 488, 586, 488, 1664, 488, 588, 486, 1666, 484, 1666, 486,
1666, 484, 590, 484, 592, 484, 1668, 484, 592, 484, 1666, 486, 590, 484,
592, 484, 592, 484, 1668, 484, 1666, 486, 5262, 4344, 4450, 484, 1668,
484, 1668, 482, 592, 484, 1668, 482, 592, 484, 1680, 472, 594, 482, 1668,
482, 616, 460, 1692, 460, 1692, 458, 616, 460, 616, 460, 1692, 460, 1692,
458, 616, 460, 616, 458, 618, 458, 616, 460, 616, 458, 616, 460, 614,
460, 616, 460, 616, 458, 616, 460, 616, 460, 616, 460, 616, 460, 616,
460, 616, 460, 616, 458, 1692, 458, 616, 460, 616, 460, 616, 460, 616,
444, 632, 438, 638, 434, 642, 434, 642, 434, 640, 434, 640, 434, 1718,
434, 1718, 434, 1718, 434, 1718, 432, 644, 432, 642, 434
}; // DURASTAR DRAW09F2A

uint8_t expectedState[18] = {
0xB2, 0x4D, 0xBF, 0x40, 0x5C, 0xA3,
0xB2, 0x4D, 0xBF, 0x40, 0x5C, 0xA3,
0xD5, 0x66, 0x00, 0x01, 0x00, 0x3C};

irsend.begin();
irsend.reset();

irsend.sendRaw(rawData, 299, 38000);
irsend.makeDecodeResult();
ASSERT_TRUE(irrecv.decode(&irsend.capture));
EXPECT_EQ(decode_type_t::BOSCH144, irsend.capture.decode_type);
EXPECT_EQ(kBosch144Bits, irsend.capture.bits);
EXPECT_STATE_EQ(expectedState, irsend.capture.state, irsend.capture.bits);
EXPECT_EQ(
"Power: On, Mode: 6 (Heat), Fan: 0 (Auto), Temp: 73F, Quiet: Off",
IRAcUtils::resultAcToString(&irsend.capture));
stdAc::state_t result, prev;
ASSERT_TRUE(IRAcUtils::decodeToState(&irsend.capture, &result, &prev));
}

TEST(TestDecodeBosch144, SyntheticSelfDecode) {
IRsendTest irsend(kGpioUnused);
IRrecv irrecv(kGpioUnused);
Expand Down
Loading