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

Initial support for G.I. Cable protocol #458

Merged
merged 2 commits into from
May 19, 2018
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
9 changes: 9 additions & 0 deletions examples/IRMQTTServer/IRMQTTServer.ino
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ void handleRoot() {
"<option value='15'>Coolix</option>"
"<option value='17'>Denon</option>"
"<option value='13'>Dish</option>"
"<option value='41'>GICable</option>"
"<option value='6'>JVC</option>"
"<option value='10'>LG</option>"
"<option value='36'>Lasertag</option>"
Expand Down Expand Up @@ -1186,6 +1187,14 @@ void sendIRCode(int const ir_type, uint64_t const code, char const * code_str,
repeat = std::max(repeat, (uint16_t) MITSUBISHI_MIN_REPEAT);
irsend.sendMitsubishi2(code, bits, repeat);
break;
#endif
#if SEND_GICABLE
case GICABLE: // 41
if (bits == 0)
bits = GICABLE_BITS;
repeat = std::max(repeat, (uint16_t) GICABLE_BITS);
irsend.sendGICable(code, bits, repeat);
break;
#endif
}
sendReqCounter++;
Expand Down
7 changes: 7 additions & 0 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,13 @@ bool IRrecv::decode(decode_results *results, irparams_t *save) {
if (decodeLG(results, LG32_BITS, true))
return true;
#endif
#if DECODE_GICABLE
// Note: Needs to happen before JVC decode, because it looks similar except
// with a required NEC-like repeat code.
DPRINTLN("Attempting GICable decode");
if (decodeGICable(results))
return true;
#endif
#if DECODE_JVC
DPRINTLN("Attempting JVC decode");
if (decodeJVC(results))
Expand Down
4 changes: 4 additions & 0 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@ class IRrecv {
bool decodeHitachiAC(decode_results *results,
uint16_t nbits = HITACHI_AC_BITS, bool strict = true);
#endif
#if DECODE_GICABLE
bool decodeGICable(decode_results *results, uint16_t nbits = GICABLE_BITS,
bool strict = true);
#endif
};

#endif // IRRECV_H_
8 changes: 7 additions & 1 deletion src/IRremoteESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@
#define DECODE_HITACHI_AC true
#define SEND_HITACHI_AC true

#define DECODE_GICABLE true
#define SEND_GICABLE true

#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 @@ -221,7 +224,8 @@ enum decode_type_t {
CARRIER_AC,
HAIER_AC,
MITSUBISHI2,
HITACHI_AC
HITACHI_AC,
GICABLE
};

// Message lengths & required repeat values
Expand All @@ -239,6 +243,8 @@ enum decode_type_t {
#define DENON_LEGACY_BITS 14U
#define DISH_BITS 16U
#define DISH_MIN_REPEAT 3U
#define GICABLE_BITS 16U
#define GICABLE_MIN_REPEAT 1U
#define GREE_STATE_LENGTH 8U
#define GREE_BITS (GREE_STATE_LENGTH * 8)
#define HAIER_AC_STATE_LENGTH 9U
Expand Down
3 changes: 3 additions & 0 deletions src/IRsend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,9 @@ void IRsend::send(uint16_t type, uint64_t data, uint16_t nbits) {
#endif
#if SEND_MIDEA
case MIDEA: sendMidea(data, nbits); break;
#endif
#if SEND_GICABLE
case GICABLE: sendGICable(data, nbits); break;
#endif
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/IRsend.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,10 @@ void send(uint16_t type, uint64_t data, uint16_t nbits);
uint16_t nbytes = HITACHI_AC_STATE_LENGTH,
uint16_t repeat = 0);
#endif
#if SEND_GICABLE
void sendGICable(uint64_t data, uint16_t nbits = GICABLE_BITS,
uint16_t repeat = GICABLE_MIN_REPEAT);
#endif

protected:
#ifdef UNIT_TEST
Expand Down
1 change: 1 addition & 0 deletions src/IRutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ std::string typeToString(const decode_type_t protocol,
case DENON: result = "DENON"; break;
case DISH: result = "DISH"; break;
case FUJITSU_AC: result = "FUJITSU_AC"; break;
case GICABLE: result = "GICABLE"; break;
case GLOBALCACHE: result = "GLOBALCACHE"; break;
case GREE: result = "GREE"; break;
case HAIER_AC: result = "HAIER_AC"; break;
Expand Down
119 changes: 119 additions & 0 deletions src/ir_GICable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright 2018 David Conran

#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include <algorithm>
#include "IRrecv.h"
#include "IRsend.h"
#include "IRutils.h"

// GGGG IIIII CCCCC AAA BBBBB LL EEEEEEE
// GG GG III CC C AAAAA BB B LL EE
// GG III CC AA AA BBBBBB LL EEEEE
// GG GG ... III ... CC C AAAAAAA BB BB LL EE
// GGGGGG ... IIIII ... CCCCC AA AA BBBBBB LLLLLLL EEEEEEE
//
// Ref:
// https://github.com/cyborg5/IRLib2/blob/master/IRLibProtocols/IRLib_P09_GICable.h
// https://github.com/markszabo/IRremoteESP8266/issues/447

// Constants
#define GICABLE_HDR_MARK 9000U
#define GICABLE_HDR_SPACE 4400U
#define GICABLE_BIT_MARK 550U
#define GICABLE_ONE_SPACE 4400U
#define GICABLE_ZERO_SPACE 2200U
#define GICABLE_RPT_SPACE 2200U
#define GICABLE_MIN_COMMAND_LENGTH 99600U
#define GICABLE_MIN_GAP (GICABLE_MIN_COMMAND_LENGTH - \
(GICABLE_HDR_MARK + GICABLE_HDR_SPACE + \
GICABLE_BITS * (GICABLE_BIT_MARK + GICABLE_ONE_SPACE) + GICABLE_BIT_MARK))


#if SEND_GICABLE
// Send a raw G.I. Cable formatted message.
//
// Args:
// data: The message to be sent.
// nbits: The number of bits of the message to be sent.
// Typically GICABLE_BITS.
// repeat: The number of times the command is to be repeated.
//
// Status: Alpha / Untested.
//
// Ref:
void IRsend::sendGICable(uint64_t data, uint16_t nbits, uint16_t repeat) {
sendGeneric(GICABLE_HDR_MARK, GICABLE_HDR_SPACE,
GICABLE_BIT_MARK, GICABLE_ONE_SPACE,
GICABLE_BIT_MARK, GICABLE_ZERO_SPACE,
GICABLE_BIT_MARK, GICABLE_MIN_GAP, GICABLE_MIN_COMMAND_LENGTH,
data, nbits, 39, true, 0, // Repeats are handled later.
50);
// Message repeat sequence.
if (repeat)
sendGeneric(GICABLE_HDR_MARK, GICABLE_RPT_SPACE,
0, 0, 0, 0, // No actual data sent.
GICABLE_BIT_MARK, GICABLE_MIN_GAP, GICABLE_MIN_COMMAND_LENGTH,
0, 0, // No data to be sent.
39, true, repeat - 1, 50);
}
#endif // SEND_GICABLE

#if DECODE_GICABLE
// Decode the supplied G.I. Cable message.
//
// Args:
// results: Ptr to the data to decode and where to store the decode result.
// nbits: The number of data bits to expect. Typically GICABLE_BITS.
// strict: Flag indicating if we should perform strict matching.
// Returns:
// boolean: True if it can decode it, false if it can't.
//
// Status: Alpha / Not tested against a real device.
bool IRrecv::decodeGICable(decode_results *results, uint16_t nbits,
bool strict) {
if (results->rawlen < 2 * (nbits + HEADER + FOOTER) - 1)
return false; // Can't possibly be a valid GICABLE message.
if (strict && nbits != GICABLE_BITS)
return false; // Not strictly an GICABLE message.

uint64_t data = 0;
uint16_t offset = OFFSET_START;

// Header
if (!matchMark(results->rawbuf[offset++], GICABLE_HDR_MARK)) return false;
if (!matchSpace(results->rawbuf[offset++], GICABLE_HDR_SPACE)) return false;

// Data
match_result_t data_result = matchData(&(results->rawbuf[offset]), nbits,
GICABLE_BIT_MARK,
GICABLE_ONE_SPACE,
GICABLE_BIT_MARK,
GICABLE_ZERO_SPACE);
if (data_result.success == false) return false;
data = data_result.data;
offset += data_result.used;

// Footer
if (!matchMark(results->rawbuf[offset++], GICABLE_BIT_MARK)) return false;
if (offset < results->rawlen &&
!matchAtLeast(results->rawbuf[offset++], GICABLE_MIN_GAP))
return false;

// Compliance
if (strict) {
// We expect a repeat frame.
if (!matchMark(results->rawbuf[offset++], GICABLE_HDR_MARK)) return false;
if (!matchSpace(results->rawbuf[offset++], GICABLE_RPT_SPACE)) return false;
if (!matchMark(results->rawbuf[offset++], GICABLE_BIT_MARK)) return false;
}

// Success
results->bits = nbits;
results->value = data;
results->decode_type = GICABLE;
results->command = 0;
results->address = 0;
return true;
}
#endif // DECODE_GICABLE
14 changes: 12 additions & 2 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ TESTS = IRutils_test IRsend_test ir_NEC_test ir_GlobalCache_test \
ir_Aiwa_test ir_Denon_test ir_Sanyo_test ir_Daikin_test ir_Coolix_test \
ir_Gree_test IRrecv_test ir_Pronto_test ir_Fujitsu_test ir_Nikai_test \
ir_Toshiba_test ir_Midea_test ir_Magiquest_test ir_Lasertag_test \
ir_Carrier_test ir_Haier_test ir_Hitachi_test
ir_Carrier_test ir_Haier_test ir_Hitachi_test ir_GICable_test

# All Google Test headers. Usually you shouldn't change this
# definition.
Expand Down Expand Up @@ -74,7 +74,8 @@ PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o ir_Denon.o ir_Dish.o \
ir_Panasonic.o ir_Whynter.o ir_Coolix.o ir_Aiwa.o ir_Sherwood.o \
ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_Nikai.o ir_Toshiba.o \
ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o ir_Hitachi.o
ir_Midea.o ir_Magiquest.o ir_Lasertag.o ir_Carrier.o ir_Haier.o \
ir_Hitachi.o ir_GICable.o

# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o ir_GlobalCache.o \
Expand Down Expand Up @@ -415,3 +416,12 @@ ir_Hitachi_test.o : ir_Hitachi_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)

ir_Hitachi_test : $(COMMON_OBJ) ir_Hitachi_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@

ir_GICable.o : $(USER_DIR)/ir_GICable.cpp $(COMMON_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GICable.cpp

ir_GICable_test.o : ir_GICable_test.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c ir_GICable_test.cpp

ir_GICable_test : $(COMMON_OBJ) ir_GICable_test.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@
Loading