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);
}