diff --git a/433/433Utils/.gitignore b/433/433Utils/.gitignore new file mode 100644 index 0000000..7a9421a --- /dev/null +++ b/433/433Utils/.gitignore @@ -0,0 +1,22 @@ +# Mac stuff +.DS_Store + +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# Compiled executables +RPi_utils/RFSniffer +RPi_utils/codesend +RPi_utils/send + diff --git a/433/433Utils/.gitmodules b/433/433Utils/.gitmodules new file mode 100644 index 0000000..2ddc352 --- /dev/null +++ b/433/433Utils/.gitmodules @@ -0,0 +1,3 @@ +[submodule "rc-switch"] + path = rc-switch + url = https://github.com/sui77/rc-switch.git diff --git a/433/433Utils/LICENSE b/433/433Utils/LICENSE new file mode 100644 index 0000000..d48be88 --- /dev/null +++ b/433/433Utils/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014-2016 Ninja Blocks Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/433/433Utils/README.md b/433/433Utils/README.md new file mode 100644 index 0000000..2ab7379 --- /dev/null +++ b/433/433Utils/README.md @@ -0,0 +1,67 @@ +# About 433Utils + +433Utils is a collection of code and documentation designed to assist you in the connection and usage of RF 433MHz transmit and receive modules to/with your Arduino and Rapberry Pi. + +It consists of two main sections- Arduino sketches and Raspberry Pi command line utilities. You'll find those in appropriately named folders. + +Despite the name, 433Utils also works with 315MHz transmit and receive modules (tested). + +## Requirements + +1. An Arduino (two is ideal) +2. A Raspberry Pi +3. The git commandline tool, on both your Arduino IDE machine and your RPi +4. RF 433MHz modules; a transmitter and receiver +5. A Ninja Block and account + +## Installation + +### Arduino\_Sketches + +Place the Sketches in your normal Arduino Sketches location. Install any required libraries: + +1. Servo motor library (Should be included in the Arduino IDE) +2. _Arduino_ [rc_switch](http://code.google.com/p/rc-switch/) library + +### RPi\_utils + +From your RPi, clone this archive: + +1. ```git clone --recursive git://github.com/ninjablocks/433Utils.git``` (recursive ensure that the rc-switch submodule gets populated which is needed by RPi\_utils) + +2. ```cd 433Utils/RPi_utils``` + +3. (As per the original rc_switch distribution) Follow the instructions to install the [wiringpi](https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/) library. +After that you can compile the example programs by executing *make*. + +## Usage + +### send +```sudo ./send systemCode unitCode command``` + +This command is unaltered from the original rc\_switch distribution. + + +### codesend +```sudo ./codesend decimalcode``` + +This command uses a single Ninja Blocks compatible decimal code. Sniff out codes using the RF\_Sniffer.ino Arduino sketch, included in this distribution. + +You can use codesend to control the wireless servo on your Arduino. +(The sketch is Servo\_Receive\_Demo.ino) + +I've implemented the most bare-bones of controls here. Try: + +```sudo ./codesend 500000 # to move the servo up``` + +```sudo ./codesend 500001 # to move the servo down``` + +```sudo ./codesend 500002 # to move the servo left``` + +```sudo ./codesend 500003 # to move the servo right``` + +```sudo ./codesend 500004 # to move the servo home``` + +## Issues + +Due to limitiations in the implementation of interrupt-driven routines in the underlying RCSwitch library, it is currently not possible to use both the send and receive functionality within the one program. diff --git a/433/433Utils/RPi_utils/Makefile b/433/433Utils/RPi_utils/Makefile new file mode 100644 index 0000000..b30f34a --- /dev/null +++ b/433/433Utils/RPi_utils/Makefile @@ -0,0 +1,20 @@ + +# Defines the RPI variable which is needed by rc-switch/RCSwitch.h +CXXFLAGS=-DRPI +CFLAGS += -Wall -Os -g + +all: send codesend RFSniffer + +send: ../rc-switch/RCSwitch.o send.o + $(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + +codesend: ../rc-switch/RCSwitch.o codesend.o + $(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + +RFSniffer: ../rc-switch/RCSwitch.o RFSniffer.o + $(CXX) $(CFLAGS) $(CXXFLAGS) $(LDFLAGS) $+ -o $@ -lwiringPi -lwiringPiDev -lcrypt + + +clean: + $(RM) ../rc-switch/*.o *.o send codesend servo RFSniffer + diff --git a/433/433Utils/RPi_utils/README.md b/433/433Utils/RPi_utils/README.md new file mode 100644 index 0000000..7a0fedf --- /dev/null +++ b/433/433Utils/RPi_utils/README.md @@ -0,0 +1,17 @@ +# About + +rcswitch-pi is for controlling rc remote controlled power sockets +with the raspberry pi. Kudos to the projects [rc-switch](http://code.google.com/p/rc-switch) +and [wiringpi](https://projects.drogon.net/raspberry-pi/wiringpi). +I just adapted the rc-switch code to use the wiringpi library instead of +the library provided by the arduino. + + +## Usage + +First you have to install the [wiringpi](https://projects.drogon.net/raspberry-pi/wiringpi/download-and-install/) library. +After that you can compile the example program *send* by executing *make*. +It uses wiringPi pin no 2 by default. You may want to change the used GPIO pin before compilation of the codesend.cpp source file. (Good Resource for Pin Details https://pinout.xyz/pinout/wiringpi) + +## Note +The 'RF\_Sniffer' code is as yet untested. It _should_ work, but it is still being tested thoroughly. It's provided to allow you to start playing with it now. diff --git a/433/433Utils/RPi_utils/RFSniffer.cpp b/433/433Utils/RPi_utils/RFSniffer.cpp new file mode 100644 index 0000000..da07200 --- /dev/null +++ b/433/433Utils/RPi_utils/RFSniffer.cpp @@ -0,0 +1,102 @@ +/* + RFSniffer + + Usage: ./RFSniffer [] + [] = optional + + Hacked from http://code.google.com/p/rc-switch/ + by @justy to provide a handy RF code sniffer +*/ + +#include "../rc-switch/RCSwitch.h" +#include +#include +#include + + +RCSwitch mySwitch; + + + +void light() +{ + digitalWrite(25, LOW); + usleep(200000); + digitalWrite(25, HIGH); + + //printf("%d\n", digitalRead(25)); +} + +int main(int argc, char *argv[]) { + + // This pin is not the first pin on the RPi GPIO header! + // Consult https://projects.drogon.net/raspberry-pi/wiringpi/pins/ + // for more information. + int PIN = 7; + + if(wiringPiSetup() == -1) { + printf("wiringPiSetup failed, exiting..."); + return 0; + } + + int pulseLength = 0; + if (argv[1] != NULL) pulseLength = atoi(argv[1]); + + mySwitch = RCSwitch(); + if (pulseLength != 0) mySwitch.setPulseLength(pulseLength); + mySwitch.enableReceive(PIN); // Receiver on interrupt 0 => that is pin #2 + + pinMode(25, OUTPUT); + + + #define LIVE 1 + + static int i=0; + unsigned long value = 0; + static int values[LIVE] = {0}; + + while(1) { + while(1) { + if (mySwitch.available()) { + value = mySwitch.getReceivedValue(); + values[i] = value; + + if (value == 0) + { + printf("Unknown encoding\n"); + } + else + { + light(); + printf("i=%d, Received %lu\n", i, values[i] ); + } + + fflush(stdout); + mySwitch.resetAvailable(); + + if (i != 0) { + if (values[1] == values[0]+1) + printf("有我的按钮发来数据\n"); + } + if (i != 1) { + if (values[0] == values[1]+1) + printf("有我的按钮发来数据\n"); + } + + + if (i==LIVE) { + i=0; + break; + } + i=i+1; + } + + } + + usleep(100); + } + + + return 0; +} + diff --git a/433/433Utils/RPi_utils/codesend.cpp b/433/433Utils/RPi_utils/codesend.cpp new file mode 100644 index 0000000..b10105f --- /dev/null +++ b/433/433Utils/RPi_utils/codesend.cpp @@ -0,0 +1,67 @@ +/* +Usage: ./codesend decimalcode [protocol] [pulselength] +decimalcode - As decoded by RFSniffer +protocol - According to rc-switch definitions +pulselength - pulselength in microseconds + + 'codesend' hacked from 'send' by @justy + + - The provided rc_switch 'send' command uses the form systemCode, unitCode, command + which is not suitable for our purposes. Instead, we call + send(code, length); // where length is always 24 and code is simply the code + we find using the RF_sniffer.ino Arduino sketch. + +(Use RF_Sniffer.ino to check that RF signals are being produced by the RPi's transmitter +or your remote control) +*/ +#include "../rc-switch/RCSwitch.h" +#include +#include + +int main(int argc, char *argv[]) +{ + + // This pin is not the first pin on the RPi GPIO header! + // Consult https://projects.drogon.net/raspberry-pi/wiringpi/pins/ + // for more information. + int PIN = 7; + + // Parse the first parameter to this command as an integer + int protocol = 0; // A value of 0 will use rc-switch's default value + int pulseLength = 0; + int bitLength = 24; + + // If no command line argument is given, print the help text + if (argc == 1) { + printf("Usage: %s decimalcode [protocol] [pulselength] [bitlength]\n", argv[0]); + printf("decimalcode\t- As decoded by RFSniffer\n"); + printf("protocol\t- According to rc-switch definitions\n"); + printf("pulselength\t- pulselength in microseconds\n"); + printf("bitlength\t- bit length\n"); + return -1; + } + // Change protocol and pulse length accroding to parameters + char *eptr; + unsigned long code = strtoul(argv[1], &eptr, 10); + if (argc >= 3) + protocol = atoi(argv[2]); + if (argc >= 4) + pulseLength = atoi(argv[3]); + if (argc >= 5) + bitLength = atoi(argv[4]); + + if (wiringPiSetup() == -1) + return 1; + printf("sending code[%lu]\n", code); + RCSwitch mySwitch = RCSwitch(); + if (protocol != 0) + mySwitch.setProtocol(protocol); + if (pulseLength != 0) + mySwitch.setPulseLength(pulseLength); + mySwitch.enableTransmit(PIN); + + mySwitch.send(code, bitLength); + + return 0; + +} diff --git a/433/433Utils/RPi_utils/send.cpp b/433/433Utils/RPi_utils/send.cpp new file mode 100644 index 0000000..f004120 --- /dev/null +++ b/433/433Utils/RPi_utils/send.cpp @@ -0,0 +1,62 @@ +/* + Usage: ./send + Command is 0 for OFF and 1 for ON + */ + +#include "../rc-switch/RCSwitch.h" +#include +#include + +int main(int argc, char *argv[]) +{ + + /* + output PIN is hardcoded for testing purposes + see https://projects.drogon.net/raspberry-pi/wiringpi/pins/ + for pin mapping of the raspberry pi GPIO connector + */ + int PIN = 7; + const char *code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + + if (argc < 4) { + printf("Sending 433 MHz remote plug control codes, hardcoded on wiringpi pin %d.\n", PIN); + printf("Usage: %s [pulseLength]\n", argv[0]); + printf("systemCode - First five settings of Type A 10 pole DIP switch, e.g. 11111\n"); + printf("unitCode - Switch number [1 .. 5] or [10000 .. 00001]\n"); + printf("command - 0 for OFF and 1 for ON\n"); + printf("pulseLength - optional pulse length\n"); + return -1; + } + + char *systemCode = argv[1]; + const char *unitCode; + if (strlen(argv[2]) == 5) { + unitCode = argv[2]; + } else if (atoi(argv[2]) > 0 and atoi(argv[2]) < 6) { + unitCode = code[atoi(argv[2])]; + } else { + return -1; + } + int command = atoi(argv[3]); + + if (wiringPiSetup() == -1) + return 1; + printf("sending systemCode[%s] unitCode[%s] command[%i]\n", systemCode, unitCode, command); + RCSwitch mySwitch = RCSwitch(); + if (argv[4] != NULL) + mySwitch.setPulseLength(atoi(argv[4])); + mySwitch.enableTransmit(PIN); + + switch (command) { + case 1: + mySwitch.switchOn(systemCode, unitCode); + break; + case 0: + mySwitch.switchOff(systemCode, unitCode); + break; + default: + printf("command[%i] is unsupported\n", command); + return -1; + } + return 0; +} diff --git a/433/433Utils/rc-switch/.gitignore b/433/433Utils/rc-switch/.gitignore new file mode 100644 index 0000000..d0972bb --- /dev/null +++ b/433/433Utils/rc-switch/.gitignore @@ -0,0 +1,17 @@ +# Mac stuff +.DS_Store + +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + diff --git a/433/433Utils/rc-switch/.travis.yml b/433/433Utils/rc-switch/.travis.yml new file mode 100644 index 0000000..d8de894 --- /dev/null +++ b/433/433Utils/rc-switch/.travis.yml @@ -0,0 +1,70 @@ +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.8.10-linux64.tar.xz + - tar xf arduino-1.8.10-linux64.tar.xz + - sudo mv arduino-1.8.10 /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 + # - pip install -U platformio + # - platformio update + +script: + # Arduino IDE + - arduino --verify --board arduino:avr:uno ${ARDUINOIDE_CI_SRC} + # PlatformIO + # - platformio run --lib="." ${BOARDS} diff --git a/433/433Utils/rc-switch/RCSwitch.cpp b/433/433Utils/rc-switch/RCSwitch.cpp new file mode 100644 index 0000000..e1e9279 --- /dev/null +++ b/433/433Utils/rc-switch/RCSwitch.cpp @@ -0,0 +1,744 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Johann Richard / .(at)gmail(dot)com + - Vlad Gheorghe / .(at)gmail(dot)com https://github.com/vgheo + - Matias Cuenca-Acuna + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + 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, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "RCSwitch.h" + +#ifdef RaspberryPi + // PROGMEM and _P functions are for AVR based microprocessors, + // so we must normalize these for the ARM processor: +#define PROGMEM +#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) +#endif + +#if defined(ESP8266) + // interrupt handler and related code must be in RAM on ESP8266, + // according to issue #46. +#define RECEIVE_ATTR ICACHE_RAM_ATTR +#define VAR_ISR_ATTR +#elif defined(ESP32) +#define RECEIVE_ATTR IRAM_ATTR +#define VAR_ISR_ATTR DRAM_ATTR +#else +#define RECEIVE_ATTR +#define VAR_ISR_ATTR +#endif + +/* Format for protocol definitions: + * {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal} + * + * 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: + * _ + * | |_______________________________ (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: + * _ + * | |___ + * "1" bit: waveform for a data bit of value "1", e.g. {3,1}: + * ___ + * | |_ + * + * These are combined to form Tri-State bits when sending or receiving codes. + */ +#if defined(ESP8266) || defined(ESP32) +static const VAR_ISR_ATTR 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) + { 200, { 3, 130}, { 7, 16}, { 3, 16}, false }, // protocol 8 Conrad RS-200 RX + { 200, { 130, 7}, { 16, 7}, { 16, 3}, true }, // protocol 9 Conrad RS-200 TX + { 365, { 18, 1}, { 3, 1}, { 1, 3}, true }, // protocol 10 (1ByOne Doorbell) + { 270, { 36, 1}, { 1, 2}, { 2, 1}, true }, // protocol 11 (HT12E) + { 320, { 36, 1}, { 1, 2}, { 2, 1}, true } // protocol 12 (SM5212) +}; + +enum { + numProto = sizeof(proto) / sizeof(proto[0]) +}; + +#if not defined( RCSwitchDisableReceiving ) +volatile unsigned 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 VAR_ISR_ATTR RCSwitch::nSeparationLimit = 4300; +// 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]; +#endif + +RCSwitch::RCSwitch() +{ + this->nTransmitterPin = -1; + this->setRepeatTransmit(10); + this->setProtocol(1); +#if not defined( RCSwitchDisableReceiving ) + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + RCSwitch::nReceivedValue = 0; +#endif +} + +/** + * Sets the protocol to send. + */ +void RCSwitch::setProtocol(Protocol protocol) +{ + this->protocol = protocol; +} + +/** + * Sets the protocol to send, from a list of predefined protocols + */ +void RCSwitch::setProtocol(int nProtocol) +{ + if (nProtocol < 1 || nProtocol > numProto) { + nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ??? + } +#if defined(ESP8266) || defined(ESP32) + this->protocol = proto[nProtocol - 1]; +#else + memcpy_P(&this->protocol, &proto[nProtocol - 1], sizeof(Protocol)); +#endif +} + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +void RCSwitch::setProtocol(int nProtocol, int nPulseLength) +{ + setProtocol(nProtocol); + this->setPulseLength(nPulseLength); +} + +/** + * Sets pulse length in microseconds + */ +void RCSwitch::setPulseLength(int nPulseLength) +{ + this->protocol.pulseLength = nPulseLength; +} + +/** + * Sets Repeat Transmits + */ +void RCSwitch::setRepeatTransmit(int nRepeatTransmit) +{ + this->nRepeatTransmit = nRepeatTransmit; +} + +/** + * Set Receiving Tolerance + */ +#if not defined( RCSwitchDisableReceiving ) +void RCSwitch::setReceiveTolerance(int nPercent) +{ + RCSwitch::nReceiveTolerance = nPercent; +} +#endif + +/** + * Enable transmissions + * + * @param nTransmitterPin Arduino Pin to which the sender is connected to + */ +void RCSwitch::enableTransmit(int nTransmitterPin) +{ + this->nTransmitterPin = nTransmitterPin; + pinMode(this->nTransmitterPin, OUTPUT); +} + +/** + * Disable transmissions + */ +void RCSwitch::disableTransmit() +{ + this->nTransmitterPin = -1; +} + +/** + * Switch a remote switch on (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOn(char sGroup, int nDevice) +{ + this->sendTriState(this->getCodeWordD(sGroup, nDevice, true)); +} + +/** + * Switch a remote switch off (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOff(char sGroup, int nDevice) +{ + this->sendTriState(this->getCodeWordD(sGroup, nDevice, false)); +} + +/** + * Switch a remote switch on (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) +{ + this->sendTriState(this->getCodeWordC(sFamily, nGroup, nDevice, true)); +} + +/** + * Switch a remote switch off (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) +{ + this->sendTriState(this->getCodeWordC(sFamily, nGroup, nDevice, false)); +} + +/** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOn(int nAddressCode, int nChannelCode) +{ + this->sendTriState(this->getCodeWordB(nAddressCode, nChannelCode, true)); +} + +/** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOff(int nAddressCode, int nChannelCode) +{ + this->sendTriState(this->getCodeWordB(nAddressCode, nChannelCode, false)); +} + +/** + * Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOn(const char *sGroup, int nChannel) +{ + const char *code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOn(sGroup, code[nChannel]); +} + +/** + * Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOff(const char *sGroup, int nChannel) +{ + const char *code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOff(sGroup, code[nChannel]); +} + +/** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOn(const char *sGroup, const char *sDevice) +{ + this->sendTriState(this->getCodeWordA(sGroup, sDevice, true)); +} + +/** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOff(const char *sGroup, const char *sDevice) +{ + this->sendTriState(this->getCodeWordA(sGroup, sDevice, false)); +} + +/** + * Returns a char[13], representing the code word to be send. + * + */ +char *RCSwitch::getCodeWordA(const char *sGroup, const char *sDevice, bool bStatus) +{ + static char sReturn[13]; + int nReturnPos = 0; + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0'; + } + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0'; + } + + sReturn[nReturnPos++] = bStatus ? '0' : 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for type B switches with two rotary/sliding switches. + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-----------------------------+----------+------------+ + * | 4 bits address | 4 bits address | 3 bits | 1 bit | + * | switch group | switch number | not used | on / off | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 | + * +-----------------------------+-----------------------------+----------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char *RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) +{ + static char sReturn[13]; + int nReturnPos = 0; + + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return 0; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F'; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F'; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Like getCodeWord (Type C = Intertechno) + */ +char *RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) +{ + static char sReturn[13]; + int nReturnPos = 0; + + int nFamily = (int)sFamily - 'a'; + if (nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return 0; + } + // encode the family into four bits + sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0'; + + // encode the device and group + sReturn[nReturnPos++] = ((nDevice - 1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nDevice - 1) & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup - 1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup - 1) & 2) ? 'F' : '0'; + + // encode the status code + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for the REV Switch Type + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-------------------+----------+--------------+ + * | 4 bits address | 3 bits address | 3 bits | 2 bits | + * | switch group | device number | not used | on / off | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 | + * +-----------------------------+-------------------+----------+--------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * @param sGroup Name of the switch group (A..D, resp. a..d) + * @param nDevice Number of the switch itself (1..3) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char *RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) +{ + static char sReturn[13]; + int nReturnPos = 0; + + // sGroup must be one of the letters in "abcdABCD" + int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A'; + if (nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) { + return 0; + } + + for (int i = 0; i < 4; i++) { + sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F'; + } + + for (int i = 1; i <= 3; i++) { + sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F'; + } + + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + + sReturn[nReturnPos++] = bStatus ? '1' : '0'; + sReturn[nReturnPos++] = bStatus ? '0' : '1'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * @param sCodeWord a tristate code word consisting of the letter 0, 1, F + */ +void RCSwitch::sendTriState(const char *sCodeWord) +{ + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char *p = sCodeWord; *p; p++) { + code <<= 2L; + switch (*p) { + case '0': + // bit pattern 00 + break; + case 'F': + // bit pattern 01 + code |= 1L; + break; + case '1': + // bit pattern 11 + code |= 3L; + break; + } + length += 2; + } + this->send(code, length); +} + +/** + * @param sCodeWord a binary code word consisting of the letter 0, 1 + */ +void RCSwitch::send(const char *sCodeWord) +{ + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char *p = sCodeWord; *p; p++) { + code <<= 1L; + if (*p != '0') + code |= 1L; + length++; + } + this->send(code, length); +} + +/** + * Transmit the first 'length' bits of the integer 'code'. The + * 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) +{ + if (this->nTransmitterPin == -1) + return; + +#if not defined( RCSwitchDisableReceiving ) + // make sure the receiver is disabled while we transmit + int nReceiverInterrupt_backup = nReceiverInterrupt; + if (nReceiverInterrupt_backup != -1) { + this->disableReceive(); + } +#endif + + for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { + for (int i = length - 1; i >= 0; i--) { + if (code & (1L << i)) + this->transmit(protocol.one); + else + this->transmit(protocol.zero); + } + this->transmit(protocol.syncFactor); + } + + // Disable transmit after sending (i.e., for inverted protocols) + digitalWrite(this->nTransmitterPin, LOW); + +#if not defined( RCSwitchDisableReceiving ) + // enable receiver again if we just disabled it + if (nReceiverInterrupt_backup != -1) { + this->enableReceive(nReceiverInterrupt_backup); + } +#endif +} + +/** + * Transmit a single high-low pulse. + */ +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 not defined( RCSwitchDisableReceiving ) +/** + * Enable receiving data + */ +void RCSwitch::enableReceive(int interrupt) +{ + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + +void RCSwitch::enableReceive() +{ + if (this->nReceiverInterrupt != -1) { + RCSwitch::nReceivedValue = 0; + RCSwitch::nReceivedBitlength = 0; +#if defined(RaspberryPi) // Raspberry Pi + wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); +#else // Arduino + attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); +#endif + } +} + +/** + * Disable receiving data + */ +void RCSwitch::disableReceive() +{ +#if not defined(RaspberryPi) // Arduino + detachInterrupt(this->nReceiverInterrupt); +#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR + this->nReceiverInterrupt = -1; +} + +bool RCSwitch::available() +{ + return RCSwitch::nReceivedValue != 0; +} + +void RCSwitch::resetAvailable() +{ + RCSwitch::nReceivedValue = 0; +} + +unsigned long RCSwitch::getReceivedValue() +{ + return RCSwitch::nReceivedValue; +} + +unsigned int RCSwitch::getReceivedBitlength() +{ + return RCSwitch::nReceivedBitlength; +} + +unsigned int RCSwitch::getReceivedDelay() +{ + return RCSwitch::nReceivedDelay; +} + +unsigned int RCSwitch::getReceivedProtocol() +{ + return RCSwitch::nReceivedProtocol; +} + +unsigned int *RCSwitch::getReceivedRawdata() +{ + return RCSwitch::timings; +} + +/* helper function for the receiveProtocol method */ +static inline unsigned int diff(int A, int B) +{ + return abs(A - B); +} + +/** + * + */ +bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) +{ +#if defined(ESP8266) || defined(ESP32) + const Protocol & pro = proto[p - 1]; +#else + Protocol pro; + 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; + const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + + /* For protocols that start low, the sync period looks like + * _________ + * _____________| |XXXXXXXXXXXX| + * + * |--1st dur--|-2nd dur-|-Start data-| + * + * The 3rd saved duration starts the data. + * + * For protocols that start high, the sync period looks like + * + * ______________ + * | |____________|XXXXXXXXXXXXX| + * + * |-filtered out-|--1st dur--|--Start data--| + * + * The 2nd saved duration starts the data + */ + const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1); + + for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { + code <<= 1; + if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { + // zero + } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) { + // one + code |= 1; + } else { + // Failed + return false; + } + } + + if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = p; + return true; + } + + return false; +} + +void RECEIVE_ATTR RCSwitch::handleInterrupt() +{ + + static unsigned int changeCount = 0; + static unsigned long lastTime = 0; + static unsigned int repeatCount = 0; + + const long time = micros(); + const unsigned int duration = time - lastTime; + + if (duration > RCSwitch::nSeparationLimit) { + // A long stretch without signal level change occurred. This could + // be the gap between two transmission. + if ((repeatCount == 0) || (diff(duration, RCSwitch::timings[0]) < 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) { + for (unsigned int i = 1; i <= numProto; i++) { + if (receiveProtocol(i, changeCount)) { + // receive succeeded for protocol i + break; + } + } + repeatCount = 0; + } + } + changeCount = 0; + } + + // detect overflow + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + + RCSwitch::timings[changeCount++] = duration; + lastTime = time; +} +#endif diff --git a/433/433Utils/rc-switch/RCSwitch.h b/433/433Utils/rc-switch/RCSwitch.h new file mode 100644 index 0000000..4a69b1a --- /dev/null +++ b/433/433Utils/rc-switch/RCSwitch.h @@ -0,0 +1,182 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + 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, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _RCSwitch_h +#define _RCSwitch_h + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific +#include "Energia.h" +#elif defined(RPI) // Raspberry Pi +#define RaspberryPi + + // Include libraries for RPi: +#include /* memcpy */ +#include /* abs */ +#include +#elif defined(SPARK) +#include "application.h" +#else +#include "WProgram.h" +#endif + +#include + +// At least for the ATTiny X4/X5, receiving has to be disabled due to +// missing libm depencies (udivmodhi4) +#if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ ) +#define RCSwitchDisableReceiving +#endif + +// 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 + +class RCSwitch { + +public: + RCSwitch(); + + void switchOn(int nGroupNumber, int nSwitchNumber); + void switchOff(int nGroupNumber, int nSwitchNumber); + void switchOn(const char *sGroup, int nSwitchNumber); + void switchOff(const char *sGroup, int nSwitchNumber); + void switchOn(char sFamily, int nGroup, int nDevice); + void switchOff(char sFamily, int nGroup, int nDevice); + void switchOn(const char *sGroup, const char *sDevice); + void switchOff(const char *sGroup, const char *sDevice); + void switchOn(char sGroup, int nDevice); + void switchOff(char sGroup, int nDevice); + + void sendTriState(const char *sCodeWord); + void send(unsigned long code, unsigned int length); + void send(const char *sCodeWord); + +#if not defined( RCSwitchDisableReceiving ) + void enableReceive(int interrupt); + void enableReceive(); + void disableReceive(); + bool available(); + void resetAvailable(); + + unsigned long getReceivedValue(); + unsigned int getReceivedBitlength(); + unsigned int getReceivedDelay(); + unsigned int getReceivedProtocol(); + unsigned int *getReceivedRawdata(); +#endif + + void enableTransmit(int nTransmitterPin); + void disableTransmit(); + void setPulseLength(int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); +#if not defined( RCSwitchDisableReceiving ) + void setReceiveTolerance(int nPercent); +#endif + + /** + * Description of a single pule, which consists of a high signal + * whose duration is "high" times the base pulse length, followed + * by a low signal lasting "low" times the base pulse length. + * Thus, the pulse overall lasts (high+low)*pulseLength + */ + struct HighLow { + uint8_t high; + uint8_t low; + }; + + /** + * A "protocol" describes how zero and one bits are encoded into high/low + * pulses. + */ + struct Protocol { + /** base pulse length in microseconds, e.g. 350 */ + uint16_t pulseLength; + + HighLow syncFactor; + HighLow zero; + HighLow one; + + /** + * If true, interchange high and low logic levels in all transmissions. + * + * By default, RCSwitch assumes that any signals it sends or receives + * can be broken down into pulses which start with a high signal level, + * followed by a a low signal level. This is e.g. the case for the + * popular PT 2260 encoder chip, and thus many switches out there. + * + * But some devices do it the other way around, and start with a low + * signal level, followed by a high signal level, e.g. the HT6P20B. To + * accommodate this, one can set invertedSignal to true, which causes + * RCSwitch to change how it interprets any HighLow struct FOO: It will + * then assume transmissions start with a low signal lasting + * FOO.high*pulseLength microseconds, followed by a high signal lasting + * FOO.low*pulseLength microseconds. + */ + bool invertedSignal; + }; + + void setProtocol(Protocol protocol); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + +private: + char *getCodeWordA(const char *sGroup, const char *sDevice, bool bStatus); + char *getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus); + char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus); + char *getCodeWordD(char group, int nDevice, bool bStatus); + void transmit(HighLow pulses); + +#if not defined( RCSwitchDisableReceiving ) + static void handleInterrupt(); + static bool receiveProtocol(const int p, unsigned int changeCount); + int nReceiverInterrupt; +#endif + int nTransmitterPin; + int nRepeatTransmit; + + Protocol protocol; + +#if not defined( RCSwitchDisableReceiving ) + static int nReceiveTolerance; + volatile static unsigned long nReceivedValue; + volatile static unsigned int nReceivedBitlength; + volatile static unsigned int nReceivedDelay; + volatile static unsigned int nReceivedProtocol; + const static unsigned int nSeparationLimit; + /* + * timings[0] contains sync timing, followed by a number of bits + */ + static unsigned int timings[RCSWITCH_MAX_CHANGES]; +#endif + +}; + +#endif diff --git a/433/433Utils/rc-switch/README.md b/433/433Utils/rc-switch/README.md new file mode 100644 index 0000000..f6a679c --- /dev/null +++ b/433/433Utils/rc-switch/README.md @@ -0,0 +1,42 @@ +# rc-switch +[![arduino-library-badge](https://www.ardu-badge.com/badge/rc-switch.svg?)](https://www.ardu-badge.com/rc-switch) +[![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch) + +Use your Arduino or [Raspberry Pi](https://github.com/r10r/rcswitch-pi) to operate remote radio controlled devices + +## Download +https://github.com/sui77/rc-switch/releases/latest + +rc-switch is also listed in the arduino library manager. + +## Wiki +https://github.com/sui77/rc-switch/wiki + +## Info +### Send RC codes + +Use your Arduino or Raspberry Pi to operate remote radio controlled devices. +This will most likely work with all popular low cost power outlet sockets. If +yours doesn't work, you might need to adjust the pulse length. + +All you need is a Arduino or Raspberry Pi, a 315/433MHz AM transmitter and one +or more devices with one of the supported chipsets: + + - SC5262 / SC5272 + - HX2262 / HX2272 + - PT2262 / PT2272 + - EV1527 / RT1527 / FP1527 / HS1527 + - Intertechno outlets + - HT6P20X + +### Receive and decode RC codes + +Find out what codes your remote is sending. Use your remote to control your +Arduino. + +All you need is an Arduino, a 315/433MHz AM receiver (altough there is no +instruction yet, yes it is possible to hack an existing device) and a remote +hand set. + +For the Raspberry Pi, clone the https://github.com/ninjablocks/433Utils project to +compile a sniffer tool and transmission commands. diff --git a/433/433Utils/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino b/433/433Utils/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino new file mode 100644 index 0000000..18380d3 --- /dev/null +++ b/433/433Utils/rc-switch/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.ino @@ -0,0 +1,24 @@ +/* + Example for receiving + + https://github.com/sui77/rc-switch/ + + If you want to visualize a telegram copy the raw data and + paste it into http://test.sui.li/oszi/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + output(mySwitch.getReceivedValue(), mySwitch.getReceivedBitlength(), mySwitch.getReceivedDelay(), mySwitch.getReceivedRawdata(),mySwitch.getReceivedProtocol()); + mySwitch.resetAvailable(); + } +} diff --git a/433/433Utils/rc-switch/examples/ReceiveDemo_Advanced/output.ino b/433/433Utils/rc-switch/examples/ReceiveDemo_Advanced/output.ino new file mode 100644 index 0000000..31e61ba --- /dev/null +++ b/433/433Utils/rc-switch/examples/ReceiveDemo_Advanced/output.ino @@ -0,0 +1,70 @@ +static const char* bin2tristate(const char* bin); +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength); + +void output(unsigned long decimal, unsigned int length, unsigned int delay, unsigned int* raw, unsigned int protocol) { + + const char* b = dec2binWzerofill(decimal, length); + Serial.print("Decimal: "); + Serial.print(decimal); + Serial.print(" ("); + Serial.print( length ); + Serial.print("Bit) Binary: "); + Serial.print( b ); + Serial.print(" Tri-State: "); + Serial.print( bin2tristate( b) ); + Serial.print(" PulseLength: "); + Serial.print(delay); + Serial.print(" microseconds"); + Serial.print(" Protocol: "); + Serial.println(protocol); + + Serial.print("Raw data: "); + for (unsigned int i=0; i<= length*2; i++) { + Serial.print(raw[i]); + Serial.print(","); + } + Serial.println(); + Serial.println(); +} + +static const char* bin2tristate(const char* bin) { + static char returnValue[50]; + int pos = 0; + int pos2 = 0; + while (bin[pos]!='\0' && bin[pos+1]!='\0') { + if (bin[pos]=='0' && bin[pos+1]=='0') { + returnValue[pos2] = '0'; + } else if (bin[pos]=='1' && bin[pos+1]=='1') { + returnValue[pos2] = '1'; + } else if (bin[pos]=='0' && bin[pos+1]=='1') { + returnValue[pos2] = 'F'; + } else { + return "not applicable"; + } + pos = pos+2; + pos2++; + } + returnValue[pos2] = '\0'; + return returnValue; +} + +static char * dec2binWzerofill(unsigned long Dec, unsigned int bitLength) { + static char bin[64]; + unsigned int i=0; + + while (Dec > 0) { + bin[32+i++] = ((Dec & 1) > 0) ? '1' : '0'; + Dec = Dec >> 1; + } + + for (unsigned int j = 0; j< bitLength; j++) { + if (j >= bitLength - i) { + bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; + } else { + bin[j] = '0'; + } + } + bin[bitLength] = '\0'; + + return bin; +} diff --git a/433/433Utils/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino b/433/433Utils/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino new file mode 100644 index 0000000..bb10763 --- /dev/null +++ b/433/433Utils/rc-switch/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.ino @@ -0,0 +1,29 @@ +/* + Simple example for receiving + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + Serial.begin(9600); + mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2 +} + +void loop() { + if (mySwitch.available()) { + + Serial.print("Received "); + Serial.print( mySwitch.getReceivedValue() ); + Serial.print(" / "); + Serial.print( mySwitch.getReceivedBitlength() ); + Serial.print("bit "); + Serial.print("Protocol: "); + Serial.println( mySwitch.getReceivedProtocol() ); + + mySwitch.resetAvailable(); + } +} diff --git a/433/433Utils/rc-switch/examples/SendDemo/SendDemo.ino b/433/433Utils/rc-switch/examples/SendDemo/SendDemo.ino new file mode 100644 index 0000000..5acb495 --- /dev/null +++ b/433/433Utils/rc-switch/examples/SendDemo/SendDemo.ino @@ -0,0 +1,57 @@ +/* + Example for different sending methods + + https://github.com/sui77/rc-switch/ + +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + Serial.begin(9600); + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set protocol (default is 1, will work for most outlets) + // mySwitch.setProtocol(2); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + + // Optional set number of transmission repetitions. + // mySwitch.setRepeatTransmit(15); + +} + +void loop() { + + /* See Example: TypeA_WithDIPSwitches */ + mySwitch.switchOn("11111", "00010"); + delay(1000); + mySwitch.switchOff("11111", "00010"); + delay(1000); + + /* Same switch as above, but using decimal code */ + mySwitch.send(5393, 24); + delay(1000); + mySwitch.send(5396, 24); + delay(1000); + + /* Same switch as above, but using binary code */ + mySwitch.send("000000000001010100010001"); + delay(1000); + mySwitch.send("000000000001010100010100"); + delay(1000); + + /* Same switch as above, but tri-state code */ + mySwitch.sendTriState("00000FFF0F0F"); + delay(1000); + mySwitch.sendTriState("00000FFF0FF0"); + delay(1000); + + delay(20000); +} diff --git a/433/433Utils/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino b/433/433Utils/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino new file mode 100644 index 0000000..14f7d2a --- /dev/null +++ b/433/433Utils/rc-switch/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.ino @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with a 10 pole DIP switch. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first 5 DIP switches. + // In this example it's ON-ON-OFF-OFF-ON. + // + // The second parameter represents the setting of the last 5 DIP switches. + // In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF. + mySwitch.switchOn("11001", "01010"); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff("11001", "01010"); + + // Wait another second + delay(1000); + +} diff --git a/433/433Utils/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/433/433Utils/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino new file mode 100644 index 0000000..214daf4 --- /dev/null +++ b/433/433Utils/rc-switch/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino @@ -0,0 +1,43 @@ +/* + This is a minimal sketch without using the library at all but only works for + the 10 pole dip switch sockets. It saves a lot of memory and thus might be + very useful to use with ATTinys :) + + https://github.com/sui77/rc-switch/ +*/ + +int RCLpin = 7; + +void setup() { + pinMode(RCLpin, OUTPUT); +} + +void loop() { + RCLswitch(0b010001000001); // DIPs an Steckdose: 0100010000 An:01 + delay(2000); + + RCLswitch(0b010001000010); // DIPs an Steckdose: 0100010000 Aus:10 + delay(2000); +} + +void RCLswitch(uint16_t code) { + for (int nRepeat=0; nRepeat<6; nRepeat++) { + for (int i=4; i<16; i++) { + RCLtransmit(1,3); + if (((code << (i-4)) & 2048) > 0) { + RCLtransmit(1,3); + } else { + RCLtransmit(3,1); + } + } + RCLtransmit(1,31); + } +} + +void RCLtransmit(int nHighPulses, int nLowPulses) { + digitalWrite(RCLpin, HIGH); + delayMicroseconds( 350 * nHighPulses); + digitalWrite(RCLpin, LOW); + delayMicroseconds( 350 * nLowPulses); +} + diff --git a/433/433Utils/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino b/433/433Utils/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino new file mode 100644 index 0000000..e8568e2 --- /dev/null +++ b/433/433Utils/rc-switch/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.ino @@ -0,0 +1,40 @@ +/* + Example for outlets which are configured with two rotary/sliding switches. + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the setting of the first rotary switch. + // In this example it's switched to "1" or "A" or "I". + // + // The second parameter represents the setting of the second rotary switch. + // In this example it's switched to "4" or "D" or "IV". + mySwitch.switchOn(1, 4); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff(1, 4); + + // Wait another second + delay(1000); + +} diff --git a/433/433Utils/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino b/433/433Utils/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino new file mode 100644 index 0000000..0fc69c7 --- /dev/null +++ b/433/433Utils/rc-switch/examples/TypeC_Intertechno/TypeC_Intertechno.ino @@ -0,0 +1,40 @@ +/* + Example for Intertechno outlets + + https://github.com/sui77/rc-switch/ +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // Optional set pulse length. + // mySwitch.setPulseLength(320); + +} + +void loop() { + + // Switch on: + // The first parameter represents the familycode (a, b, c, ... f) + // The second parameter represents the group number + // The third parameter represents the device number + // + // In this example it's family 'b', group #3, device #2 + mySwitch.switchOn('b', 3, 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('b', 3, 2); + + // Wait another second + delay(1000); + +} \ No newline at end of file diff --git a/433/433Utils/rc-switch/examples/TypeD_REV/TypeD_REV.ino b/433/433Utils/rc-switch/examples/TypeD_REV/TypeD_REV.ino new file mode 100644 index 0000000..8782729 --- /dev/null +++ b/433/433Utils/rc-switch/examples/TypeD_REV/TypeD_REV.ino @@ -0,0 +1,41 @@ +/* + Example for REV outlets (e.g. 8342L) + + https://github.com/sui77/rc-switch/ + + Need help? http://forum.ardumote.com +*/ + +#include + +RCSwitch mySwitch = RCSwitch(); + +void setup() { + + // Transmitter is connected to Arduino Pin #10 + mySwitch.enableTransmit(10); + + // set pulse length. + mySwitch.setPulseLength(360); + +} + +void loop() { + + // Switch on: + // The first parameter represents the channel (a, b, c, d) + // The second parameter represents the device number + // + // In this example it's family 'd', device #2 + mySwitch.switchOn('d', 2); + + // Wait a second + delay(1000); + + // Switch off + mySwitch.switchOff('d', 2); + + // Wait another second + delay(1000); + +} diff --git a/433/433Utils/rc-switch/examples/Webserver/Webserver.ino b/433/433Utils/rc-switch/examples/Webserver/Webserver.ino new file mode 100644 index 0000000..66668e7 --- /dev/null +++ b/433/433Utils/rc-switch/examples/Webserver/Webserver.ino @@ -0,0 +1,154 @@ +/* + A simple RCSwitch/Ethernet/Webserver demo + + https://github.com/sui77/rc-switch/ +*/ + +#include +#include +#include + +// Ethernet configuration +uint8_t mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC Address +uint8_t ip[] = { 192,168,0, 2 }; // IP Address +EthernetServer server(80); // Server Port 80 + +// RCSwitch configuration +RCSwitch mySwitch = RCSwitch(); +int RCTransmissionPin = 7; + +// More to do... +// You should also modify the processCommand() and +// httpResponseHome() functions to fit your needs. + + + +/** + * Setup + */ +void setup() { + Ethernet.begin(mac, ip); + server.begin(); + mySwitch.enableTransmit( RCTransmissionPin ); +} + +/** + * Loop + */ +void loop() { + char* command = httpServer(); +} + +/** + * Command dispatcher + */ +void processCommand(char* command) { + if (strcmp(command, "1-on") == 0) { + mySwitch.switchOn(1,1); + } else if (strcmp(command, "1-off") == 0) { + mySwitch.switchOff(1,1); + } else if (strcmp(command, "2-on") == 0) { + mySwitch.switchOn(1,2); + } else if (strcmp(command, "2-off") == 0) { + mySwitch.switchOff(1,2); + } +} + +/** + * HTTP Response with homepage + */ +void httpResponseHome(EthernetClient c) { + c.println("HTTP/1.1 200 OK"); + c.println("Content-Type: text/html"); + c.println(); + c.println(""); + c.println(""); + c.println( "RCSwitch Webserver Demo"); + c.println( ""); + c.println(""); + c.println(""); + c.println( "

RCSwitch Webserver Demo

"); + c.println( ""); + c.println( ""); + c.println( "
"); + c.println( "https://github.com/sui77/rc-switch/"); + c.println(""); + c.println(""); +} + +/** + * HTTP Redirect to homepage + */ +void httpResponseRedirect(EthernetClient c) { + c.println("HTTP/1.1 301 Found"); + c.println("Location: /"); + c.println(); +} + +/** + * HTTP Response 414 error + * Command must not be longer than 30 characters + **/ +void httpResponse414(EthernetClient c) { + c.println("HTTP/1.1 414 Request URI too long"); + c.println("Content-Type: text/plain"); + c.println(); + c.println("414 Request URI too long"); +} + +/** + * Process HTTP requests, parse first request header line and + * call processCommand with GET query string (everything after + * the ? question mark in the URL). + */ +char* httpServer() { + EthernetClient client = server.available(); + if (client) { + char sReturnCommand[32]; + int nCommandPos=-1; + sReturnCommand[0] = '\0'; + while (client.connected()) { + if (client.available()) { + char c = client.read(); + if ((c == '\n') || (c == ' ' && nCommandPos>-1)) { + sReturnCommand[nCommandPos] = '\0'; + if (strcmp(sReturnCommand, "\0") == 0) { + httpResponseHome(client); + } else { + processCommand(sReturnCommand); + httpResponseRedirect(client); + } + break; + } + if (nCommandPos>-1) { + sReturnCommand[nCommandPos++] = c; + } + if (c == '?' && nCommandPos == -1) { + nCommandPos = 0; + } + } + if (nCommandPos > 30) { + httpResponse414(client); + sReturnCommand[0] = '\0'; + break; + } + } + if (nCommandPos!=-1) { + sReturnCommand[nCommandPos] = '\0'; + } + // give the web browser time to receive the data + delay(1); + client.stop(); + + return sReturnCommand; + } + return '\0'; +} \ No newline at end of file diff --git a/433/433Utils/rc-switch/keywords.txt b/433/433Utils/rc-switch/keywords.txt new file mode 100644 index 0000000..2474367 --- /dev/null +++ b/433/433Utils/rc-switch/keywords.txt @@ -0,0 +1,57 @@ +####################################### +# Syntax Coloring Map For RCSwitch +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +RCSwitch KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +########## +#SENDS Begin +########## +switchOn KEYWORD2 +switchOff KEYWORD2 +sendTriState KEYWORD2 +send KEYWORD2 +########## +#SENDS End +########## + +########## +#RECEIVE Begin +########## +enableReceive KEYWORD2 +disableReceive KEYWORD2 +available KEYWORD2 +resetAvailable KEYWORD2 +setReceiveTolerance KEYWORD2 +getReceivedValue KEYWORD2 +getReceivedBitlength KEYWORD2 +getReceivedDelay KEYWORD2 +getReceivedProtocol KEYWORD2 +getReceivedRawdata KEYWORD2 +########## +#RECEIVE End +########## + +########## +#OTHERS Begin +########## +enableTransmit KEYWORD2 +disableTransmit KEYWORD2 +setPulseLength KEYWORD2 +setProtocol KEYWORD2 +setRepeatTransmit KEYWORD2 +########## +#OTHERS End +########## + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/433/433Utils/rc-switch/library.json b/433/433Utils/rc-switch/library.json new file mode 100644 index 0000000..b98e28f --- /dev/null +++ b/433/433Utils/rc-switch/library.json @@ -0,0 +1,21 @@ +{ + "name": "rc-switch", + "description": "Use your Arduino or Raspberry Pi to operate remote radio controlled devices", + "keywords": "rf, radio, wireless", + "authors": + { + "name": "Suat Ozgur" + }, + "repository": + { + "type": "git", + "url": "https://github.com/sui77/rc-switch.git" + }, + "version": "2.6.4", + "frameworks": [ + "arduino", + "energia", + "wiringpi" + ], + "platforms": "*" +} diff --git a/433/433Utils/rc-switch/library.properties b/433/433Utils/rc-switch/library.properties new file mode 100644 index 0000000..d60b460 --- /dev/null +++ b/433/433Utils/rc-switch/library.properties @@ -0,0 +1,10 @@ +name=rc-switch +version=2.6.4 +author=sui77 +maintainer=sui77,fingolfin +sentence=Operate 433/315Mhz devices. +paragraph=Use your Arduino, ESP8266/ESP32 or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets. +category=Device Control +url=https://github.com/sui77/rc-switch +architectures=avr,esp8266,esp32,stm32,megaavr +includes=RCSwitch.h diff --git a/433/rc-switch-pico/.gitignore b/433/rc-switch-pico/.gitignore new file mode 100644 index 0000000..fa6d8c6 --- /dev/null +++ b/433/rc-switch-pico/.gitignore @@ -0,0 +1,16 @@ +.DS_Store +CMakeFiles/ +elf2uf2/ +generated/ +pico-sdk/ +CMakeCache.txt +CMakeDoxyfile.in +CMakeDoxygenDefaults.cmake +Makefile +cmake_install.cmake +*.bin +*.dis +*.elf +*.elf.map +*.hex +*.uf2 \ No newline at end of file diff --git a/433/rc-switch-pico/CMakeLists.txt b/433/rc-switch-pico/CMakeLists.txt new file mode 100644 index 0000000..e952009 --- /dev/null +++ b/433/rc-switch-pico/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.12) + +# Pull in SDK (must be before project) +include(pico_sdk_import.cmake) + +project(pico_examples C CXX ASM) +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR}) + +# Initialize the SDK +pico_sdk_init() + +# Add blink example +add_subdirectory(examples/Transmit) +add_subdirectory(examples/Receive) + + + + + + diff --git a/433/rc-switch-pico/LICENSE b/433/rc-switch-pico/LICENSE new file mode 100644 index 0000000..8adf5b6 --- /dev/null +++ b/433/rc-switch-pico/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 oshawa-connection + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/433/rc-switch-pico/examples/Receive/CMakeLists.txt b/433/rc-switch-pico/examples/Receive/CMakeLists.txt new file mode 100644 index 0000000..ce9017d --- /dev/null +++ b/433/rc-switch-pico/examples/Receive/CMakeLists.txt @@ -0,0 +1,31 @@ +add_executable(receive + Receive.cc + ../../radio-switch.cc + ) + + +add_compile_options(-Wall +-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int +-Wno-unused-function # we have some for the docs that aren't called +-Wno-maybe-uninitialized +) + +# Pull in our pico_stdlib which pulls in commonly used features + +target_link_libraries(receive +pico_stdlib +hardware_adc +pico_multicore) + +# enable usb output, disable uart output +pico_enable_stdio_usb(receive 1) +pico_enable_stdio_uart(receive 0) + +# create map/bin/hex file etc. +pico_add_extra_outputs(receive) + + + + + + diff --git a/433/rc-switch-pico/examples/Receive/Receive.cc b/433/rc-switch-pico/examples/Receive/Receive.cc new file mode 100644 index 0000000..7f6cf29 --- /dev/null +++ b/433/rc-switch-pico/examples/Receive/Receive.cc @@ -0,0 +1,235 @@ +#include +#include "pico/stdlib.h" +#include "../../radio-switch.h" +#include "pico/stdio.h" + +#include +#include "pico/stdlib.h" +#include "pico/multicore.h" + +//#include "hardware/adc.h" +//#include + +#include + +#define BUFFER_SIZ 1024 + +// 闪烁LED +void light() +{ + const uint LED_PIN = PICO_DEFAULT_LED_PIN; + gpio_init(LED_PIN); + gpio_set_dir(LED_PIN, GPIO_OUT); + gpio_put(LED_PIN, 1); + sleep_ms(100); + gpio_put(LED_PIN, 0); + sleep_ms(100); + +} + +/* +int temperature() { + // 数模转换器为 0~3.3v 最大值为 12bit + const float conversion_factor = 3.3f / (1 << 12); + + float v; + float t; + stdio_init_all(); + printf("Use adc channel 4, measuring temptutre\n"); + // ADC初始化 + adc_init(); + adc_set_temp_sensor_enabled(true); + adc_select_input(4); + + // 数字转换为电压 + v = adc_read() * conversion_factor; + t = 27 - (v - 0.706) / 0.001721; + printf("t:%.2f v:%.2f\n", t, v); + + sleep_ms(100); + + return 0; +} +*/ + +static char pool[] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9' +}; + +// 随即数 +static int RAND() +{ + int PASSWD_LEN = 3; + char password[BUFFER_SIZ]; + int i = 0; + FILE *fp; + + memset(password, 0, BUFFER_SIZ); + srand(time(NULL)); + + while (i != PASSWD_LEN) { + password[i++] = pool[rand() % sizeof(pool)]; + } + + //printf("%d\n", atoi(password)); + return atoi(password); +} + +static void SEND(const int ID) +{ + const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚 + const uint BUTTON = 21; // 按钮发射 + + const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED + const uint REPEAT_TRANSMIT = 4; // set this to whatever works best for you. // 重复发送 + const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED + const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED + + gpio_init(RADIO_TRANSMIT_PIN); + RCSwitch mySwitch = RCSwitch(); + mySwitch.enableTransmit(RADIO_TRANSMIT_PIN); + mySwitch.setProtocol(PROTOCOL); + mySwitch.setPulseLength(PULSE_LENGTH); + mySwitch.setRepeatTransmit(REPEAT_TRANSMIT); + + int RANDOM = 500; + int LOOP_NUM = 1; // 循环发送次数 + + for (int i = 0; i <= LOOP_NUM; i++) { + RANDOM = RAND(); + light(); // 灯闪烁 + + sleep_ms(RANDOM * 2 / 3); // 等待随机时间 + + mySwitch.send(ID, BIT_LENGTH); // 第一次发射 + sleep_ms(130); + + mySwitch.send(ID + 1, BIT_LENGTH); // 第二次发射 + sleep_ms(130); + } + +} + + +int int_string(int val, char *string, int string_len, int *str_len, char *dest, int *dest_len) +{ + char s[] = "55"; + char d = '2'; + + snprintf(string, string_len, "%d", val); + *str_len = strlen(string); + + if (0 == strncasecmp(string, s, 2)) { + dest[0] = d; + dest[1] = d; + strncpy(dest + 2, string + 2, (*str_len) - 2); + + *dest_len = strlen(dest); + } + + return 0; +} + + + +// 核心0发送数据到核心1, 核心1判断是否有数据到来, 然后打印. +void core1_main() +{ + const uint RADIO_RECEIVER_PIN = 17; + gpio_init(RADIO_RECEIVER_PIN); + + RCSwitch rcSwitch = RCSwitch(); + rcSwitch.enableReceive(RADIO_RECEIVER_PIN); + + char str[270]; + char dest[270]; + int str_len; + int dest_len; + memset(str, 0, 270); + memset(dest, 0, 270); + + while (true) { + if (rcSwitch.available()) { + light(); + + uint32_t val = rcSwitch.getReceivedValue(); + //printf("核心1接收到的433MHZ数值%u\n", val); + + int_string(val, str, 270, &str_len, dest, &dest_len); + + if (val != 0) { + if (str[0] == '5' && str[1] == '5') + { + + multicore_fifo_push_blocking(atoi(dest)); + } + else + { + rcSwitch.resetAvailable(); + val = 0; + continue; + } + + } + + + + rcSwitch.resetAvailable(); + val = 0; + } + + + + +/* + if (multicore_fifo_rvalid()) { + uint32_t i = multicore_fifo_pop_blocking(); + printf("核心1接收到核心0的数值%u\n", i); + + } +*/ + sleep_ms(130); + + + } + + + return ; +} + +int main() +{ + stdio_init_all(); + + multicore_reset_core1(); + multicore_launch_core1(core1_main); + + + while (1) { + + if (multicore_fifo_rvalid()) { + uint32_t i = multicore_fifo_pop_blocking(); // 读取核心1发送来的数据 + //printf("核心0接收到核心1的数值%u\n", i); + + //multicore_reset_core1(); // 关闭核心1 + //SEND(i); // 433MHZ发送 + //multicore_launch_core1(core1_main); // 开启核心1 + //multicore_fifo_push_blocking(i); // 给核心1发送数据 + + + + + + SEND(i); + printf("核心0转发433MHZ %u\n", i); + + + } + + + sleep_ms(130); + } + + + return 0; +} diff --git a/433/rc-switch-pico/examples/Transmit/CMakeLists.txt b/433/rc-switch-pico/examples/Transmit/CMakeLists.txt new file mode 100644 index 0000000..67a46cc --- /dev/null +++ b/433/rc-switch-pico/examples/Transmit/CMakeLists.txt @@ -0,0 +1,21 @@ +add_executable(transmit + Transmit.cc + ../../radio-switch.cc + ) + + +add_compile_options(-Wall +-Wno-format # int != int32_t as far as the compiler is concerned because gcc has int32_t as long int +-Wno-unused-function # we have some for the docs that aren't called +-Wno-maybe-uninitialized +) + +# Pull in our pico_stdlib which pulls in commonly used features +target_link_libraries(transmit pico_stdlib) + +# enable usb output, disable uart output +pico_enable_stdio_usb(transmit 1) +pico_enable_stdio_uart(transmit 0) + +# create map/bin/hex file etc. +pico_add_extra_outputs(transmit) diff --git a/433/rc-switch-pico/examples/Transmit/Transmit.cc b/433/rc-switch-pico/examples/Transmit/Transmit.cc new file mode 100644 index 0000000..1f8fd0e --- /dev/null +++ b/433/rc-switch-pico/examples/Transmit/Transmit.cc @@ -0,0 +1,101 @@ +#include +#include "pico/stdlib.h" +#include "../../radio-switch.h" + +#include + +#define BUFFER_SIZ 1024 + + +// 闪烁LED +static void light() +{ + const uint LED_PIN = PICO_DEFAULT_LED_PIN; + gpio_init(LED_PIN); + gpio_set_dir(LED_PIN, GPIO_OUT); + gpio_put(LED_PIN, 1); + sleep_ms(100); + gpio_put(LED_PIN, 0); + sleep_ms(100); + +} + +static char pool[] = { + '1', '2', '3', '4', '5', '6', '7', '8', '9' +}; + +// 随即数 +static int RAND() +{ + int PASSWD_LEN = 3; + char password[BUFFER_SIZ]; + int i = 0; + FILE *fp; + + + memset(password, 0, BUFFER_SIZ); + srand(time(NULL)); + + while (i != PASSWD_LEN) { + password[i++] = pool[rand() % sizeof(pool)]; + } + + + + printf("%d\n", atoi(password)); + + return atoi(password); +} + +int main(void) { + + const uint RADIO_TRANSMIT_PIN = 16; // 433发射模块引脚 + const uint BUTTON = 17; // 按钮发射 + + + const uint PULSE_LENGTH = 169; // set this to PULSELENGTH RECIEVED + const uint REPEAT_TRANSMIT = 4; // set this to whatever works best for you. // 重复发送 + const uint PROTOCOL = 1; // set this to PROTOCOL RECIEVED + const uint BIT_LENGTH = 24; // set this to BIT LENGTH RECIEVED + + stdio_init_all(); + gpio_init(RADIO_TRANSMIT_PIN); + RCSwitch mySwitch = RCSwitch(); + mySwitch.enableTransmit(RADIO_TRANSMIT_PIN); + mySwitch.setProtocol(PROTOCOL); + mySwitch.setPulseLength(PULSE_LENGTH); + mySwitch.setRepeatTransmit(REPEAT_TRANSMIT); + + int RANDOM = 30; + int LOOP_NUM = 2; // 循环发送次数 + + + const int but = 55001; + + + while(1) + { + + //if (1 == gpio_get(BUTTON)) { // 按钮按下 + for (int i=0; i<=LOOP_NUM; i++) { + RANDOM = RAND(); + light(); // 灯闪烁 + + sleep_ms(RANDOM * 2 / 3); // 等待随机时间 + + mySwitch.send(but, BIT_LENGTH); // 第一次发射 + sleep_ms(130); + + + //mySwitch.send(but+1, BIT_LENGTH); // 第二次发射 + //sleep_ms(130); + } + //} + + sleep_ms(3000); + } + + + return 0; +} + diff --git a/433/rc-switch-pico/pico_sdk_import.cmake b/433/rc-switch-pico/pico_sdk_import.cmake new file mode 100644 index 0000000..28efe9e --- /dev/null +++ b/433/rc-switch-pico/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/433/rc-switch-pico/pioasm/pioasm b/433/rc-switch-pico/pioasm/pioasm new file mode 100644 index 0000000..a9d9967 Binary files /dev/null and b/433/rc-switch-pico/pioasm/pioasm differ diff --git a/433/rc-switch-pico/radio-switch.cc b/433/rc-switch-pico/radio-switch.cc new file mode 100644 index 0000000..01f9875 --- /dev/null +++ b/433/rc-switch-pico/radio-switch.cc @@ -0,0 +1,728 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Andreas Steinel / A.(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + - Johann Richard / .(at)gmail(dot)com + - Vlad Gheorghe / .(at)gmail(dot)com https://github.com/vgheo + - Matias Cuenca-Acuna + + Project home: https://github.com/sui77/rc-switch/ + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + 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, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "radio-switch.h" +#include "pico/stdlib.h" +#include "hardware/gpio.h" +#include "hardware/uart.h" + +#ifdef _PICO_STDLIB_H +#define HIGH 1 +#define LOW 0 +#endif + + +#define PROGMEM +#define memcpy_P(dest, src, num) memcpy((dest), (src), (num)) + + +#if defined(ESP8266) + // interrupt handler and related code must be in RAM on ESP8266, + // according to issue #46. + #define RECEIVE_ATTR ICACHE_RAM_ATTR + #define VAR_ISR_ATTR +#elif defined(ESP32) + #define RECEIVE_ATTR IRAM_ATTR + #define VAR_ISR_ATTR DRAM_ATTR +#else + #define RECEIVE_ATTR + #define VAR_ISR_ATTR +#endif + +/* Format for protocol definitions: + * {pulselength, Sync bit, "0" bit, "1" bit, invertedSignal} + * + * 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: + * _ + * | |_______________________________ (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: + * _ + * | |___ + * "1" bit: waveform for a data bit of value "1", e.g. {3,1}: + * ___ + * | |_ + * + * These are combined to form Tri-State bits when sending or receiving codes. + */ +#if defined(ESP8266) || defined(ESP32) +static const VAR_ISR_ATTR 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) + { 200, { 3, 130}, { 7, 16 }, { 3, 16}, false}, // protocol 8 Conrad RS-200 RX + { 200, { 130, 7 }, { 16, 7 }, { 16, 3 }, true}, // protocol 9 Conrad RS-200 TX + { 365, { 18, 1 }, { 3, 1 }, { 1, 3 }, true }, // protocol 10 (1ByOne Doorbell) + { 270, { 36, 1 }, { 1, 2 }, { 2, 1 }, true }, // protocol 11 (HT12E) + { 320, { 36, 1 }, { 1, 2 }, { 2, 1 }, true } // protocol 12 (SM5212) +}; + +void RCSwitch::gpio_callback(unsigned int gpio, uint32_t events) { + RCSwitch::handleInterrupt(); +} + +enum { + numProto = sizeof(proto) / sizeof(proto[0]) +}; + +#if not defined( RCSwitchDisableReceiving ) +volatile unsigned 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 VAR_ISR_ATTR RCSwitch::nSeparationLimit = 4300; +// 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]; +#endif + +RCSwitch::RCSwitch() { + this->nTransmitterPin = -1; + this->setRepeatTransmit(10); + this->setProtocol(1); + #if not defined( RCSwitchDisableReceiving ) + this->nReceiverInterrupt = -1; + this->setReceiveTolerance(60); + RCSwitch::nReceivedValue = 0; + #endif +} + +/** + * Sets the protocol to send. + */ +void RCSwitch::setProtocol(Protocol protocol) { + this->protocol = protocol; +} + +/** + * Sets the protocol to send, from a list of predefined protocols + */ +void RCSwitch::setProtocol(int nProtocol) { + if (nProtocol < 1 || nProtocol > numProto) { + nProtocol = 1; // TODO: trigger an error, e.g. "bad protocol" ??? + } +#if defined(ESP8266) || defined(ESP32) + this->protocol = proto[nProtocol-1]; +#else + memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol)); +#endif +} + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { + setProtocol(nProtocol); + this->setPulseLength(nPulseLength); +} + + +/** + * Sets pulse length in microseconds + */ +void RCSwitch::setPulseLength(int nPulseLength) { + this->protocol.pulseLength = nPulseLength; +} + +/** + * Sets Repeat Transmits + */ +void RCSwitch::setRepeatTransmit(int nRepeatTransmit) { + this->nRepeatTransmit = nRepeatTransmit; +} + +/** + * Set Receiving Tolerance + */ +#if not defined( RCSwitchDisableReceiving ) +void RCSwitch::setReceiveTolerance(int nPercent) { + RCSwitch::nReceiveTolerance = nPercent; +} +#endif + + +/** + * Enable transmissions + * + * @param nTransmitterPin Arduino Pin to which the sender is connected to + */ +void RCSwitch::enableTransmit(int nTransmitterPin) { + this->nTransmitterPin = nTransmitterPin; + // pinMode(this->nTransmitterPin, OUTPUT); + gpio_set_dir(this->nTransmitterPin,GPIO_OUT); +} + +/** + * Disable transmissions + */ +void RCSwitch::disableTransmit() { + this->nTransmitterPin = -1; +} + +/** + * Switch a remote switch on (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOn(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type D REV) + * + * @param sGroup Code of the switch group (A,B,C,D) + * @param nDevice Number of the switch itself (1..3) + */ +void RCSwitch::switchOff(char sGroup, int nDevice) { + this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) ); +} + +/** + * Switch a remote switch off (Type C Intertechno) + * + * @param sFamily Familycode (a..f) + * @param nGroup Number of group (1..4) + * @param nDevice Number of device (1..4) + */ +void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) { + this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) ); +} + +/** + * Switch a remote switch on (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOn(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) ); +} + +/** + * Switch a remote switch off (Type B with two rotary/sliding switches) + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + */ +void RCSwitch::switchOff(int nAddressCode, int nChannelCode) { + this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) ); +} + +/** + * Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOn(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOn(sGroup, code[nChannel]); +} + +/** + * Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead! + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param nChannelCode Number of the switch itself (1..5) + */ +void RCSwitch::switchOff(const char* sGroup, int nChannel) { + const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" }; + this->switchOff(sGroup, code[nChannel]); +} + +/** + * Switch a remote switch on (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOn(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) ); +} + +/** + * Switch a remote switch off (Type A with 10 pole DIP switches) + * + * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") + * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") + */ +void RCSwitch::switchOff(const char* sGroup, const char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); +} + + +/** + * Returns a char[13], representing the code word to be send. + * + */ +char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0'; + } + + for (int i = 0; i < 5; i++) { + sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0'; + } + + sReturn[nReturnPos++] = bStatus ? '0' : 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for type B switches with two rotary/sliding switches. + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-----------------------------+----------+------------+ + * | 4 bits address | 4 bits address | 3 bits | 1 bit | + * | switch group | switch number | not used | on / off | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF | on=F off=0 | + * +-----------------------------+-----------------------------+----------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return 0; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F'; + } + + for (int i = 1; i <= 4; i++) { + sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F'; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Like getCodeWord (Type C = Intertechno) + */ +char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + int nFamily = (int)sFamily - 'a'; + if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return 0; + } + + // encode the family into four bits + sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0'; + sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0'; + + // encode the device and group + sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0'; + sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0'; + + // encode the status code + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = bStatus ? 'F' : '0'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * Encoding for the REV Switch Type + * + * The code word is a tristate word and with following bit pattern: + * + * +-----------------------------+-------------------+----------+--------------+ + * | 4 bits address | 3 bits address | 3 bits | 2 bits | + * | switch group | device number | not used | on / off | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000 | on=10 off=01 | + * +-----------------------------+-------------------+----------+--------------+ + * + * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ + * + * @param sGroup Name of the switch group (A..D, resp. a..d) + * @param nDevice Number of the switch itself (1..3) + * @param bStatus Whether to switch on (true) or off (false) + * + * @return char[13], representing a tristate code word of length 12 + */ +char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) { + static char sReturn[13]; + int nReturnPos = 0; + + // sGroup must be one of the letters in "abcdABCD" + int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A'; + if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) { + return 0; + } + + for (int i = 0; i < 4; i++) { + sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F'; + } + + for (int i = 1; i <= 3; i++) { + sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F'; + } + + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = '0'; + + sReturn[nReturnPos++] = bStatus ? '1' : '0'; + sReturn[nReturnPos++] = bStatus ? '0' : '1'; + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + +/** + * @param sCodeWord a tristate code word consisting of the letter 0, 1, F + */ +void RCSwitch::sendTriState(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 2L; + switch (*p) { + case '0': + // bit pattern 00 + break; + case 'F': + // bit pattern 01 + code |= 1L; + break; + case '1': + // bit pattern 11 + code |= 3L; + break; + } + length += 2; + } + this->send(code, length); +} + +/** + * @param sCodeWord a binary code word consisting of the letter 0, 1 + */ +void RCSwitch::send(const char* sCodeWord) { + // turn the tristate code word into the corresponding bit pattern, then send it + unsigned long code = 0; + unsigned int length = 0; + for (const char* p = sCodeWord; *p; p++) { + code <<= 1L; + if (*p != '0') + code |= 1L; + length++; + } + this->send(code, length); +} + +/** + * Transmit the first 'length' bits of the integer 'code'. The + * 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) { + if (this->nTransmitterPin == -1) + return; + +#if not defined( RCSwitchDisableReceiving ) + // make sure the receiver is disabled while we transmit + int nReceiverInterrupt_backup = nReceiverInterrupt; + if (nReceiverInterrupt_backup != -1) { + this->disableReceive(); + } +#endif + + for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) { + for (int i = length-1; i >= 0; i--) { + if (code & (1L << i)) + this->transmit(protocol.one); + else + this->transmit(protocol.zero); + } + this->transmit(protocol.syncFactor); + } + + // Disable transmit after sending (i.e., for inverted protocols) + // digitalWrite(this->nTransmitterPin, LOW); + gpio_put(this->nTransmitterPin, LOW); + +#if not defined( RCSwitchDisableReceiving ) + // enable receiver again if we just disabled it + if (nReceiverInterrupt_backup != -1) { + this->enableReceive(nReceiverInterrupt_backup); + } +#endif +} + +/** + * Transmit a single high-low pulse. + */ +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); + gpio_put(this->nTransmitterPin, firstLogicLevel); + sleep_us(this->protocol.pulseLength * pulses.high); + gpio_put(this->nTransmitterPin, secondLogicLevel); + sleep_us(this->protocol.pulseLength * pulses.low); +} + + +#if not defined( RCSwitchDisableReceiving ) +/** + * Enable receiving data + */ +void RCSwitch::enableReceive(int interrupt) { + this->nReceiverInterrupt = interrupt; + this->enableReceive(); +} + +void RCSwitch::enableReceive() { + if (this->nReceiverInterrupt != -1) { + RCSwitch::nReceivedValue = 0; + RCSwitch::nReceivedBitlength = 0; + gpio_set_irq_enabled_with_callback(this->nReceiverInterrupt, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback); + // attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); + + + } +} + +/** + * Disable receiving data + */ +void RCSwitch::disableReceive() { +#if not defined(RaspberryPi) // Arduino + // detachInterrupt(this->nReceiverInterrupt); +#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR + this->nReceiverInterrupt = -1; +} + +bool RCSwitch::available() { + return RCSwitch::nReceivedValue != 0; +} + +void RCSwitch::resetAvailable() { + RCSwitch::nReceivedValue = 0; +} + +unsigned long RCSwitch::getReceivedValue() { + return RCSwitch::nReceivedValue; +} + +unsigned int RCSwitch::getReceivedBitlength() { + return RCSwitch::nReceivedBitlength; +} + +unsigned int RCSwitch::getReceivedDelay() { + return RCSwitch::nReceivedDelay; +} + +unsigned int RCSwitch::getReceivedProtocol() { + return RCSwitch::nReceivedProtocol; +} + +unsigned int* RCSwitch::getReceivedRawdata() { + return RCSwitch::timings; +} + +/* helper function for the receiveProtocol method */ +static inline unsigned int diff(int A, int B) { + return abs(A - B); +} + +/** + * + */ +bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) { +#if defined(ESP8266) || defined(ESP32) + const Protocol &pro = proto[p-1]; +#else + Protocol pro; + 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; + const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + + /* For protocols that start low, the sync period looks like + * _________ + * _____________| |XXXXXXXXXXXX| + * + * |--1st dur--|-2nd dur-|-Start data-| + * + * The 3rd saved duration starts the data. + * + * For protocols that start high, the sync period looks like + * + * ______________ + * | |____________|XXXXXXXXXXXXX| + * + * |-filtered out-|--1st dur--|--Start data--| + * + * The 2nd saved duration starts the data + */ + const unsigned int firstDataTiming = (pro.invertedSignal) ? (2) : (1); + + for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { + code <<= 1; + if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { + // zero + } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && + diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) { + // one + code |= 1; + } else { + // Failed + return false; + } + } + + if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = p; + return true; + } + + return false; +} + + + +void RECEIVE_ATTR RCSwitch::handleInterrupt() { + + static unsigned int changeCount = 0; + static unsigned long lastTime = 0; + static unsigned int repeatCount = 0; + + // const long time = micros(); + const long time = to_us_since_boot(get_absolute_time()); + const unsigned int duration = time - lastTime; + + if (duration > RCSwitch::nSeparationLimit) { + + // A long stretch without signal level change occurred. This could + // be the gap between two transmission. + if ((repeatCount==0) || (diff(duration, RCSwitch::timings[0]) < 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) { + for(unsigned int i = 1; i <= numProto; i++) { + if (receiveProtocol(i, changeCount)) { + // receive succeeded for protocol i + break; + } + } + repeatCount = 0; + } + } + changeCount = 0; + } + + // detect overflow + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + + RCSwitch::timings[changeCount++] = duration; + lastTime = time; +} +#endif diff --git a/433/rc-switch-pico/radio-switch.h b/433/rc-switch-pico/radio-switch.h new file mode 100644 index 0000000..24d72a1 --- /dev/null +++ b/433/rc-switch-pico/radio-switch.h @@ -0,0 +1,170 @@ +/* + RCSwitch - Arduino libary for remote control outlet switches + Copyright (c) 2011 Suat Özgür. All right reserved. + + Contributors: + - Andre Koehler / info(at)tomate-online(dot)de + - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com + - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46 + - Dominik Fischer / dom_fischer(at)web(dot)de + - Frank Oltmanns / .(at)gmail(dot)com + - Max Horn / max(at)quendi(dot)de + - Robert ter Vehn / .(at)gmail(dot)com + + Project home: https://github.com/sui77/rc-switch/ + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + 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, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef _RCSwitch_h +#define _RCSwitch_h + + +// #define RaspberryPi + +// Include libraries for RPi: +#include /* memcpy */ +#include /* abs */ + + + +#include + +// 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 + +class RCSwitch { + + public: + RCSwitch(); + + void switchOn(int nGroupNumber, int nSwitchNumber); + void switchOff(int nGroupNumber, int nSwitchNumber); + void switchOn(const char* sGroup, int nSwitchNumber); + void switchOff(const char* sGroup, int nSwitchNumber); + void switchOn(char sFamily, int nGroup, int nDevice); + void switchOff(char sFamily, int nGroup, int nDevice); + void switchOn(const char* sGroup, const char* sDevice); + void switchOff(const char* sGroup, const char* sDevice); + void switchOn(char sGroup, int nDevice); + void switchOff(char sGroup, int nDevice); + + void sendTriState(const char* sCodeWord); + void send(unsigned long code, unsigned int length); + void send(const char* sCodeWord); + + #if not defined( RCSwitchDisableReceiving ) + void enableReceive(int interrupt); + void enableReceive(); + void disableReceive(); + bool available(); + void resetAvailable(); + + unsigned long getReceivedValue(); + unsigned int getReceivedBitlength(); + unsigned int getReceivedDelay(); + unsigned int getReceivedProtocol(); + unsigned int* getReceivedRawdata(); + #endif + + void enableTransmit(int nTransmitterPin); + void disableTransmit(); + void setPulseLength(int nPulseLength); + void setRepeatTransmit(int nRepeatTransmit); + #if not defined( RCSwitchDisableReceiving ) + void setReceiveTolerance(int nPercent); + #endif + + /** + * Description of a single pule, which consists of a high signal + * whose duration is "high" times the base pulse length, followed + * by a low signal lasting "low" times the base pulse length. + * Thus, the pulse overall lasts (high+low)*pulseLength + */ + struct HighLow { + uint8_t high; + uint8_t low; + }; + + /** + * A "protocol" describes how zero and one bits are encoded into high/low + * pulses. + */ + struct Protocol { + /** base pulse length in microseconds, e.g. 350 */ + uint16_t pulseLength; + + HighLow syncFactor; + HighLow zero; + HighLow one; + + /** + * If true, interchange high and low logic levels in all transmissions. + * + * By default, RCSwitch assumes that any signals it sends or receives + * can be broken down into pulses which start with a high signal level, + * followed by a a low signal level. This is e.g. the case for the + * popular PT 2260 encoder chip, and thus many switches out there. + * + * But some devices do it the other way around, and start with a low + * signal level, followed by a high signal level, e.g. the HT6P20B. To + * accommodate this, one can set invertedSignal to true, which causes + * RCSwitch to change how it interprets any HighLow struct FOO: It will + * then assume transmissions start with a low signal lasting + * FOO.high*pulseLength microseconds, followed by a high signal lasting + * FOO.low*pulseLength microseconds. + */ + bool invertedSignal; + }; + + void setProtocol(Protocol protocol); + void setProtocol(int nProtocol); + void setProtocol(int nProtocol, int nPulseLength); + + private: + static void gpio_callback(unsigned int gpio, uint32_t events); + char* getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus); + char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus); + char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus); + char* getCodeWordD(char group, int nDevice, bool bStatus); + void transmit(HighLow pulses); + + #if not defined( RCSwitchDisableReceiving ) + static void handleInterrupt(); + static bool receiveProtocol(const int p, unsigned int changeCount); + int nReceiverInterrupt; + #endif + int nTransmitterPin; + int nRepeatTransmit; + + Protocol protocol; + + #if not defined( RCSwitchDisableReceiving ) + static int nReceiveTolerance; + volatile static unsigned long nReceivedValue; + volatile static unsigned int nReceivedBitlength; + volatile static unsigned int nReceivedDelay; + volatile static unsigned int nReceivedProtocol; + const static unsigned int nSeparationLimit; + /* + * timings[0] contains sync timing, followed by a number of bits + */ + static unsigned int timings[RCSWITCH_MAX_CHANGES]; + #endif + + +}; + +#endif diff --git a/433/rc-switch-pico/readme.md b/433/rc-switch-pico/readme.md new file mode 100644 index 0000000..d0170f3 --- /dev/null +++ b/433/rc-switch-pico/readme.md @@ -0,0 +1,23 @@ +# RcSwitch +A port of the brilliant [RC-Switch](https://github.com/sui77/rc-switch) library to the raspberry pi pico. + +It allows you to send and recieve radio signals from 433/315Mhz devices like radio controlled power sockets, using cheap radio modules. + +This works for both recieving and transmitting. Check out the examples for code for both of these. + +## Building +This library can be developed on any platform that the pico-sdk works on, through cmake. + +In the root directory, make sure that the pico-sdk is on your path and run +```bash +cmake . +``` + +then change directory into `examples/recieve`, then run +```bash +make +``` +which will spit out your uf2 file. + +## Issues +If you experience an error while using this library, please raise an issue here on Github and I'll try to help out. Pull requests are also very welcome! \ No newline at end of file diff --git a/circuits/Smart home.fzz b/circuits/Smart home.fzz index 92cae92..bd05998 100644 Binary files a/circuits/Smart home.fzz and b/circuits/Smart home.fzz differ