Added 433 MHz transmitter and receiver library and demo programs

Sun, 04 May 2014 17:18:27 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 04 May 2014 17:18:27 +0200
changeset 20
f7f9463cdefd
parent 19
eaa03048c269
child 21
ff107bf4d216

Added 433 MHz transmitter and receiver library and demo programs

.hgignore file | annotate | diff | comparison | revisions
configure file | annotate | diff | comparison | revisions
configure.ac file | annotate | diff | comparison | revisions
lib/Makefile file | annotate | diff | comparison | revisions
lib/mbselib.h file | annotate | diff | comparison | revisions
lib/rc-switch.c file | annotate | diff | comparison | revisions
rc433/Makefile file | annotate | diff | comparison | revisions
rc433/recv.c file | annotate | diff | comparison | revisions
rc433/recv.h file | annotate | diff | comparison | revisions
rc433/send.c file | annotate | diff | comparison | revisions
rc433/send.h file | annotate | diff | comparison | revisions
rc433/sniffer.c file | annotate | diff | comparison | revisions
rc433/sniffer.h file | annotate | diff | comparison | revisions
--- 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
--- 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"
 
--- 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)
--- 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
--- 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 <stdlib.h>
 #include <stdio.h>
+#include <stdint.h>
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
@@ -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
 
 
--- /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 <mbroek at mbse dot eu>
+ *
+ * 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; nRepeat<nRepeatTransmit; nRepeat++) {
+    int i = 0;
+    while (sCodeWord[i] != '\0') {
+      switch(sCodeWord[i]) {
+        case '0':
+          this->send0();
+        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<changeCount ; i=i+2) {
+      
+	if (timings[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<changeCount ; i=i+2) {
+	if (timings[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<changeCount ; i=i+2) {
+      
+	if (timings[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
+
--- /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
--- /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 <mbroek at mbse dot eu>
+ *
+ * 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;
+}
+
--- /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
--- /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 <mbroek at mbse dot eu>
+ *
+ * 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;
+}
--- /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
--- /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 <mbroek at mbse dot eu>
+ *
+ * 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);
+}
+
--- /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

mercurial