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

Add Lego Power Functions send protocol #309

Merged
merged 3 commits into from
May 21, 2016
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
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 2 additions & 3 deletions Contributors.md
Original file line number Diff line number Diff line change
@@ -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: [email protected]
Expand All @@ -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.


14 changes: 13 additions & 1 deletion IRremote.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -115,6 +118,7 @@ typedef
SHARP,
DENON,
PRONTO,
LEGO_PF,
}
decode_type_t;

Expand Down Expand Up @@ -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
} ;

//------------------------------------------------------------------------------
Expand Down Expand Up @@ -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
9 changes: 6 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
22 changes: 22 additions & 0 deletions examples/LegoPowerFunctionsSendDemo/LegoPowerFunctionsSendDemo.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* LegoPowerFunctionsSendDemo: LEGO Power Functions
* Copyright (c) 2016 Philipp Henkel
*/

#include <IRremote.h>
#include <IRremoteInt.h>

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);
}
9 changes: 7 additions & 2 deletions irRecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down
133 changes: 133 additions & 0 deletions ir_Lego_PF.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#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
//==============================================================================

// Supported Devices
// LEGO® Power Functions IR Receiver 8884

//+=============================================================================
//
#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