diff --git a/trunk/NfcEmul/nfcemulator.c b/trunk/NfcEmul/nfcemulator.c new file mode 100644 index 0000000..ec474e4 --- /dev/null +++ b/trunk/NfcEmul/nfcemulator.c @@ -0,0 +1,396 @@ +/***************************************************************************** +Written and Copyright (C) by Nicolas Kruse + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*****************************************************************************/ + +#include +#include +#include "nfcemulator.h" + +static uint8_t RX_MASK[18] = {0, 1, 0, 2, 0, 4, 0, 8, 0, 16, 0, 32, 0, 64, 0, 128, 0, 0}; +static uint8_t TX_MASK[8] = {1, 2, 4, 8, 16, 32, 64, 128}; +static uint16_t FDT_DELAY[2] = {FDT_DELAY_BIT0, FDT_DELAY_BIT1}; + +static uint8_t REQA[1] = {0x26}; +static uint8_t WUPA[1] = {0x52}; +static uint8_t HLTA[4] = {0x50, 0x00, 0x57, 0}; //'50' '00' CRC_A +static uint8_t ATQA[2] = {0x44, 0x00}; //Anticollision with udi size = double +static uint8_t SEL_CL1[2] = {0x93, 0x20}; +static uint8_t SEL_CL2[2] = {0x95, 0x20}; +static uint8_t CT_UID1[5] = {0x88, 0x04, 0xE3, 0xEF, 0}; //uid0 uid1 uid2 uid3 BCC +static uint8_t UID2[5] = {0xA2, 0xEF, 0x20, 0x80, 0}; //uid3 uid4 uid5 uid6 BCC +static uint8_t SAK_NC[3] = {0x04, 0xDA, 0x17}; //Select acknowledge uid not complete +static uint8_t SAK_C[3] = {0x00, 0xFE, 0x51}; //Select acknowledge uid complete, Type 2 (PICC not compliant to ISO/IEC 14443-4) +static uint8_t READ[1] = {0x30}; +static uint8_t WRITE[1] = {0xA2}; + +uint8_t *sto; //Pointer to tag content +uint16_t stoSize; //Number of avalible bytes on the tag + +uint8_t buffer[64]; +uint8_t rCount = 0; + +void setupNfcEmulator(uint8_t *storage, uint16_t storageSize) +{ + //clock divider for 8 bit timer0: clk/1 -> 13.5225 MHz + TCCR0B |= (1<> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4); + } while (--Length); + + *Data = (uint8_t) (wCrc & 0xFF); + Data++; + *Data = (uint8_t) ((wCrc >> 8) & 0xFF); +} + + +void addBcc(uint8_t *Data) //add exclusive-OR of 4 bytes +{ + Data[4] = Data[0] ^ Data[1] ^ Data[2] ^ Data[3]; +} + +void waitForBitend() +{ + while(!(TIFR1 & (1< 7) + { + if (parity) + { + waitForOneBitTime(); + DDRB &= ~(1<<2); + waitForOneBitTime(); + DDRB |= (1<<2); + } + else + { + waitForOneBitTime(); + DDRB |= (1<<2); + waitForOneBitTime(); + DDRB &= ~(1<<2); + } + + txBytePos++; + txbitPos=0; + parity = 0; + } + } + while(txBytePos < length); + + //Send EOC + waitForOneBitTime(); + DDRB &= ~(1<<2); +} + +inline void resetRxFlags() +{ + TCNT1 = 0; + TIFR1 |= (1< CMIN)) + { + t = TCNT1; + resetRxFlags(); + + hbitPos += (t > CLCS) + (t > CLCM); + + if(hbitPos > 17) + { + bytePos++; + hbitPos -= 18; + buffer[bytePos] = 0; + } + + buffer[bytePos] |= RX_MASK[hbitPos]; + + hbitPos += 2; + } //34 or 41 (hbitPos > 17) click cycles + } + while(~TIFR1 & (1< 7) bytePos++; + + return bytePos; +} + +void sendData(uint8_t block) +{ + uint8_t i = 0; + uint16_t pos = (uint16_t)block * 4; + + for(i=0; i < 16; i++) + { + if (pos >= stoSize) + { + buffer[i] = 0; + } + else + { + buffer[i] = sto[pos]; + } + + pos++; + } + + addCrc16(buffer, 16); + txManchester(buffer, 18); +} + +void receiveData(uint8_t block) +{ + uint8_t i = 0; + uint16_t pos = (uint16_t)block * 4; + uint8_t crc1 = buffer[6]; + uint8_t crc2 = buffer[7]; + + addCrc16(buffer, 6); + + if (buffer[6] == crc1 && buffer[7] == crc2) + { + for(i=2; i < 6; i++) //byte 2-5 contains Data + { + if (pos < stoSize) sto[pos] = buffer[i]; + pos++; + } + + buffer[0] = 0x0A; //ACK + txManchester(buffer, 1); + } + else + { + buffer[0] = 0x01; //NAK for CRC error + txManchester(buffer, 1); + } +} + +void checkForNfcReader() +{ + uint8_t bytes = 1; + uint8_t state = 0; + uint8_t cdow = 8; + + if (ACSR & (1< 0) + { + bytes = rxMiller(); + + if ((state & 7) == S_READY) + { + if (buffer[0] == SEL_CL1[0] && buffer[1] == SEL_CL1[1] ) + { + txManchester(CT_UID1, sizeof(CT_UID1)); + } + else if (buffer[0] == SEL_CL2[0] && buffer[1] == SEL_CL2[1] ) + { + txManchester(UID2, sizeof(UID2)); + } + else if (buffer[0] == SEL_CL1[0] && buffer[1] == 0x70 ) + { + txManchester(SAK_NC, sizeof(SAK_NC)); + } + else if (buffer[0] == SEL_CL2[0] && buffer[1] == 0x70 ) + { + txManchester(SAK_C, sizeof(SAK_C)); + state++; //Set state to ACTIVE + } + else + { + state &= 8; //Set state to IDLE/HALT + } + } + else if ((state & 7) == S_ACTIVE) + { + if (buffer[0] == READ[0]) + { + sendData(buffer[1]); + } + else if (buffer[0] == WRITE[0]) + { + receiveData(buffer[1]); + } + else if (buffer[0] == HLTA[0] && buffer[2] == HLTA[2] ) + { + state = S_HALT; + } + else if(bytes) + { + state &= 8; //Set state to IDLE/HALT + } + } + else if (bytes == 1 && (buffer[0] == REQA[0] || buffer[0] == WUPA[0])) //state == S_IDLE + { + txManchester(ATQA, sizeof(ATQA)); + state = (state & 8) + S_READY; //Set state to READY + } + + cdow -= (bytes == 0); + } + AIN1_PRNG |= (1<