/*
|
|
* RemoteSwitch library v2.0.0 made by Randy Simons http://randysimons.nl
|
|
* See RemoteSwitchSender.h for details.
|
|
*
|
|
* License: "Free BSD license". See license.txt
|
|
*/
|
|
|
|
#include "RemoteReceiver.h"
|
|
|
|
|
|
/************
|
|
* RemoteReceiver
|
|
************/
|
|
|
|
unsigned short RemoteReceiver::_interrupt;
|
|
volatile int RemoteReceiver::_state;
|
|
unsigned short RemoteReceiver::_minRepeats;
|
|
RemoteReceiverCallBack RemoteReceiver::_callback;
|
|
boolean RemoteReceiver::_inCallback = false;
|
|
|
|
void RemoteReceiver::init(unsigned short interrupt, unsigned short minRepeats, RemoteReceiverCallBack callback) {
|
|
_interrupt = interrupt;
|
|
_minRepeats = minRepeats;
|
|
_callback = callback;
|
|
|
|
//enable();
|
|
}
|
|
|
|
void RemoteReceiver::enable() {
|
|
_state = -1;
|
|
attachInterrupt(_interrupt, interruptHandler, CHANGE);
|
|
}
|
|
|
|
void RemoteReceiver::disable() {
|
|
detachInterrupt(_interrupt);
|
|
}
|
|
|
|
|
|
void RemoteReceiver::interruptHandler() {
|
|
static unsigned int period; //Calculated duration of 1 period
|
|
static unsigned short receivedBit; //Contains "bit" currently receiving
|
|
static unsigned long receivedCode; //Contains received code
|
|
static unsigned long previousCode; //Contains previous received code
|
|
static unsigned short repeats = 0; //The number of times the an identical code is received in a row.
|
|
static unsigned long lastChange=0; //Timestamp of previous edge
|
|
static unsigned int min1Period, max1Period, min3Period, max3Period;
|
|
|
|
unsigned long currentTime=micros();
|
|
unsigned int duration=currentTime-lastChange; //Duration = Time between edges
|
|
lastChange=currentTime;
|
|
|
|
|
|
if (_state==-1) { //Waiting for sync-signal
|
|
if (duration>3720) { //==31*120 minimal time between two edges before decoding starts.
|
|
//Sync signal received.. Preparing for decoding
|
|
period=duration/31;
|
|
receivedCode=previousCode=repeats=0;
|
|
|
|
//Allow for large error-margin. ElCheapo-hardware :(
|
|
min1Period=period*4/10; //Avoid floating point math; saves memory.
|
|
max1Period=period*16/10;
|
|
min3Period=period*23/10;
|
|
max3Period=period*37/10;
|
|
}
|
|
else {
|
|
return;
|
|
}
|
|
} else if (_state<48) { //Decoding message
|
|
//bit part durations can ONLY be 1 or 3 periods.
|
|
if (duration>=min1Period && duration<=max1Period) {
|
|
bitClear(receivedBit,_state%4); //Note: this sets the bits in reversed order! Correct order would be: 3-(_state%4), but that's overhead we don't want.
|
|
}
|
|
else if (duration>=min3Period && duration<=max3Period) {
|
|
bitSet(receivedBit,_state%4); //Note: this sets the bits in reversed order!
|
|
}
|
|
else { //Otherwise the entire sequence is invalid
|
|
_state=-1;
|
|
return;
|
|
}
|
|
|
|
if ((_state%4)==3) { //Last bit part?
|
|
//Shift
|
|
receivedCode*=3;
|
|
//Decode bit.
|
|
if (receivedBit==B1010) { //short long short long == B0101, but bits are set in reversed order, so compare to B1010
|
|
//bit "0" received
|
|
receivedCode+=0; //I hope the optimizer handles this ;)
|
|
}
|
|
else if (receivedBit==B0101) { //long short long short == B101, but bits are set in reversed order, so compare to B0101
|
|
//bit "1" received
|
|
receivedCode+=1;
|
|
}
|
|
else if (receivedBit==B0110) { //short long long short. Reversed too, but makes no difference.
|
|
//bit "f" received
|
|
receivedCode+=2;
|
|
}
|
|
else {
|
|
//Bit was rubbish. Abort.
|
|
_state=-1;
|
|
return;
|
|
}
|
|
}
|
|
} else if (_state==48) { //Waiting for sync bit part 1
|
|
//Must be 1 period.
|
|
if (duration<min1Period || duration>max1Period) {
|
|
_state=-1;
|
|
return;
|
|
}
|
|
} else { //Waiting for sync bit part 2
|
|
//Must be 31 periods.
|
|
if (duration<period*25 || duration>period*36) {
|
|
_state=-1;
|
|
return;
|
|
}
|
|
|
|
//receivedCode is a valid code!
|
|
|
|
if (receivedCode!=previousCode) {
|
|
repeats=0;
|
|
previousCode=receivedCode;
|
|
}
|
|
|
|
repeats++;
|
|
|
|
if (repeats>=_minRepeats) {
|
|
if (!_inCallback) {
|
|
_inCallback = true;
|
|
(_callback)(receivedCode, period);
|
|
_inCallback = false;
|
|
}
|
|
//Reset after callback.
|
|
_state=-1;
|
|
return;
|
|
}
|
|
|
|
//Reset for next round
|
|
receivedCode = 0;
|
|
_state=0; //no need to wait for another sync-bit!
|
|
return;
|
|
}
|
|
|
|
_state++;
|
|
return;
|
|
}
|
|
|
|
boolean RemoteReceiver::isReceiving(int waitMillis) {
|
|
unsigned long startTime=millis();
|
|
|
|
int waited; //signed int!
|
|
do {
|
|
if (_state!=-1) {
|
|
return true;
|
|
}
|
|
waited = (millis()-startTime);
|
|
} while(waited>=0 && waited <= waitMillis); //Yes, clock wraps every 50 days. And then you'd have to wait for a looooong time.
|
|
|
|
return false;
|
|
}
|