Remove Keeloq

This commit is contained in:
Jason2866 2020-08-21 00:14:57 +02:00
parent 98818806f0
commit 9f87647af6
19 changed files with 336 additions and 134 deletions

View File

@ -1,69 +0,0 @@
language: c
python:
- "2.7"
# Cache PlatformIO packages using Travis CI container-based infrastructure
cache:
pip: true
directories:
- "~/.platformio"
env:
- >
PLATFORMIO_CI_SRC=$PWD/examples/Webserver
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/Webserver.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
- >
PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Simple
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Simple.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
- >
PLATFORMIO_CI_SRC=$PWD/examples/TypeC_Intertechno
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeC_Intertechno.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
- >
PLATFORMIO_CI_SRC=$PWD/examples/TypeD_REV
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeD_REV.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
- >
PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
- >
PLATFORMIO_CI_SRC=$PWD/examples/TypeA_WithDIPSwitches_Lightweight
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeA_WithDIPSwitches_Lightweight.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
- >
PLATFORMIO_CI_SRC=$PWD/examples/TypeB_WithRotaryOrSlidingSwitches
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/TypeB_WithRotaryOrSlidingSwitches.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01 --board=attiny25 --board=attiny24"
- >
PLATFORMIO_CI_SRC=$PWD/examples/SendDemo
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/SendDemo.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
- >
PLATFORMIO_CI_SRC=$PWD/examples/ReceiveDemo_Advanced
ARDUINOIDE_CI_SRC=$PLATFORMIO_CI_SRC/ReceiveDemo_Advanced.ino
BOARDS="--board=diecimilaatmega328 --board=uno --board=esp01"
before_install:
# Arduino IDE
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
- sleep 3
- export DISPLAY=:1.0
- wget http://downloads.arduino.cc/arduino-1.6.9-linux64.tar.xz
- tar xf arduino-1.6.9-linux64.tar.xz
- sudo mv arduino-1.6.9 /usr/local/share/arduino
- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino
install:
# Arduino IDE
- ln -s $PWD /usr/local/share/arduino/libraries/rc-switch
# PlatformIO
- sudo pip install -U platformio
script:
# Arduino IDE
- arduino --verify --board arduino:avr:uno ${ARDUINOIDE_CI_SRC}
# PlatformIO
- platformio ci --lib="." ${BOARDS}

View File

@ -1,15 +1,17 @@
**Fork of RC-SWITCH by @sui77**
# rc-switch # rc-switch
[![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch) [![Build Status](https://travis-ci.org/1technophile/rc-switch.svg?branch=master)](https://travis-ci.org/1technophile/rc-switch)
Use your Arduino or Raspberry Pi to operate remote radio controlled devices Use your Arduino or Raspberry Pi to operate remote radio controlled devices
## Download ## Download
https://github.com/sui77/rc-switch/releases/latest https://github.com/1technophile/rc-switch/releases/latest
rc-switch is also listed in the arduino library manager. rc-switch is also listed in the arduino library manager.
## Wiki ## Wiki
https://github.com/sui77/rc-switch/wiki https://github.com/1technophile/rc-switch/wiki
## Info ## Info
### Send RC codes ### Send RC codes

View File

@ -0,0 +1,103 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[platformio]
src_dir = examples/ReceiveDemo_Advanced
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ENVIRONMENT CHOICE ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Uncomment the env line corresponding to your board and modules required, ;
;you can also adapt the modules by removing the corresponding lines in the env detail ;
; if you go to the build flag section of your env you will see that some user_config.h ;
; parameters can be overwritten here, for example the gateway name. ;
; If you want to avoid the lost of your environments at each update you can put them ;
; into a separate file called prod_env.ini, it will be automatically read by pio ;
; an example (prod_env.ini.example) is available into the same folder as this file. ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;default_envs = sonoff-basic-rfr3
;default_envs = esp32dev-rf
;default_envs = nodemcuv2-rf
;default_envs = rf-wifi-gateway
;default_envs = uno-rf
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ENVIRONMENTS PARAMETERS ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Libraries and parameters shared accross environements ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[env]
lib_extra_dirs = .
framework = arduino
build_flags =
-w ; supress all warnings
monitor_speed = 115200
[com]
esp8266_platform = espressif8266@2.2.3
esp32_platform = espressif32@1.11.1
atmelavr_platform = atmelavr@1.13.0
[com-esp]
build_flags =
${env.build_flags}
[com-arduino]
build_flags =
${env.build_flags}
[com-arduino-low-memory]
build_flags =
${env.build_flags}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ENVIRONMENTS LIST ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;List of environments that can be build ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[env:esp32dev-rf]
platform = ${com.esp32_platform}
board = esp32dev
build_flags =
${com-esp.build_flags}
[env:nodemcuv2-rf]
platform = ${com.esp8266_platform}
board = nodemcuv2
build_flags =
${com-esp.build_flags}
board_build.flash_mode = dout
[env:rf-wifi-gateway]
platform = ${com.esp8266_platform}
board = nodemcuv2
build_flags =
${com-esp.build_flags}
board_build.flash_mode = dout
[env:sonoff-basic-rfr3]
platform = ${com.esp8266_platform}
board = esp8285
build_flags =
${com-esp.build_flags}
board_build.flash_mode = dout
[env:uno-rf]
platform = ${com.atmelavr_platform}
board = uno
build_flags =
${com-arduino-low-memory.build_flags}

View File

@ -13,20 +13,19 @@
- Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com - Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
- Johann Richard / <first name>.<last name>(at)gmail(dot)com - Johann Richard / <first name>.<last name>(at)gmail(dot)com
- Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo - Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo
- Matias Cuenca-Acuna
Project home: https://github.com/sui77/rc-switch/ Project home: https://github.com/sui77/rc-switch/
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
@ -55,42 +54,77 @@
#endif #endif
/* Format for protocol definitions: /* Protocol description format
* {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal} *
* {Pulse length, Preamble, Sync bit, "0" bit, "1" bit, Inverted Signal, Guard time}
* *
* pulselength: pulse length in microseconds, e.g. 350 * Pulse length: pulse duration Te in microseconds,
* Sync bit: {1, 31} means 1 high pulse and 31 low pulses * example 350
* (perceived as a 31*pulselength long pulse, total length of sync bit is * Preamble: Alternating high and low levels
* 32*pulselength microseconds), i.e: * {20, 1} means 20 alternations of 1 Te duration
* _ _ _ _ _ _ _ _ _ _
* | |_| |_| |_| |_| |_| |_| |_| |_| |_| |_
* Sync bit: Header and clock
* {1, 31} means 1 pulse long Te high and 31 low
* _ * _
* | |_______________________________ (don't count the vertical bars) * | |_______________________________ (don't count the vertical bars)
* "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse * "0" bit: pulse shape defining a data bit, which is a logical "0"
* and 3 low pulses, total length (1+3)*pulselength, i.e: * {1, 3} means 1 pulse duration Te high level and 3 low
* _ * _
* | |___ * | |___
* "1" bit: waveform for a data bit of value "1", e.g. {3,1}: * "1" bit: pulse shape that defines the data bit, which is a logical "1"
* {3, 1} means 3 pulses with a duration of Te high level and 1 low
* ___ * ___
* | |_ * | |_
* *
* These are combined to form Tri-State bits when sending or receiving codes. * (note: to form the state bit Z (Tri-State bit), these two codes are combined)
* Inverted Signal: Signal inversion - if true the signal is inverted
* replacing high to low in a transmitted / received packet
* Guard time: Safety time, followed by the next preamble of the next packet
* for example 39 pulses of low duration Te
*/ */
#if defined(ESP8266) || defined(ESP32) #if defined(ESP8266) || defined(ESP32)
static const VAR_ISR_ATTR RCSwitch::Protocol proto[] = { static const VAR_ISR_ATTR RCSwitch::Protocol proto[] = {
#else #else
static const RCSwitch::Protocol PROGMEM proto[] = { static const RCSwitch::Protocol PROGMEM proto[] = {
#endif #endif
{ 350, { 1, 31 }, { 1, 3 }, { 3, 1 }, false }, // protocol 1 { 350, 0, { 0, 0 }, 1, { 1, 31 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 01 (Princeton, PT-2240)
{ 650, { 1, 10 }, { 1, 2 }, { 2, 1 }, false }, // protocol 2 { 650, 0, { 0, 0 }, 1, { 1, 10 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 02
{ 100, { 30, 71 }, { 4, 11 }, { 9, 6 }, false }, // protocol 3 { 100, 0, { 0, 0 }, 1, { 30, 71 }, { 4, 11 }, { 9, 6 }, false, 0 }, // 03
{ 380, { 1, 6 }, { 1, 3 }, { 3, 1 }, false }, // protocol 4 { 380, 0, { 0, 0 }, 1, { 1, 6 }, { 1, 3 }, { 3, 1 }, false, 0 }, // 04
{ 500, { 6, 14 }, { 1, 2 }, { 2, 1 }, false }, // protocol 5 { 500, 0, { 0, 0 }, 1, { 6, 14 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 05
{ 450, { 23, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 6 (HT6P20B) { 450, 0, { 0, 0 }, 1, { 23, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 06 (HT6P20B)
{ 150, { 2, 62 }, { 1, 6 }, { 6, 1 }, false }, // protocol 7 (HS2303-PT, i. e. used in AUKEY Remote) { 150, 0, { 0, 0 }, 1, { 2, 62 }, { 1, 6 }, { 6, 1 }, false, 0 }, // 07 (HS2303-PT, i. e. used in AUKEY Remote)
{ 200, { 3, 130}, { 7, 16 }, { 3, 16}, false}, // protocol 8 Conrad RS-200 RX { 320, 0, { 0, 0 }, 1, { 36, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 08 (Came 12bit, HT12E)
{ 200, { 130, 7 }, { 16, 7 }, { 16, 3 }, true}, // protocol 9 Conrad RS-200 TX { 700, 0, { 0, 0 }, 1, { 32, 1 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 09 (Nice_Flo 12bit)
{ 365, { 18, 1 }, { 3, 1 }, { 1, 3 }, true }, // protocol 10 (1ByOne Doorbell) { 420, 0, { 0, 0 }, 1, { 60, 6 }, { 1, 2 }, { 2, 1 }, true, 0 }, // 10 (V2 phoenix)
{ 270, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 11 (HT12E) { 500, 2, { 3, 3 }, 0, { 0, 0 }, { 1, 2 }, { 2, 1 }, false, 37 }, // 11 (Nice_FloR-S 52bit)
{ 320, { 36, 1 }, { 1, 2 }, { 2, 1 }, true } // protocol 12 (SM5212) { 400, 23, { 1, 1 }, 1, { 0, 9 }, { 2, 1 }, { 1, 2 }, false, 39 }, // 12 Placeholder not working! (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) from @Tho85 https://github.com/sui77/rc-switch/pull/115
{ 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)
{ 400, 0, { 0, 0 }, 1, { 1, 1 }, { 1, 2 }, { 2, 1 }, false, 43 }, // 31 (Mertik Maxitrol G6R-H4T1)
{ 365, 0, { 0, 0 }, 1, { 18, 1 }, { 3, 1 }, { 1, 3 }, true, 0 }, // 32 (1ByOne Doorbell) from @Fatbeard https://github.com/sui77/rc-switch/pull/277
{ 340, 0, { 0, 0 }, 1, { 14, 4 }, { 1, 2 }, { 2, 1 }, false, 0 }, // 33 (Dooya Control DC2708L)
{ 120, 0, { 0, 0 }, 1, { 1, 28 }, { 1, 3 }, { 3, 1 }, false, 0 } // 34 DIGOO SD10
}; };
enum { enum {
@ -98,21 +132,23 @@ enum {
}; };
#if not defined( RCSwitchDisableReceiving ) #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::nReceivedBitlength = 0;
volatile unsigned int RCSwitch::nReceivedDelay = 0; volatile unsigned int RCSwitch::nReceivedDelay = 0;
volatile unsigned int RCSwitch::nReceivedProtocol = 0; volatile unsigned int RCSwitch::nReceivedProtocol = 0;
int RCSwitch::nReceiveTolerance = 60; int RCSwitch::nReceiveTolerance = 60;
const unsigned int RCSwitch::nSeparationLimit = 4300; const unsigned int RCSwitch::nSeparationLimit = 2600; // 4300 default
// separationLimit: minimum microseconds between received codes, closer codes are ignored. // 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 // 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. // limit to the same time as the 'low' part of the sync signal for the current protocol.
// should be set to the minimum value of pulselength * the sync signal
unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
unsigned int RCSwitch::buftimings[4];
#endif #endif
RCSwitch::RCSwitch() { RCSwitch::RCSwitch() {
this->nTransmitterPin = -1; this->nTransmitterPin = -1;
this->setRepeatTransmit(10); this->setRepeatTransmit(5);
this->setProtocol(1); this->setProtocol(1);
#if not defined( RCSwitchDisableReceiving ) #if not defined( RCSwitchDisableReceiving )
this->nReceiverInterrupt = -1; this->nReceiverInterrupt = -1;
@ -452,7 +488,7 @@ char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) {
*/ */
void RCSwitch::sendTriState(const char* sCodeWord) { void RCSwitch::sendTriState(const char* sCodeWord) {
// turn the tristate code word into the corresponding bit pattern, then send it // 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; unsigned int length = 0;
for (const char* p = sCodeWord; *p; p++) { for (const char* p = sCodeWord; *p; p++) {
code <<= 2L; code <<= 2L;
@ -462,11 +498,11 @@ void RCSwitch::sendTriState(const char* sCodeWord) {
break; break;
case 'F': case 'F':
// bit pattern 01 // bit pattern 01
code |= 1L; code |= 1ULL;
break; break;
case '1': case '1':
// bit pattern 11 // bit pattern 11
code |= 3L; code |= 3ULL;
break; break;
} }
length += 2; length += 2;
@ -474,17 +510,37 @@ void RCSwitch::sendTriState(const char* sCodeWord) {
this->send(code, length); this->send(code, length);
} }
/**
* @param duration no. of microseconds to delay
*/
static inline void safeDelayMicroseconds(unsigned long duration) {
#if defined(ESP8266) || defined(ESP32)
if (duration > 10000) {
// if delay > 10 milliseconds, use yield() to avoid wdt reset
unsigned long start = micros();
while ((micros() - start) < duration) {
yield();
}
}
else {
delayMicroseconds(duration);
}
#else
delayMicroseconds(duration);
#endif
}
/** /**
* @param sCodeWord a binary code word consisting of the letter 0, 1 * @param sCodeWord a binary code word consisting of the letter 0, 1
*/ */
void RCSwitch::send(const char* sCodeWord) { void RCSwitch::send(const char* sCodeWord) {
// turn the tristate code word into the corresponding bit pattern, then send it // 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; unsigned int length = 0;
for (const char* p = sCodeWord; *p; p++) { for (const char* p = sCodeWord; *p; p++) {
code <<= 1L; code <<= 1ULL;
if (*p != '0') if (*p != '0')
code |= 1L; code |= 1ULL;
length++; length++;
} }
this->send(code, length); this->send(code, length);
@ -495,7 +551,7 @@ void RCSwitch::send(const char* sCodeWord) {
* bits are sent from MSB to LSB, i.e., first the bit at position length-1, * 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. * 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) if (this->nTransmitterPin == -1)
return; return;
@ -507,14 +563,41 @@ void RCSwitch::send(unsigned long code, unsigned int length) {
} }
#endif #endif
// repeat sending the packet nRepeatTransmit times
for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
for (int i = length-1; i >= 0; i--) { // send the preamble
if (code & (1L << i)) for (int i = 0; i < ((protocol.PreambleFactor / 2) + (protocol.PreambleFactor %2 )); i++) {
this->transmit({protocol.Preamble.high, protocol.Preamble.low});
}
// send the header
if (protocol.HeaderFactor > 0) {
for (int i = 0; i < protocol.HeaderFactor; i++) {
this->transmit(protocol.Header);
}
}
// send the code
for (int i = length - 1; i >= 0; i--) {
if (code & (1ULL << i))
this->transmit(protocol.one); this->transmit(protocol.one);
else else
this->transmit(protocol.zero); this->transmit(protocol.zero);
} }
this->transmit(protocol.syncFactor); // for kilok, there should be a duration of 66, and 64 significant data codes are stored
// send two more bits for even count
if (length == 64) {
if (nRepeat == 0) {
this->transmit(protocol.zero);
this->transmit(protocol.zero);
} else {
this->transmit(protocol.one);
this->transmit(protocol.one);
}
}
// Set the guard Time
if (protocol.Guard > 0) {
digitalWrite(this->nTransmitterPin, LOW);
safeDelayMicroseconds(this->protocol.pulseLength * protocol.Guard);
}
} }
// Disable transmit after sending (i.e., for inverted protocols) // Disable transmit after sending (i.e., for inverted protocols)
@ -535,10 +618,14 @@ void RCSwitch::transmit(HighLow pulses) {
uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH; uint8_t firstLogicLevel = (this->protocol.invertedSignal) ? LOW : HIGH;
uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW; uint8_t secondLogicLevel = (this->protocol.invertedSignal) ? HIGH : LOW;
digitalWrite(this->nTransmitterPin, firstLogicLevel); if (pulses.high > 0) {
delayMicroseconds( this->protocol.pulseLength * pulses.high); digitalWrite(this->nTransmitterPin, firstLogicLevel);
digitalWrite(this->nTransmitterPin, secondLogicLevel); delayMicroseconds( this->protocol.pulseLength * pulses.high);
delayMicroseconds( this->protocol.pulseLength * pulses.low); }
if (pulses.low > 0) {
digitalWrite(this->nTransmitterPin, secondLogicLevel);
delayMicroseconds( this->protocol.pulseLength * pulses.low);
}
} }
@ -581,7 +668,7 @@ void RCSwitch::resetAvailable() {
RCSwitch::nReceivedValue = 0; RCSwitch::nReceivedValue = 0;
} }
unsigned long RCSwitch::getReceivedValue() { unsigned long long RCSwitch::getReceivedValue() {
return RCSwitch::nReceivedValue; return RCSwitch::nReceivedValue;
} }
@ -617,12 +704,41 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun
memcpy_P(&pro, &proto[p-1], sizeof(Protocol)); memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
#endif #endif
unsigned long code = 0; unsigned long long code = 0;
//Assuming the longer pulse length is the pulse captured in timings[0] unsigned int FirstTiming = 0;
const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high); if (pro.PreambleFactor > 0) {
const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses; FirstTiming = pro.PreambleFactor + 1;
}
unsigned int BeginData = 0;
if (pro.HeaderFactor > 0) {
BeginData = (pro.invertedSignal) ? (2) : (1);
// Header pulse count correction for more than one
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; 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 /* For protocols that start low, the sync period looks like
* _________ * _________
* _____________| |XXXXXXXXXXXX| * _____________| |XXXXXXXXXXXX|
@ -640,9 +756,16 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun
* *
* The 2nd saved duration starts the data * 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; code <<= 1;
if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance &&
diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
@ -657,9 +780,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::nReceivedValue = code;
RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; RCSwitch::nReceivedBitlength = bitChangeCount / 2;
RCSwitch::nReceivedDelay = delay; RCSwitch::nReceivedDelay = delay;
RCSwitch::nReceivedProtocol = p; RCSwitch::nReceivedProtocol = p;
return true; return true;
@ -672,32 +795,63 @@ void RECEIVE_ATTR RCSwitch::handleInterrupt() {
static unsigned int changeCount = 0; static unsigned int changeCount = 0;
static unsigned long lastTime = 0; static unsigned long lastTime = 0;
static unsigned int repeatCount = 0; static byte repeatCount = 0;
const long time = micros(); const long time = micros();
const unsigned int duration = time - lastTime; 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 // A long stretch without signal level change occurred. This could
// be the gap between two transmission. // be the gap between two transmission.
if ((repeatCount==0) || (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 // This long signal is close in length to the long signal which
// started the previously recorded timings; this suggests that // started the previously recorded timings; this suggests that
// it may indeed by a a gap between two transmissions (we assume // it may indeed by a a gap between two transmissions (we assume
// here that a sender will send the signal multiple times, // here that a sender will send the signal multiple times,
// with roughly the same gap between them). // with roughly the same gap between them).
// количество повторных пакетов
repeatCount++; repeatCount++;
if (repeatCount == 2) { // при приеме второго повторного начинаем анализ принятого первым
if (repeatCount == 1) {
for(unsigned int i = 1; i <= numProto; i++) { for(unsigned int i = 1; i <= numProto; i++) {
if (receiveProtocol(i, changeCount)) { if (receiveProtocol(i, changeCount)) {
// receive succeeded for protocol i // receive succeeded for protocol i
break; break;
} }
} }
// очищаем количество повторных пакетов
repeatCount = 0; repeatCount = 0;
} }
} }
// дительность отличается более чем на +-200 от первого
// принятого ранее, очищаем счетчик для приема нового пакета
changeCount = 0; 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 // detect overflow
@ -706,7 +860,12 @@ void RECEIVE_ATTR RCSwitch::handleInterrupt() {
repeatCount = 0; repeatCount = 0;
} }
RCSwitch::timings[changeCount++] = duration; // заносим в массив длительность очередного принятого импульса
if (changeCount > 0 && duration < 100) { // игнорируем шумовые всплески менее 100 мкс
RCSwitch::timings[changeCount-1] += duration;
} else {
RCSwitch::timings[changeCount++] = duration;
}
lastTime = time; lastTime = time;
} }
#endif #endif

View File

@ -58,7 +58,8 @@
// Number of maximum high/Low changes per packet. // 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 // 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 67 // default 67
class RCSwitch { class RCSwitch {
@ -77,7 +78,7 @@ class RCSwitch {
void switchOff(char sGroup, int nDevice); void switchOff(char sGroup, int nDevice);
void sendTriState(const char* sCodeWord); 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); void send(const char* sCodeWord);
#if not defined( RCSwitchDisableReceiving ) #if not defined( RCSwitchDisableReceiving )
@ -87,7 +88,7 @@ class RCSwitch {
bool available(); bool available();
void resetAvailable(); void resetAvailable();
unsigned long getReceivedValue(); unsigned long long getReceivedValue();
unsigned int getReceivedBitlength(); unsigned int getReceivedBitlength();
unsigned int getReceivedDelay(); unsigned int getReceivedDelay();
unsigned int getReceivedProtocol(); unsigned int getReceivedProtocol();
@ -120,8 +121,11 @@ class RCSwitch {
struct Protocol { struct Protocol {
/** base pulse length in microseconds, e.g. 350 */ /** base pulse length in microseconds, e.g. 350 */
uint16_t pulseLength; uint16_t pulseLength;
uint8_t PreambleFactor;
HighLow Preamble;
uint8_t HeaderFactor;
HighLow Header;
HighLow syncFactor;
HighLow zero; HighLow zero;
HighLow one; HighLow one;
@ -142,6 +146,7 @@ class RCSwitch {
* FOO.low*pulseLength microseconds. * FOO.low*pulseLength microseconds.
*/ */
bool invertedSignal; bool invertedSignal;
uint16_t Guard;
}; };
void setProtocol(Protocol protocol); void setProtocol(Protocol protocol);
@ -167,7 +172,7 @@ class RCSwitch {
#if not defined( RCSwitchDisableReceiving ) #if not defined( RCSwitchDisableReceiving )
static int nReceiveTolerance; static int nReceiveTolerance;
volatile static unsigned long nReceivedValue; volatile static unsigned long long nReceivedValue;
volatile static unsigned int nReceivedBitlength; volatile static unsigned int nReceivedBitlength;
volatile static unsigned int nReceivedDelay; volatile static unsigned int nReceivedDelay;
volatile static unsigned int nReceivedProtocol; volatile static unsigned int nReceivedProtocol;
@ -176,6 +181,8 @@ class RCSwitch {
* timings[0] contains sync timing, followed by a number of bits * timings[0] contains sync timing, followed by a number of bits
*/ */
static unsigned int timings[RCSWITCH_MAX_CHANGES]; static unsigned int timings[RCSWITCH_MAX_CHANGES];
// буфер длительностей последних четырех пакетов, [0] - последний
static unsigned int buftimings[4];
#endif #endif