/* * 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 (durationmax1Period) { _state=-1; return; } } else { //Waiting for sync bit part 2 //Must be 31 periods. if (durationperiod*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; }