From 5d01071e43a68c284485ebe99355046c69249a27 Mon Sep 17 00:00:00 2001 From: animavitis Date: Thu, 15 Nov 2018 19:51:10 +0100 Subject: [PATCH] update rc-switch (#313) --- lib/rc-switch/RCSwitch.cpp | 343 +++++++++++++++++++++++++++++++------ lib/rc-switch/RCSwitch.h | 31 +++- 2 files changed, 321 insertions(+), 53 deletions(-) diff --git a/lib/rc-switch/RCSwitch.cpp b/lib/rc-switch/RCSwitch.cpp index 1a6736e..ef56b0a 100644 --- a/lib/rc-switch/RCSwitch.cpp +++ b/lib/rc-switch/RCSwitch.cpp @@ -31,6 +31,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#define KeeLoq_NLF 0x3A5C742EUL + #include "RCSwitch.h" #ifdef RaspberryPi @@ -49,37 +51,72 @@ #endif -/* Format for protocol definitions: - * {pulselength, Sync bit, "0" bit, "1" bit} +/* Формат для описания протокола: + * + * {Pulse length, Preamble, Sync bit, "0" bit, "1" bit, Inverted Signal, Guard time} * - * pulselength: pulse length in microseconds, e.g. 350 - * Sync bit: {1, 31} means 1 high pulse and 31 low pulses - * (perceived as a 31*pulselength long pulse, total length of sync bit is - * 32*pulselength microseconds), i.e: + * Pulse length: длительность импульса Te в микросекундах, + * например 350 + * Preamble: преамбула - Чередование высоких и низких уровней + * {20, 1} означает 20 чередований длительностью 1 Te + * _ _ _ _ _ _ _ _ _ _ + * | |_| |_| |_| |_| |_| |_| |_| |_| |_| |_ + * Sync bit: Хедер и синхроимпульс + * {1, 31} означает 1 импульс длительностью Te высокого уровня и 31 низкого * _ * | |_______________________________ (don't count the vertical bars) - * "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse - * and 3 low pulses, total length (1+3)*pulselength, i.e: + * "0" bit: форма импульсов, определяющая бит данных, являющийся логическим "0" + * {1, 3} означает 1 импульс длительностью Te высокого уровня и 3 низкого * _ * | |___ - * "1" bit: waveform for a data bit of value "1", e.g. {3,1}: + * "1" bit: форма импульсов, определяющая бит данных, являющийся логической "1" + * {3, 1} означает 3 импульса длительностью Te высокого уровня и 1 низкого * ___ * | |_ * - * These are combined to form Tri-State bits when sending or receiving codes. + * (примечание: для формирования бита состояния Z (Tri-State bit) эти два кода объединяются) + * Inverted Signal: Инверсия сигнала - если принимает значение true, то это означает + * замену высокого уровня на низкий в передаваемом/принимаемом пакете + * Guard time: Защитное время, после которого следует очередная преамбула следующего пакета + * например 39 импульсов длительностью Te низкого уровня */ #if defined(ESP8266) || defined(ESP32) static const RCSwitch::Protocol proto[] = { #else static const RCSwitch::Protocol PROGMEM proto[] = { #endif - { 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1 - { 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2 - { 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3 - { 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4 - { 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5 - { 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B) - { 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false } // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote) + { 350, 0, { 0, 0 }, 1, { 1, 31 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 01 (Princeton, PT-2240) + { 650, 0, { 0, 0 }, 1, { 1, 10 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 02 + { 100, 0, { 0, 0 }, 1, { 30, 71 }, { 4, 11 }, { 9, 6 }, false, 0 }, // 03 + { 380, 0, { 0, 0 }, 1, { 1, 6 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 04 + { 500, 0, { 0, 0 }, 1, { 6, 14 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 05 + { 450, 0, { 0, 0 }, 1, { 23, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 06 (HT6P20B) + { 150, 0, { 0, 0 }, 1, { 2, 62 }, { 1, 6 }, { 6, 1 }, false, 0 }, // 07 (HS2303-PT, i. e. used in AUKEY Remote) + { 320, 0, { 0, 0 }, 1, { 36, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 08 (Came 12bit, HT12E) + { 700, 0, { 0, 0 }, 1, { 32, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 09 (Nice_Flo 12bit) + { 420, 0, { 0, 0 }, 1, { 60, 6 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 10 (V2 phoenix) + { 500, 2, { 3, 3 }, 0, { 0, 0 }, { 1, 2 }, { 2, 1 }, false, 37 }, // 11 (Nice_FloR-S 52bit) + { 400, 23, { 1, 1 }, 1, { 0, 9 }, { 2, 1 }, { 1, 2 }, false, 39 }, // 12 (Keeloq 64/66) + { 300, 6, { 2, 2 }, 3, { 8, 3 }, { 2, 2 }, { 3, 3 }, false, 0 }, // 13 test (CFM) + { 250, 12, { 4, 4 }, 0, { 0, 0 }, { 1, 1 }, { 2, 2 }, false, 0 }, // 14 test (StarLine) + { 500, 0, { 0, 0 }, 0, { 100, 1 }, { 1, 2 }, { 2, 1 }, false, 35 }, // 15 + + { 361, 0, { 0, 0 }, 1, { 52, 1 }, { 1, 3 }, { 3, 1 }, true, 0 }, // 16 (Einhell) + { 500, 0, { 0, 0 }, 1, { 1, 23 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 17 (InterTechno PAR-1000) + { 180, 0, { 0, 0 }, 1, { 1, 15 }, { 1, 1 }, { 1, 8 }, false, 0 }, // 18 (Intertechno ITT-1500) + { 350, 0, { 0, 0 }, 1, { 1, 2 }, { 0, 2 }, { 3, 2 }, false, 0 }, // 19 (Murcury) + { 150, 0, { 0, 0 }, 1, { 34, 3 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 20 (AC114) + { 360, 0, { 0, 0 }, 1, { 13, 4 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 21 (DC250) + { 650, 0, { 0, 0 }, 1, { 1, 10 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 22 (Mandolyn/Lidl TR-502MSV/RC-402/RC-402DX) + { 641, 0, { 0, 0 }, 1, { 115, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 23 (Lidl TR-502MSV/RC-402 - Flavien) + { 620, 0, { 0, 0 }, 1, { 0, 64 }, { 0, 1 }, { 1, 0 }, false, 0 }, // 24 (Lidl TR-502MSV/RC701) + { 560, 0, { 0, 0 }, 1, { 16, 8 }, { 1, 1 }, { 1, 3 }, false, 0 }, // 25 (NEC) + { 385, 0, { 0, 0 }, 1, { 1, 17 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 26 (Arlec RC210) + { 188, 0, { 0, 0 }, 1, { 1, 31 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 27 (Zap, FHT-7901) + + { 700, 1, { 0, 1 }, 1, { 116, 0 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 28 (Quigg GT-7000) + { 220, 0, { 0, 0 }, 1, { 1, 46 }, { 1, 6 }, { 1, 1 }, false, 2 }, // 29 (NEXA) + { 260, 0, { 0, 0 }, 1, { 1, 8 }, { 1, 4 }, { 4, 1 }, true, 0 } // 30 (Anima) }; enum { @@ -87,21 +124,22 @@ enum { }; #if not defined( RCSwitchDisableReceiving ) -volatile unsigned long RCSwitch::nReceivedValue = 0; +volatile unsigned long long RCSwitch::nReceivedValue = 0; volatile unsigned int RCSwitch::nReceivedBitlength = 0; volatile unsigned int RCSwitch::nReceivedDelay = 0; volatile unsigned int RCSwitch::nReceivedProtocol = 0; int RCSwitch::nReceiveTolerance = 60; -const unsigned int RCSwitch::nSeparationLimit = 4300; +const unsigned int RCSwitch::nSeparationLimit = 4100; // 4300 default // separationLimit: minimum microseconds between received codes, closer codes are ignored. // according to discussion on issue #14 it might be more suitable to set the separation // limit to the same time as the 'low' part of the sync signal for the current protocol. unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; +unsigned int RCSwitch::buftimings[4]; #endif RCSwitch::RCSwitch() { this->nTransmitterPin = -1; - this->setRepeatTransmit(10); + this->setRepeatTransmit(5); this->setProtocol(1); #if not defined( RCSwitchDisableReceiving ) this->nReceiverInterrupt = -1; @@ -441,7 +479,7 @@ char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) { */ void RCSwitch::sendTriState(const char* sCodeWord) { // turn the tristate code word into the corresponding bit pattern, then send it - unsigned long code = 0; + unsigned long long code = 0; unsigned int length = 0; for (const char* p = sCodeWord; *p; p++) { code <<= 2L; @@ -451,11 +489,11 @@ void RCSwitch::sendTriState(const char* sCodeWord) { break; case 'F': // bit pattern 01 - code |= 1L; + code |= 1ULL; break; case '1': // bit pattern 11 - code |= 3L; + code |= 3ULL; break; } length += 2; @@ -468,12 +506,12 @@ void RCSwitch::sendTriState(const char* sCodeWord) { */ void RCSwitch::send(const char* sCodeWord) { // turn the tristate code word into the corresponding bit pattern, then send it - unsigned long code = 0; + unsigned long long code = 0; unsigned int length = 0; for (const char* p = sCodeWord; *p; p++) { - code <<= 1L; + code <<= 1ULL; if (*p != '0') - code |= 1L; + code |= 1ULL; length++; } this->send(code, length); @@ -484,7 +522,7 @@ void RCSwitch::send(const char* sCodeWord) { * bits are sent from MSB to LSB, i.e., first the bit at position length-1, * then the bit at position length-2, and so on, till finally the bit at position 0. */ -void RCSwitch::send(unsigned long code, unsigned int length) { +void RCSwitch::send(unsigned long long code, unsigned int length) { if (this->nTransmitterPin == -1) return; @@ -496,14 +534,41 @@ void RCSwitch::send(unsigned long code, unsigned int length) { } #endif + // повторяем отправку пакета nRepeatTransmit раз for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { - for (int i = length-1; i >= 0; i--) { - if (code & (1L << i)) + // отправляем преамбулу (меандр) + for (int i = 0; i < ((protocol.PreambleFactor / 2) + (protocol.PreambleFactor %2 )); i++) { + this->transmit({protocol.Preamble.high, protocol.Preamble.low}); + } + // отправляем хедер + if (protocol.HeaderFactor > 0) { + for (int i = 0; i < protocol.HeaderFactor; i++) { + this->transmit(protocol.Header); + } + } + // отправляем код посылки + for (int i = length - 1; i >= 0; i--) { + if (code & (1ULL << i)) this->transmit(protocol.one); else this->transmit(protocol.zero); } - this->transmit(protocol.syncFactor); + // для килока должна быть длительность 66, а сохраняется 64 значащих кода данных + // поэтому отправим еще два бита для ровного счета + if (length == 64) { + if (nRepeat == 0) { + this->transmit(protocol.zero); + this->transmit(protocol.zero); + } else { + this->transmit(protocol.one); + this->transmit(protocol.one); + } + } + // выдерживаем Защитное время (Guard Time) + if (protocol.Guard > 0) { + digitalWrite(this->nTransmitterPin, LOW); + delayMicroseconds(this->protocol.pulseLength * protocol.Guard); + } } // Disable transmit after sending (i.e., for inverted protocols) @@ -524,10 +589,14 @@ void RCSwitch::transmit(HighLow pulses) { uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH; uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW; - digitalWrite(this->nTransmitterPin, firstLogicLevel); - delayMicroseconds( this->protocol.pulseLength * pulses.high); - digitalWrite(this->nTransmitterPin, secondLogicLevel); - delayMicroseconds( this->protocol.pulseLength * pulses.low); + if (pulses.high > 0) { + digitalWrite(this->nTransmitterPin, firstLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.high); + } + if (pulses.low > 0) { + digitalWrite(this->nTransmitterPin, secondLogicLevel); + delayMicroseconds( this->protocol.pulseLength * pulses.low); + } } @@ -570,7 +639,7 @@ void RCSwitch::resetAvailable() { RCSwitch::nReceivedValue = 0; } -unsigned long RCSwitch::getReceivedValue() { +unsigned long long RCSwitch::getReceivedValue() { return RCSwitch::nReceivedValue; } @@ -606,12 +675,41 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun memcpy_P(&pro, &proto[p-1], sizeof(Protocol)); #endif - unsigned long code = 0; - //Assuming the longer pulse length is the pulse captured in timings[0] - const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high); - const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses; + unsigned long long code = 0; + unsigned int FirstTiming = 0; + if (pro.PreambleFactor > 0) { + FirstTiming = pro.PreambleFactor + 1; + } + unsigned int BeginData = 0; + if (pro.HeaderFactor > 0) { + BeginData = (pro.invertedSignal) ? (2) : (1); + // коррекция на количество импульсов в Хедере для более одного + if (pro.HeaderFactor > 1) { + BeginData += (pro.HeaderFactor - 1) * 2; + } + } + //Assuming the longer pulse length is the pulse captured in timings[FirstTiming] + // берем наибольшее значение из Header + const unsigned int syncLengthInPulses = ((pro.Header.low) > (pro.Header.high)) ? (pro.Header.low) : (pro.Header.high); + // определяем длительность Te как длительность первого импульса header деленную на количество импульсов в нем + // или как длительность импульса preamble деленную на количество Te в нем + unsigned int sdelay = 0; + if (syncLengthInPulses > 0) { + sdelay = RCSwitch::timings[FirstTiming] / syncLengthInPulses; + } else { + sdelay = RCSwitch::timings[FirstTiming-2] / pro.PreambleFactor; + } + const unsigned int delay = sdelay; + // nReceiveTolerance = 60 + // допустимое отклонение длительностей импульсов на 60 % const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + // 0 - sync перед preamble или data + // BeginData - сдвиг на 1 или 2 от sync к preamble/data + // FirstTiming - сдвиг на preamble к header + // firstDataTiming первый импульс data + // bitChangeCount - количество импульсов в data + /* For protocols that start low, the sync period looks like * _________ * _____________| |XXXXXXXXXXXX| @@ -629,9 +727,16 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun * * The 2nd saved duration starts the data */ - const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1); + // если invertedSignal=false, то сигнал начинается с 1 элемента массива (высокий уровень) + // если invertedSignal=true, то сигнал начинается со 2 элемента массива (низкий уровень) + // добавляем поправку на Преамбулу и Хедер + const unsigned int firstDataTiming = BeginData + FirstTiming; + unsigned int bitChangeCount = changeCount - firstDataTiming - 1 + pro.invertedSignal; + if (bitChangeCount > 128) { + bitChangeCount = 128; + } - for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { + for (unsigned int i = firstDataTiming; i < firstDataTiming + bitChangeCount; i += 2) { code <<= 1; if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { @@ -646,9 +751,9 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun } } - if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + if (bitChangeCount > 14) { // ignore very short transmissions: no device sends them, so this must be noise RCSwitch::nReceivedValue = code; - RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedBitlength = bitChangeCount / 2; RCSwitch::nReceivedDelay = delay; RCSwitch::nReceivedProtocol = p; return true; @@ -661,32 +766,63 @@ void RECEIVE_ATTR RCSwitch::handleInterrupt() { static unsigned int changeCount = 0; static unsigned long lastTime = 0; - static unsigned int repeatCount = 0; + static byte repeatCount = 0; const long time = micros(); const unsigned int duration = time - lastTime; - if (duration > RCSwitch::nSeparationLimit) { + RCSwitch::buftimings[3]=RCSwitch::buftimings[2]; + RCSwitch::buftimings[2]=RCSwitch::buftimings[1]; + RCSwitch::buftimings[1]=RCSwitch::buftimings[0]; + RCSwitch::buftimings[0]=duration; + + if (duration > RCSwitch::nSeparationLimit || + changeCount == 156 || + (diff(RCSwitch::buftimings[3], RCSwitch::buftimings[2]) < 50 && + diff(RCSwitch::buftimings[2], RCSwitch::buftimings[1]) < 50 && + changeCount > 25)) { + // принят длинный импульс продолжительностью более nSeparationLimit (4300) // A long stretch without signal level change occurred. This could // be the gap between two transmission. - if (diff(duration, RCSwitch::timings[0]) < 200) { + if (diff(duration, RCSwitch::timings[0]) < 400 || + changeCount == 156 || + (diff(RCSwitch::buftimings[3], RCSwitch::timings[1]) < 50 && + diff(RCSwitch::buftimings[2], RCSwitch::timings[2]) < 50 && + diff(RCSwitch::buftimings[1], RCSwitch::timings[3]) < 50 && + changeCount > 25)) { + // если его длительность отличается от первого импульса, + // который приняли раньше, менее чем на +-200 (исходно 200) + // то считаем это повторным пакетом и игнорируем его // This long signal is close in length to the long signal which // started the previously recorded timings; this suggests that // it may indeed by a a gap between two transmissions (we assume // here that a sender will send the signal multiple times, // with roughly the same gap between them). + + // количество повторных пакетов repeatCount++; - if (repeatCount == 2) { + // при приеме второго повторного начинаем анализ принятого первым + if (repeatCount == 1) { for(unsigned int i = 1; i <= numProto; i++) { if (receiveProtocol(i, changeCount)) { // receive succeeded for protocol i break; } } + // очищаем количество повторных пакетов repeatCount = 0; } } + // дительность отличается более чем на +-200 от первого + // принятого ранее, очищаем счетчик для приема нового пакета changeCount = 0; + if (diff(RCSwitch::buftimings[3], RCSwitch::buftimings[2]) < 50 && + diff(RCSwitch::buftimings[2], RCSwitch::buftimings[1]) < 50) { + RCSwitch::timings[1]=RCSwitch::buftimings[3]; + RCSwitch::timings[2]=RCSwitch::buftimings[2]; + RCSwitch::timings[3]=RCSwitch::buftimings[1]; + changeCount = 4; + } } // detect overflow @@ -695,7 +831,118 @@ void RECEIVE_ATTR RCSwitch::handleInterrupt() { repeatCount = 0; } - RCSwitch::timings[changeCount++] = duration; + // заносим в массив длительность очередного принятого импульса + if (changeCount > 0 & duration < 100) { // игнорируем шумовые всплески менее 100 мкс + RCSwitch::timings[changeCount-1] += duration; + } else { + RCSwitch::timings[changeCount++] = duration; + } lastTime = time; } #endif + +/** + * Initilize Keeloq + */ +Keeloq::Keeloq() { + _keyHigh = 0; + _keyLow = 0; +} + +/** + * Set Keeloq 64 bit cypher key + */ +void Keeloq::SetKey(unsigned long keyHigh, unsigned long keyLow) { + _keyHigh = keyHigh; + _keyLow = keyLow; +} + +/** + * Get Key data + */ +unsigned long Keeloq::GetKey(bool HighLow) { + if (HighLow) { + return _keyHigh; + } + return _keyLow; +} + +/** + * Encrypt Keeloq 32 bit data + */ +unsigned long Keeloq::Encrypt(unsigned long data) { + unsigned long x = data; + unsigned long r; + int keyBitNo, index; + unsigned long keyBitVal,bitVal; + + for (r = 0; r < 528; r++) { + keyBitNo = r & 63; + if (keyBitNo < 32) { + keyBitVal = bitRead(_keyLow,keyBitNo); + } else { + keyBitVal = bitRead(_keyHigh, keyBitNo - 32); + } + index = 1 * bitRead(x, 1) + 2 * bitRead(x, 9) + 4 * bitRead(x, 20) + 8 * bitRead(x, 26) + 16 * bitRead(x, 31); + bitVal = bitRead(x, 0) ^ bitRead(x, 16) ^ bitRead(KeeLoq_NLF, index) ^ keyBitVal; + x = (x >> 1) ^ bitVal << 31; + } + return x; +} + +/** + * Decrypt Keeloq 32 bit data + */ +unsigned long Keeloq::Decrypt(unsigned long data) { + unsigned long x = data; + unsigned long r; + int keyBitNo, index; + unsigned long keyBitVal,bitVal; + + for (r = 0; r < 528; r++) { + keyBitNo = (15-r) & 63; + if(keyBitNo < 32) { + keyBitVal = bitRead(_keyLow,keyBitNo); + } else { + keyBitVal = bitRead(_keyHigh, keyBitNo - 32); + } + index = 1 * bitRead(x, 0) + 2 * bitRead(x, 8) + 4 * bitRead(x, 19) + 8 * bitRead(x, 25) + 16 * bitRead(x, 30); + bitVal = bitRead(x, 31) ^ bitRead(x, 15) ^ bitRead(KeeLoq_NLF, index) ^ keyBitVal; + x = (x << 1) ^ bitVal; + } + return x; +} + +/** + * Set Normal Learning Keeloq key + */ +void Keeloq::NormLearn(unsigned long FixSN) { + unsigned long tmpFixSN; + // заготовки для формируемого ключа + unsigned long NewkeyHigh; + unsigned long NewkeyLow; + + tmpFixSN = FixSN & 0x0FFFFFFF; + tmpFixSN |= 0x20000000; + NewkeyLow = Decrypt(tmpFixSN); + tmpFixSN = FixSN & 0x0FFFFFFF; + tmpFixSN |= 0x60000000; + NewkeyHigh = Decrypt(tmpFixSN); + _keyHigh = NewkeyHigh; + _keyLow = NewkeyLow; +} + +/** + * Reflect a 32 bit package + */ +unsigned long Keeloq::ReflectPack(unsigned long PackSrc) { + unsigned long long PackOut = 0; + for (byte i = 0; i < 32; i++) { + PackOut = PackOut << 1; + if (PackSrc & 1) { + PackOut = PackOut | 1; + } + PackSrc = PackSrc >> 1; + } + return PackOut; +} \ No newline at end of file diff --git a/lib/rc-switch/RCSwitch.h b/lib/rc-switch/RCSwitch.h index b7755e0..5cc698b 100644 --- a/lib/rc-switch/RCSwitch.h +++ b/lib/rc-switch/RCSwitch.h @@ -58,7 +58,8 @@ // Number of maximum high/Low changes per packet. // We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync -#define RCSWITCH_MAX_CHANGES 67 +// Для keeloq нужно увеличить RCSWITCH_MAX_CHANGES до 23+1+66*2+1=157 +#define RCSWITCH_MAX_CHANGES 157 // default 67 class RCSwitch { @@ -77,7 +78,7 @@ class RCSwitch { void switchOff(char sGroup, int nDevice); void sendTriState(const char* sCodeWord); - void send(unsigned long code, unsigned int length); + void send(unsigned long long code, unsigned int length); void send(const char* sCodeWord); #if not defined( RCSwitchDisableReceiving ) @@ -87,7 +88,7 @@ class RCSwitch { bool available(); void resetAvailable(); - unsigned long getReceivedValue(); + unsigned long long getReceivedValue(); unsigned int getReceivedBitlength(); unsigned int getReceivedDelay(); unsigned int getReceivedProtocol(); @@ -120,8 +121,11 @@ class RCSwitch { struct Protocol { /** base pulse length in microseconds, e.g. 350 */ uint16_t pulseLength; + uint8_t PreambleFactor; + HighLow Preamble; + uint8_t HeaderFactor; + HighLow Header; - HighLow syncFactor; HighLow zero; HighLow one; @@ -142,6 +146,7 @@ class RCSwitch { * FOO.low*pulseLength microseconds. */ bool invertedSignal; + uint16_t Guard; }; void setProtocol(Protocol protocol); @@ -167,7 +172,7 @@ class RCSwitch { #if not defined( RCSwitchDisableReceiving ) static int nReceiveTolerance; - volatile static unsigned long nReceivedValue; + volatile static unsigned long long nReceivedValue; volatile static unsigned int nReceivedBitlength; volatile static unsigned int nReceivedDelay; volatile static unsigned int nReceivedProtocol; @@ -176,9 +181,25 @@ class RCSwitch { * timings[0] contains sync timing, followed by a number of bits */ static unsigned int timings[RCSWITCH_MAX_CHANGES]; + // буфер длительностей последних четырех пакетов, [0] - последний + static unsigned int buftimings[4]; #endif }; +class Keeloq { + public: + Keeloq(); + void SetKey(unsigned long keyHigh, unsigned long keyLow); + unsigned long GetKey(bool HighLow); + unsigned long Encrypt(unsigned long data); + unsigned long Decrypt(unsigned long data); + void NormLearn(unsigned long FixSN); + unsigned long ReflectPack(unsigned long PackSrc); + private: + unsigned long _keyHigh; + unsigned long _keyLow; +}; + #endif