|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
-
- //==============================================================================
- // 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, 2017 Philipp Henkel
- //==============================================================================
-
- //+=============================================================================
- //
-
- class LegoPfBitStreamEncoder {
- private:
- uint16_t data;
- bool repeatMessage;
- uint8_t messageBitIdx;
- uint8_t repeatCount;
- uint16_t messageLength;
-
- public:
- // HIGH data bit = IR mark + high pause
- // LOW data bit = IR mark + low pause
- static const uint16_t LOW_BIT_DURATION = 421;
- static const uint16_t HIGH_BIT_DURATION = 711;
- static const uint16_t START_BIT_DURATION = 1184;
- static const uint16_t STOP_BIT_DURATION = 1184;
- static const uint8_t IR_MARK_DURATION = 158;
- static const uint16_t HIGH_PAUSE_DURATION = HIGH_BIT_DURATION - IR_MARK_DURATION;
- static const uint16_t LOW_PAUSE_DURATION = LOW_BIT_DURATION - IR_MARK_DURATION;
- static const uint16_t START_PAUSE_DURATION = START_BIT_DURATION - IR_MARK_DURATION;
- static const uint16_t STOP_PAUSE_DURATION = STOP_BIT_DURATION - IR_MARK_DURATION;
- static const uint8_t MESSAGE_BITS = 18;
- static const uint16_t MAX_MESSAGE_LENGTH = 16000;
-
- 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); }
-
- uint16_t getMessageLength() const {
- // Sum up all marks
- uint16_t 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;
- }
- }
-
- uint8_t getMarkDuration() const { return IR_MARK_DURATION; }
-
- uint32_t getPauseDuration() const {
- if (messageBitIdx == 0)
- return START_PAUSE_DURATION;
- else if (messageBitIdx < MESSAGE_BITS - 1) {
- return getDataBitPause();
- } else {
- return getStopPause();
- }
- }
-
- private:
- uint16_t getDataBitPause() const {
- const int pos = MESSAGE_BITS - 2 - messageBitIdx;
- const bool isHigh = data & (1 << pos);
- return isHigh ? HIGH_PAUSE_DURATION : LOW_PAUSE_DURATION;
- }
-
- uint32_t getStopPause() const {
- if (repeatMessage) {
- return getRepeatStopPause();
- } else {
- return STOP_PAUSE_DURATION;
- }
- }
-
- uint32_t getRepeatStopPause() const {
- if (repeatCount == 0 || repeatCount == 1) {
- return STOP_PAUSE_DURATION + (uint32_t)5 * MAX_MESSAGE_LENGTH - messageLength;
- } else if (repeatCount == 2 || repeatCount == 3) {
- return STOP_PAUSE_DURATION
- + (uint32_t)(6 + 2 * getChannelId()) * MAX_MESSAGE_LENGTH - messageLength;
- } else {
- return STOP_PAUSE_DURATION;
- }
- }
- };
|