From 34e5cd87ca553bcdfbfcb62a69bbe3f2bafa2bc5 Mon Sep 17 00:00:00 2001 From: Philipp Henkel Date: Wed, 27 Apr 2016 21:57:57 +0200 Subject: [PATCH 1/3] Add Lego Power Functions send protocol --- .travis.yml | 1 + IRremote.h | 14 +- .../LegoPowerFunctionsSendDemo.ino | 22 +++ irRecv.cpp | 9 +- ir_Lego_PF.cpp | 130 ++++++++++++++++++ 5 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 examples/LegoPowerFunctionsSendDemo/LegoPowerFunctionsSendDemo.ino create mode 100644 ir_Lego_PF.cpp diff --git a/.travis.yml b/.travis.yml index 72fb6659b..d62004f8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ env: - PLATFORMIO_CI_SRC=examples/IRtest PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6" - PLATFORMIO_CI_SRC=examples/IRtest2 PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6" - PLATFORMIO_CI_SRC=examples/JVCPanasonicSendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_JVC -DSEND_PANASONIC" + - PLATFORMIO_CI_SRC=examples/LegoPowerFunctionsSendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_LEGO_PF" - PLATFORMIO_CI_SRC=examples/IRremoteInfo install: diff --git a/IRremote.h b/IRremote.h index 96d82ca71..fe1a87029 100644 --- a/IRremote.h +++ b/IRremote.h @@ -56,7 +56,7 @@ #define SEND_AIWA_RC_T501 1 #define DECODE_LG 1 -#define SEND_LG 1 +#define SEND_LG 1 #define DECODE_SANYO 1 #define SEND_SANYO 0 // NOT WRITTEN @@ -76,6 +76,9 @@ #define DECODE_PRONTO 0 // This function doe not logically make sense #define SEND_PRONTO 1 +#define DECODE_LEGO_PF 0 // NOT WRITTEN +#define SEND_LEGO_PF 1 + //------------------------------------------------------------------------------ // When sending a Pronto code we request to send either the "once" code // or the "repeat" code @@ -115,6 +118,7 @@ typedef SHARP, DENON, PRONTO, + LEGO_PF, } decode_type_t; @@ -243,6 +247,10 @@ class IRrecv # if DECODE_DENON bool decodeDenon (decode_results *results) ; # endif +//...................................................................... +# if DECODE_LEGO_PF + bool decodeLegoPowerFunctions (decode_results *results) ; +# endif } ; //------------------------------------------------------------------------------ @@ -327,6 +335,10 @@ class IRsend # if SEND_PRONTO void sendPronto (char* code, bool repeat, bool fallback) ; # endif +//...................................................................... +# if SEND_LEGO_PF + void sendLegoPowerFunctions (uint16_t data, bool repeat = true) ; +# endif } ; #endif diff --git a/examples/LegoPowerFunctionsSendDemo/LegoPowerFunctionsSendDemo.ino b/examples/LegoPowerFunctionsSendDemo/LegoPowerFunctionsSendDemo.ino new file mode 100644 index 000000000..e43d06c2e --- /dev/null +++ b/examples/LegoPowerFunctionsSendDemo/LegoPowerFunctionsSendDemo.ino @@ -0,0 +1,22 @@ +/* + * LegoPowerFunctionsSendDemo: LEGO Power Functions + * Copyright (c) 2016 Philipp Henkel + */ + +#include +#include + +IRsend irsend; + +void setup() { +} + +void loop() { + // Send repeated command "channel 1, blue forward, red backward" + irsend.sendLegoPowerFunctions(0x197); + delay(2000); + + // Send single command "channel 1, blue forward, red backward" + irsend.sendLegoPowerFunctions(0x197, false); + delay(2000); +} diff --git a/irRecv.cpp b/irRecv.cpp index a3ff452e0..63438566a 100644 --- a/irRecv.cpp +++ b/irRecv.cpp @@ -80,6 +80,11 @@ int IRrecv::decode (decode_results *results) if (decodeDenon(results)) return true ; #endif +#if DECODE_LEGO_PF + DBG_PRINTLN("Attempting Lego Power Functions"); + if (decodeLegoPowerFunctions(results)) return true ; +#endif + // decodeHash returns a hash on any input. // Thus, it needs to be last in the list. // If you add any decodes, add them before this. @@ -145,8 +150,8 @@ void IRrecv::blink13 (int blinkflag) //+============================================================================= // Return if receiving new IR signals -// -bool IRrecv::isIdle ( ) +// +bool IRrecv::isIdle ( ) { return (irparams.rcvstate == STATE_IDLE || irparams.rcvstate == STATE_STOP) ? true : false; } diff --git a/ir_Lego_PF.cpp b/ir_Lego_PF.cpp new file mode 100644 index 000000000..dc94243ec --- /dev/null +++ b/ir_Lego_PF.cpp @@ -0,0 +1,130 @@ +#include "IRremote.h" +#include "IRremoteInt.h" + +//============================================================================== +// L EEEEEE EEEE OOOO +// L E E O O +// L EEEE E EEE O O +// L E E E O O LEGO Power Functions +// LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016 Philipp Henkel +//============================================================================== + +//+============================================================================= +// +#if SEND_LEGO_PF + +class BitStreamEncoder { + private: + uint16_t data; + bool repeatMessage; + int messageBitIdx; + int repeatCount; + int messageLength; + + // HIGH data bit = IR mark + high pause + // LOW data bit = IR mark + low pause + static const int LOW_BIT_DURATION = 421; + static const int HIGH_BIT_DURATION = 711; + static const int START_BIT_DURATION = 1184; + static const int STOP_BIT_DURATION = 1184; + static const int IR_MARK_DURATION = 158; + static const int HIGH_PAUSE_DURATION = HIGH_BIT_DURATION - IR_MARK_DURATION; + static const int LOW_PAUSE_DURATION = LOW_BIT_DURATION - IR_MARK_DURATION; + static const int START_PAUSE_DURATION = START_BIT_DURATION - IR_MARK_DURATION; + static const int STOP_PAUSE_DURATION = STOP_BIT_DURATION - IR_MARK_DURATION; + static const int MESSAGE_BITS = 18; + static const int MAX_MESSAGE_LENGTH = 16000; + + public: + void reset(uint16_t data, bool repeatMessage) { + this->data = data; + this->repeatMessage = repeatMessage; + messageBitIdx = 0; + repeatCount = 0; + messageLength = getMessageLength(); + } + + int getChannelId() const { return 1 + ((data >> 12) & 0x3); } + + int getMessageLength() const { + // Sum up all marks + int length = MESSAGE_BITS * IR_MARK_DURATION; + + // Sum up all pauses + length += START_PAUSE_DURATION; + for (unsigned long mask = 1UL << 15; mask; mask >>= 1) { + if (data & mask) { + length += HIGH_PAUSE_DURATION; + } else { + length += LOW_PAUSE_DURATION; + } + } + length += STOP_PAUSE_DURATION; + return length; + } + + boolean next() { + messageBitIdx++; + if (messageBitIdx >= MESSAGE_BITS) { + repeatCount++; + messageBitIdx = 0; + } + if (repeatCount >= 1 && !repeatMessage) { + return false; + } else if (repeatCount >= 5) { + return false; + } else { + return true; + } + } + + int getMarkDuration() const { return IR_MARK_DURATION; } + + int getPauseDuration() const { + if (messageBitIdx == 0) + return START_PAUSE_DURATION; + else if (messageBitIdx < MESSAGE_BITS - 1) { + return getDataBitPause(); + } else { + return getStopPause(); + } + } + + private: + int getDataBitPause() const { + const int pos = MESSAGE_BITS - 2 - messageBitIdx; + const bool isHigh = data & (1 << pos); + return isHigh ? HIGH_PAUSE_DURATION : LOW_PAUSE_DURATION; + } + + int getStopPause() const { + if (repeatMessage) { + return getRepeatStopPause(); + } else { + return STOP_PAUSE_DURATION; + } + } + + int getRepeatStopPause() const { + if (repeatCount == 0 || repeatCount == 1) { + return STOP_PAUSE_DURATION + 5 * MAX_MESSAGE_LENGTH - messageLength; + } else if (repeatCount == 2 || repeatCount == 3) { + return STOP_PAUSE_DURATION + + (6 + 2 * getChannelId()) * MAX_MESSAGE_LENGTH - messageLength; + } else { + return STOP_PAUSE_DURATION; + } + } +}; + +void IRsend::sendLegoPowerFunctions(uint16_t data, bool repeat) +{ + enableIROut(38); + static BitStreamEncoder bitStreamEncoder; + bitStreamEncoder.reset(data, repeat); + do { + mark(bitStreamEncoder.getMarkDuration()); + space(bitStreamEncoder.getPauseDuration()); + } while (bitStreamEncoder.next()); +} +#endif From d0f1d0d33d18b9aa8dd2eddb3ed096a730f660de Mon Sep 17 00:00:00 2001 From: Philipp Henkel Date: Wed, 27 Apr 2016 23:51:56 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Add=20supported=20device=20LEGO=C2=AE=20Pow?= =?UTF-8?q?er=20Functions=20IR=20Receiver=208884?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ir_Lego_PF.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ir_Lego_PF.cpp b/ir_Lego_PF.cpp index dc94243ec..2196bed6f 100644 --- a/ir_Lego_PF.cpp +++ b/ir_Lego_PF.cpp @@ -9,6 +9,9 @@ // LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016 Philipp Henkel //============================================================================== +// Supported Devices +// LEGO® Power Functions IR Receiver 8884 + //+============================================================================= // #if SEND_LEGO_PF From 92c7f0013869fd1289eebb1391861557783e8e68 Mon Sep 17 00:00:00 2001 From: Philipp Henkel Date: Wed, 4 May 2016 22:08:52 +0200 Subject: [PATCH 3/3] Update changelog and contributors --- Contributors.md | 5 ++--- changelog.md | 9 ++++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Contributors.md b/Contributors.md index 6988f52d0..1b559fea8 100644 --- a/Contributors.md +++ b/Contributors.md @@ -1,5 +1,5 @@ ## Contributors -These are the active contributors of this project that you may contact if there is anything you need help with or if you have suggestions. +These are the active contributors of this project that you may contact if there is anything you need help with or if you have suggestions. - [z3t0](https://github.com/z3t0) : Active Contributor and currently also the main contributor. * Email: zetoslab@gmail.com @@ -15,7 +15,6 @@ These are the active contributors of this project that you may contact if there - [Sebazzz](https://github.com/sebazz): Contributor - [lumbric](https://github.com/lumbric): Contributor - [ElectricRCAircraftGuy](https://github.com/electricrcaircraftguy): Active Contributor +- [henkel](https://github.com/henkel): Contributor Note: This list is being updated constantly so please let [z3t0](https://github.com/z3t0) know if you have been missed. - - diff --git a/changelog.md b/changelog.md index 2901dd167..41a214f18 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,6 @@ +## 2.1.1 - 2016/05/04 +- Added Lego Power Functions Protocol [PR #309](https://github.com/z3t0/Arduino-IRremote/pull/309) + ## 2.1.0 - 2016/02/20 - Improved Debugging [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258) - Display TIME instead of TICKS [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258) @@ -15,7 +18,7 @@ ## 2.0.1 - 2015/07/26 - [Release](https://github.com/shirriff/Arduino-IRremote/releases/tag/BETA) ### Changes - Updated README -- Updated Contributors +- Updated Contributors - Fixed #110 Mess - Created Gitter Room - Added Gitter Badge @@ -35,7 +38,7 @@ - Added Denon Protocol - Added Pronto Support - Added Library Properties -- Added Template For New Protocols +- Added Template For New Protocols - Added this changelog - Added Teensy LC Support - Added ATtiny84 Support @@ -44,7 +47,7 @@ ### Deletions - Removed (Fixed) #110 -- Broke Teensy 3 / 3.1 Support +- Broke Teensy 3 / 3.1 Support ### Not Working - Teensy 3 / 3.1 Support is in Development