Added oregon v2.1 support to ArduinoTellstick along with some code cleanup
Former-commit-id: d05ee71fa4f2f91afd6452e894385bbcd7020917
This commit is contained in:
parent
c2d03347ca
commit
1c23a7c360
11 changed files with 391 additions and 116 deletions
210
arduino/ArduinoTellstickDuo/oregonV2.1.cpp
Normal file
210
arduino/ArduinoTellstickDuo/oregonV2.1.cpp
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
#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
|
||||
Loading…
Add table
Add a link
Reference in a new issue