Work in Card->Reader direction only, WIP

(cherry picked from commit 9ce138c)
This commit is contained in:
chenzitai
2018-08-15 22:44:41 +01:00
parent 38b7ea459a
commit fd57c63ba8
5 changed files with 156 additions and 60 deletions
+145 -53
View File
@@ -50,6 +50,7 @@ void Reader14443ACodecInit(void) {
CodecInitCommon();
CodecSetDemodPower(true);
CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1;
CODEC_TIMER_SAMPLING.CCB = 0;
CODEC_TIMER_SAMPLING.CCC = 0;
@@ -66,9 +67,11 @@ void Reader14443ACodecInit(void) {
Flags.RxDone = false;
}
void Reader14443ACodecDeInit(void) {
CodecSetDemodPower(false);
CodecReaderFieldStop();
// CodecReaderFieldStop();
CODEC_TIMER_SAMPLING.CTRLA = 0;
CODEC_TIMER_SAMPLING.INTCTRLB = 0;
CODEC_TIMER_LOADMOD.CTRLA = 0;
@@ -94,8 +97,11 @@ INLINE void Insert1(void)
*CodecBufferPtr++ = SampleRegister;
}
// End of Card-> reader communication and enter frame delay time
INLINE void Reader14443A_EOC(void)
{
CODEC_TIMER_LOADMOD.INTCTRLB = 0;
CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc;
CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0;
@@ -128,6 +134,7 @@ INLINE void Reader14443A_EOC(void)
INLINE void BufferToSequence(void)
{
uint16_t count = BitCount;
if (count > BITS_PER_BYTE * CODEC_BUFFER_SIZE / 2) // todo is this correct?
return;
@@ -138,6 +145,7 @@ INLINE void BufferToSequence(void)
uint8_t * Buffer = CodecBuffer + CODEC_BUFFER_SIZE / 2;
CodecBufferPtr = CodecBuffer;
// Modified Miller Coding ISO14443-2 8.1.3
Insert1(); // SOC
Insert0();
@@ -175,12 +183,14 @@ INLINE void BufferToSequence(void)
if (BitCount % 8)
CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8));
}
// Frame Delay Time PCD to PICC ends
ISR (TCD0_CCC_vect)
{
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm;
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc;
/* Enable the AC interrupt, which either finds the SOC and then starts the pause-finding timer,
* or it is triggered before the SOC, which mostly isn't bad at all, since the first pause
* needs to be found. */
@@ -192,6 +202,7 @@ ISR (TCD0_CCC_vect)
SampleRegister = 0x00;
RxPendingSince = SystemGetSysTick();
Flags.RxPending = true;
// reset for future use
@@ -202,8 +213,11 @@ ISR (TCD0_CCC_vect)
PORTE.OUTTGL = PIN3_bm;
}
// Reader -> card send bits finished
// Start Frame delay time PCD to PICC
void Reader14443AMillerEOC(void)
{
CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1;
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm | TC0_CCCIF_bm;
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc | TC_CCCINTLVL_HI_gc;
@@ -211,21 +225,32 @@ void Reader14443AMillerEOC(void)
PORTE.OUTTGL = PIN3_bm;
}
// EOC of Card->Reader found
ISR(CODEC_TIMER_TIMESTAMPS_CCA_VECT) // EOC found
{
Reader14443A_EOC();
}
// This interrupt find Card -> Reader SOC
ISR(ACA_AC1_vect) // this interrupt either finds the SOC or gets triggered before
{
LED_PORT.OUTSET=LED_RED;
ACA.AC1CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt
// enable the pause-finding timer
CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH0_gc;
CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc;
}
// Decode the Card -> Reader signal
// according to the pause and modulated period
// if the half bit duration is modulated, then add 1 to buffer
// if the half bit duration is not modulated, then add 0 to buffer
ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found
{
uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL;
CODEC_TIMER_TIMESTAMPS.CNT = 0;
@@ -266,23 +291,72 @@ ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found
return;
}
static void StartDemod(void){
LED_PORT.OUTCLR = LED_RED;
/*
* Prepare for Manchester decoding.
* The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal
* passes a (configurable) threshold. This is realized with the event system and an analog
* comparator.
* Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we
* assume there is a pause. Now we read the second timers count value and can decide how many
* bit halves had modulations since the last pause.
*/
// Comparator ADC
/* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */
ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm;
/* This timer will be used to detect the pauses between the modulation sequences. */
CODEC_TIMER_LOADMOD.CTRLA = 0;
CODEC_TIMER_LOADMOD.CNT = 0;
CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width
CODEC_TIMER_LOADMOD.CCA = 95; // with 27.12 MHz this is 3/4 of a half bit width
CODEC_TIMER_LOADMOD.INTCTRLA = 0;
CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCAIF_bm;
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_HI_gc;
/* This timer will be used to find out how many bit halfs since the last pause have been passed. */
CODEC_TIMER_TIMESTAMPS.CNT = 0; // Reset timer
CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF;
CODEC_TIMER_TIMESTAMPS.CCA = 160;
CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0;
CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCAIF_bm; // Clear interrupt flag
CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_LO_gc;
/* Use the event system for resetting the pause-detecting timer. */
EVSYS.CH0MUX = EVSYS_CHMUX_ACA_CH1_gc; // on every ACA_AC1 INT
EVSYS.CH0CTRL = EVSYS_DIGFILT_1SAMPLE_gc;
ACA.AC0CTRL = 0;
CODEC_DEMOD_IN_PORT.INTCTRL = 0;
}
void Reader14443ACodecTask(void)
{
if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1)
{
Reader14443A_EOC();
BitCount = 0;
Flags.RxDone = true;
Flags.RxPending = false;
}
if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady())
return;
// Waiting for response time out
// if (Flags.RxPending && SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1)
// {
// Reader14443A_EOC();
// BitCount = 0;
// Flags.RxDone = true;
// Flags.RxPending = false;
// }
// if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady())
// return;
if (!Flags.RxPending && (Flags.Start || Flags.RxDone))
{
if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) // we are in frame delay time, so we can return later
return;
// if (State == STATE_FDT && CODEC_TIMER_LOADMOD.CNT < ISO14443A_PICC_TO_PCD_MIN_FDT) { // we are in frame delay time, so we can return later
// return;
// }
if (Flags.RxDone && BitCount > 0) // decode the raw received data
{
if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2)
{
BitCount = 0;
@@ -296,6 +370,8 @@ void Reader14443ACodecTask(void)
bool breakflag = false;
TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored
// Manchester Code ISO14443-2 8.2.5
while (!breakflag && BitCountTmp < TotalBitCount)
{
uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03;
@@ -322,9 +398,11 @@ void Reader14443ACodecTask(void)
}
if (BitCount % 8) // copy the last byte, if there is an incomplete byte
CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8));
LEDHook(LED_CODEC_RX, LED_PULSE);
LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8);
Flags.RxPending=true;
}
}
Flags.Start = false;
Flags.RxDone = false;
@@ -332,55 +410,31 @@ void Reader14443ACodecTask(void)
/* Call application with received data */
BitCount = ApplicationProcess(CodecBuffer, BitCount);
if (BitCount > 0)
// Application have data to be sent
if (false)//BitCount > 0)
{
/*
* Prepare for Manchester decoding.
* The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal
* passes a (configurable) threshold. This is realized with the event system and an analog
* comparator.
* Once this timer reaches 3/4 of a bit half (this means it has not been reset this long), we
* assume there is a pause. Now we read the second timers count value and can decide how many
* bit halves had modulations since the last pause.
*/
/* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */
ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm;
/* This timer will be used to detect the pauses between the modulation sequences. */
CODEC_TIMER_LOADMOD.CTRLA = 0;
CODEC_TIMER_LOADMOD.CNT = 0;
CODEC_TIMER_LOADMOD.PER = 0xFFFF; // with 27.12 MHz this is exactly one half bit width
CODEC_TIMER_LOADMOD.CCA = 95; // with 27.12 MHz this is 3/4 of a half bit width
CODEC_TIMER_LOADMOD.INTCTRLA = 0;
CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCAIF_bm;
CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_HI_gc;
/* This timer will be used to find out how many bit halfs since the last pause have been passed. */
CODEC_TIMER_TIMESTAMPS.CNT = 0;
CODEC_TIMER_TIMESTAMPS.PER = 0xFFFF;
CODEC_TIMER_TIMESTAMPS.CCA = 160;
CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0;
CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCAIF_bm;
CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_LO_gc;
/* Use the event system for resetting the pause-detecting timer. */
EVSYS.CH0MUX = EVSYS_CHMUX_ACA_CH1_gc; // on every ACA_AC1 INT
EVSYS.CH0CTRL = EVSYS_DIGFILT_1SAMPLE_gc;
ACA.AC0CTRL = 0;
CODEC_DEMOD_IN_PORT.INTCTRL = 0;
StartDemod();
LEDHook(LED_CODEC_TX, LED_PULSE);
LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8);
/* Set state and start timer for Miller encoding. */
// Send bits to card using TCD0_CCB interrupt (See Reader14443-ISR.S)
BufferToSequence();
State = STATE_MILLER_SEND;
CodecBufferPtr = CodecBuffer;
CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm;
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_HI_gc;
_delay_loop_1(85);
_delay_loop_1(85); // Wait for sending to finish
}else{ // No data need to be send or in SNIFFING mode
// TODO: add another sniff flag, in case of no Application data need to be send (Non sniffing mode)
StartDemod();
Reader14443AMillerEOC();
// Sniffing mode, enable sampling interrupt only
}
}
}
@@ -391,7 +445,7 @@ void Reader14443ACodecStart(void)
BitCount = 0;
Flags.Start = true;
CodecReaderFieldStart();
// CodecReaderFieldStart();
}
void Reader14443ACodecReset(void)
@@ -400,5 +454,43 @@ void Reader14443ACodecReset(void)
State = STATE_IDLE;
Flags.RxDone = false;
Flags.Start = false;
CodecReaderFieldStop();
//CodecReaderFieldStop();
}
void TestSniff14443ACodecInit(void){
////////////////////////////
// Same as reader init
/* Initialize common peripherals and start listening
* for incoming data. */
CodecInitCommon();
CodecSetDemodPower(true);
CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1;
CODEC_TIMER_SAMPLING.CCB = 0;
CODEC_TIMER_SAMPLING.CCC = 0;
CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc;
CODEC_TIMER_SAMPLING.INTCTRLA = 0;
CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc;
CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc;
CODEC_TIMER_LOADMOD.CTRLA = 0;
State = STATE_IDLE;
BitCount = 0;
Flags.Start = false;
Flags.RxPending = false;
Flags.RxDone = false;
///////////////////////////
Flags.Start = true;
// Flags.RxPending = true;
//LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18);
//Reader14443A_EOC();
}
@@ -15,6 +15,7 @@
void Reader14443ACodecInit(void);
void Reader14443ACodecDeInit(void);
void Reader14443ACodecTask(void);
void TestSniff14443ACodecInit(void);
/* Application Interface */
void Reader14443ACodecStart(void);
@@ -13,13 +13,16 @@
#include <util/delay.h>
void Sniff14443ACodecInit(void){
void Sniff14443ACodecInit(void)
{
}
void Sniff14443ACodecDeInit(void) {
void Sniff14443ACodecDeInit(void)
{
Reader14443ACodecDeInit();
}
void Sniff14443ACodecTask(void)
{
Reader14443ACodecTask();
}
+3 -3
View File
@@ -188,9 +188,9 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = {
#endif
#ifdef CONFIG_ISO14443A_SNIFF_SUPPORT
[CONFIG_ISO14443A_SNIFF] = {
.CodecInitFunc = ISO14443ACodecInit,
.CodecDeInitFunc = ISO14443ACodecDeInit,
.CodecTaskFunc = ISO14443ACodecTask,
.CodecInitFunc = TestSniff14443ACodecInit,
.CodecDeInitFunc = Reader14443ACodecDeInit,
.CodecTaskFunc = Reader14443ACodecTask,
.ApplicationInitFunc = ApplicationInitDummy,
.ApplicationResetFunc = ApplicationResetDummy,
.ApplicationTaskFunc = ApplicationTaskDummy,
+1 -1
View File
@@ -92,7 +92,7 @@ TARGET = Chameleon-Mini
OPTIMIZATION = s
SRC += $(TARGET).c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c
SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Terminal/CommandLine.c
SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/Reader14443-ISR.S
SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S
SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c
SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
LUFA_PATH = ../LUFA