X2D lib first commit

X2D.cpp

Committer:
sev2000
Date:
2022-10-01
Revision:
25:28895e3d96c5
Parent:
24:eac91efdc315

File content as of revision 25:28895e3d96c5:

#include "mbed.h" 
#include "rtos.h" 
#include "X2D.h" 

#define BUF_SIZE    1000
#define BIT_SIZE    160     //16Bytes + 0xFF + 0x00 + 3 bits + (n * 0 bit inserted by the X2D protocole to cut 0xFF

int processData(int size);
void write_ctrl_reg(unsigned long write_data);
unsigned long read_ctrl_reg(void);


DigitalOut Reg_Data(PC_1);  // Jaune
DigitalOut RxTx(PC_0, 0);   // Violet? , reset to force Application mode (not FBL)
DigitalOut Tx(PA_9);        // Noir
DigitalOut UART(PA_0, 1);   // Rouge, set to UART mode

//DigitalIn CD(PC_0);       // Bleu
//DigitalIn Rx(PB_7);       // Vert
//DigitalIn BU(PA_4);       // Blanc
DigitalIn CLR(PA_1);        // Orange
DigitalIn RSTO(PC_2);       // Gris

InterruptIn Rx(PB_7, PullUp);

//PlatformMutex sendbit_mutex;

pulse_t timeDiff;
CircularBuffer<pulse_t, BUF_SIZE> PulseWidth;
CircularBuffer<msg_t, 10> MessageTx;
CircularBuffer<msg_t, 10> MessageRx;

static char cnt_1=0;

bool dataBits[BIT_SIZE]={0};

unsigned short maison=0;
const unsigned char source = 0x02;
const unsigned char trans = 0x02;


long startedAt=0;
long endedAt=0;

Timer xTime; 

Thread thread(osPriorityAboveNormal);

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 wait_posedge(void)
{
    if(CLR != 0)
    {
        while(CLR != 0) ;
    }
    else ;
    while(CLR == 0) ;
}

void wait_negedge(void)
{
    if(CLR == 0)
    {
        while(CLR == 0) ;
    }   
    else ;
    while(CLR != 0) ;
}

unsigned long read_ctrl_reg(void)
{
    unsigned long return_value = 0;
    unsigned long curr_bit = 0 ;
    int i ;
    
    RxTx = 1;
    //Reg_Data = 0;
    wait_posedge();
    //wait_ms(10);
    Reg_Data = 1;
    RxTx = 1;

    for(i=0;i<=23;i++)
    {
        //DBG("i= %d", i);
        wait_posedge();
        curr_bit = Rx ;
        return_value |= ((curr_bit) << (23-i)) ;
    }
    //wait_negedge();

    Reg_Data = 0;   //clr pin reg_data

    wait(1) ;
    return return_value ;
}

void write_ctrl_reg(unsigned long write_data)
{
    int i ;

    Reg_Data = 1;   //set pin reg_data to Register mode
    RxTx = 0;       //set pin rxtx to Tx mode
    wait_posedge();   //find posedge for Tcr

    for(i=0;i<=23;i++) //low code effciency may result in wrong writing
    {
        if(((write_data >> (23-i)) & 0x1) == 0)
        {
            Tx = 0;
        }
        else
        {
            Tx = 1;
        }
        wait_posedge();
    }
    RxTx = 1;       //set pin rxtx to Rx
    Reg_Data = 0;   //set pin reg_data
    Tx = 0;
    wait(0.1);
}

void SendBit(bool value)
{
//    DBG("%d ", value);
    Tx = !Tx;
    if(value)
        {
        wait_us(800);
        Tx = !Tx;
        wait_us(800);
        }
    else
        {
        wait_us(1600);
        }
}
    
void SendByte(char value)
{
int i=0;
bool bit;

    //pc.printf("%0.2X ", value);
    for(i=0; i<8; i++)
        {
        bit = (bool)(0x01 & (value>>i)); // LSB first
        SendBit(bit); 
        if(bit)
            cnt_1++;
        else
            cnt_1=0;
        if(cnt_1 == 5)
            {
            SendBit(0);
            cnt_1=0;
            }
        }
}

void SendPreamble(void)
{
int i;

    //pc.printf("\r\n");
// EM 20210117 remove to avoid glitch (tested)
//    Tx=1;
    for(i=0; i<17; i++)
        SendBit(0);
    for(i=0; i<6; i++)
        SendBit(1);
    SendBit(0);

}

void SendPostamble(void)
{
int i;

    for(i=0; i<8; i++)  // Send 0xFF
        SendBit(1);
    for(i=0; i<8; i++)
        SendBit(0);

}

void SendFrame(unsigned char *data, int length)
{

int i, chksum=0;

    RxTx = 0;       //set pin rxtx to Tx
// EM removed 20210117 don't need since it is already set to 1 at the end
//    Tx=0;

    SendPreamble();
    cnt_1 =0;   // reset counter of consecutive 1 bits

    for(i=0; i<length; i++)
        {
        SendByte(data[i]);
        chksum += data[i];
        }
    chksum = ~chksum +1;

    SendByte((char)(chksum>>8));
    SendByte((char)chksum);
    SendPostamble();

    RxTx = 1;       //set pin rxtx to Rx

//EM 20210117 Always finish then restart with Tx=1 (tested)
    Tx=1;
    //pc.printf("\r\n");
}

void SendAssoc(int zone, int delest)
{
msg_t msg={0xFF,0xFF,0x02,0xFF,0x02,0xF0,0xFF,0xFF,0xF1,0xE6,0x13,0x03,0x06,0x03, 14}; // zone 4, 3 zone, 6 delest channels, delest chan 3

unsigned char dest = 0;

    dest = 0x10 + zone-1;

    msg.data[2] = source;
    msg.data[4] = trans;
    msg.data[8] = maison >>8;
    msg.data[9] = maison & 0xFF;
    msg.data[10] = dest;
    msg.data[13] = delest;
 
    MessageTx.push(msg);
}

void SendCmd(int zone, h_mode prog)
{
//char tab[8]={0xF1,0xE6,0x01,0x10,0x01,0x00,0x03,0x64};    // Zone1 Sun
msg_t msg;
unsigned char dest = 0;
// control 1 char
// information 0-8 char

int i;

    dest = 0x10 + zone-1;
    msg.data[0] = maison >>8;
    msg.data[1] = maison & 0xFF;
    msg.data[2] = source;
    msg.data[3] = dest;
    msg.data[4] = trans;
    msg.data[6] = (char)prog;
    msg.data[7] = 0x64;

    msg.length = 8;

    for(i=0; i<3; i++)
        {
        msg.data[5]=i;     //message count
        MessageTx.push(msg);
        //wait_ms(30);
        }
}

void SendCmda(char *tab, int length)
{
msg_t msg;
int i;

/*    dest = 0x10 + zone-1;
    tab[3] = dest;
    tab[6] = prog;
*/
    memcpy(msg.data, tab, length);
    for(i=0; i<3; i++)
        {
        msg.data[5] = tab[5] + i;    //message count
        MessageTx.push(msg);
        //wait_ms(30);
        }
}

void TASK_SndRcv(void)
{
pulse_t pulse;
int cnt_1 = 0, rcv_cnt=0;
//char tmp[32]={0};
char state=0;
char s=0, l=0, bit_ptr=0;
msg_t msg;

while(true)
    {
    rcv_cnt=0;
    while(!PulseWidth.empty() && rcv_cnt < 200)
        {
        PulseWidth.pop(pulse);
        //sprintf(tmp, "%d, %ld|", pulse.pin, pulse.v);
        //pc.printf("%s ", tmp);
        
        if ((pulse.v > 700) && (pulse.v < 1000))
                { // short off detected
                    s++;
                    l=0;
                }
        else if ((pulse.v > 1500) && (pulse.v < 1800))
                { // long off detected
                    l++;
                    s=0;
                }
        else
                {
                    l=0;
                    s=0;
                    state=0;
                }
        switch(state)
            {
            case 0:     // Detect preamble 
                        if(s >= 12) // out of 12
                            state=1;
                        //pc.printf("%d ", s);
                        break;
            case 1:     // wait start bit (first long)
                        //pc.printf("OK2");
                        s=0;
                        if (l==1)
                            {
                            state = 2;
                            cnt_1=0;
                            bit_ptr=0;
                            //bit_ptr++; inculde start bit in payload
                            }
                        l=0;
                        break;
            case 2: 
                        //pc.printf(" %d", pulse.v);
            
                        if (s == 2)
                            { 
                            dataBits[bit_ptr] = 1;
                            l=0;
                            s=0;
                            bit_ptr++;
                            cnt_1++;    // Count bit for ETX detection
                            }
                        if (l == 1 && s==0)
                            {
                            dataBits[bit_ptr] = 0;
                            l=0;
                            s=0;

                            if(cnt_1 != 5) // skip the 0 after 5 bits = 1
                                bit_ptr++;
                            cnt_1=0;

                            }
                        if(bit_ptr > BIT_SIZE)
                            {
                            state=0;
                            ERR("Frame too long : dropped\r\n");
                            }
                        if(cnt_1 == 8)
                            {
                            processData(bit_ptr-1);
                            state=0;
                            //PulseWidth.reset();
                            }
                        break;
                
            }
        rcv_cnt++;
        }

// Send Frame
    if (!MessageTx.empty() && rcv_cnt == 0 && RxTx==1)  // If message to emit and didn't received message nor sending in progress
        {
        MessageTx.pop(msg);
 //       sendbit_mutex.lock();
        SendFrame(msg.data, msg.length);
 //       sendbit_mutex.unlock();
        
        }
    
    Thread::wait(30); // evey 30 mS we can send a message
    }
}


int processData( int size)
{
int x=0;
int i = 0;
int j=  0;
char nibble[18]={0};
int chksum=0, ETX_pos=0;
msg_t message;

    ETX_pos= size/8;
    for (i=0; i<ETX_pos; i++)
        {
        for (j=0;j<8;j++)
            {
            if ( dataBits[x])
                nibble[i] |= 1<<j;
            dataBits[x] =0; // clean variable
            x++;
            }
        }
                
    for (i=0; i<ETX_pos-2; i++)   // Calculate Checksum
        {
        message.data[i] = nibble[i];
        message.length = ETX_pos-2;
        chksum += nibble[i];
        }
    chksum = ~chksum +1;
        
#if __DEBUG__
    for (i=0; i<ETX_pos; i++)
        debug("%0.2X ",nibble[i]);
    debug("\r\n");
#endif
    if ( (char)(chksum>>8) != nibble[ETX_pos-2] || (char)chksum != nibble[ETX_pos-1] )
        debug("CRC Error\r\n");
    else
        MessageRx.push(message);

    return 0;
}


void Init_X2D(void)
{
unsigned long Ctrl_Reg = 0;

    Rx.fall(&getPulseF);
    Rx.rise(&getPulseR);
    UART = 1;

#if NO_STM8
    write_ctrl_reg(0x01E22F); // see .xls file ; 1200 baud, deviation =1, Asynchrone, clock OFF
    Ctrl_Reg = read_ctrl_reg();
    DBG("Ctrl_reg = %X", Ctrl_Reg);
#endif

    RxTx = 1;       //set pin rxtx to Rx
    Reg_Data = 0;   //set pin reg_data 
    Tx = 0;

    xTime.start();
    xTime.reset();
    startedAt = xTime.read_us(); // set initial timer end

    thread.start(callback(TASK_SndRcv));
}