Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TOTO: An experimental _(s)wipe_ at support for Toto Toilets. #1811

Merged
merged 5 commits into from
May 24, 2022
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
7 changes: 6 additions & 1 deletion src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,11 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
DPRINTLN("Attempting Carrier AC 128-bit decode");
if (decodeCarrierAC128(results, offset)) return true;
#endif // DECODE_CARRIER_AC128
#if DECODE_TOTO
DPRINTLN("Attempting Toto 48/24-bit decode");
if (decodeToto(results, offset, kTotoLongBits) || // Long needs to be first
decodeToto(results, offset, kTotoShortBits)) return true;
#endif // DECODE_TOTO
// Typically new protocols are added above this line.
}
#if DECODE_HASH
Expand All @@ -1128,7 +1133,7 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
if (!resumed) // Check if we have already resumed.
resume();
return false;
}
} // NOLINT(readability/fn_size)

/// Convert the tolerance percentage into something valid.
/// @param[in] percentage An integer percentage.
Expand Down
5 changes: 5 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,11 @@ class IRrecv {
const uint16_t nbits = kAirtonBits,
const bool strict = true);
#endif // DECODE_AIRTON
#if DECODE_TOTO
bool decodeToto(decode_results *results, uint16_t offset = kStartOffset,
const uint16_t nbits = kTotoBits,
const bool strict = true);
#endif // DECODE_TOTO
};

#endif // IRRECV_H_
14 changes: 13 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,13 @@
#define SEND_HAIER_AC160 _IR_ENABLE_DEFAULT_
#endif // SEND_HAIER_AC160

#ifndef DECODE_TOTO
#define DECODE_TOTO _IR_ENABLE_DEFAULT_
#endif // DECODE_TOTO
#ifndef SEND_TOTO
#define SEND_TOTO _IR_ENABLE_DEFAULT_
#endif // SEND_TOTO

#if (DECODE_ARGO || DECODE_DAIKIN || DECODE_FUJITSU_AC || DECODE_GREE || \
DECODE_KELVINATOR || DECODE_MITSUBISHI_AC || DECODE_TOSHIBA_AC || \
DECODE_TROTEC || DECODE_HAIER_AC || DECODE_HITACHI_AC || \
Expand Down Expand Up @@ -1055,8 +1062,9 @@ enum decode_type_t {
DAIKIN200,
HAIER_AC160, // 115
CARRIER_AC128,
TOTO,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = CARRIER_AC128,
kLastDecodeType = TOTO,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -1298,6 +1306,10 @@ const uint16_t kToshibaACStateLengthShort = kToshibaACStateLength - 2;
const uint16_t kToshibaACBitsShort = kToshibaACStateLengthShort * 8;
const uint16_t kToshibaACStateLengthLong = kToshibaACStateLength + 1;
const uint16_t kToshibaACBitsLong = kToshibaACStateLengthLong * 8;
const uint16_t kTotoBits = 24;
const uint16_t kTotoShortBits = kTotoBits;
const uint16_t kTotoLongBits = kTotoShortBits * 2;
const uint16_t kTotoDefaultRepeat = kSingleRepeat;
const uint16_t kTranscoldBits = 24;
const uint16_t kTranscoldDefaultRepeat = kNoRepeat;
const uint16_t kTrotecStateLength = 9;
Expand Down
7 changes: 7 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,7 @@ uint16_t IRsend::minRepeats(const decode_type_t protocol) {
case MULTIBRACKETS:
case SHERWOOD:
case TOSHIBA_AC:
case TOTO:
return kSingleRepeat;
// Special
case AIRWELL:
Expand Down Expand Up @@ -633,6 +634,7 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
case MIDEA24:
case NIKAI:
case RCMM:
case TOTO:
case TRANSCOLD:
return 24;
case LG:
Expand Down Expand Up @@ -1072,6 +1074,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
sendTeco(data, nbits, min_repeat);
break;
#endif // SEND_TECO
#if SEND_TOTO
case TOTO:
sendToto(data, nbits, min_repeat);
break;
#endif // SEND_TOTO
#if SEND_TRANSCOLD
case TRANSCOLD:
sendTranscold(data, nbits, min_repeat);
Expand Down
4 changes: 4 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,10 @@ class IRsend {
void sendAirton(const uint64_t data, const uint16_t nbits = kAirtonBits,
const uint16_t repeat = kAirtonDefaultRepeat);
#endif // SEND_AIRTON
#if SEND_TOTO
void sendToto(const uint64_t data, const uint16_t nbits = kTotoBits,
const uint16_t repeat = kTotoDefaultRepeat);
#endif // SEND_TOTO

protected:
#ifdef UNIT_TEST
Expand Down
1 change: 1 addition & 0 deletions src/IRtext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
D_STR_DAIKIN200 "\x0"
D_STR_HAIER_AC160 "\x0"
D_STR_CARRIER_AC128 "\x0"
D_STR_TOTO "\x0"
///< New protocol strings should be added just above this line.
"\x0" ///< This string requires double null termination.
};
Expand Down
131 changes: 131 additions & 0 deletions src/ir_Toto.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Copyright 2022 David Conran (crankyoldgit)
/// @file
/// @brief Support for the Toto Toilet IR protocols.
/// @see https://www.d-resi.jp/dt/nishi-shinjuku/limited/imgs/pdf/book6.pdf
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806

// Supports:
// Brand: Toto, Model: Washlet Toilet NJ

#include <algorithm>
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"

// Constants
const uint16_t kTotoHdrMark = 6197;
const uint16_t kTotoHdrSpace = 2754;
const uint16_t kTotoBitMark = 600;
const uint16_t kTotoOneSpace = 1634;
const uint16_t kTotoZeroSpace = 516;
const uint16_t kTotoGap = 38000;
const uint16_t kTotoSpecialGap = 42482;
const uint64_t kTotoPrefix = 0x0802;
const uint16_t kTotoPrefixBits = 15;

#if SEND_TOTO
/// Send a Toto Toilet formatted message.
/// Status: BETA / Seems to work.
/// @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.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806
void IRsend::sendToto(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
if (nbits <= kTotoShortBits) { // Short code message.
sendGeneric(kTotoHdrMark, kTotoHdrSpace,
kTotoBitMark, kTotoOneSpace,
kTotoBitMark, kTotoZeroSpace,
kTotoBitMark, kTotoGap,
(data << kTotoPrefixBits) | kTotoPrefix,
nbits + kTotoPrefixBits,
38, false, repeat, kDutyDefault);
} else { // Long code message
// This is really two messages sent at least one extra time each.
sendToto(data >> kTotoShortBits, nbits - kTotoShortBits, repeat + 1);
sendToto(GETBITS64(data, 0, kTotoShortBits), kTotoShortBits, repeat + 1);
}
}
#endif // SEND_TOTO

#if DECODE_TOTO
/// Decode the supplied Toto Toilet message.
/// Status: ALPHA / Untested.
/// @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.
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues/1806
bool IRrecv::decodeToto(decode_results *results, uint16_t offset,
const uint16_t nbits, const bool strict) {
if (strict && nbits != kTotoShortBits && nbits != kTotoLongBits)
return false; // We expect Toto to be a certain sized messages.

const uint16_t repeats = (nbits > kTotoShortBits) ? kTotoDefaultRepeat + 1
: kTotoDefaultRepeat;
const uint16_t ksections = (nbits > kTotoShortBits) ? 2 : 1;
const uint16_t ksection_bits = nbits / ksections;

if (results->rawlen < (2 * (nbits + kTotoPrefixBits) + kHeader + kFooter) *
(repeats + 1) - 1 + offset)
return false; // We don't have enough entries to possibly match.

uint16_t used = 0;

// Long messages have two sections, short have only one.
for (uint16_t section = 1; section <= ksections; section++) {
results->value <<= ksection_bits;
uint64_t data = 0;
uint64_t repeat_data = 0;
for (uint16_t r = 0; r <= repeats; r++) { // We expect a repeat.
uint64_t prefix = 0;
// Header + Prefix
used = matchGeneric(results->rawbuf + offset, &prefix,
results->rawlen - offset, kTotoPrefixBits,
kTotoHdrMark, kTotoHdrSpace,
kTotoBitMark, kTotoOneSpace,
kTotoBitMark, kTotoZeroSpace,
0, 0, false, // No Footer
kUseDefTol, kMarkExcess, false);
if (!used) return false; // Didn't match, so fail.
offset += used;
if (strict && (prefix != kTotoPrefix)) return false;
// Data + Footer + Gap
used = matchGeneric(results->rawbuf + offset, &data,
results->rawlen - offset, ksection_bits,
0, 0, // No Header
kTotoBitMark, kTotoOneSpace,
kTotoBitMark, kTotoZeroSpace,
kTotoBitMark, kTotoGap, true,
kUseDefTol, kMarkExcess, false);
if (!used) return false; // Didn't match, so fail.
offset += used;
if (strict) {
if (r && data != repeat_data) return false; // Repeat didn't match.
// Integrity check.
uint8_t result = 0;
uint64_t check = data;
uint16_t bits = 0;
// Loop over the data 8 bits at a time.
while (bits < ksection_bits) {
result ^= (check & 0b111111111); // Xor with the last 8 bits.
bits += 8;
check >>= 8;
}
if (result) return false; // Intergrity check failed.
}
repeat_data = data;
}
results->value |= data;
}
// Success
results->bits = nbits;
results->decode_type = decode_type_t::TOTO;
results->command = GETBITS64(results->value, 0, ksection_bits - 8);
results->address = GETBITS64(results->value, ksection_bits,
ksection_bits - 8);
return true;
}
#endif // DECODE_TOTO
3 changes: 3 additions & 0 deletions src/locale/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,9 @@ D_STR_INDIRECT " " D_STR_MODE
#ifndef D_STR_TOSHIBA_AC
#define D_STR_TOSHIBA_AC "TOSHIBA_AC"
#endif // D_STR_TOSHIBA_AC
#ifndef D_STR_TOTO
#define D_STR_TOTO "TOTO"
#endif // D_STR_TOTO
#ifndef D_STR_TRANSCOLD
#define D_STR_TRANSCOLD "TRANSCOLD"
#endif // D_STR_TRANSCOLD
Expand Down
Loading