Oregon Scientific Decoder V2 and V3 for Nucleo-F401RE
Oregon-Scientific Decoder for V2 and V3 protocol. As exemple it handles THGR122NX (V2) and THGR810 (V3) sensors.
The software use interrupts to collect frames in a buffer and decode them in a background task.
Diff: OregonBit.cpp
- Revision:
- 1:265557f4b6b8
- Parent:
- 0:7d471396cb64
--- a/OregonBit.cpp Sat Oct 12 11:55:05 2019 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,303 +0,0 @@ -#include "mbed.h" -#include "Regul.h" - -int processData(measure_t*, int version); - -typedef struct { - int v; - bool pin; -}pulse_t; - -int onShortLo = 200; -int onShortHi = 615; -int offShortLo = 400; -int offShortHi = 850; -int onLongLo = 615; -int onLongHi = 1100; -int offLongLo = 850; -int offLongHi = 1400; -long startedAt; -long endedAt; - -bool dataBits[145]={0}; // 18 Nibbles +1 - -Thread thread; -Timer xTime; - -InterruptIn dataPin(PB_8, PullUp); - -CircularBuffer<pulse_t, BUF_SIZE> PulseWidth; - -measure_t Sensor[NB_CHAN] ={0}; -pulse_t timeDiff; - -void getPulseF(void) -{ - endedAt = xTime.read_us(); // set timer end for last pin - timeDiff.v = endedAt - startedAt; - timeDiff.pin = 1; - PulseWidth.push(timeDiff); - startedAt= endedAt; // set timer start for this pin -} - -void getPulseR(void) -{ - endedAt = xTime.read_us(); // set timer end for last pin - timeDiff.v = endedAt - startedAt; - timeDiff.pin = 0; - PulseWidth.push(timeDiff); - startedAt= endedAt; // set timer start for this pin -} - - - -void getData() -{ -pulse_t pulse; -// get next 128 data bits, we determined bit 0 in SYNC -int i= 0; -int l= 0; // long pulse; -int s= 0; // short pulse -int bit_ptr= 1; //first bit[0] was derived in Preamble; -char state=0; - -while(true) - { - i=0; - while(!PulseWidth.empty() && i<100) - { - PulseWidth.pop(pulse); - //pc.printf("%d,", pulse.v); - if (pulse.pin == 0) //Pin was OFF - { - if ((pulse.v > offShortLo) && (pulse.v < offShortHi)) - { // short off detected - s++; - l=0; - } - else if ((pulse.v > offLongLo) && (pulse.v < offLongHi)) - { // long off detected - l++; - s=0; - } - else - { - l=0; - s=0; - } - } - else // Pin was ON - { - if ((pulse.v > onShortLo) && (pulse.v < onShortHi)) // half-time - { // short on detetcted - s++; - l=0; - } - else if ((pulse.v > onLongLo) && (pulse.v < onLongHi)) // full-time - { // long on detected - l++; - s=0; - } - else - { - l=0; - s=0; - } - } - - switch(state) - { - case 0: // Detect preamble - if(l >= 24) // out of 32 - state=1; - if(s >= 40) // out of 48 - state=11; - //pc.printf("%d ", l); - break; - case 1: // wait start bit (first short in V2.1) - //pc.printf("OK2"); - l=0; - if (s==1) - state = 2; - break; - case 11: // wait start bit (first long in V3) - //pc.printf("OK3"); - s=0; - if (l==1) - { - state = 21; - dataBits[1]=0; // l => opposite of previous (1) - bit_ptr=2; - l=0; - } - break; - case 2: - //pc.printf(" %d", pulse.v); - if(s==0 && l==0) - { - ERR(" %s : %d\t", (pulse.pin ? "on" : "off"), pulse.v); - if (0 == bit_ptr%2) - l=1; // V2.1 2nd bit is !(bit n-1) - else - if (pulse.v > 736) - l=1; - else - s=1; - } - if (0 == bit_ptr%2 && !l) - { - ERR("%d V2.1 : 2nd pulse should be long",bit_ptr); - s=0; - l=1; - } - - if (s == 2) - { // 2 short pulses this bit equals previous bit (we know 1st bit from sync) - dataBits[bit_ptr] = dataBits[bit_ptr-1]; - /* if(dataBits[bit_ptr] != !pulse.pin) - pc.printf("Error : V2.1 : pin level don't match"); */ - bit_ptr++; - s=0; - l=0; - } - if (l == 1 && s==0) - { // 1 long pulse this bit is inverse of previous bit (we know 1st bit from sync) - dataBits[bit_ptr] = !dataBits[bit_ptr-1]; - l=0; - s=0; - bit_ptr++; - } - if(bit_ptr>144) - { - processData(Sensor,2); - state=0; - bit_ptr=1; - WARN(" Waiting..."); - } - break; - case 21: - //pc.printf(" %d", pulse.v); - if(s==0 && l==0) - { - ERR(" %s : %d\t", (pulse.pin ? "on" : "off"), pulse.v); - - if (pulse.v > 736) - l=1; - else - s=1; - } - - if(s==1 && l==1) - ERR(" %s : %d\t", (pulse.pin ? "on" : "off"), pulse.v); - - if (s == 2) - { // 2 short pulses this bit equals previous bit (we know 1st bit from sync) - dataBits[bit_ptr] = dataBits[bit_ptr-1]; - /* if(dataBits[bit_ptr] != !pulse.pin) - ERR("Error : V2.1 : pin level don't match");*/ - //pc.printf(",[%d]%d",bit_ptr, dataBits[bit_ptr]); - bit_ptr++; - s=0; - l=0; - } - if (l == 1) - { // 1 long pulse this bit is inverse of previous bit (we know 1st bit from sync) - dataBits[bit_ptr] = !dataBits[bit_ptr-1]; - l=0; - s=0; - //pc.printf(",[%d]%d",bit_ptr, dataBits[bit_ptr]); - bit_ptr++; - } - if(bit_ptr>72) - { - processData(Sensor,3); - state=0; - bit_ptr=1; - WARN(" Waiting..."); - } - break; - } - i++; - } - ThisThread::sleep_for(50); - } - // return 0; -} - -int processData(measure_t *data, int version) -{ -int x; -int i = 0; -int j= 0; -char nibble[18]={0}, chksum=0; -int tmp; -char channel; - - x= (version==2) ? 2 : 1; - for (i=0;i<18;i++) - { - for (j=0;j<4;j++) - { - if ( dataBits[x]) - nibble[i] |= 1<<j; - x+= (version==2) ? 2 : 1; - } - } - - for (x=1;x<73;x++) - { -// pc.printf("%d", dataBits[x]); - dataBits[x]=0; - } - -#ifdef __DEBUG__ - for (i=0;i<18;i++) - pc.printf("%X ",nibble[i]); - pc.printf("\r\n"); -#endif - - if( 0x0A == nibble[0]) - { - for (i=1;i<16;i++) - chksum += nibble[i]; //no overflow if computed on 15 Nibbles - - if (chksum == (nibble[17]<<4 | nibble[16])) - { - channel = nibble[5]; - data[channel].deviceID = channel; - DBG("Channel: %d", channel); - - tmp= (nibble[8] & 0x4) ? 10 : 90; - DBG("Batterie: %d", tmp); - - int sign = (nibble[12]>0x0) ? -1 : 1; - float temp = nibble[11]*10 + nibble[10] + (float)(nibble[9] / 10.0); - temp= sign * temp; - data[channel].temp1= temp; - DBG("Temperature: %0.1f", temp); - - tmp= nibble[14] * 10 + nibble[13]; - data[channel].hum1= (float)tmp; - DBG("Humidity: %d", tmp); - - data[channel].timestamp=time(NULL); - } - else - ERR("Checksum error %X", chksum); - } - else - ERR("Sync error"); - return 0; -} - -void Init_Oregon() -{ - dataPin.fall(&getPulseF); - dataPin.rise(&getPulseR); - dataPin.enable_irq(); - - xTime.start(); - xTime.reset(); - dataBits[0] = 1; - thread.start(getData); -} \ No newline at end of file