Classe de gestion du HTRC110
Diff: RFIDer.cpp
- Revision:
- 0:ec877e8509d0
- Child:
- 1:02db8b7c40fb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RFIDer.cpp Tue May 02 13:45:17 2017 +0000 @@ -0,0 +1,386 @@ +#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); +} + +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){ + // 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; +} \ No newline at end of file