Hi everyone....I have a sketch that does exactly what I need it to on the Uno....but it wont compile properly for the Due.
"TIMSK1 not declared in this scope".
Ive done some searching and reading on this and understand that its because the timers/interrupts work a lot differently on the 8-bit AVR's vs the 32-bit ARM.
My question is...how would I/what would be the best way to "convert/translate" this sketch into something equivalent that will work on the Due??
The sketch is to read/interpret the J1850-VPW automotive databus protocol, and then print it to the serial terminal as decoded 8-byte hex messages from the J1850 bus.
===========================================================================
Quick background: the J1850 VPW bus uses a series of alternating high/low pulses on a single wire of either 64uS or 128uS to signify a "1" bit or "0" bit. A 200uS "high" pulse is first sent by the transmitting node denotes start of frame, to alert all nodes on the bus that a message is about to be sent out...
A "low" pulse of 128uS or a "high" pulse of 64uS signifies a "1" bit.
A "high" pulse of 128uS or a "low" pulse of 64uS signifies a "0" bit.
The entire message starts as a 200uS "high" pulse...then 3 bytes of header info, 8 bytes max data payload, a 1 byte CRC, and finally a 200uS "low" pulse to signify end of message transmission.
===========================================================================
// I/O and interrupts. Pin/Int
// UNO: 2/0, 3/1.
#define J1850_PIN 3
#define J1850_INT 1
// Timing for start of frame
#define SOF_TIME 200
#define SOF_DEV 18
// Timing for end of frame
#define EOF_TIME 200
#define EOF_DEV 18
// Timing for a long bit pulse
#define LONGBIT_TIME 128
#define LONGBIT_DEV 16
// Timing for short bit pulse
#define SHORTBIT_TIME 64
#define SHORTBIT_DEV 15
// timeout after 250 microsec
#define TMR_PRELOAD (65536 - (EOF_TIME*16))
#define TMROVF_INT_OFF TIMSK1 &= (~_BV(TOIE1))
#define TMROVF_INT_ON TIMSK1 |= _BV(TOIE1)
#define TMROVF_INT_CLR TIFR1 &= _BV(TOV1)
// forward decl
void j1850_interrupt(void);
volatile boolean idle = true;
// Storage, max 11 data bytes + CRC
#define BUFSIZE 13
volatile uint8_t msgbuf[BUFSIZE];
volatile uint8_t msgLen;
//
// Initialization
//
void setup(void)
{
pinMode(J1850_PIN, INPUT);
Serial.begin(115200);
delay(1000);
Serial.println(F("j1850decoder/v1.5"));
TMROVF_INT_OFF;
TCCR1A = 0;
TCNT1 = TMR_PRELOAD; // preload timer 65536-16MHz/256/2Hz
TCCR1B = _BV(CS10); // no prescaler, start timer
idle = true;
msgLen = 0;
attachInterrupt(J1850_INT, j1850_interrupt, CHANGE);
interrupts();
}
//
// Background loop - print message when available
//
void loop(void)
{
if (msgLen > 0) {
Serial.print(F("> "));
for (int i = 0; i < msgLen; i++) {
if ((i == 3) || (i == msgLen -1)){
Serial.print(" ");
}
if (msgbuf[i] < 16) Serial.print("0");
Serial.print(msgbuf[i], HEX);
}
Serial.println();
msgLen = 0;
}
}
//
// Interrupt routine for changes on j1850 data pin
//
volatile unsigned long lastInt = 0;
volatile uint8_t bitCnt;
volatile long delta;
volatile unsigned long tstamp;
volatile uint8_t aByte;
volatile uint8_t buf[BUFSIZE];
volatile uint8_t bufIdx;
void j1850_interrupt(void)
{
tstamp = micros();
uint8_t pin = digitalRead(J1850_PIN);
// reload the overflow timer with EOF timeout
TCNT1 = TMR_PRELOAD;
delta = tstamp - lastInt;
long longbit, shortbit;
if (idle)
{
if (pin == 0)
{
longbit = delta - SOF_TIME;
if (abs(longbit) < SOF_DEV)
{
// found SOF, start header/data sampling
idle = false;
bitCnt = 0;
bufIdx = 0;
aByte = 0;
}
}
}
else
{
shortbit = delta - SHORTBIT_TIME;
longbit = delta - LONGBIT_TIME;
if (abs(shortbit) < SHORTBIT_DEV) {
// short pulse
if (pin == 0)
// short pulse & pulse was high => active "1"
aByte = (aByte << 1) | 0x01;
else
// short pulse & pulse was low => passive "0"
aByte = (aByte << 1) & 0xFE;
bitCnt++;
}
else if (abs(longbit) < LONGBIT_DEV) {
// long pulse
if (pin == 0)
// long pulse & pulse was high => active "0"
aByte = (aByte << 1) & 0xFE;
else
// long pulse & pulse was low => passive "1"
aByte = (aByte << 1) | 0x01;
bitCnt++;
}
else {
// unknown bit, reset
TMROVF_INT_OFF;
idle = true;
lastInt = tstamp;
return;
}
if (bitCnt >= 8) {
buf[bufIdx++] = aByte;
bitCnt = 0;
if (bufIdx >= sizeof(buf)) {
// too many data bytes, error
TMROVF_INT_OFF;
idle = true;
}
else {
// if all is ok, start the EOF timeout
TMROVF_INT_CLR;
TMROVF_INT_ON;
}
}
}
lastInt = tstamp;
}
// Timer overlflow interrupt
// Occurs when the EOF pulse times out the timer
//
ISR(TIMER1_OVF_vect)
{
TCNT1 = TMR_PRELOAD;
TMROVF_INT_OFF;
// copy the data so that we can start to fill the buffer again
// but only if the buffer has been consumed in the background
if (bufIdx > 0 && msgLen == 0)
{
memcpy((void*)msgbuf, (const void*)buf, bufIdx);
msgLen = bufIdx;
}
idle = true;
}
Ideally it would be nice to make this code "non-blocking" on the Due as well...Im sure its something that could be handled as a background task??
Thanks for any help/advice!