mirror of
https://github.com/crankyoldgit/IRremoteESP8266.git
synced 2026-01-12 00:05:10 +08:00
Add support the WowWee 11-Bit RoboRaptor-X protocol. (#1939)
* Basic `sendWowwee()` & decodeWowwee()` routines. * Unit test coverage including decoding of two different captured messages from a real remote. * Add reference for available/known RoboRaptor-X codes. Fixes #1938
This commit is contained in:
@@ -1169,6 +1169,10 @@ bool IRrecv::decode(decode_results *results, irparams_t *save,
|
||||
DPRINTLN("Attempting GORENJE decode");
|
||||
if (decodeGorenje(results, offset)) return true;
|
||||
#endif // DECODE_GORENJE
|
||||
#if DECODE_WOWWEE
|
||||
DPRINTLN("Attempting WOWWEE decode");
|
||||
if (decodeWowwee(results, offset)) return true;
|
||||
#endif // DECODE_WOWWEE
|
||||
// Typically new protocols are added above this line.
|
||||
}
|
||||
#if DECODE_HASH
|
||||
|
||||
@@ -865,6 +865,12 @@ class IRrecv {
|
||||
const uint16_t nbits = kBosch144Bits,
|
||||
const bool strict = true);
|
||||
#endif // DECODE_BOSCH144
|
||||
#if DECODE_WOWWEE
|
||||
bool decodeWowwee(decode_results *results,
|
||||
uint16_t offset = kStartOffset,
|
||||
const uint16_t nbits = kWowweeBits,
|
||||
const bool strict = true);
|
||||
#endif // DECODE_WOWWEE
|
||||
};
|
||||
|
||||
#endif // IRRECV_H_
|
||||
|
||||
@@ -931,6 +931,13 @@
|
||||
#define SEND_GORENJE _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_GORENJE
|
||||
|
||||
#ifndef DECODE_WOWWEE
|
||||
#define DECODE_WOWWEE _IR_ENABLE_DEFAULT_
|
||||
#endif // DECODE_WOWWEE
|
||||
#ifndef SEND_WOWWEE
|
||||
#define SEND_WOWWEE _IR_ENABLE_DEFAULT_
|
||||
#endif // SEND_WOWWEE
|
||||
|
||||
#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 || \
|
||||
@@ -1112,8 +1119,9 @@ enum decode_type_t {
|
||||
SANYO_AC152,
|
||||
DAIKIN312,
|
||||
GORENJE,
|
||||
WOWWEE,
|
||||
// Add new entries before this one, and update it to point to the last entry.
|
||||
kLastDecodeType = GORENJE,
|
||||
kLastDecodeType = WOWWEE,
|
||||
};
|
||||
|
||||
// Message lengths & required repeat values
|
||||
@@ -1387,6 +1395,8 @@ const uint16_t kWhirlpoolAcStateLength = 21;
|
||||
const uint16_t kWhirlpoolAcBits = kWhirlpoolAcStateLength * 8;
|
||||
const uint16_t kWhirlpoolAcDefaultRepeat = kNoRepeat;
|
||||
const uint16_t kWhynterBits = 32;
|
||||
const uint16_t kWowweeBits = 11;
|
||||
const uint16_t kWowweeDefaultRepeat = kNoRepeat;
|
||||
const uint8_t kVestelAcBits = 56;
|
||||
const uint16_t kXmpBits = 64;
|
||||
const uint16_t kZepealBits = 16;
|
||||
|
||||
@@ -605,6 +605,8 @@ uint16_t IRsend::defaultBits(const decode_type_t protocol) {
|
||||
case MULTIBRACKETS:
|
||||
case GORENJE:
|
||||
return 8;
|
||||
case WOWWEE:
|
||||
return 11;
|
||||
case RC5:
|
||||
case SYMPHONY:
|
||||
return 12;
|
||||
@@ -1120,6 +1122,11 @@ bool IRsend::send(const decode_type_t type, const uint64_t data,
|
||||
sendWhynter(data, nbits, min_repeat);
|
||||
break;
|
||||
#endif
|
||||
#if SEND_WOWWEE
|
||||
case WOWWEE:
|
||||
sendWowwee(data, nbits, min_repeat);
|
||||
break;
|
||||
#endif // SEND_WOWWEE
|
||||
#if SEND_XMP
|
||||
case XMP:
|
||||
sendXmp(data, nbits, min_repeat);
|
||||
|
||||
@@ -870,6 +870,10 @@ class IRsend {
|
||||
const uint16_t nbytes = kBosch144StateLength,
|
||||
const uint16_t repeat = kNoRepeat);
|
||||
#endif // SEND_BOSCH144
|
||||
#if SEND_WOWWEE
|
||||
void sendWowwee(const uint64_t data, const uint16_t nbits = kWowweeBits,
|
||||
const uint16_t repeat = kWowweeDefaultRepeat);
|
||||
#endif // SEND_WOWWEE
|
||||
|
||||
protected:
|
||||
#ifdef UNIT_TEST
|
||||
|
||||
@@ -549,6 +549,8 @@ IRTEXT_CONST_BLOB_DECL(kAllProtocolNamesStr) {
|
||||
D_STR_DAIKIN312, D_STR_UNSUPPORTED) "\x0"
|
||||
COND(DECODE_GORENJE || SEND_GORENJE,
|
||||
D_STR_GORENJE, D_STR_UNSUPPORTED) "\x0"
|
||||
COND(DECODE_WOWWEE || SEND_WOWWEE,
|
||||
D_STR_WOWWEE, D_STR_UNSUPPORTED) "\x0"
|
||||
///< New protocol (macro) strings should be added just above this line.
|
||||
"\x0" ///< This string requires double null termination.
|
||||
};
|
||||
|
||||
91
src/ir_Wowwee.cpp
Normal file
91
src/ir_Wowwee.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright 2022 David Conran
|
||||
|
||||
/// @file
|
||||
/// @brief Support for WowWee RoboRapter protocol
|
||||
/// @see https://github.com/crankyoldgit/IRremoteESP8266/issues1938
|
||||
|
||||
// Supports:
|
||||
// Brand: WowWee, Model: RoboRapter-X
|
||||
|
||||
// WowWee RoboRapter-X messages
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issuecomment-1367968228
|
||||
//
|
||||
// Button Code
|
||||
// ====== =====
|
||||
// Left 0x180
|
||||
// Forward 0x186
|
||||
// Backward 0x187
|
||||
// Right 0x188
|
||||
// Stop 0x18E
|
||||
// Head Counterclockwise 0x191
|
||||
// Tail Left 0x192
|
||||
// Tail Right 0x193
|
||||
// Head Clockwise 0x194
|
||||
// Guard Mode 0x1B0
|
||||
// Roam 0x1B1
|
||||
// Cautious Mood 0x1B2
|
||||
// Playful Mood 0x1B3
|
||||
// Hunting Mood 0x1B4
|
||||
// Demo 0x1D0
|
||||
// Bite 0x1D1
|
||||
|
||||
#include <algorithm>
|
||||
#include "IRrecv.h"
|
||||
#include "IRsend.h"
|
||||
#include "IRutils.h"
|
||||
|
||||
// Constants
|
||||
const uint16_t kWowweeHdrMark = 6684;
|
||||
const uint16_t kWowweeHdrSpace = 723;
|
||||
const uint16_t kWowweeBitMark = 912;
|
||||
const uint16_t kWowweeOneSpace = 3259;
|
||||
const uint16_t kWowweeZeroSpace = kWowweeHdrSpace;
|
||||
const uint16_t kWowweeFreq = 38000; // Hz. (Just a guess)
|
||||
|
||||
|
||||
#if SEND_WOWWEE
|
||||
/// Send a WowWee formatted message.
|
||||
/// Status: STABLE / Confirmed working with real device.
|
||||
/// @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.
|
||||
void IRsend::sendWowwee(uint64_t data, uint16_t nbits, uint16_t repeat) {
|
||||
sendGeneric(kWowweeHdrMark, kWowweeHdrSpace,
|
||||
kWowweeBitMark, kWowweeOneSpace,
|
||||
kWowweeBitMark, kWowweeZeroSpace,
|
||||
kWowweeBitMark, kDefaultMessageGap, data,
|
||||
nbits, kWowweeFreq, true, repeat, 33);
|
||||
}
|
||||
#endif // SEND_WOWWEE
|
||||
|
||||
#if DECODE_WOWWEE
|
||||
/// Decode the supplied WowWee message.
|
||||
/// Status: STABLE / Confirmed working with real device.
|
||||
/// @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.
|
||||
bool IRrecv::decodeWowwee(decode_results *results, uint16_t offset,
|
||||
const uint16_t nbits, const bool strict) {
|
||||
if (strict && nbits != kWowweeBits)
|
||||
return false; // We expect Wowwee to be a certain sized message.
|
||||
|
||||
uint64_t data = 0;
|
||||
|
||||
// Match Header + Data + Footer
|
||||
if (!matchGeneric(results->rawbuf + offset, &data,
|
||||
results->rawlen - offset, nbits,
|
||||
kWowweeHdrMark, kWowweeHdrSpace,
|
||||
kWowweeBitMark, kWowweeOneSpace,
|
||||
kWowweeBitMark, kWowweeZeroSpace,
|
||||
kWowweeBitMark, kDefaultMessageGap, true)) return false;
|
||||
// Success
|
||||
results->bits = nbits;
|
||||
results->value = data;
|
||||
results->decode_type = WOWWEE;
|
||||
results->command = 0;
|
||||
results->address = 0;
|
||||
return true;
|
||||
}
|
||||
#endif // DECODE_WOWWEE
|
||||
@@ -1105,6 +1105,9 @@ D_STR_INDIRECT " " D_STR_MODE
|
||||
#ifndef D_STR_WHYNTER
|
||||
#define D_STR_WHYNTER "WHYNTER"
|
||||
#endif // D_STR_WHYNTER
|
||||
#ifndef D_STR_WOWWEE
|
||||
#define D_STR_WOWWEE "WOWWEE"
|
||||
#endif // D_STR_WOWWEE
|
||||
#ifndef D_STR_XMP
|
||||
#define D_STR_XMP "XMP"
|
||||
#endif // D_STR_XMP
|
||||
|
||||
103
test/ir_Wowwee_test.cpp
Normal file
103
test/ir_Wowwee_test.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright 2022 David Conran
|
||||
|
||||
#include "IRac.h"
|
||||
#include "IRrecv.h"
|
||||
#include "IRrecv_test.h"
|
||||
#include "IRsend.h"
|
||||
#include "IRsend_test.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(TestUtils, Housekeeping) {
|
||||
ASSERT_EQ("WOWWEE", typeToString(decode_type_t::WOWWEE));
|
||||
ASSERT_EQ(decode_type_t::WOWWEE, strToDecodeType("WOWWEE"));
|
||||
ASSERT_FALSE(hasACState(decode_type_t::WOWWEE));
|
||||
ASSERT_FALSE(IRac::isProtocolSupported(decode_type_t::WOWWEE));
|
||||
ASSERT_EQ(kWowweeBits, IRsend::defaultBits(decode_type_t::WOWWEE));
|
||||
ASSERT_EQ(kWowweeDefaultRepeat, IRsend::minRepeats(decode_type_t::WOWWEE));
|
||||
}
|
||||
|
||||
// Tests for sendWowwee().
|
||||
// Test sending typical data only.
|
||||
TEST(TestSendWowwee, SendDataOnly) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
irsend.reset();
|
||||
irsend.sendWowwee(0x186); // Nikai TV Power Off.
|
||||
EXPECT_EQ(
|
||||
"f38000d33"
|
||||
"m6684s723"
|
||||
"m912s723m912s723m912s3259m912s3259m912s723m912s723m912s723m912s723"
|
||||
"m912s3259m912s3259m912s723m912s100000",
|
||||
irsend.outputStr());
|
||||
|
||||
irsend.reset();
|
||||
}
|
||||
|
||||
// Tests for decodeWowwee().
|
||||
|
||||
// Decode normal Wowwee messages.
|
||||
TEST(TestDecodeWowwee, RealDecode) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issue-1513240242
|
||||
const uint16_t rawForward[25] = {
|
||||
6684, 740, 918, 724, 942, 724, 918, 3250, 870, 3268, 872, 770, 940, 690,
|
||||
942, 688, 942, 738, 942, 3250, 868, 3268, 872, 732, 918
|
||||
}; // UNKNOWN 7469BF81
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawForward, 25, 38);
|
||||
irsend.makeDecodeResult();
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
|
||||
EXPECT_EQ(0x186, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
|
||||
// Ref: https://github.com/crankyoldgit/IRremoteESP8266/issues/1938#issue-1513240242
|
||||
const uint16_t rawLeft[25] = {
|
||||
6630, 764, 868, 762, 892, 788, 866, 3324, 792, 3348, 818, 760, 866, 788,
|
||||
894, 772, 892, 750, 870, 786, 920, 750, 864, 776, 868
|
||||
}; // UNKNOWN 28A1120F
|
||||
irsend.reset();
|
||||
irsend.sendRaw(rawLeft, 25, 38);
|
||||
irsend.makeDecodeResult();
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
|
||||
EXPECT_EQ(0x180, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
}
|
||||
|
||||
// Decode normal repeated Wowwee messages.
|
||||
TEST(TestDecodeWowwee, SyntheticDecode) {
|
||||
IRsendTest irsend(kGpioUnused);
|
||||
IRrecv irrecv(kGpioUnused);
|
||||
irsend.begin();
|
||||
|
||||
// Normal Wowwee 11-bit message.
|
||||
irsend.reset();
|
||||
irsend.sendWowwee(0x186);
|
||||
irsend.makeDecodeResult();
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
|
||||
EXPECT_EQ(0x186, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
|
||||
// Normal Wowwee 11-bit message.
|
||||
irsend.reset();
|
||||
irsend.sendWowwee(0x180);
|
||||
irsend.makeDecodeResult();
|
||||
ASSERT_TRUE(irrecv.decode(&irsend.capture));
|
||||
EXPECT_EQ(decode_type_t::WOWWEE, irsend.capture.decode_type);
|
||||
EXPECT_EQ(kWowweeBits, irsend.capture.bits);
|
||||
EXPECT_EQ(0x180, irsend.capture.value);
|
||||
EXPECT_EQ(0x0, irsend.capture.command);
|
||||
EXPECT_EQ(0x0, irsend.capture.address);
|
||||
}
|
||||
Reference in New Issue
Block a user