hal/arduino/ArduinoTellstickDuo/oregonV2.1.cpp
Daniel Collin 1c23a7c360 Added oregon v2.1 support to ArduinoTellstick along with some code cleanup
Former-commit-id: d05ee71fa4f2f91afd6452e894385bbcd7020917
2016-01-29 14:14:21 +01:00

210 lines
4.6 KiB
C++

#include "oregonV2.1.h"
#include "buffer.h"
/*******************************************************************************
--OREGON v2.1 PROTOCOL SPECIFICATION--
----SIGNAL----
A signal consists of a PREAMBLE, DATA and an POSTAMBLE.
Each signal is sent 2 times in a row to increase the delivery success rate.
Between the two times there is a "low" pause of 8192us.
----PREAMBLE----
send 16 "1"(ones) over the air
----DATA----
16 bits of sensor type
XX bits of data (where XX <= 64)
The length XX depends on the sensor type. I.e. 0x1A2D => XX=56
Over air a "1"(one) is sent as:
send high for 512 microseconds
send low for 1024 microseconds
send high for 512 microseconds
Over air a "0"(zero) is sent as:
send low for 512 microseconds
send high for 1024 microseconds
send low for 512 microseconds
----POSTAMBLE----
send 8 "0"(zeros) over the air
*******************************************************************************/
#define SMALL_PULSE(x) ( 4<=x && x<=13 )
#define BIG_PULSE(x) ( 12<=x && x<=22 )
#define MORE_DATA_NEEDED -1
#define INVALID_DATA -2
enum {
PARSE_PREAMP = 0,
PARSE_ID,
PARSE_DATA
} static state = PARSE_PREAMP;
static uint8_t byteCnt = 0;
static uint8_t bitCnt = 0;
static uint8_t totByteCnt = 0;
int8_t byteLength = -1;
void reset() {
byteCnt = 0;
bitCnt = 0;
totByteCnt = 0;
state = PARSE_PREAMP;
byteLength = -1;
}; //end reset
void parseOregonStream(bool level, uint8_t count) {
static uint8_t cnt = 0; //used for counting stuff independent in every state
static uint16_t sensorType = 0;
static int8_t byte;
static uint8_t bytesToParse = 0; //the number of bytes left in the data part to parse
static uint8_t buffer[8];
if (level) {
count+=3;
} else {
count-=3;
}
switch(state) {
case PARSE_PREAMP: //look for 25 big pulses followed by one short in a row
if (BIG_PULSE(count)) {
++cnt;
break;
}
if (SMALL_PULSE(count)) {
if (cnt > 25) {
state=PARSE_ID;
sensorType = 0;
}
cnt = 0;
}
break;
case PARSE_ID: //get the two first Bytes
byte = getByte(level, count);
if (byte == INVALID_DATA) {
reset();
cnt = 0;
break;
} else if (byte == MORE_DATA_NEEDED) {
break;
} else {
if (sensorType == 0) {
sensorType = byte << 8;
} else {
sensorType |= byte;
switch (sensorType) {
case 0xEA4C:
bytesToParse = 5;
byteLength = 63;
break;
case 0x0A4D:
case 0x1A2D: //sensor THGR2228N (channel + sensor_id + battery_level + temp + humidity + checksum)
bytesToParse = 7;
byteLength = 79;
break;
default:
reset();
cnt = 0;
return;
}
state = PARSE_DATA;
cnt = 0;
}
}
break;
case PARSE_DATA: //get the remaining data
byte = getByte(level, count);
if (byte == INVALID_DATA) {
reset();
cnt = 0;
break;
} else if (byte == MORE_DATA_NEEDED) {
break;
}
buffer[cnt] = byte;
++cnt;
if (bytesToParse == 0) {
Serial.print(F("+Wclass:sensor;protocol:oregon;model:0x"));
Serial.print(sensorType, HEX);
Serial.print(F(";data:0x"));
for (int8_t i = 0; i < cnt; ++i) {
Serial.print(buffer[i], HEX);
}
Serial.println(F(";"));
reset();
cnt = 0;
}
--bytesToParse;
break;
}
}; //end parseOregonStream
int8_t getByte(bool level, uint8_t count) {
int8_t bit = getBit(level, count);
static uint8_t byte = 0;
if (bit == INVALID_DATA) {
return INVALID_DATA;
} else if (bit == MORE_DATA_NEEDED) {
return MORE_DATA_NEEDED;
}
byte >>= 1;
if (bit) {
byte |= (1<<7);
}
++totByteCnt;
++byteCnt;
if (byteCnt < 8) {
return MORE_DATA_NEEDED;
}
byteCnt=0;
return byte;
}; //end getByte
int8_t getBit(bool level, uint8_t count) {
static bool bit = 0;
if (bitCnt == 0) {
//First pulse must be small
if (!SMALL_PULSE(count)) {
return INVALID_DATA;
}
bitCnt = 1;
} else if (bitCnt == 1) {
//Second pulse must be long
if (!BIG_PULSE(count) && totByteCnt!=byteLength){ //special check - last byte might have strange values
bitCnt = 0;
return INVALID_DATA;
}
bit = level;
bitCnt = 2;
return bit;
} else if (bitCnt == 2) {
//Prepare for next bit
if (level && SMALL_PULSE(count)) {
//Clean start
bitCnt = 0;
} else if (BIG_PULSE(count)) {
//Combined bit
bitCnt = 1;
} else if (SMALL_PULSE(count)) {
//Clean start
bitCnt = 0;
}
return MORE_DATA_NEEDED;
}
return MORE_DATA_NEEDED;
}; //end getBit