Some bugs fixed for the use with none 13.56 MHz crystals

This commit is contained in:
mail001@ntalk.de 2013-11-20 21:13:36 +00:00
parent e384b912dc
commit 2b8fb8e0f7
1 changed files with 400 additions and 395 deletions

View File

@ -1,396 +1,401 @@
/***************************************************************************** /*****************************************************************************
Written and Copyright (C) by Nicolas Kruse Written and Copyright (C) by Nicolas Kruse
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*****************************************************************************/ *****************************************************************************/
#include <avr/io.h> #include <avr/io.h>
#include <util/delay.h> #include <util/delay.h>
#include "nfcemulator.h" #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 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 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 uint16_t FDT_DELAY[2] = {FDT_DELAY_BIT0, FDT_DELAY_BIT1};
static uint8_t REQA[1] = {0x26}; static uint8_t REQA[1] = {0x26};
static uint8_t WUPA[1] = {0x52}; static uint8_t WUPA[1] = {0x52};
static uint8_t HLTA[4] = {0x50, 0x00, 0x57, 0}; //'50' '00' CRC_A 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 ATQA[2] = {0x44, 0x00}; //Anticollision with udi size = double
static uint8_t SEL_CL1[2] = {0x93, 0x20}; static uint8_t SEL_CL1[2] = {0x93, 0x20};
static uint8_t SEL_CL2[2] = {0x95, 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 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 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_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 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 READ[1] = {0x30};
static uint8_t WRITE[1] = {0xA2}; static uint8_t WRITE[1] = {0xA2};
uint8_t *sto; //Pointer to tag content uint8_t *sto; //Pointer to tag content
uint16_t stoSize; //Number of avalible bytes on the tag uint16_t stoSize; //Number of avalible bytes on the tag
uint8_t buffer[64]; uint8_t buffer[64];
uint8_t rCount = 0; uint8_t rCount = 0;
void setupNfcEmulator(uint8_t *storage, uint16_t storageSize) void setupNfcEmulator(uint8_t *storage, uint16_t storageSize)
{ {
//clock divider for 8 bit timer0: clk/1 -> 13.5225 MHz //clock divider for 8 bit timer0: clk/1 -> 13.5225 MHz
TCCR0B |= (1<<CS00); TCCR0B |= (1<<CS00);
//8 bit timer0: Toggle OC0A on Compare Match and CTC-Mode //8 bit timer0: Toggle OC0A on Compare Match and CTC-Mode
//for 847.5 kHz subcarrier //for 847.5 kHz subcarrier
TCCR0A |= (1<<COM0A0) | (1<<WGM01); TCCR0A |= (1<<COM0A0) | (1<<WGM01);
//set up 847.5 kHz subcarrier for sending (8 bit timer0) //set up 847.5 kHz subcarrier for sending (8 bit timer0)
OCR0A = SUBC_OVF; OCR0A = SUBC_OVF;
//CTC-Mode and no clock divider for 16 bit timer1: clk/1 //CTC-Mode and no clock divider for 16 bit timer1: clk/1
TCCR1B = (1<<WGM12) | (1<<CS10); TCCR1B = (1<<WGM12) | (1<<CS10);
//Setup Analog Comparator, Enable (ACD), Set Analog Comparator //Setup Analog Comparator, Enable (ACD), Set Analog Comparator
//Interrupt Flag on Rising Output Edge (ACIS0, ACIS1) //Interrupt Flag on Rising Output Edge (ACIS0, ACIS1)
ACSR = (0<<ACD) | (1<<ACIS0) | (1<<ACIS1); ACSR = (0<<ACD) | (1<<ACIS0) | (1<<ACIS1);
addCrc16(HLTA); addCrc16(HLTA);
addBcc(CT_UID1); addBcc(CT_UID1);
addBcc(UID2); addBcc(UID2);
stoSize = storageSize; stoSize = storageSize;
sto = storage; sto = storage;
} }
void addCrc16(uint8_t *Data, uint8_t Length) void addCrc16(uint8_t *Data, uint8_t Length)
{ {
uint8_t ch; uint8_t ch;
uint16_t wCrc = 0x6363; // ITU-V.41 uint16_t wCrc = 0x6363; // ITU-V.41
do { do {
ch = *Data++; ch = *Data++;
ch = (ch^(uint8_t)((wCrc) & 0x00FF)); ch = (ch^(uint8_t)((wCrc) & 0x00FF));
ch = (ch^(ch<<4)); ch = (ch^(ch<<4));
wCrc = (wCrc >> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4); wCrc = (wCrc >> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4);
} while (--Length); } while (--Length);
*Data = (uint8_t) (wCrc & 0xFF); *Data = (uint8_t) (wCrc & 0xFF);
Data++; Data++;
*Data = (uint8_t) ((wCrc >> 8) & 0xFF); *Data = (uint8_t) ((wCrc >> 8) & 0xFF);
} }
void addBcc(uint8_t *Data) //add exclusive-OR of 4 bytes void addBcc(uint8_t *Data) //add exclusive-OR of 4 bytes
{ {
Data[4] = Data[0] ^ Data[1] ^ Data[2] ^ Data[3]; Data[4] = Data[0] ^ Data[1] ^ Data[2] ^ Data[3];
} }
void waitForBitend() void waitForBitend()
{ {
while(!(TIFR1 & (1<<OCF1A))); //Wait till end of bit-time while(!(TIFR1 & (1<<OCF1A))); //Wait till end of bit-time
TIFR1 |= (1<<OCF1A); TIFR1 |= (1<<OCF1A);
} }
#if (F_CPU == RFID_FREQU) #if (F_CPU == RFID_FREQU)
void waitForOneBitTime() void waitForOneBitTime()
{ {
waitForBitend(); waitForBitend();
} }
#elif (F_CPU == 22000000UL) #elif (F_CPU == 22000000UL)
//Skip every 17 bit times 1 cycle //Skip every 17 bit times 1 cycle
void waitForOneBitTime() void waitForOneBitTime()
{ {
if (rCount < 17) if (rCount < 7)
{ {
OCR1AL = CLC_PBIT / 2 - 1; OCR1AL = CLC_PBIT / 2 - 1;
rCount++; rCount++;
} }
else else
{ {
OCR1AL = CLC_PBIT / 2 - 2; OCR1AL = CLC_PBIT / 2 - 2;
rCount = 0; rCount = 0;
} }
waitForBitend(); waitForBitend();
} }
#elif (F_CPU == 13592500UL) #elif (F_CPU == 13592500UL)
//Add every 6 bit times 1 cycle //Add every 6 bit times 1 cycle
void waitForOneBitTime() void waitForOneBitTime()
{ {
if (rCount < 6) if (rCount < 6)
{ {
OCR1AL = CLC_PBIT / 2 - 1; OCR1AL = CLC_PBIT / 2 - 1;
rCount++; rCount++;
} }
else else
{ {
OCR1AL = CLC_PBIT / 2; OCR1AL = CLC_PBIT / 2;
rCount = 0; rCount = 0;
} }
waitForBitend(); waitForBitend();
} }
#else #else
#error "Not supported frequency, please add support if possible" #error "Not supported frequency, please add support if possible"
#endif #endif
void txManchester(uint8_t *data, uint8_t length) void txManchester(uint8_t *data, uint8_t length)
{ {
uint8_t txBytePos = 0; uint8_t txBytePos = 0;
uint8_t txbitPos = 0; uint8_t txbitPos = 0;
uint8_t parity = 0; uint8_t parity = 0;
TIFR1 |= (1<<OCF1A); TIFR1 |= (1<<OCF1A);
//Send SOC //Send SOC
waitForBitend(); waitForBitend();
DDRB |= (1<<2); DDRB |= (1<<2);
OCR1A = CLC_PBIT / 2 - 1; //Set Hi- and Low-Bit OCR1A = CLC_PBIT / 2 - 1; //Set Hi- and Low-Bit
waitForOneBitTime(); waitForOneBitTime();
DDRB &= ~(1<<2); DDRB &= ~(1<<2);
do do
{ {
if (TX_MASK[txbitPos] & data[txBytePos]) if (TX_MASK[txbitPos] & data[txBytePos])
{ {
waitForOneBitTime(); waitForOneBitTime();
DDRB |= (1<<2); DDRB |= (1<<2);
parity ^= 1; parity ^= 1;
waitForOneBitTime(); waitForOneBitTime();
DDRB &= ~(1<<2); DDRB &= ~(1<<2);
} }
else else
{ {
waitForOneBitTime(); waitForOneBitTime();
DDRB &= ~(1<<2); DDRB &= ~(1<<2);
waitForOneBitTime(); waitForOneBitTime();
DDRB |= (1<<2); DDRB |= (1<<2);
} }
txbitPos++; txbitPos++;
if (txbitPos > 7) if (txbitPos > 7)
{ {
if (parity) if (parity)
{ {
waitForOneBitTime(); waitForOneBitTime();
DDRB &= ~(1<<2); DDRB &= ~(1<<2);
waitForOneBitTime(); waitForOneBitTime();
DDRB |= (1<<2); DDRB |= (1<<2);
} }
else else
{ {
waitForOneBitTime(); waitForOneBitTime();
DDRB |= (1<<2); DDRB |= (1<<2);
waitForOneBitTime(); waitForOneBitTime();
DDRB &= ~(1<<2); DDRB &= ~(1<<2);
} }
txBytePos++; txBytePos++;
txbitPos=0; txbitPos=0;
parity = 0; parity = 0;
} }
} }
while(txBytePos < length); while(txBytePos < length);
//Send EOC //Send EOC
waitForOneBitTime(); waitForOneBitTime();
DDRB &= ~(1<<2); DDRB &= ~(1<<2);
} }
inline void resetRxFlags() inline void resetRxFlags()
{ {
TCNT1 = 0; TCNT1 = 0;
TIFR1 |= (1<<OCF1A); //Clear Timer Overflow Flag TIFR1 |= (1<<OCF1A); //Clear Timer Overflow Flag
ACSR |= (1<<ACI); //Clear Analog Comparator Interrupt Flag ACSR |= (1<<ACI); //Clear Analog Comparator Interrupt Flag
} }
uint8_t rxMiller() uint8_t rxMiller()
{ {
uint8_t t; #if (F_CPU > 16000000)
uint16_t cDown = 0xFFF; uint16_t t; //For hi cpu clock a 8 bit variable will overflow (CLCM > 0xFF)
uint8_t bytePos = 0; #else
uint8_t hbitPos = 0; uint8_t t; //For low cpu clock computing time is to low for 16bit a variable
#endif
OCR1A = CLCL-1;
buffer[0] = 0; uint16_t cDown = 0x0FFF;
uint8_t bytePos = 0;
//Wait for transmission end if there is data arriving uint8_t hbitPos = 0;
do
{ OCR1A = CLCL-1;
if (ACSR & (1<<ACI)) resetRxFlags(); buffer[0] = 0;
}
while(~TIFR1 & (1<<OCF1A)); //Wait for transmission end if there is data arriving
do
//Wait for transmission end if there is data arriving {
do if (ACSR & (1<<ACI)) resetRxFlags();
{ }
if (TIFR1 & (1<<OCF1A)) while(~TIFR1 & (1<<OCF1A));
{
TCNT1 = 0; //Wait for transmission end if there is data arriving
TIFR1 |= (1<<OCF1A); do
cDown--; {
if (!cDown) break; if (TIFR1 & (1<<OCF1A))
} {
} TCNT1 = 0;
while(~ACSR & (1<<ACI)); TIFR1 |= (1<<OCF1A);
cDown--;
if (cDown) if (!cDown) break;
{ }
resetRxFlags(); }
do while(~ACSR & (1<<ACI));
{
if ((ACSR & (1<<ACI)) && (TCNT1 > CMIN)) if (cDown)
{ {
t = TCNT1; resetRxFlags();
resetRxFlags(); do
{
hbitPos += (t > CLCS) + (t > CLCM); if ((ACSR & (1<<ACI)) && (TCNT1 > 1))
{
if(hbitPos > 17) t = TCNT1;
{ resetRxFlags();
bytePos++;
hbitPos -= 18; hbitPos += (t > CLCS) + (t > CLCM);
buffer[bytePos] = 0;
} if(hbitPos > 17)
{
buffer[bytePos] |= RX_MASK[hbitPos]; bytePos++;
hbitPos -= 18;
hbitPos += 2; buffer[bytePos] = 0;
} //34 or 41 (hbitPos > 17) click cycles }
}
while(~TIFR1 & (1<<OCF1A)); buffer[bytePos] |= RX_MASK[hbitPos];
}
hbitPos += 2;
OCR1A = FDT_DELAY[hbitPos & 1]; //Set delay for answer } //34 or 41 (hbitPos > 17) click cycles
TIFR1 |= (1<<OCF1A); }
while(~TIFR1 & (1<<OCF1A));
if (hbitPos > 7) bytePos++; }
return bytePos; OCR1A = FDT_DELAY[hbitPos & 1]; //Set delay for answer
} TIFR1 |= (1<<OCF1A);
void sendData(uint8_t block) if (hbitPos > 7) bytePos++;
{
uint8_t i = 0; return bytePos;
uint16_t pos = (uint16_t)block * 4; }
for(i=0; i < 16; i++) void sendData(uint8_t block)
{ {
if (pos >= stoSize) uint8_t i = 0;
{ uint16_t pos = (uint16_t)block * 4;
buffer[i] = 0;
} for(i=0; i < 16; i++)
else {
{ if (pos >= stoSize)
buffer[i] = sto[pos]; {
} buffer[i] = 0;
}
pos++; else
} {
buffer[i] = sto[pos];
addCrc16(buffer, 16); }
txManchester(buffer, 18);
} pos++;
}
void receiveData(uint8_t block)
{ addCrc16(buffer, 16);
uint8_t i = 0; txManchester(buffer, 18);
uint16_t pos = (uint16_t)block * 4; }
uint8_t crc1 = buffer[6];
uint8_t crc2 = buffer[7]; void receiveData(uint8_t block)
{
addCrc16(buffer, 6); uint8_t i = 0;
uint16_t pos = (uint16_t)block * 4;
if (buffer[6] == crc1 && buffer[7] == crc2) uint8_t crc1 = buffer[6];
{ uint8_t crc2 = buffer[7];
for(i=2; i < 6; i++) //byte 2-5 contains Data
{ addCrc16(buffer, 6);
if (pos < stoSize) sto[pos] = buffer[i];
pos++; if (buffer[6] == crc1 && buffer[7] == crc2)
} {
for(i=2; i < 6; i++) //byte 2-5 contains Data
buffer[0] = 0x0A; //ACK {
txManchester(buffer, 1); if (pos < stoSize) sto[pos] = buffer[i];
} pos++;
else }
{
buffer[0] = 0x01; //NAK for CRC error buffer[0] = 0x0A; //ACK
txManchester(buffer, 1); txManchester(buffer, 1);
} }
} else
{
void checkForNfcReader() buffer[0] = 0x01; //NAK for CRC error
{ txManchester(buffer, 1);
uint8_t bytes = 1; }
uint8_t state = 0; }
uint8_t cdow = 8;
void checkForNfcReader()
if (ACSR & (1<<ACI)) //13.56 MHz carrier available? {
{ uint8_t bytes = 1;
AIN1_PRNG &= ~(1<<AIN1_PORT); //Deactivate pull up to increase sensitivity uint8_t state = 0;
uint8_t cdow = 8;
while(cdow > 0)
{ if (ACSR & (1<<ACI)) //13.56 MHz carrier available?
bytes = rxMiller(); {
AIN1_PORT &= ~(1<<AIN1_BIT); //Deactivate pull up to increase sensitivity
if ((state & 7) == S_READY)
{ while(cdow > 0)
if (buffer[0] == SEL_CL1[0] && buffer[1] == SEL_CL1[1] ) {
{ bytes = rxMiller();
txManchester(CT_UID1, sizeof(CT_UID1));
} if ((state & 7) == S_READY)
else if (buffer[0] == SEL_CL2[0] && buffer[1] == SEL_CL2[1] ) {
{ if (buffer[0] == SEL_CL1[0] && buffer[1] == SEL_CL1[1] )
txManchester(UID2, sizeof(UID2)); {
} txManchester(CT_UID1, sizeof(CT_UID1));
else if (buffer[0] == SEL_CL1[0] && buffer[1] == 0x70 ) }
{ else if (buffer[0] == SEL_CL2[0] && buffer[1] == SEL_CL2[1] )
txManchester(SAK_NC, sizeof(SAK_NC)); {
} txManchester(UID2, sizeof(UID2));
else if (buffer[0] == SEL_CL2[0] && buffer[1] == 0x70 ) }
{ else if (buffer[0] == SEL_CL1[0] && buffer[1] == 0x70 )
txManchester(SAK_C, sizeof(SAK_C)); {
state++; //Set state to ACTIVE txManchester(SAK_NC, sizeof(SAK_NC));
} }
else else if (buffer[0] == SEL_CL2[0] && buffer[1] == 0x70 )
{ {
state &= 8; //Set state to IDLE/HALT txManchester(SAK_C, sizeof(SAK_C));
} state++; //Set state to ACTIVE
} }
else if ((state & 7) == S_ACTIVE) else
{ {
if (buffer[0] == READ[0]) state &= 8; //Set state to IDLE/HALT
{ }
sendData(buffer[1]); }
} else if ((state & 7) == S_ACTIVE)
else if (buffer[0] == WRITE[0]) {
{ if (buffer[0] == READ[0])
receiveData(buffer[1]); {
} sendData(buffer[1]);
else if (buffer[0] == HLTA[0] && buffer[2] == HLTA[2] ) }
{ else if (buffer[0] == WRITE[0])
state = S_HALT; {
} receiveData(buffer[1]);
else if(bytes) }
{ else if (buffer[0] == HLTA[0] && buffer[2] == HLTA[2] )
state &= 8; //Set state to IDLE/HALT {
} state = S_HALT;
} }
else if (bytes == 1 && (buffer[0] == REQA[0] || buffer[0] == WUPA[0])) //state == S_IDLE else if(bytes)
{ {
txManchester(ATQA, sizeof(ATQA)); state &= 8; //Set state to IDLE/HALT
state = (state & 8) + S_READY; //Set state to READY }
} }
else if (bytes == 1 && (buffer[0] == REQA[0] || buffer[0] == WUPA[0])) //state == S_IDLE
cdow -= (bytes == 0); {
} txManchester(ATQA, sizeof(ATQA));
AIN1_PRNG |= (1<<AIN1_PORT); //Activate pull up to prevent noise from toggling the comparator state = (state & 8) + S_READY; //Set state to READY
} }
ACSR |= (1<<ACI); //Clear comparator interrupt flag
cdow -= (bytes == 0);
}
AIN1_PORT |= (1<<AIN1_BIT); //Activate pull up to prevent noise from toggling the comparator
}
ACSR |= (1<<ACI); //Clear comparator interrupt flag
} }