0-SIM waveform decoding

The data format of SIM card sending and answering is specified, starting with low level and ending with high level, taking EUT as the basic pulse width and 8bit as one byte, which is consistent with the serial port protocol.

Data format.png

First look at a waveform captured by a logic analyzer, as follows:
Logic analyzer data.png

It can be observed that the minimum pulse width is 77.54us, so the baud rate is 1 / 77.5 = 12903, configure as follows:
8Bit, 2 stop bits, even parity

Logic analyzer configuration.png

It is easier to write SIM data, just follow the sequence, as follows:

void Sim_Write_Byte(uint8_t ChannelID, uint8_t senddata) 
{
    uint8_t i; 
    bool parity_bit = 0;
    
    Set_Sim_Io(ChannelID, SIM_DATA, 0);
    Delay_One_ETU();
    for(i=0; i<8; i++) 
    {
        if(1 == (senddata & 0x01))
        {
            Set_Sim_Io(ChannelID, SIM_DATA, 1);
        }
        else
        {
            Set_Sim_Io(ChannelID, SIM_DATA, 0);        
        }
        parity_bit ^= senddata & 0x01;
        senddata >>= 1;
        Delay_One_ETU();
    }
    Set_Sim_Io(ChannelID, SIM_DATA, parity_bit);
    Delay_One_ETU();
    Set_Sim_Io(ChannelID, SIM_DATA, 1);
    Delay_One_ETU();
    Delay_One_ETU();
}

The decoding of SIM data is nothing more than sampling decoding, so we start with a low level and wait for the low level to start decoding, as follows:

uint8_t Sim_Read_Byte(uint8_t ChannelID, uint32_t WaitTime) 
{
    uint32_t count = 0; 
    uint8_t i = 0;
    uint8_t recvdata = 0x00;
    bool parity_bit = 0;

    while(Get_Sim_Io(ChannelID, SIM_DATA))
    {
        if(0 == Get_Sim_Io(ChannelID, SIM_DATA)) 
        {
            break;
        }
        count++;
        if(count >= WaitTime)
        {
            pSimChannelCtl->bReadTimeOut = 1;
            return YFI_FAIL; 
        }
        Delay_Us(10);
    }
    Delay_One_ETU();
    Delay_Half_ETU();  //偏移1/2,使采样位于中间
    
    for(i=0; i<8; i++) 
    {
        recvdata >>= 1;
        if(Get_Sim_Io(ChannelID, SIM_DATA))
        {
            recvdata |= 0x80;
        }
        parity_bit ^= Get_Sim_Io(ChannelID, SIM_DATA); 
        Delay_One_ETU();
    }
    
    parity_bit ^= Get_Sim_Io(ChannelID, SIM_DATA);
    Delay_One_ETU();
    if (!parity_bit)
    {
        recvdata = recvdata;
    }
    else
    {
        recvdata = '\xbb';  //parity error
    }
    
    return recvdata; 
}

After testing, because the above is equivalent to sampling a point of 1bit, even if the Little offset is added, decoding errors will occur, and it is necessary to optimize the increase of the sampling point.

10 points are sampled in one bit, and 100 points are sampled in one data.

uint8_t Sim_Read_Byte(uint8_t ChannelID, uint32_t WaitTime) 
{
    uint32_t count = 0; 
    uint8_t i = 0, first = 0;
    uint8_t lnum = 0, hnum = 0;
    uint8_t recvdata = 0x00;
    uint32_t recvpoint = 0;
    bool parity_bit = 0;

    PSIMROOTST     pSimRootSt;
    PSIMCHANNELST  pSimChannelCtl;
    
    pSimRootSt     = (PSIMROOTST)&stSimRootSt;    
    pSimChannelCtl = &pSimRootSt->stChannelSt[ChannelID];

    while(Get_Sim_Io(ChannelID, SIM_DATA))
    {
        if(0 == Get_Sim_Io(ChannelID, SIM_DATA))  //检测到低电平,即起始位,开始解码
        {
            break;
        }
        count++;
        if(count >= WaitTime)                     //未检测到低电平,到达超时时间退出
        {
            pSimChannelCtl->bReadTimeOut = 1;
            return YFI_FAIL; 
        }
        Delay_Us(10);
    }
    //32point
    for(i=0; i<32; i++) 
    {
        recvpoint >>= 1;
        if(Get_Sim_Io(ChannelID, SIM_DATA))
        {
            recvpoint |= 0x80000000;
        }
        Delay_Us(31);
    } 

    lnum = 0;
    hnum = 0;
    first = 0;
    for(i=0; i<32; i++) 
    {
        if(1 == (recvpoint & 0x00000001))
        {
            if(0 == lnum)
            {
                hnum++;
            }
            else
            {
                if(0 == first)
                {
                    first = 1;
                    lnum = lnum - 2;
                }
                if((lnum > 0)&&(lnum <= 4))
                {
                    recvdata |= 0x00;
                    recvdata >>= 1;
                }
                else if((lnum > 4)&&(lnum <= 7))
                {
                    recvdata |= 0x00;
                    recvdata >>= 2;
                }
                else if((lnum > 7)&&(lnum <= 10))
                {
                    recvdata |= 0x00;
                    recvdata >>= 3;
                }
                else if((lnum > 10)&&(lnum <= 13))
                {
                    recvdata |= 0x00;
                    recvdata >>= 4;
                }
                else if((lnum > 13)&&(lnum <= 16))
                {
                    recvdata |= 0x00;
                    recvdata >>= 5;
                }
                else if((lnum > 16)&&(lnum <= 19))
                {
                    recvdata |= 0x00;
                    recvdata >>= 6;
                }
                else if((lnum > 18)&&(lnum <= 22))
                {
                    recvdata |= 0x00;
                    recvdata >>= 7;
                }
                else if((lnum > 22)&&(lnum <= 25))
                {
                    recvdata |= 0x00;
                    recvdata >>= 8;
                }
                else if((lnum > 25)&&(lnum <= 28))
                {
                    recvdata = 0x00;
                }
                else if((lnum > 28)&&(lnum <= 31))
                {
                    recvdata = 0x00;
                }
                lnum = 0;
                hnum = 1;
            }
        }
        else
        {
            if(0 == hnum)
            {
                lnum++;
            }
            else
            {
                if((hnum > 0)&&(hnum <= 4))
                {
                    recvdata &= 0x80;
                    recvdata >>= 1;
                }
                else if((hnum > 4)&&(hnum <= 7))
                {
                    recvdata &= 0xC0;
                    recvdata >>= 2;
                }
                else if((hnum > 7)&&(hnum <= 10))
                {
                    recvdata &= 0xE0;
                    recvdata >>= 3;
                }
                else if((hnum > 10)&&(hnum <= 13))
                {
                    recvdata &= 0xF0;
                    recvdata >>= 4;
                }
                else if((hnum > 13)&&(hnum <= 16))
                {
                    recvdata &= 0xF8;
                    recvdata >>= 5;
                }
                else if((hnum > 16)&&(hnum <= 19))
                {
                    recvdata &= 0xFC;
                    recvdata >>= 6;
                }
                else if((hnum > 18)&&(hnum <= 22))
                {
                    recvdata &= 0xFE;
                    recvdata >>= 7;
                }
                else if((hnum > 22)&&(hnum <= 25))
                {
                    recvdata &= 0xFF;
                    recvdata >>= 8;
                }
                else if((hnum > 25)&&(hnum <= 28))
                {
                    recvdata = 0xFF;
                }
                else if((hnum > 28)&&(hnum <= 31))
                {
                    recvdata = 0xFF;
                }
                hnum = 0;
                lnum = 1;
            }
        }
        recvpoint >>= 1;
    }
    
    /*if (!parity_bit)
    {
        recvdata = recvdata;
    }
    else
    {
        recvdata = '\xbb';  //parity error
    }*/
    return recvdata; 
}
Published 106 original articles · praised 76 · 130,000 visits +

Guess you like

Origin blog.csdn.net/Creator_Ly/article/details/105673800