Oregegon scientific decoder V2.1 and V3
Dependents: Oregon_Decoder_V2_V3
Oregon decoding Library.
It manages protocoles V2.1 and V3.
To be used with RTOS OS2 or MBED V5
OregonBit.cpp
- Committer:
- sev2000
- Date:
- 2020-07-14
- Revision:
- 12:6d3638a225dd
- Parent:
- 11:4cfdb2d79394
- Child:
- 13:87e9b1cd65c2
File content as of revision 12:6d3638a225dd:
#include "mbed.h" #include "Regul.h" //#define Level 3 int processData(measure_t*, int version); int processDataTFA(measure_t*); typedef struct { int v; bool pin; }pulse_t; int onShortLo = 200; int onShortHi = 700; int offShortLo = 200; int offShortHi = 700; int onLongLo = 700; int onLongHi = 1200; int offLongLo = 700; int offLongHi = 1200; /* int onShortLo = 201; int onShortHi = 615; int offShortLo = 400; int offShortHi = 850; int onLongLo = 615; int onLongHi = 1100; int offLongLo = 850; int offLongHi = 1400; */ static long startedAt; static long endedAt; static bool dataBits[145]={0}; // 18 Nibbles +1 //Thread O_thread(osPriorityBelowNormal); Thread O_thread(osPriorityNormal); static Timer xTime; InterruptIn dataPin(PB_8); DigitalOut StbyPin(PB_9, 1); static CircularBuffer<pulse_t, BUF_SIZE> PulseWidth; measure_t Sensor[NB_CHAN] ={0}; static pulse_t timeDiff; static 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 } static 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; if(PulseWidth.empty()) //If no pulse received since 100 ms, we are no more in the frame state=0; while(!PulseWidth.empty() && i<200) { PulseWidth.pop(pulse); i++; //pc.printf("%d,", pulse.v); if ((pulse.v > onShortLo) && (pulse.v < offLongHi)) { 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) // If we are here (pulse.v < offLongHi) { // long off detected l++; s=0; } else { l=0; s=0; } } else // Pin was ON { if (pulse.v < onShortHi) // half-time, If we are here (pulse.v > onShortLo) { // 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; } } } else // Not Oregon Pulse { l=0; s=0; state=0; continue; } switch(state) { case 0: // Detect preamble if(l >= 24) // out of 32 state=1; if(s == 18) // out of 22 state=11; if(s >= 40) // out of 48 state=12; //pc.printf("%d ", l); break; case 1: // wait start bit (first short in V2.1) //printf("OK2"); l=0; if (s==1) { state = 2; bit_ptr=1; } break; case 11: // wait start bit (2 longs in WS-07) //printf("OK4"); if(s>22) state=0; if(l==2) { state = 22; dataBits[1]=1; // l => opposite of previous (0) bit_ptr=2; l=0; s=0; } break; case 12: // wait start bit (first long in V3) //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]; //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; case 22: //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]; //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>50) { processDataTFA(Sensor); state=0; bit_ptr=1; WARN(" Waiting..."); } break; } } ThisThread::sleep_for(100); } // 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; } #if __DEBUG__ for (i=0;i<18;i++) printf("%X ",nibble[i]); printf("\r\n"); #endif //Decoding for THGR122NX(1D20) and THGR810(F8B4) if( 0x0A == nibble[0]) { //Compute Checksum 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; } uint8_t Checksum(int length, uint8_t *buff) { uint8_t mask = 0x7C; uint8_t checksum = 0x64; uint8_t data; int byteCnt; for ( byteCnt = 0; byteCnt < length; byteCnt++) { int bitCnt; data = buff[byteCnt*2]<<4 | buff[byteCnt*2+1]; for ( bitCnt = 7; bitCnt >= 0 ; bitCnt-- ) { uint8_t bit; // Rotate mask right bit = mask & 1; mask = (mask >> 1 ) | (mask << 7); if ( bit ) { mask ^= 0x18; } // XOR mask into checksum if data bit is 1 if ( data & 0x80 ) { checksum ^= mask; } data <<= 1; } } return checksum; } int processDataTFA(measure_t *data) { int x; int i = 0; int j= 0; char nibble[12]={0}, chksum=0; int tmp; char channel; x= 2; for (i=0;i<12;i++) { for (j=0;j<4;j++) { if ( dataBits[x]) nibble[i] |= 1<< (3-j); x++; } } for (x=1;x<50;x++) { //printf("%d", dataBits[x]); dataBits[x]=0; } #if __DEBUG__ for (i=0;i<12;i++) printf("%X ",nibble[i]); printf("\r\n"); #endif //Decoding for WS-07, sensor_id==0x46 if( 0x04 == nibble[0]) { //45 4F 04 4B 0B 52 0 //01000101 01001111 00000100 01001011 00001011 01010010 0000 //SSSSSSSS NRRRRRRR bCCCTTTT TTTTTTTT HHHHHHHH CCCCCCCC ???? chksum = Checksum(5, (uint8_t*)nibble); if (chksum == (nibble[10]<<4 | nibble[11])) { channel = nibble[4]+1; data[channel].deviceID = channel; DBG("Channel: %d", channel); // tmp= (nibble[8] & 0x4) ? 10 : 90; // DBG("Batterie: %d", tmp); float temp = ((nibble[5]<<8 | nibble[6]<<4 | nibble[7])-720) * 0.0556; data[channel].temp1= temp; DBG("Temperature: %0.1f", temp); tmp= nibble[8] <<4 | nibble[9]; 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 RF_Active() { DBG("RF Active"); xTime.reset(); startedAt= 0; dataPin.enable_irq(); StbyPin = 1; } void RF_StdBy() { DBG("RF Standby"); StbyPin = 0; dataPin.disable_irq(); PulseWidth.reset(); //clear Circular Buffer } void Init_Oregon() { dataPin.fall(&getPulseF); dataPin.rise(&getPulseR); RF_Active(); xTime.start(); xTime.reset(); dataBits[0] = 1; O_thread.start(getData); }