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

Experimental support for Samsung 36 bit protocol #625

Merged
merged 1 commit into from
Feb 26, 2019
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
10 changes: 9 additions & 1 deletion examples/IRMQTTServer/IRMQTTServer.ino
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ const uint16_t kMinUnknownSize = 2 * 10;
// ----------------- End of User Configuration Section -------------------------

// Globals
#define _MY_VERSION_ "v0.8.3"
#define _MY_VERSION_ "v0.8.4"
// HTML arguments we will parse for IR code information.
#define argType "type"
#define argData "code"
Expand Down Expand Up @@ -467,6 +467,7 @@ void handleRoot() {
"<option value='2'>RC-6</option>"
"<option value='21'>RC-MM</option>"
"<option value='7'>Samsung</option>"
"<option value='56'>Samsung36</option>"
"<option value='11'>Sanyo</option>"
"<option value='22'>Sanyo LC7461</option>"
"<option value='14'>Sharp</option>"
Expand Down Expand Up @@ -1413,6 +1414,13 @@ bool sendIRCode(int const ir_type, uint64_t const code, char const * code_str,
irsend.sendSAMSUNG(code, bits, repeat);
break;
#endif
#if SEND_SAMSUNG36
case SAMSUNG36: // 56
if (bits == 0)
bits = kSamsung36Bits;
irsend.sendSamsung36(code, bits, repeat);
break;
#endif
#if SEND_WHYNTER
case WHYNTER: // 8
if (bits == 0)
Expand Down
4 changes: 4 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
DPRINTLN("Attempting SAMSUNG decode");
if (decodeSAMSUNG(results)) return true;
#endif
#if DECODE_SAMSUNG36
DPRINTLN("Attempting Samsung36 decode");
if (decodeSamsung36(results)) return true;
#endif
#if DECODE_WHYNTER
DPRINTLN("Attempting Whynter decode");
if (decodeWhynter(results)) return true;
Expand Down
5 changes: 5 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ class IRrecv {
bool decodeSAMSUNG(decode_results *results, uint16_t nbits = kSamsungBits,
bool strict = true);
#endif
#if DECODE_SAMSUNG
bool decodeSamsung36(decode_results *results,
const uint16_t nbits = kSamsung36Bits,
const bool strict = true);
#endif
#if DECODE_SAMSUNG_AC
bool decodeSamsungAC(decode_results *results, uint16_t nbits = kSamsungAcBits,
bool strict = true);
Expand Down
6 changes: 6 additions & 0 deletions src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
#define DECODE_SAMSUNG true
#define SEND_SAMSUNG true

#define DECODE_SAMSUNG36 true
#define SEND_SAMSUNG36 true

#define DECODE_SAMSUNG_AC true
#define SEND_SAMSUNG_AC true

Expand Down Expand Up @@ -285,6 +288,8 @@ enum decode_type_t {
MWM,
DAIKIN2,
VESTEL_AC,
TECO, // (55)
SAMSUNG36,
};

// Message lengths & required repeat values
Expand Down Expand Up @@ -373,6 +378,7 @@ const uint16_t kRC6Mode0Bits = 20; // Excludes the 'start' bit.
const uint16_t kRC6_36Bits = 36; // Excludes the 'start' bit.
const uint16_t kRCMMBits = 24;
const uint16_t kSamsungBits = 32;
const uint16_t kSamsung36Bits = 36;
const uint16_t kSamsungAcStateLength = 14;
const uint16_t kSamsungAcBits = kSamsungAcStateLength * 8;
const uint16_t kSamsungAcExtendedStateLength = 21;
Expand Down
4 changes: 4 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ class IRsend {
uint16_t repeat = kNoRepeat);
uint32_t encodeSAMSUNG(uint8_t customer, uint8_t command);
#endif
#if SEND_SAMSUNG36
void sendSamsung36(const uint64_t data, const uint16_t nbits = kSamsung36Bits,
const uint16_t repeat = kNoRepeat);
#endif
#if SEND_SAMSUNG_AC
void sendSamsungAC(unsigned char data[],
uint16_t nbytes = kSamsungAcStateLength,
Expand Down
3 changes: 3 additions & 0 deletions src/IRutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ std::string typeToString(const decode_type_t protocol, const bool isRepeat) {
case SAMSUNG:
result = "SAMSUNG";
break;
case SAMSUNG36:
result = "SAMSUNG36";
break;
case SAMSUNG_AC:
result = "SAMSUNG_AC";
break;
Expand Down
123 changes: 122 additions & 1 deletion src/ir_Samsung.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright 2009 Ken Shirriff
// Copyright 2017 David Conran
// Copyright 2017, 2018, 2019 David Conran

#include "ir_Samsung.h"
#include <algorithm>
Expand Down Expand Up @@ -168,6 +168,127 @@ bool IRrecv::decodeSAMSUNG(decode_results *results, uint16_t nbits,
}
#endif

#if SEND_SAMSUNG36
// Send a Samsung 36-bit formatted message.
//
// Args:
// data: The message to be sent.
// nbits: The bit size of the message being sent. typically kSamsung36Bits.
// repeat: The number of times the message is to be repeated.
//
// Status: Alpha / Experimental.
//
// Note:
// Protocol is used by Samsung Bluray Remote: ak59-00167a
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/621
void IRsend::sendSamsung36(const uint64_t data, const uint16_t nbits,
const uint16_t repeat) {
if (nbits < 16) return; // To small to send.
for (uint16_t r = 0; r <= repeat; r++) {
// Block #1 (16 bits)
sendGeneric(kSamsungHdrMark, kSamsungHdrSpace,
kSamsungBitMark, kSamsungOneSpace,
kSamsungBitMark, kSamsungZeroSpace,
kSamsungBitMark, kSamsungHdrSpace,
data >> (nbits - 16), 16, 38, true, 0, kDutyDefault);
// Block #2 (The rest, typically 20 bits)
sendGeneric(0, 0, // No header
kSamsungBitMark, kSamsungOneSpace,
kSamsungBitMark, kSamsungZeroSpace,
kSamsungBitMark, kSamsungMinGap, // Gap is just a guess.
// Mask off the rest of the bits.
data & ((1ULL << (nbits - 16)) - 1),
nbits - 16, 38, true, 0, kDutyDefault);
}
}
#endif // SEND_SAMSUNG36

#if DECODE_SAMSUNG36
// Decode the supplied Samsung36 message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: Nr. of bits to expect in the data portion.
// Typically kSamsung36Bits.
// 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 / Experimental
//
// Note:
// Protocol is used by Samsung Bluray Remote: ak59-00167a
//
// Ref:
// https://github.com/markszabo/IRremoteESP8266/issues/621
bool IRrecv::decodeSamsung36(decode_results *results, const uint16_t nbits,
const bool strict) {
if (results->rawlen < 2 * nbits + kHeader + kFooter * 2 - 1)
return false; // Can't possibly be a valid Samsung message.
// We need to be looking for > 16 bits to make sense.
if (nbits <= 16) return false;
if (strict && nbits != kSamsung36Bits)
return false; // We expect nbits to be 36 bits of message.

uint64_t data = 0;
uint16_t offset = kStartOffset;

// Header
if (!matchMark(results->rawbuf[offset], kSamsungHdrMark)) return false;
// Calculate how long the common tick time is based on the header mark.
uint32_t m_tick = results->rawbuf[offset++] * kRawTick / kSamsungHdrMarkTicks;
if (!matchSpace(results->rawbuf[offset], kSamsungHdrSpace)) return false;
// Calculate how long the common tick time is based on the header space.
uint32_t s_tick =
results->rawbuf[offset++] * kRawTick / kSamsungHdrSpaceTicks;
// Data (Block #1)
match_result_t data_result =
matchData(&(results->rawbuf[offset]), 16,
kSamsungBitMarkTicks * m_tick, kSamsungOneSpaceTicks * s_tick,
kSamsungBitMarkTicks * m_tick, kSamsungZeroSpaceTicks * s_tick);
if (data_result.success == false) return false;
data = data_result.data;
offset += data_result.used;
uint16_t bitsSoFar = data_result.used / 2;
// Footer (Block #1)
if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
return false;
if (!matchSpace(results->rawbuf[offset++], kSamsungHdrSpaceTicks * s_tick))
return false;
// Data (Block #2)
data_result = matchData(&(results->rawbuf[offset]),
nbits - 16,
kSamsungBitMarkTicks * m_tick,
kSamsungOneSpaceTicks * s_tick,
kSamsungBitMarkTicks * m_tick,
kSamsungZeroSpaceTicks * s_tick);
if (data_result.success == false) return false;
data <<= (nbits - 16);
data += data_result.data;
offset += data_result.used;
bitsSoFar += data_result.used / 2;
// Footer (Block #2)
if (!matchMark(results->rawbuf[offset++], kSamsungBitMarkTicks * m_tick))
return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset], kSamsungMinGapTicks * s_tick))
return false;

// Compliance
if (nbits != bitsSoFar) return false;

// Success
results->bits = bitsSoFar;
results->value = data;
results->decode_type = SAMSUNG36;
results->command = data & ((1ULL << (nbits - 16)) - 1);
results->address = data >> (nbits - 16);
return true;
}
#endif // DECODE_SAMSUNG36

#if SEND_SAMSUNG_AC
// Send a Samsung A/C message.
//
Expand Down
Loading