Skip to content

Commit 44f801d

Browse files
committed
Merge pull request Arduino-IRremote#309 from henkel/lego_power_functions
Add Lego Power Functions send protocol
2 parents d064c7d + 92c7f00 commit 44f801d

File tree

7 files changed

+184
-9
lines changed

7 files changed

+184
-9
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ env:
1919
- PLATFORMIO_CI_SRC=examples/IRtest PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6"
2020
- PLATFORMIO_CI_SRC=examples/IRtest2 PLATFORMIO_BUILD_FLAGS="-DSEND_NEC -DSEND_SONY -DSEND_RC5 -DSEND_RC6"
2121
- PLATFORMIO_CI_SRC=examples/JVCPanasonicSendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_JVC -DSEND_PANASONIC"
22+
- PLATFORMIO_CI_SRC=examples/LegoPowerFunctionsSendDemo PLATFORMIO_BUILD_FLAGS="-DSEND_LEGO_PF"
2223
- PLATFORMIO_CI_SRC=examples/IRremoteInfo
2324

2425
install:

Contributors.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
## Contributors
2-
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.
2+
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.
33

44
- [z3t0](https://github.com/z3t0) : Active Contributor and currently also the main contributor.
55
@@ -15,7 +15,6 @@ These are the active contributors of this project that you may contact if there
1515
- [Sebazzz](https://github.com/sebazz): Contributor
1616
- [lumbric](https://github.com/lumbric): Contributor
1717
- [ElectricRCAircraftGuy](https://github.com/electricrcaircraftguy): Active Contributor
18+
- [henkel](https://github.com/henkel): Contributor
1819

1920
Note: This list is being updated constantly so please let [z3t0](https://github.com/z3t0) know if you have been missed.
20-
21-

IRremote.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
#define SEND_AIWA_RC_T501 1
5757

5858
#define DECODE_LG 1
59-
#define SEND_LG 1
59+
#define SEND_LG 1
6060

6161
#define DECODE_SANYO 1
6262
#define SEND_SANYO 0 // NOT WRITTEN
@@ -76,6 +76,9 @@
7676
#define DECODE_PRONTO 0 // This function doe not logically make sense
7777
#define SEND_PRONTO 1
7878

79+
#define DECODE_LEGO_PF 0 // NOT WRITTEN
80+
#define SEND_LEGO_PF 1
81+
7982
//------------------------------------------------------------------------------
8083
// When sending a Pronto code we request to send either the "once" code
8184
// or the "repeat" code
@@ -115,6 +118,7 @@ typedef
115118
SHARP,
116119
DENON,
117120
PRONTO,
121+
LEGO_PF,
118122
}
119123
decode_type_t;
120124

@@ -243,6 +247,10 @@ class IRrecv
243247
# if DECODE_DENON
244248
bool decodeDenon (decode_results *results) ;
245249
# endif
250+
//......................................................................
251+
# if DECODE_LEGO_PF
252+
bool decodeLegoPowerFunctions (decode_results *results) ;
253+
# endif
246254
} ;
247255

248256
//------------------------------------------------------------------------------
@@ -327,6 +335,10 @@ class IRsend
327335
# if SEND_PRONTO
328336
void sendPronto (char* code, bool repeat, bool fallback) ;
329337
# endif
338+
//......................................................................
339+
# if SEND_LEGO_PF
340+
void sendLegoPowerFunctions (uint16_t data, bool repeat = true) ;
341+
# endif
330342
} ;
331343

332344
#endif

changelog.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 2.1.1 - 2016/05/04
2+
- Added Lego Power Functions Protocol [PR #309](https://github.com/z3t0/Arduino-IRremote/pull/309)
3+
14
## 2.1.0 - 2016/02/20
25
- Improved Debugging [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258)
36
- Display TIME instead of TICKS [PR #258](https://github.com/z3t0/Arduino-IRremote/pull/258)
@@ -15,7 +18,7 @@
1518
## 2.0.1 - 2015/07/26 - [Release](https://github.com/shirriff/Arduino-IRremote/releases/tag/BETA)
1619
### Changes
1720
- Updated README
18-
- Updated Contributors
21+
- Updated Contributors
1922
- Fixed #110 Mess
2023
- Created Gitter Room
2124
- Added Gitter Badge
@@ -35,7 +38,7 @@
3538
- Added Denon Protocol
3639
- Added Pronto Support
3740
- Added Library Properties
38-
- Added Template For New Protocols
41+
- Added Template For New Protocols
3942
- Added this changelog
4043
- Added Teensy LC Support
4144
- Added ATtiny84 Support
@@ -44,7 +47,7 @@
4447

4548
### Deletions
4649
- Removed (Fixed) #110
47-
- Broke Teensy 3 / 3.1 Support
50+
- Broke Teensy 3 / 3.1 Support
4851

4952
### Not Working
5053
- Teensy 3 / 3.1 Support is in Development
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* LegoPowerFunctionsSendDemo: LEGO Power Functions
3+
* Copyright (c) 2016 Philipp Henkel
4+
*/
5+
6+
#include <IRremote.h>
7+
#include <IRremoteInt.h>
8+
9+
IRsend irsend;
10+
11+
void setup() {
12+
}
13+
14+
void loop() {
15+
// Send repeated command "channel 1, blue forward, red backward"
16+
irsend.sendLegoPowerFunctions(0x197);
17+
delay(2000);
18+
19+
// Send single command "channel 1, blue forward, red backward"
20+
irsend.sendLegoPowerFunctions(0x197, false);
21+
delay(2000);
22+
}

irRecv.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ int IRrecv::decode (decode_results *results)
8080
if (decodeDenon(results)) return true ;
8181
#endif
8282

83+
#if DECODE_LEGO_PF
84+
DBG_PRINTLN("Attempting Lego Power Functions");
85+
if (decodeLegoPowerFunctions(results)) return true ;
86+
#endif
87+
8388
// decodeHash returns a hash on any input.
8489
// Thus, it needs to be last in the list.
8590
// If you add any decodes, add them before this.
@@ -145,8 +150,8 @@ void IRrecv::blink13 (int blinkflag)
145150

146151
//+=============================================================================
147152
// Return if receiving new IR signals
148-
//
149-
bool IRrecv::isIdle ( )
153+
//
154+
bool IRrecv::isIdle ( )
150155
{
151156
return (irparams.rcvstate == STATE_IDLE || irparams.rcvstate == STATE_STOP) ? true : false;
152157
}

ir_Lego_PF.cpp

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
#include "IRremote.h"
2+
#include "IRremoteInt.h"
3+
4+
//==============================================================================
5+
// L EEEEEE EEEE OOOO
6+
// L E E O O
7+
// L EEEE E EEE O O
8+
// L E E E O O LEGO Power Functions
9+
// LLLLLL EEEEEE EEEE OOOO Copyright (c) 2016 Philipp Henkel
10+
//==============================================================================
11+
12+
// Supported Devices
13+
// LEGO® Power Functions IR Receiver 8884
14+
15+
//+=============================================================================
16+
//
17+
#if SEND_LEGO_PF
18+
19+
class BitStreamEncoder {
20+
private:
21+
uint16_t data;
22+
bool repeatMessage;
23+
int messageBitIdx;
24+
int repeatCount;
25+
int messageLength;
26+
27+
// HIGH data bit = IR mark + high pause
28+
// LOW data bit = IR mark + low pause
29+
static const int LOW_BIT_DURATION = 421;
30+
static const int HIGH_BIT_DURATION = 711;
31+
static const int START_BIT_DURATION = 1184;
32+
static const int STOP_BIT_DURATION = 1184;
33+
static const int IR_MARK_DURATION = 158;
34+
static const int HIGH_PAUSE_DURATION = HIGH_BIT_DURATION - IR_MARK_DURATION;
35+
static const int LOW_PAUSE_DURATION = LOW_BIT_DURATION - IR_MARK_DURATION;
36+
static const int START_PAUSE_DURATION = START_BIT_DURATION - IR_MARK_DURATION;
37+
static const int STOP_PAUSE_DURATION = STOP_BIT_DURATION - IR_MARK_DURATION;
38+
static const int MESSAGE_BITS = 18;
39+
static const int MAX_MESSAGE_LENGTH = 16000;
40+
41+
public:
42+
void reset(uint16_t data, bool repeatMessage) {
43+
this->data = data;
44+
this->repeatMessage = repeatMessage;
45+
messageBitIdx = 0;
46+
repeatCount = 0;
47+
messageLength = getMessageLength();
48+
}
49+
50+
int getChannelId() const { return 1 + ((data >> 12) & 0x3); }
51+
52+
int getMessageLength() const {
53+
// Sum up all marks
54+
int length = MESSAGE_BITS * IR_MARK_DURATION;
55+
56+
// Sum up all pauses
57+
length += START_PAUSE_DURATION;
58+
for (unsigned long mask = 1UL << 15; mask; mask >>= 1) {
59+
if (data & mask) {
60+
length += HIGH_PAUSE_DURATION;
61+
} else {
62+
length += LOW_PAUSE_DURATION;
63+
}
64+
}
65+
length += STOP_PAUSE_DURATION;
66+
return length;
67+
}
68+
69+
boolean next() {
70+
messageBitIdx++;
71+
if (messageBitIdx >= MESSAGE_BITS) {
72+
repeatCount++;
73+
messageBitIdx = 0;
74+
}
75+
if (repeatCount >= 1 && !repeatMessage) {
76+
return false;
77+
} else if (repeatCount >= 5) {
78+
return false;
79+
} else {
80+
return true;
81+
}
82+
}
83+
84+
int getMarkDuration() const { return IR_MARK_DURATION; }
85+
86+
int getPauseDuration() const {
87+
if (messageBitIdx == 0)
88+
return START_PAUSE_DURATION;
89+
else if (messageBitIdx < MESSAGE_BITS - 1) {
90+
return getDataBitPause();
91+
} else {
92+
return getStopPause();
93+
}
94+
}
95+
96+
private:
97+
int getDataBitPause() const {
98+
const int pos = MESSAGE_BITS - 2 - messageBitIdx;
99+
const bool isHigh = data & (1 << pos);
100+
return isHigh ? HIGH_PAUSE_DURATION : LOW_PAUSE_DURATION;
101+
}
102+
103+
int getStopPause() const {
104+
if (repeatMessage) {
105+
return getRepeatStopPause();
106+
} else {
107+
return STOP_PAUSE_DURATION;
108+
}
109+
}
110+
111+
int getRepeatStopPause() const {
112+
if (repeatCount == 0 || repeatCount == 1) {
113+
return STOP_PAUSE_DURATION + 5 * MAX_MESSAGE_LENGTH - messageLength;
114+
} else if (repeatCount == 2 || repeatCount == 3) {
115+
return STOP_PAUSE_DURATION
116+
+ (6 + 2 * getChannelId()) * MAX_MESSAGE_LENGTH - messageLength;
117+
} else {
118+
return STOP_PAUSE_DURATION;
119+
}
120+
}
121+
};
122+
123+
void IRsend::sendLegoPowerFunctions(uint16_t data, bool repeat)
124+
{
125+
enableIROut(38);
126+
static BitStreamEncoder bitStreamEncoder;
127+
bitStreamEncoder.reset(data, repeat);
128+
do {
129+
mark(bitStreamEncoder.getMarkDuration());
130+
space(bitStreamEncoder.getPauseDuration());
131+
} while (bitStreamEncoder.next());
132+
}
133+
#endif

0 commit comments

Comments
 (0)