Classe de gestion du HTRC110

Dependents:   RFID_test

RFIDer.cpp

Committer:
gr66
Date:
2017-12-04
Revision:
1:02db8b7c40fb
Parent:
0:ec877e8509d0

File content as of revision 1:02db8b7c40fb:

#include "mbed.h"
#include "RFIDer.h"

RFIDer::RFIDer(PinName clk, PinName mosi, PinName miso) : clk(DigitalOut(clk)), mosi(DigitalOut(mosi)), miso(DigitalIn(miso)), data(InterruptIn(miso))
{
    Tserial = 40;
    Tdata = 250;
    lastBit = 2;
    tagAvailable = 0;
}

void RFIDer::setSamplingTime(char ts)
{
    sendCmd((0b10 << 6) | (ts & 0b00111111)); // no response
}

char RFIDer::getSamplingTime()
{
    return sendCmd(0b00000010); // reponse : 0 0 D5-D0
}

void RFIDer::setComPeriod(short half_period)
{
    Tserial = half_period;
}

short RFIDer::getComPeriod()
{
    return Tserial;
}

void RFIDer::setConfigPage(char mode, char data)
{
    /* Format : 0 1 P1 P0 D3 D2 D1 D0
     * P1,P0 - D3,D2,D1,D0
     * 0,0 - GAIN1,GAIN0,FILTERH,FILTERL
     * 0,1 - PD_MODE,PD_HYSTERESIS,TXDIS
     * 1,0 - THRESET,ACQAMP,FREEZ1,FREEZ0
     * 1,1 - DIPSL1,DISSMARTCOMP,FSEL1,FSEL0
     */
    switch(mode) {
        case 0 :
            sendCmd((0b0100 << 4) | (0b00001111 & data)); // no response
            break;
        case 1 :
            sendCmd((0b0101 << 4) | (0b00001111 & data)); // no response
            break;
        case 2 :
            sendCmd((0b0110 << 4) | (0b00001111 & data)); // no response
            break;
        case 3 :
            sendCmd((0b0111 << 4) | (0b00001111 & data)); // no response
            printf("Config sent : %X\r\n", (0b0111 << 4) | (0b00001111 & data));
            break;
    }
}

char RFIDer::getConfigPage(char mode)
{
    char response;
    switch(mode) {
        case 0 :
            response = sendCmd(0b00000100); // no response
            break;
        case 1 :
            response = sendCmd(0b00000101); // no response
            break;
        case 2 :
            response = sendCmd(0b00000110); // no response
            break;
        case 3 :
            response = sendCmd(0b00000111); // no response
            break;
    }
    return response;
}

void RFIDer::setClockFrequency(int frequency)
{
    // Get value
    char data = getConfigPage(3);
    printf("Get initial config : %X\r\n", data);
    switch(frequency) {
        case 4000000: //4Mhz => FSEL = 00
            setConfigPage(3, ((data & 0b1100) | 0b00) & 0b00001111);
            break;
        case 8000000: //8Mhz => FSEL = 01
            setConfigPage(3, ((data & 0b1100) | 0b01) & 0b00001111);
            break;
        case 12000000: //12Mhz => FSEL = 10
            setConfigPage(3, ((data & 0b1100) | 0b10) & 0b00001111);
            break;
        case 16000000: //16Mhz => FSEL = 11
            setConfigPage(3, ((data & 0b1100) | 0b11) & 0b00001111);
            break;
        default: // default 8Mhz
            setConfigPage(3, ((data & 0b1100) | 0b00) & 0b00001111);
            break;
    }
}

int RFIDer::getClockFrequency()
{
    char page = getConfigPage(3);
    switch(page & 0b00000011) {
        case 0 :
            return 4000000;
        case 1 :
            return 8000000;
        case 2 :
            return 12000000;
        case 3 :
            return 16000000;
        default :
            return 0;
    }
}

int RFIDer::getAntennaStatus()
{
    char page = getConfigPage(3);
    return ((page & 0b00010000) >> 4);
}

char RFIDer::readPhase()
{
    return sendCmd(0b00001000); // response : 0 0 D5-D0
}

char RFIDer::sendCmd(char cmd)
{
    int i;
    bool b;
    char response = 0;
    // initialisation
    clk = 1; //CLK High
    wait_us(Tserial);
    mosi = 0;
    wait_us(Tserial);
    mosi = 1;
    wait_us(Tserial);
    //8 clock periods to send the commands
    for (i=7; i>=0; i--) {
        // Falling edge
        clk = 0;
        b = (cmd & ( 1 << i )) >> i;
        mosi = b;
        wait_us(Tserial);
        // Rising edge
        clk = 1;
        wait_us(Tserial);
    }
    // 8 clocks period for data
    for (i=7; i>=0; i--) {
        // Falling edge
        clk = 0;
        wait_us(Tserial);
        clk = 1;
        //Rising edge
        b = miso;
        response = response | (b << i);
        wait_us(Tserial);
    }
    clk = 0;
    mosi = 1;
    return response;
}

void RFIDer::startReadingTag()
{
    int i;
    // initialisation
    clk = 1; //CLK High
    wait_us(Tserial);
    mosi = 0;
    wait_us(Tserial);
    mosi = 1;
    wait_us(Tserial);
    //8 clock periods to send the commands
    for (i=2; i>=0; i--) {
        // Falling edge
        clk = 0;
        mosi = 1;
        wait_us(Tserial);
        // Rising edge
        clk = 1;
        wait_us(Tserial);
    }
    clk = 0;
    mosi = 0;
    // Preparing for decoding
    timer.reset();
    tagAvailable = 0;
    // Attach interrupt for tag reading
    data.rise(this, &RFIDer::ISR_tag_reading);
    data.fall(this, &RFIDer::ISR_tag_reading);
    data.enable_irq(); // gr
}

void RFIDer::stopReadingTag()
{
    // Disable isr
    data.disable_irq();
    clk = 0; //CLK low
    wait_us(Tserial);
    clk = 1; //CLK high
}

void RFIDer::ISR_tag_reading()
{
    // Timer management
    timer.stop();
    int delay = timer.read_us(); // Save delay between the last 2 rises
    timer.reset();
    timer.start();

    static char counter = 0;    // '1' header counter
    static char bit_i = 0;      // bit Array index
    static TagReaderState tagReaderState = IDLE;

    // Decoding bit
    char bit = decodeBit(delay);
    if(bit == -1) { // Not synchronized or an error occurred
        tagReaderState = IDLE; // Reset the tag reader
        counter = 0;
        bit_i = 0;
        return;
    } else if(bit == 2) // Single short edge detected : bit value is unknown
        return; // Nothing to do : wait for the next edge

    // FSM : TAG READER
    switch(tagReaderState) {
            /*
             * Looking for the nine 1 header
             */
        case IDLE :
            if(bit == 1) { // If '1' is read
                counter++;
            } else { // If '0' is read
                counter = 0; // Start again
            }

            if(counter == 9) { // If 9 following '1' are read
                counter = 0;
                bit_i = 0;
                tagReaderState = READING;
            }
            break;
            /*
             * Header has been found : Reading stream
             */
        case READING:
            array[bit_i] = bit;
            bit_i++;

            if(bit_i > 54) { // A complete transponder memory has been read
                timer.stop();               // Stop timer
                timer.reset();              // Reset timer
                data.disable_irq();         // Disable interrupts
                // Check data integrity (row even parity, column even parity and stop bit)
                if(checkDataIntegrity()) { // Data is ok
                    decodeTag();            // Read tag
                    tagAvailable = 1;       // Set flag
                    tagReaderState = DONE;  // Change FSM state
                } else { // Corrupted data : start again !
                    tagReaderState = IDLE;
                }
                data.enable_irq();          // Reactivating interrupts
            }
            break;
            /*
             *  A tag reading has been done : immediately relaunching the FSM
             */
        case DONE :
            counter = 0;
            bit_i = 0;                // Reset array pointer
            data.enable_irq();
            tagReaderState = IDLE;
            break;
            /*
             * Default case
             */
        default :
            tagReaderState = IDLE;
            break;
    }
}

char RFIDer::decodeBit(int delay)
{
    static DecoderState decoderState = SYNC;
    static char lastBit = 0;
    static char TdelayCounter = 0;
    char currentBit = -1; // Error default value

    switch(decoderState) {
            /*  Synchronisation with the clock
             *  The routine looks for a Tdatarate-delay between 2 edges
             */
        case SYNC :
            if(delay > 0.75*2*Tdata && delay < 1.25*2*Tdata) {
                lastBit = miso;
                decoderState = READY;
            }
            break;

            /* Decoder is ready to decode stream
             */
        case READY :
            if(delay > 0.70*Tdata && delay < 1.30*Tdata) {
                TdelayCounter++;
                if(TdelayCounter == 2) { // 2nd consecutive T-delay edge
                    TdelayCounter = 0;
                    currentBit = lastBit;
                } else currentBit = 2; // Undetermined value : waiting for a second edge
            } else if(delay > 0.70*2*Tdata && delay < 1.30*2*Tdata) {
                if(TdelayCounter == 1) { // Error
                    TdelayCounter = 0;
                    decoderState = SYNC; // Try to resynchronize
                } else {
                    currentBit = !lastBit;
                    lastBit = !lastBit;
                }
            } else { // Error (delay too small or too big)
                TdelayCounter = 0;
                decoderState = SYNC; // Try to resynchronize
            }
            break;
        default : // Error
            TdelayCounter = 0;
            decoderState = SYNC; // Try to resynchronize
            break;
    }
    return currentBit;
}

char RFIDer::checkDataIntegrity(void)
{
    char sum = 0;

    // Check if last bit is not Stop bit
    if(array[54] != 0) {
        return 0;
    }

    // Even parity row check
    for (int row = 0 ; row <= 9 ; row++) {
        sum = 0;
        for (int i = 0; i <=4 ; i++) {
            //printf("%d",array[5*row+i]);
            if(i == 4) { // End of row
                if(sum%2 != array[5*row+i]) {
                    //printf("Row parity error!\n\r");
                    return 0;
                }
                //else printf("\n\r");
            }
            sum+=array[5*row+i];
        }
    }

    // Even parity column check
    for (int col=0 ; col <= 3 ; col++) {
        sum = 0;
        for (int i = 0; i <=10 ; i++) {
            if(i == 10) { // End of column
                if(sum%2 != array[col+5*i]) {
                    //printf("Col parity error!\n\r");
                    return 0;
                }
            }
            sum+=array[col+5*i];
        }
    }

    return 1;
}


void RFIDer::decodeTag(void)
{
    /* Init tag */
    for(char i = 0 ; i < 10 ; i++) {
        tag[i] = 0; // init
    }
    /* Get 10-hex half bytes id */
    for (char row = 0 ; row < 10 ; row++) {
        for (char col = 0; col < 4 ; col++) {
            tag[row/2]+=array[5*row+col] << ((3-col) + 4*((row+1)%2));
        }
    }
}
/*
void RFIDer::decodeTag(void)
{

     // Get 8-hex word id
     for (int row = 0 ; row <= 7 ; row++) {
         tag[row] = 0; // init
         for (int i = 0; i <=3 ; i++) {
             tag[row]+=array[5*(row+2)+i] << (3-i);
         }
     }
}
*/
char* RFIDer::getTag(void)
{
    tagAvailable = 0; // Reset flag
    return tag;
}

bool RFIDer::isTagAvailable(void)
{
    return tagAvailable;
}