Hey All,
I've developed an interrupt-driven serial receive function. It works great as a single file but I can't implement it as a class. I'm testing it against an EM-406A GPS sending NMEA sentences at 4800 baud.
This is the working single-file sketch
#define BUFFER_LENGTH 100
#define BAUD 4800
int symbolPeriod = 1000000/BAUD; //micro-seconds
int lockPeriod = 10 * symbolPeriod;
volatile boolean bufferOverrun = false;
volatile char buffer[BUFFER_LENGTH];
volatile int bufferWrite = 0;
int bufferRead = 0;
volatile boolean lock = false;
volatile int flag = 0;
int byteCount = 0;
void setup()
{
Serial.begin(115200);
Serial.println("setup()");
attachInterrupt(1, spike, CHANGE);
}
boolean availableBuffer()
{
return !(bufferRead == bufferWrite);
}
byte readBuffer()
{
if(availableBuffer)
{
byte out = buffer[bufferRead];
bufferRead++;
bufferRead %= BUFFER_LENGTH;
return out;
}
}
void writeBuffer(byte& in)
{
buffer[bufferWrite] = in;
if(bufferWrite == bufferRead) bufferOverrun = true;
bufferWrite++;
bufferWrite %= BUFFER_LENGTH;
}
void loop()
{
while(availableBuffer()) Serial.print(readBuffer());
}
boolean bufferAvailable()
{
return bufferRead < bufferWrite;
}
void spike()
{
static boolean polarity = HIGH;
static unsigned long tick;
static unsigned long tock;
static unsigned long gap;
static unsigned long ulMax = -1;
static int symbols = 0; // number of bits in timing window
static int offset = -2; // bit position in output byte
static int count = 0; // general loop counter
static byte character; // output byte
tock = tick;
tick = micros();
if(tick > tock)
gap = tick - tock;
else
gap = tick + ulMax - tock; // Prevents one-in-70-minute loss of lock. See: http://arduino.cc/en/Reference/Micros
if(gap > lockPeriod)
{
polarity = HIGH;
lock = true; //indicate start of data found...
return; // ... but dump the first "gap" anyway.
}
if(!lock) return; //ignore incoming data until locked. Waits for "start" of pulse train.
polarity = !polarity;
symbols = (gap + 8) / symbolPeriod; // 8 being twice the maximum resolution on micros() function
for(count = 0; count < symbols; count++)
{
if(offset > 7) // ran out of data bits, into wait bits
{
if(!polarity) lock = false; // some kind of data/timing error occurred. Expected polarity HIGH wait bits, got LOW.
offset = -2; // restart bit positions in output byte
writeBuffer(character);
character = 0; // reset output byte
return; // drop remaining bits
}
offset++;
if(offset < 0) continue; // drop start bit
character |= polarity << offset;
}
}
The problem comes when I try to move the code out to a class. So far I'm just testing the attachInterrup part and can't get it to work. The error I'm getting at the moment is:
In constructor 'ISRSerialRX::ISRSerialRX()':
error: argument of type 'void (ISRSerialRX::)()' does not match 'void (*)()
Here's the main sketch for the "class version" of my code
#include "ISRSerialRX.h"
ISRSerialRX gps;
void setup()
{
Serial.begin(115200);
Serial.println("Setup()");
}
void loop()
{
}
Header File:
#ifndef ISRSerialRX_h
#define ISRSerialRX_h
#include "WProgram.h"
class ISRSerialRX
{
public:
ISRSerialRX();
void spike(); //ISR
private:
};
#endif
Implementation File:
#include "ISRSerialRX.h"
ISRSerialRX::ISRSerialRX()
{
attachInterrupt(1, spike, CHANGE);
}
void ISRSerialRX::spike()
{
static unsigned long count = 0;
count++;
if(count % 1000 == 0) Serial.println(count);
}
What do you think? Do I have a syntax issue or am I trying to do something attachInterrupt() is not designed for?
Thanks in advance. Sorry for the long post; I see "where's the code" all the time - so here it all is!