# HG changeset patch # User Michiel Broek # Date 1399216707 -7200 # Node ID f7f9463cdefde8c78e122f946522ad04bb5bf00b # Parent eaa03048c269def4e2c48c9d39ae2b40ac3ba65d Added 433 MHz transmitter and receiver library and demo programs diff -r eaa03048c269 -r f7f9463cdefd .hgignore --- a/.hgignore Sat May 03 23:21:00 2014 +0200 +++ b/.hgignore Sun May 04 17:18:27 2014 +0200 @@ -6,6 +6,9 @@ autom4te.cache .filelist thermometers/thermometers +rc433/recv +rc433/send +rc433/sniffer syntax: glob *.o diff -r eaa03048c269 -r f7f9463cdefd configure --- a/configure Sat May 03 23:21:00 2014 +0200 +++ b/configure Sun May 04 17:18:27 2014 +0200 @@ -2028,11 +2028,11 @@ ac_config_headers="$ac_config_headers config.h" -SUBDIRS="lib thermometers" +SUBDIRS="lib rc433 thermometers" PACKAGE="mbsePi-apps" -VERSION="0.0.2" +VERSION="0.0.3" COPYRIGHT="Copyright (C) 2014 Michiel Broek, All Rights Reserved" CYEARS="2014" diff -r eaa03048c269 -r f7f9463cdefd configure.ac --- a/configure.ac Sat May 03 23:21:00 2014 +0200 +++ b/configure.ac Sun May 04 17:18:27 2014 +0200 @@ -2,13 +2,13 @@ AC_INIT(thermometers/main.c) AM_CONFIG_HEADER(config.h) -SUBDIRS="lib thermometers" +SUBDIRS="lib rc433 thermometers" AC_SUBST(SUBDIRS) dnl General settings dnl After changeing the version number, run autoconf! PACKAGE="mbsePi-apps" -VERSION="0.0.2" +VERSION="0.0.3" COPYRIGHT="Copyright (C) 2014 Michiel Broek, All Rights Reserved" CYEARS="2014" AC_SUBST(PACKAGE) diff -r eaa03048c269 -r f7f9463cdefd lib/Makefile --- a/lib/Makefile Sat May 03 23:21:00 2014 +0200 +++ b/lib/Makefile Sun May 04 17:18:27 2014 +0200 @@ -2,8 +2,8 @@ include ../Makefile.global -SRCS = xutil.c rdconfig.c lcd-pcf8574.c -OBJS = xutil.o rdconfig.o lcd-pcf8574.o +SRCS = xutil.c rdconfig.c lcd-pcf8574.c rc-switch.c +OBJS = xutil.o rdconfig.o lcd-pcf8574.o rc-switch.o HDRS = mbselib.h TARGET = libmbse.a @@ -47,4 +47,5 @@ xutil.o: ../config.h mbselib.h rdconfig.o: ../config.h mbselib.h lcd-pcf8574.o: ../config.h mbselib.h +rc-switch.o: ../config.h mbselib.h # End of generated dependencies diff -r eaa03048c269 -r f7f9463cdefd lib/mbselib.h --- a/lib/mbselib.h Sat May 03 23:21:00 2014 +0200 +++ b/lib/mbselib.h Sun May 04 17:18:27 2014 +0200 @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -73,9 +74,9 @@ #ifdef HAVE_WIRINGPI_H + /* lcd-pcf8574.c */ // Defines for the pcf8574 Pi LCD interface board - #define AF_BASE 100 #define AF_RS (AF_BASE + 0) @@ -90,6 +91,62 @@ void setBacklight (int); int initLCD (int, int); + + +/* rc-switch.c */ +#define CHANGE 1 + +//typedef uint8_t boolean; +//typedef uint8_t byte; + +// 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 + +#define PROTOCOL3_SYNC_FACTOR 71 +#define PROTOCOL3_0_HIGH_CYCLES 4 +#define PROTOCOL3_0_LOW_CYCLES 11 +#define PROTOCOL3_1_HIGH_CYCLES 9 +#define PROTOCOL3_1_LOW_CYCLES 6 + + +void switchOn(int, int); +void switchOff(int, int); +/* +void switchOn(char* sGroup, int nSwitchNumber); +void switchOff(char* sGroup, int nSwitchNumber); +void switchOn(char sFamily, int nGroup, int nDevice); +void switchOff(char sFamily, int nGroup, int nDevice); +void switchOn(char* sGroup, char* sDevice); +void switchOff(char* sGroup, char* sDevice); +void switchOn(char sGroup, int nDevice); +void switchOff(char sGroup, int nDevice); +*/ +//void sendTriState(char* Code); +//void send(unsigned long Code, unsigned int length); +//void send(char* Code); + +void enableReceiveIRQ(int interrupt); +void enableReceive(void); +void disableReceive(void); +bool available(void); +void resetAvailable(void); + +unsigned long getReceivedValue(void); +unsigned int getReceivedBitlength(void); +unsigned int getReceivedDelay(void); +unsigned int getReceivedProtocol(void); +unsigned int *getReceivedRawdata(void); + +void enableTransmit(int); +void disableTransmit(void); +void setPulseLength(int); +void setRepeatTransmit(int); +void setReceiveTolerance(int); +void setProtocol(int); +//void setProtocol(int nProtocol, int nPulseLength); + + #endif diff -r eaa03048c269 -r f7f9463cdefd lib/rc-switch.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/rc-switch.c Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,923 @@ +/***************************************************************************** + * Copyright (C) 2014 + * + * Michiel Broek + * + * This file is part of the mbsePi-apps + * + * Based on the Arduino libary for remote control outlet switches. + * Project home: http://code.google.com/p/rc-switch/ + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * mbsePi-apps 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EC-65K; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "../config.h" +#include "mbselib.h" + +#ifdef HAVE_WIRINGPI_H + +unsigned long rcReceivedValue = 0; +unsigned int rcReceivedBitlength = 0; +unsigned int rcReceivedDelay = 0; +unsigned int rcReceivedProtocol = 0; +int rcReceiveTolerance = 60; +int rcReceiverInterrupt = -1; + +unsigned int timings[RCSWITCH_MAX_CHANGES]; +int rcTransmitterPin = -1; +int rcPulseLength = 350; +int rcRepeatTransmit = 10; +int rcProtocol = 1; + + +char *getCodeWordA(char*, char*, bool); +char *getCodeWordB(int, int, bool); +char *getCodeWordC(char, int, int, bool); +char *getCodeWordD(char, int, bool); +void sendTriState(char*); +void transmit(int, int); +void send0(void); +void send1(void); +void sendT0(void); +void sendT1(void); +void sendTF(void); +void sendSync(void); +bool receiveProtocol1(unsigned int); +bool receiveProtocol2(unsigned int); +bool receiveProtocol3(unsigned int); +void handleInterrupt(void); +char *dec2binWzerofill(unsigned long, unsigned int); +char *dec2binWcharfill(unsigned long, unsigned int, char); + + + + +/* + * Sets the protocol to send. + */ +void setProtocol(int nProtocol) { + rcProtocol = nProtocol; + if (nProtocol == 1){ + setPulseLength(350); + } + else if (nProtocol == 2) { + setPulseLength(650); + } + else if (nProtocol == 3) { + setPulseLength(100); + } +} + + + +/** + * Sets the protocol to send with pulse length in microseconds. + */ +/*void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { + this->nProtocol = nProtocol; + this->setPulseLength(nPulseLength); +}*/ + + + +/* + * Sets pulse length in microseconds + */ +void setPulseLength(int nPulseLength) { + rcPulseLength = nPulseLength; +} + + + +/* + * Sets Repeat Transmits + */ +void setRepeatTransmit(int nRepeatTransmit) { + rcRepeatTransmit = nRepeatTransmit; +} + + + +/* + * Set Receiving Tolerance + */ +void setReceiveTolerance(int nPercent) { + rcReceiveTolerance = nPercent; +} + + +/* + * Enable transmissions + * + * @param nTransmitterPin Pin to which the sender is connected to + */ +void enableTransmit(int nTransmitterPin) { + rcTransmitterPin = nTransmitterPin; + pinMode(rcTransmitterPin, OUTPUT); +} + + + +/* + * Disable transmissions + */ +void disableTransmit(void) { + rcTransmitterPin = -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 switchOn(int nAddressCode, int nChannelCode) { + sendTriState( 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 switchOff(int nAddressCode, int nChannelCode) { + sendTriState( getCodeWordB(nAddressCode, nChannelCode, false) ); +} + + + +/** + * Deprecated, use switchOn(char* sGroup, 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(char* sGroup, int nChannel) { + char* code[6] = { (char *)"00000", (char *)"10000", (char *)"01000", (char *)"00100", (char *)"00010", (char *)"00001" }; + this->switchOn(sGroup, code[nChannel]); +}*/ + +/** + * Deprecated, use switchOff(char* sGroup, 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(char* sGroup, int nChannel) { + char* code[6] = { (char *)"00000", (char *)"10000", (char *)"01000", (char *)"00100", (char *)"00010", (char *)"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(char* sGroup, 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(char* sGroup, char* sDevice) { + this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); +}*/ + + + +/* + * Returns a char[13], representing the Code Word to be send. + * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used. + * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit) + * + * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ + * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit | + * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S | + * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ + * + * @param nAddressCode Number of the switch group (1..4) + * @param nChannelCode Number of the switch itself (1..4) + * @param bStatus Wether to switch on (true) or off (false) + * + * @return char[13] + */ +char *getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) +{ + int i, nReturnPos = 0; + static char sReturn[13]; + + char* code[5] = { (char *)"FFFF", (char *)"0FFF", (char *)"F0FF", (char *)"FF0F", (char *)"FFF0" }; + if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { + return '\0'; + } + for (i = 0; i<4; i++) { + sReturn[nReturnPos++] = code[nAddressCode][i]; + } + + for (i = 0; i<4; i++) { + sReturn[nReturnPos++] = code[nChannelCode][i]; + } + + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + if (bStatus) { + sReturn[nReturnPos++] = 'F'; + } else { + sReturn[nReturnPos++] = '0'; + } + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + + + +/* + * Returns a char[13], representing the Code Word to be send. + * + * getCodeWordA(char*, char*) + * + */ +char *getCodeWordA(char* sGroup, char* sDevice, bool bOn) +{ + static char sDipSwitches[13]; + int i = 0; + int j = 0; + + for (i=0; i < 5; i++) { + if (sGroup[i] == '0') { + sDipSwitches[j++] = 'F'; + } else { + sDipSwitches[j++] = '0'; + } + } + + for (i=0; i < 5; i++) { + if (sDevice[i] == '0') { + sDipSwitches[j++] = 'F'; + } else { + sDipSwitches[j++] = '0'; + } + } + + if ( bOn ) { + sDipSwitches[j++] = '0'; + sDipSwitches[j++] = 'F'; + } else { + sDipSwitches[j++] = 'F'; + sDipSwitches[j++] = '0'; + } + + sDipSwitches[j] = '\0'; + return sDipSwitches; +} + + + +/* + * Like getCodeWord (Type C = Intertechno) + */ +char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) +{ + static char sReturn[13]; + int i, nReturnPos = 0; + + if ( (uint8_t)sFamily < 97 || (uint8_t)sFamily > 112 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { + return '\0'; + } + + char* sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 ); + char familycode[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" }; + for (i = 0; i<4; i++) { + sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i]; + } + for (i = 0; i<4; i++) { + sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0'); + } + + sReturn[nReturnPos++] = '0'; + sReturn[nReturnPos++] = 'F'; + sReturn[nReturnPos++] = 'F'; + + if (bStatus) { + sReturn[nReturnPos++] = 'F'; + } else { + sReturn[nReturnPos++] = '0'; + } + + sReturn[nReturnPos] = '\0'; + return sReturn; +} + + + +/* + * Decoding for the REV Switch Type + * + * Returns a char[13], representing the Tristate to be send. + * A Code Word consists of 7 address bits and 5 command data bits. + * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high) + * + * +-------------------------------+--------------------------------+-----------------------+ + * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) | + * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 | + * +-------------------------------+--------------------------------+-----------------------+ + * + * 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 Wether to switch on (true) or off (false) + * + * @return char[13] + */ +char *getCodeWordD(char sGroup, int nDevice, bool bStatus){ + static char sReturn[13]; + int i, nReturnPos = 0; + + // Building 4 bits address + // (Potential problem if dec2binWcharfill not returning correct string) + char *sGroupCode; + switch(sGroup){ + case 'a': + case 'A': + sGroupCode = dec2binWcharfill(8, 4, 'F'); break; + case 'b': + case 'B': + sGroupCode = dec2binWcharfill(4, 4, 'F'); break; + case 'c': + case 'C': + sGroupCode = dec2binWcharfill(2, 4, 'F'); break; + case 'd': + case 'D': + sGroupCode = dec2binWcharfill(1, 4, 'F'); break; + default: + return '\0'; + } + + for (i = 0; i<4; i++) { + sReturn[nReturnPos++] = sGroupCode[i]; + } + + + // Building 3 bits address + // (Potential problem if dec2binWcharfill not returning correct string) + char *sDevice; + switch(nDevice) { + case 1: + sDevice = dec2binWcharfill(4, 3, 'F'); break; + case 2: + sDevice = dec2binWcharfill(2, 3, 'F'); break; + case 3: + sDevice = dec2binWcharfill(1, 3, 'F'); break; + default: + return '\0'; + } + + for (i = 0; i<3; i++) + sReturn[nReturnPos++] = sDevice[i]; + + // fill up rest with zeros + for (i = 0; i<5; i++) + sReturn[nReturnPos++] = '0'; + + // encode on or off + if (bStatus) + sReturn[10] = '1'; + else + sReturn[11] = '1'; + + // last position terminate string + sReturn[12] = '\0'; + return sReturn; + +} + + + +/* + * @param sCodeWord /^[10FS]*$/ -> see getCodeWord + */ +void sendTriState(char* sCodeWord) { + int nRepeat; + + for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) { + int i = 0; + while (sCodeWord[i] != '\0') { + switch(sCodeWord[i]) { + case '0': + sendT0(); + break; + case 'F': + sendTF(); + break; + case '1': + sendT1(); + break; + } + i++; + } + sendSync(); + } +} + + + +/* +void RCSwitch::send(unsigned long Code, unsigned int length) { + this->send( this->dec2binWzerofill(Code, length) ); +} + +void RCSwitch::send(char* sCodeWord) { + for (int nRepeat=0; nRepeatsend0(); + break; + case '1': + this->send1(); + break; + } + i++; + } + this->sendSync(); + } +} +*/ + + +void transmit(int nHighPulses, int nLowPulses) +{ + bool disabled_Receive = false; + int nReceiverInterrupt_backup = rcReceiverInterrupt; + + if (rcTransmitterPin != -1) { + if (rcReceiverInterrupt != -1) { + disableReceive(); + disabled_Receive = true; + } + digitalWrite(rcTransmitterPin, HIGH); + delayMicroseconds( rcPulseLength * nHighPulses); + digitalWrite(rcTransmitterPin, LOW); + delayMicroseconds( rcPulseLength * nLowPulses); + + if (disabled_Receive) { + enableReceiveIRQ(nReceiverInterrupt_backup); + } + } +} + + + +/* + * Sends a "0" Bit + * _ + * Waveform Protocol 1: | |___ + * _ + * Waveform Protocol 2: | |__ + * ____ + * Waveform Protocol 3: | |___________ + */ +void send0(void) { + if (rcProtocol == 1){ + transmit(1,3); + } + else if (rcProtocol == 2) { + transmit(1,2); + } + else if (rcProtocol == 3) { + transmit(4,11); + } +} + + + +/* + * Sends a "1" Bit + * ___ + * Waveform Protocol 1: | |_ + * __ + * Waveform Protocol 2: | |_ + * _________ + * Waveform Protocol 3: | |______ + */ +void send1(void) { + if (rcProtocol == 1){ + transmit(3,1); + } + else if (rcProtocol == 2) { + transmit(2,1); + } + else if (rcProtocol == 3) { + transmit(9,6); + } +} + + + +/* + * Sends a Tri-State "0" Bit + * _ _ + * Waveform: | |___| |___ + */ +void sendT0(void) { + transmit(1,3); + transmit(1,3); +} + + + +/* + * Sends a Tri-State "1" Bit + * ___ ___ + * Waveform: | |_| |_ + */ +void sendT1(void) { + transmit(3,1); + transmit(3,1); +} + + + +/* + * Sends a Tri-State "F" Bit + * _ ___ + * Waveform: | |___| |_ + */ +void sendTF(void) { + transmit(1,3); + transmit(3,1); +} + + + +/* + * Sends a "Sync" Bit + * _ + * Waveform Protocol 1: | |_______________________________ + * _ + * Waveform Protocol 2: | |__________ + * _ + * Waveform Protocol 3: | |_______________________________________________________________________ + */ +void sendSync(void) { + + if (rcProtocol == 1){ + transmit(1,31); + } + else if (rcProtocol == 2) { + transmit(1,10); + } + else if (rcProtocol == 3) { + transmit(1,71); + } +} + + + +/* + * Enable receiving data + */ +void enableReceiveIRQ(int interrupt) { + rcReceiverInterrupt = interrupt; + enableReceive(); +} + +void enableReceive(void) { + if (rcReceiverInterrupt != -1) { + rcReceivedValue = 0; + rcReceivedBitlength = 0; + wiringPiISR(rcReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); + } +} + + + +/* + * Disable receiving data + */ +void disableReceive() { + // wiringPi disable interrupts ??? + rcReceiverInterrupt = -1; +} + + + +bool available(void) { + return rcReceivedValue != 0; +} + + + +void resetAvailable(void) { + rcReceivedValue = 0; +} + + + +unsigned long getReceivedValue(void) { + return rcReceivedValue; +} + + + +unsigned int getReceivedBitlength(void) { + return rcReceivedBitlength; +} + + + +unsigned int getReceivedDelay(void) { + return rcReceivedDelay; +} + + + +unsigned int getReceivedProtocol(void) { + return rcReceivedProtocol; +} + + + +unsigned int* getReceivedRawdata(void) { + return timings; +} + + + +/* + * ASK protool 1 + */ +bool receiveProtocol1(unsigned int changeCount) +{ + unsigned long code = 0; + unsigned long ldelay = timings[0] / 31; + unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; + int i; + + for (i = 1; i ldelay-delayTolerance && + timings[i] < ldelay+delayTolerance && + timings[i+1] > ldelay*3-delayTolerance && + timings[i+1] < ldelay*3+delayTolerance) { + code = code << 1; + } else if (timings[i] > ldelay*3-delayTolerance && + timings[i] < ldelay*3+delayTolerance && + timings[i+1] > ldelay-delayTolerance && + timings[i+1] < ldelay+delayTolerance) { + code+=1; + code = code << 1; + } else { + // Failed + i = changeCount; + code = 0; + } + } + code = code >> 1; + if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise + rcReceivedValue = code; + rcReceivedBitlength = changeCount / 2; + rcReceivedDelay = ldelay; + rcReceivedProtocol = 1; + } + + if (code == 0) { + return false; + } + return true; +} + + + +bool receiveProtocol2(unsigned int changeCount) +{ + unsigned long code = 0; + unsigned long ldelay = timings[0] / 10; + unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; + int i; + + for (i = 1; i ldelay-delayTolerance && + timings[i] < ldelay+delayTolerance && + timings[i+1] > ldelay*2-delayTolerance && + timings[i+1] < ldelay*2+delayTolerance) { + code = code << 1; + } else if (timings[i] > ldelay*2-delayTolerance && + timings[i] < ldelay*2+delayTolerance && + timings[i+1] > ldelay-delayTolerance && + timings[i+1] < ldelay+delayTolerance) { + code+=1; + code = code << 1; + } else { + // Failed + i = changeCount; + code = 0; + } + } + code = code >> 1; + + if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise + rcReceivedValue = code; + rcReceivedBitlength = changeCount / 2; + rcReceivedDelay = ldelay; + rcReceivedProtocol = 2; + } + + if (code == 0) { + return false; + } + return true; +} + + + +/* + * Protocol 3 is used by BL35P02. + */ +bool receiveProtocol3(unsigned int changeCount) +{ + unsigned long code = 0; + unsigned long ldelay = timings[0] / PROTOCOL3_SYNC_FACTOR; + unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; + int i; + + for (i = 1; i ldelay*PROTOCOL3_0_HIGH_CYCLES - delayTolerance && + timings[i] < ldelay*PROTOCOL3_0_HIGH_CYCLES + delayTolerance && + timings[i+1] > ldelay*PROTOCOL3_0_LOW_CYCLES - delayTolerance && + timings[i+1] < ldelay*PROTOCOL3_0_LOW_CYCLES + delayTolerance) { + code = code << 1; + } else if (timings[i] > ldelay*PROTOCOL3_1_HIGH_CYCLES - delayTolerance && + timings[i] < ldelay*PROTOCOL3_1_HIGH_CYCLES + delayTolerance && + timings[i+1] > ldelay*PROTOCOL3_1_LOW_CYCLES - delayTolerance && + timings[i+1] < ldelay*PROTOCOL3_1_LOW_CYCLES + delayTolerance) { + code+=1; + code = code << 1; + } else { + // Failed + i = changeCount; + code = 0; + } + } + code = code >> 1; + if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise + rcReceivedValue = code; + rcReceivedBitlength = changeCount / 2; + rcReceivedDelay = ldelay; + rcReceivedProtocol = 3; + } + + if (code == 0) { + return false; + } + return true; +} + + + +void handleInterrupt() { + + static unsigned int duration; + static unsigned int changeCount; + static unsigned long lastTime; + static unsigned int repeatCount; + + + long time = micros(); + duration = time - lastTime; + + if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) { + repeatCount++; + changeCount--; + if (repeatCount == 2) { + if (receiveProtocol1(changeCount) == false){ + if (receiveProtocol2(changeCount) == false){ + if (receiveProtocol3(changeCount) == false){ + //failed + } + } + } + repeatCount = 0; + } + changeCount = 0; + } else if (duration > 5000) { + changeCount = 0; + } + + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; + } + timings[changeCount++] = duration; + lastTime = time; +} + + + +/* + * Turns a decimal value to its binary representation + */ +char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength) +{ + return dec2binWcharfill(Dec, bitLength, '0'); +} + +char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill) +{ + static char bin[64]; + unsigned int i = 0, j; + + while (Dec > 0) { + bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill; + Dec = Dec >> 1; + } + + for (j = 0; j< bitLength; j++) { + if (j >= bitLength - i) { + bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; + } else { + bin[j] = fill; + } + } + bin[bitLength] = '\0'; + + return bin; +} + + +#endif + diff -r eaa03048c269 -r f7f9463cdefd rc433/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/Makefile Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,65 @@ +# Makefile for the mbsePi-apps/thermometers. + +include ../Makefile.global + +SRCS = recv.c send.c sniffer.c +HDRS = recv.h send.h sniffer.h +OBJS = recv.o send.o sniffer.o +SLIBS = ../lib/libmbse.a +TARGET = recv send sniffer +OTHER = Makefile + +############################################################################# + +.c.o: + ${CC} ${CFLAGS} ${INCLUDES} ${DEFINES} -c $< + +all: ${TARGET} + +recv: recv.o ${SLIBS} + ${CC} -o recv recv.o ${LDFLAGS} ${LIBS} ${SLIBS} + +send: send.o ${SLIBS} + ${CC} -o send send.o ${LDFLAGS} ${LIBS} ${SLIBS} + +sniffer: sniffer.o ${SLIBS} + ${CC} -o sniffer sniffer.o ${LDFLAGS} ${LIBS} ${SLIBS} +clean: + rm -f ${TARGET} *.o *.h~ *.c~ core filelist Makefile.bak + +install: all + ${INSTALL} -c -s -g root -o root -m 0755 ${TARGET} ${BINDIR} + +filelist: Makefile + BASE=`pwd`; \ + BASE=`basename $${BASE}`; \ + (for f in ${SRCS} ${HDRS} ${OTHER} ;do echo ${PACKAGE}-${VERSION}/$${BASE}/$$f; done) >filelist + +depend: + @rm -f Makefile.bak; \ + mv Makefile Makefile.bak; \ + sed -e '/^# DO NOT DELETE/,$$d' Makefile.bak >Makefile; \ + ${ECHO} '# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT' \ + >>Makefile; \ + ${ECHO} '# Dependencies generated by make depend' >>Makefile; \ + for f in ${SRCS}; \ + do \ + ${ECHO} "Dependencies for $$f:\c"; \ + ${ECHO} "`basename $$f .c`.o:\c" >>Makefile; \ + for h in `sed -n -e \ + 's/^#[ ]*include[ ]*"\([^"]*\)".*/\1/p' $$f`; \ + do \ + ${ECHO} " $$h\c"; \ + ${ECHO} " $$h\c" >>Makefile; \ + done; \ + ${ECHO} " done."; \ + ${ECHO} "" >>Makefile; \ + done; \ + ${ECHO} '# End of generated dependencies' >>Makefile + +# DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT +# Dependencies generated by make depend +recv.o: ../lib/mbselib.h recv.h +send.o: ../lib/mbselib.h send.h +sniffer.o: ../lib/mbselib.h sniffer.h +# End of generated dependencies diff -r eaa03048c269 -r f7f9463cdefd rc433/recv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/recv.c Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (C) 2014 + * + * Michiel Broek + * + * This file is part of the mbsePi-apps + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * mbsePi-apps 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EC-65K; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "../lib/mbselib.h" +#include "recv.h" + + +int main(int argc, char *argv[]) { + + /* + input 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 = 2; + + if (wiringPiSetup () ) + return 1; + + enableReceiveIRQ(PIN); + + while (1) { + if (available()) { + + int value = getReceivedValue(); + + if (value == 0) { + printf("Unknown encoding\n"); + } else { + printf("Received %ld/%d bit Protocol: %d\n", getReceivedValue(), getReceivedBitlength(), getReceivedProtocol() ); + } + + resetAvailable(); + } else { + /* + * Don't hog the CPU. + */ + delay(10); + } + } + + return 0; +} + diff -r eaa03048c269 -r f7f9463cdefd rc433/recv.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/recv.h Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,9 @@ +#ifndef _RECV_H +#define _RECV_H + + +#define TRUE 1 +#define FALSE 0 + + +#endif diff -r eaa03048c269 -r f7f9463cdefd rc433/send.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/send.c Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,58 @@ +/***************************************************************************** + * Copyright (C) 2014 + * + * Michiel Broek + * + * This file is part of the mbsePi-apps + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * mbsePi-apps 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EC-65K; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "../lib/mbselib.h" +#include "send.h" + + +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 = 0; + int systemCode = atoi(argv[1]); + int unitCode = atoi(argv[2]); + int command = atoi(argv[3]); + + if (wiringPiSetup () ) + return 1; + + printf("sending systemCode[%d] unitCode[%i] command[%i]\n", systemCode, unitCode, command); + enableTransmit(PIN); + + switch(command) { + case 1: + switchOn(systemCode, unitCode); + break; + case 0: + switchOff(systemCode, unitCode); + break; + default: + printf("command[%i] is unsupported\n", command); + return -1; + } + + return 0; +} diff -r eaa03048c269 -r f7f9463cdefd rc433/send.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/send.h Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,9 @@ +#ifndef _SEND_H +#define _SEND_H + + +#define TRUE 1 +#define FALSE 0 + + +#endif diff -r eaa03048c269 -r f7f9463cdefd rc433/sniffer.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/sniffer.c Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,61 @@ +/***************************************************************************** + * Copyright (C) 2014 + * + * Michiel Broek + * + * This file is part of the mbsePi-apps + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * mbsePi-apps 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with EC-65K; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "../lib/mbselib.h" +#include "sniffer.h" + + +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 = 2; + + if (wiringPiSetup() == -1) + return 0; + + enableReceiveIRQ(PIN); // Receiver on inerrupt 0 => that is pin #2 + + while(1) { + + if (available()) { + unsigned long value = getReceivedValue(); + + if (value == 0) { + printf("Unknown encoding\n"); + } else { + printf("Protocol %d received 0x%lx\n", getReceivedProtocol(), value); + } + resetAvailable(); + + } else { + /* + * Don't hog the CPU + */ + delay(10); + } + } + + exit(0); +} + diff -r eaa03048c269 -r f7f9463cdefd rc433/sniffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rc433/sniffer.h Sun May 04 17:18:27 2014 +0200 @@ -0,0 +1,9 @@ +#ifndef _SNIFFER_H +#define _SNIFFER_H + + +#define TRUE 1 +#define FALSE 0 + + +#endif