From 5b46650edded2d8119c384bbde475593b24e3598 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 26 Jun 2018 23:46:36 +0100 Subject: [PATCH 01/26] Set up framework for sniffing (cherry picked from commit 8a0b331) --- Firmware/Chameleon-Mini/Codec/Codec.h | 3 +++ .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 25 +++++++++++++++++++ .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 19 ++++++++++++++ 3 files changed, 47 insertions(+) create mode 100644 Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c create mode 100644 Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index cf9d67d..0a74d25 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -17,6 +17,7 @@ #include "ISO14443-2A.h" #include "Reader14443-2A.h" +#include "SniffISO14443-2A.h" /* Timing definitions for ISO14443A */ #define ISO14443A_SUBCARRIER_DIVIDER 16 @@ -231,6 +232,7 @@ INLINE void CodecSetLoadmodState(bool bOnOff) { } } +// Turn on and off the codec Reader field INLINE void CodecSetReaderField(bool bOnOff) { // this is the function for turning on/off the reader field dumbly; before using this function, please consider to use CodecReaderField{Start,Stop} if (bOnOff) { @@ -244,6 +246,7 @@ INLINE void CodecSetReaderField(bool bOnOff) { // this is the function for turni } } +// Get the status of the reader field INLINE bool CodecGetReaderField(void) { return (CODEC_READER_TIMER.CTRLA == TC_CLKSEL_DIV1_gc) && (AWEXC.OUTOVEN == CODEC_READER_MASK); } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c new file mode 100644 index 0000000..9e98f0d --- /dev/null +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -0,0 +1,25 @@ +// +// Created by Zitai Chen on 05/07/2018. +// + +#include "SniffISO14443-2A.h" + +#include "Reader14443-2A.h" +#include "Codec.h" +#include "../System.h" +#include "../Application/Application.h" +#include "LEDHook.h" +#include "Terminal/Terminal.h" +#include + + +void Sniff14443ACodecInit(void){ + +} + +void Sniff14443ACodecDeInit(void) { + +} +void Sniff14443ACodecTask(void) +{ +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h new file mode 100644 index 0000000..eb0317a --- /dev/null +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -0,0 +1,19 @@ +// +// Created by 陈子泰 on 05/07/2018. +// + +#ifndef CHAMELEON_MINI_SNIFFISO14443_2A_H +#define CHAMELEON_MINI_SNIFFISO14443_2A_H + + +#include "Codec.h" +#include "Terminal/CommandLine.h" + +/* Codec Interface */ +void Sniff14443ACodecInit(void); +void Sniff14443ACodecDeInit(void); +void Sniff14443ACodecTask(void); + + + +#endif //CHAMELEON_MINI_SNIFFISO14443_2A_H From 38b7ea459a83b78578383710616c1f0686b59b5c Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 26 Jun 2018 23:56:25 +0100 Subject: [PATCH 02/26] Add some comments for better understanding (cherry picked from commit df39123) --- Firmware/Chameleon-Mini/Application/Reader14443A.c | 1 + Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 8 ++++++-- Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.c b/Firmware/Chameleon-Mini/Application/Reader14443A.c index b865df8..471dc30 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.c +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.c @@ -141,6 +141,7 @@ uint16_t addParityBits(uint8_t * Buffer, uint16_t BitCount) uint16_t removeParityBits(uint8_t * Buffer, uint16_t BitCount) { + // Short frame, no parity bit is added if (BitCount == 7) return 7; diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index e43ea61..ebf565b 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -66,8 +66,8 @@ static void StartDemod(void) { StateRegister = DEMOD_DATA_BIT; /* Configure sampling-timer free running and sync to first modulation-pause. */ - CODEC_TIMER_SAMPLING.CNT = 0; - CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; + CODEC_TIMER_SAMPLING.CNT = 0; // Reset the timer count + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; // Set Period regisiter CODEC_TIMER_SAMPLING.CCA = 0xFFFF; /* CCA Interrupt is not active! */ CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; @@ -79,6 +79,7 @@ static void StartDemod(void) { CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; } +// Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT0_VECT) { /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start @@ -112,6 +113,7 @@ ISR(CODEC_DEMOD_IN_INT0_VECT) { CODEC_DEMOD_IN_PORT.INT0MASK = 0; } +// Sampling with timer and demod ISR(CODEC_TIMER_SAMPLING_CCA_VECT) { /* This interrupt gets called twice for every bit to sample it. */ uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; @@ -220,6 +222,7 @@ ISR(CODEC_TIMER_SAMPLING_CCA_VECT) { CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; } +// Enumulate as a card to send card responds ISR(CODEC_TIMER_LOADMOD_OVF_VECT) { /* Bit rate timer. Output a half bit on the output. */ @@ -418,6 +421,7 @@ void ISO14443ACodecTask(void) { uint16_t AnswerBitCount = ISO14443A_APP_NO_RESPONSE; if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + // For logging data LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S b/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S index f41b045..82ba110 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-ISR.S @@ -15,6 +15,7 @@ #define AWEXC__OUTOVEN 0x088C #define CODEC_READER_TIMER__CTRLA 0x0800 +; For sending reader bits to cards .global TCD0_CCB_vect, Reader14443AMillerEOC TCD0_CCB_vect: push Zero ; 1 From fd57c63ba85d9f0de9c72f42e2810e218ddd9ada Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sat, 7 Jul 2018 00:16:18 +0100 Subject: [PATCH 03/26] Work in Card->Reader direction only, WIP (cherry picked from commit 9ce138c) --- .../Chameleon-Mini/Codec/Reader14443-2A.c | 198 +++++++++++++----- .../Chameleon-Mini/Codec/Reader14443-2A.h | 1 + .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 9 +- Firmware/Chameleon-Mini/Configuration.c | 6 +- Firmware/Chameleon-Mini/Makefile | 2 +- 5 files changed, 156 insertions(+), 60 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 6a70968..9192c1f 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -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(); + + +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h index e9a2c1e..a96fff2 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h @@ -15,6 +15,7 @@ void Reader14443ACodecInit(void); void Reader14443ACodecDeInit(void); void Reader14443ACodecTask(void); +void TestSniff14443ACodecInit(void); /* Application Interface */ void Reader14443ACodecStart(void); diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 9e98f0d..48f3ee8 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -13,13 +13,16 @@ #include -void Sniff14443ACodecInit(void){ +void Sniff14443ACodecInit(void) +{ } -void Sniff14443ACodecDeInit(void) { - +void Sniff14443ACodecDeInit(void) +{ + Reader14443ACodecDeInit(); } void Sniff14443ACodecTask(void) { + Reader14443ACodecTask(); } \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 72ffce1..22eaf3b 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -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, diff --git a/Firmware/Chameleon-Mini/Makefile b/Firmware/Chameleon-Mini/Makefile index 9d3175f..5870a2b 100644 --- a/Firmware/Chameleon-Mini/Makefile +++ b/Firmware/Chameleon-Mini/Makefile @@ -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 From 64534c8912f956a2703a769b78be52bb14a63a21 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 8 Jul 2018 01:27:05 +0100 Subject: [PATCH 04/26] Works for one round of traffic (cherry picked from commit 800f72a) --- Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 13 +++++ .../Chameleon-Mini/Codec/Reader14443-2A.c | 50 +++++++++++++++++-- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 23 ++++++++- .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 4 +- Firmware/Chameleon-Mini/Configuration.c | 6 +-- 5 files changed, 86 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index ebf565b..5d367ef 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -425,6 +425,18 @@ void ISO14443ACodecTask(void) { LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); + + if(SniffEnable == true){ + // TODO: Start interrupt for finding Card -> Reader direction traffic + + ISO14443ACodecDeInit(); + + TrafficSource = TRAFFIC_CARD; + TestSniff14443ACodecInit(); + return; + + } + /* Call application if we received data */ AnswerBitCount = ApplicationProcess(CodecBuffer, DemodBitCount); @@ -437,6 +449,7 @@ void ISO14443ACodecTask(void) { /* We have to generate the parity bits ourself */ ParityBufferPtr = 0; } + } if (AnswerBitCount != ISO14443A_APP_NO_RESPONSE) { diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 9192c1f..84a3a4a 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -130,6 +130,8 @@ INLINE void Reader14443A_EOC(void) CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; State = STATE_FDT; + + } INLINE void BufferToSequence(void) @@ -292,7 +294,6 @@ ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found } static void StartDemod(void){ - LED_PORT.OUTCLR = LED_RED; /* @@ -401,6 +402,17 @@ void Reader14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); Flags.RxPending=true; + + + if (SniffEnable) + { + + Reader14443ACodecDeInit(); + ISO14443ACodecInit(); + TrafficSource = TRAFFIC_CARD; + + return; + } } } @@ -431,8 +443,8 @@ void Reader14443ACodecTask(void) }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(); +// StartDemod(); +// Reader14443AMillerEOC(); // Sniffing mode, enable sampling interrupt only } @@ -487,10 +499,38 @@ void TestSniff14443ACodecInit(void){ /////////////////////////// Flags.Start = true; -// Flags.RxPending = true; + + StartDemod(); + + // CODEC_TIMER_SAMPLING_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. */ + ACA.STATUS = AC_AC1IF_bm; + ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + + CodecBufferPtr = CodecBuffer; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister = 0x00; + + RxPendingSince = SystemGetSysTick(); + + Flags.RxPending = true; + + // reset for future use + CodecBufferIdx = 0; + BitCountUp = 0; + + State = STATE_IDLE; + PORTE.OUTTGL = PIN3_bm; + + //Flags.RxPending = true; //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); //Reader14443A_EOC(); - } \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 48f3ee8..6a20493 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -13,16 +13,37 @@ #include +bool SniffEnable; +enum RCTraffic TrafficSource; + void Sniff14443ACodecInit(void) { + SniffEnable = true; + TrafficSource = TRAFFIC_READER; + // Start with sniffing Reader->Card direction traffic + // Card -> Reader traffic sniffing interrupt will be enbaled + // when Reader-> Card direction sniffing finished + // See ISO14443-2A.c ISO14443ACodecTask() + ISO14443ACodecInit(); + + // Also configure Interrupt settings for Reader function +// Reader14443ACodecInit(); + } void Sniff14443ACodecDeInit(void) { + ISO14443ACodecDeInit(); Reader14443ACodecDeInit(); } void Sniff14443ACodecTask(void) { - Reader14443ACodecTask(); + if (TrafficSource == TRAFFIC_READER){ + ISO14443ACodecTask(); + } else{ + Reader14443ACodecTask(); + } +// ISO14443ACodecDeInit(); +// Reader14443ACodecTask(); } \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h index eb0317a..44d50c8 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -1,5 +1,5 @@ // -// Created by 陈子泰 on 05/07/2018. +// Created by Zitai Chen on 05/07/2018. // #ifndef CHAMELEON_MINI_SNIFFISO14443_2A_H @@ -9,6 +9,8 @@ #include "Codec.h" #include "Terminal/CommandLine.h" +extern bool SniffEnable; +extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; /* Codec Interface */ void Sniff14443ACodecInit(void); void Sniff14443ACodecDeInit(void); diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 22eaf3b..5fda354 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -188,9 +188,9 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { #endif #ifdef CONFIG_ISO14443A_SNIFF_SUPPORT [CONFIG_ISO14443A_SNIFF] = { - .CodecInitFunc = TestSniff14443ACodecInit, - .CodecDeInitFunc = Reader14443ACodecDeInit, - .CodecTaskFunc = Reader14443ACodecTask, + .CodecInitFunc = Sniff14443ACodecInit, + .CodecDeInitFunc = Sniff14443ACodecDeInit, + .CodecTaskFunc = Sniff14443ACodecTask, .ApplicationInitFunc = ApplicationInitDummy, .ApplicationResetFunc = ApplicationResetDummy, .ApplicationTaskFunc = ApplicationTaskDummy, From 288ae733089ebccf73fc5f0a30769daf95b6fdfe Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 9 Jul 2018 19:47:03 +0100 Subject: [PATCH 05/26] Remove repeately called function: CodecInitCommon and keep demod power on (cherry picked from commit 8eb0d58) --- Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 6 ++-- .../Chameleon-Mini/Codec/Reader14443-2A.c | 28 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index 5d367ef..b0db926 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -408,7 +408,9 @@ void ISO14443ACodecDeInit(void) CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); - CodecSetDemodPower(false); + if (!SniffEnable) { + CodecSetDemodPower(false); + } CodecSetLoadmodState(false); } @@ -431,8 +433,8 @@ void ISO14443ACodecTask(void) { ISO14443ACodecDeInit(); - TrafficSource = TRAFFIC_CARD; TestSniff14443ACodecInit(); + TrafficSource = TRAFFIC_CARD; return; } diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 84a3a4a..9a0719c 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -70,7 +70,7 @@ void Reader14443ACodecInit(void) { void Reader14443ACodecDeInit(void) { - CodecSetDemodPower(false); +// CodecSetDemodPower(false); // CodecReaderFieldStop(); CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; @@ -399,6 +399,9 @@ void Reader14443ACodecTask(void) } if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + +// BitCount = removeParityBits(CodecBuffer, BitCount); + LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); Flags.RxPending=true; @@ -407,9 +410,10 @@ void Reader14443ACodecTask(void) if (SniffEnable) { + LED_PORT.OUTCLR = LED_RED; Reader14443ACodecDeInit(); ISO14443ACodecInit(); - TrafficSource = TRAFFIC_CARD; + TrafficSource = TRAFFIC_READER; return; } @@ -477,9 +481,9 @@ void TestSniff14443ACodecInit(void){ * for incoming data. */ - CodecInitCommon(); +// CodecInitCommon(); - CodecSetDemodPower(true); +// CodecSetDemodPower(true); CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; CODEC_TIMER_SAMPLING.CCB = 0; @@ -493,8 +497,8 @@ void TestSniff14443ACodecInit(void){ State = STATE_IDLE; BitCount = 0; - Flags.Start = false; - Flags.RxPending = false; +// Flags.Start = false; +// Flags.RxPending = false; Flags.RxDone = false; /////////////////////////// @@ -502,9 +506,13 @@ void TestSniff14443ACodecInit(void){ StartDemod(); +// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; +// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; +// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; +// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; + PORTE.OUTTGL = PIN3_bm; + // CODEC_TIMER_SAMPLING_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, @@ -525,8 +533,8 @@ void TestSniff14443ACodecInit(void){ CodecBufferIdx = 0; BitCountUp = 0; - State = STATE_IDLE; - PORTE.OUTTGL = PIN3_bm; +// State = STATE_IDLE; +// PORTE.OUTTGL = PIN3_bm; //Flags.RxPending = true; From 43ebccbb53ee29def916c82eeda67f1865f3ff6a Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 10 Jul 2018 01:48:17 +0100 Subject: [PATCH 06/26] Remove redundancy code, disable sniff flag when deInit the siniff mode (cherry picked from commit 58df0cd) --- .../Chameleon-Mini/Codec/Reader14443-2A.c | 22 +++++++++---------- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 3 +-- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 9a0719c..0e2b794 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -496,13 +496,22 @@ void TestSniff14443ACodecInit(void){ CODEC_TIMER_LOADMOD.CTRLA = 0; State = STATE_IDLE; - BitCount = 0; +// BitCount = 0; + CodecBufferPtr = CodecBuffer; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister = 0x00; + // Flags.Start = false; // Flags.RxPending = false; Flags.RxDone = false; /////////////////////////// Flags.Start = true; + // reset for future use +// CodecBufferIdx = 0; +// BitCountUp = 0; + + Flags.RxPending = true; StartDemod(); @@ -510,7 +519,7 @@ void TestSniff14443ACodecInit(void){ // CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; // CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; // CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; - PORTE.OUTTGL = PIN3_bm; +// PORTE.OUTTGL = PIN3_bm; // CODEC_TIMER_SAMPLING_CCC_vect @@ -521,17 +530,8 @@ void TestSniff14443ACodecInit(void){ ACA.STATUS = AC_AC1IF_bm; ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - CodecBufferPtr = CodecBuffer; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister = 0x00; - RxPendingSince = SystemGetSysTick(); - Flags.RxPending = true; - - // reset for future use - CodecBufferIdx = 0; - BitCountUp = 0; // State = STATE_IDLE; // PORTE.OUTTGL = PIN3_bm; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 6a20493..6371a2e 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -28,12 +28,11 @@ void Sniff14443ACodecInit(void) // Also configure Interrupt settings for Reader function // Reader14443ACodecInit(); - - } void Sniff14443ACodecDeInit(void) { + SniffEnable = false; ISO14443ACodecDeInit(); Reader14443ACodecDeInit(); } From 4b23bc379bf10740c4ae0cb7fcf58540bc9ccec9 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 10 Jul 2018 02:16:41 +0100 Subject: [PATCH 07/26] Refactor SniffISO14443-2A code structure for further modification (cherry picked from commit cd07c68) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 6371a2e..0813e6a 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -16,6 +16,29 @@ bool SniffEnable; enum RCTraffic TrafficSource; +// Card->Reader Direction Traffic +INLINE void CardSniffInit(void) +{ + +} + +INLINE void CardSniffDeinit(void) +{ + Reader14443ACodecDeInit(); +} + +// Reader->Card Direction Traffic +INLINE void ReaderSniffInit(void) +{ + ISO14443ACodecInit(); +} + +INLINE void ReaderSniffDeInit(void) +{ + ISO14443ACodecDeInit(); +} + + void Sniff14443ACodecInit(void) { SniffEnable = true; @@ -24,7 +47,7 @@ void Sniff14443ACodecInit(void) // Card -> Reader traffic sniffing interrupt will be enbaled // when Reader-> Card direction sniffing finished // See ISO14443-2A.c ISO14443ACodecTask() - ISO14443ACodecInit(); + ReaderSniffInit(); // Also configure Interrupt settings for Reader function // Reader14443ACodecInit(); @@ -33,8 +56,9 @@ void Sniff14443ACodecInit(void) void Sniff14443ACodecDeInit(void) { SniffEnable = false; - ISO14443ACodecDeInit(); - Reader14443ACodecDeInit(); + CardSniffDeinit(); + ReaderSniffDeInit(); + } void Sniff14443ACodecTask(void) { @@ -45,4 +69,6 @@ void Sniff14443ACodecTask(void) } // ISO14443ACodecDeInit(); // Reader14443ACodecTask(); -} \ No newline at end of file +} + + From 08404604c21c951dde317ed40b165d87ee77f54c Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 10 Jul 2018 18:42:29 +0100 Subject: [PATCH 08/26] Separate Reader->Card sniffing from the ISO14443-2A code Use PORTB INT1, TCD0 CCD for sampling The card->reader sniffing of this commint may be buggy (cherry picked from commit 73b6c51) --- Firmware/Chameleon-Mini/Codec/Codec.h | 3 +- Firmware/Chameleon-Mini/Codec/ISO14443-2A.c | 19 +- .../Chameleon-Mini/Codec/Reader14443-2A.c | 3 +- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 310 +++++++++++++++++- 4 files changed, 303 insertions(+), 32 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 0a74d25..1e530bc 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -141,7 +141,8 @@ INLINE void CodecInitCommon(void) CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL0 = PORT_ISC_RISING_gc; CODEC_DEMOD_IN_PORT.CODEC_DEMOD_IN_PINCTRL1 = PORT_ISC_FALLING_gc; CODEC_DEMOD_IN_PORT.INT0MASK = 0; - CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT0LVL_HI_gc; + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT0LVL_HI_gc | PORT_INT1LVL_HI_gc; EVSYS.CH0MUX = CODEC_DEMOD_IN_EVMUX0; EVSYS.CH1MUX = CODEC_DEMOD_IN_EVMUX1; diff --git a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c index b0db926..1f9d965 100644 --- a/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/ISO14443-2A.c @@ -75,7 +75,7 @@ static void StartDemod(void) { CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCAINTLVL_HI_gc; /* Start looking out for modulation pause via interrupt. */ - CODEC_DEMOD_IN_PORT.INTFLAGS = 0x03; + CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT0IF_bm; CODEC_DEMOD_IN_PORT.INT0MASK = CODEC_DEMOD_IN_MASK0; } @@ -408,9 +408,7 @@ void ISO14443ACodecDeInit(void) CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; CodecSetSubcarrier(CODEC_SUBCARRIERMOD_OFF, 0); - if (!SniffEnable) { - CodecSetDemodPower(false); - } + CodecSetDemodPower(false); CodecSetLoadmodState(false); } @@ -427,18 +425,6 @@ void ISO14443ACodecTask(void) { LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); - - if(SniffEnable == true){ - // TODO: Start interrupt for finding Card -> Reader direction traffic - - ISO14443ACodecDeInit(); - - TestSniff14443ACodecInit(); - TrafficSource = TRAFFIC_CARD; - return; - - } - /* Call application if we received data */ AnswerBitCount = ApplicationProcess(CodecBuffer, DemodBitCount); @@ -451,7 +437,6 @@ void ISO14443ACodecTask(void) { /* We have to generate the parity bits ourself */ ParityBufferPtr = 0; } - } if (AnswerBitCount != ISO14443A_APP_NO_RESPONSE) { diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index 0e2b794..cb52073 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -412,7 +412,8 @@ void Reader14443ACodecTask(void) LED_PORT.OUTCLR = LED_RED; Reader14443ACodecDeInit(); - ISO14443ACodecInit(); + Sniff14443ACodecInit(); +// ISO14443ACodecInit(); TrafficSource = TRAFFIC_READER; return; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 0813e6a..0ab899c 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -1,5 +1,7 @@ // // Created by Zitai Chen on 05/07/2018. +// Some interrupt handling vect +// modified form ISO14443-2A.c and Reader14443-2A.c // #include "SniffISO14443-2A.h" @@ -12,14 +14,262 @@ #include "Terminal/Terminal.h" #include +/* Sampling is done using internal clock, synchronized to the field modulation. + * For that we need to convert the bit rate for the internal clock. */ +#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) + +#define ISO14443A_MIN_BITS_PER_FRAME 7 + + +/* Define pseudo variables to use fast register access. This is useful for global vars */ +#define DataRegister Codec8Reg0 +#define StateRegister Codec8Reg1 +#define ParityRegister Codec8Reg2 +#define SampleIdxRegister Codec8Reg2 +#define SampleRegister Codec8Reg3 +#define BitSent CodecCount16Register1 +#define BitCount CodecCount16Register2 +#define CodecBufferPtr CodecPtrRegister1 +#define ParityBufferPtr CodecPtrRegister2 bool SniffEnable; enum RCTraffic TrafficSource; +static volatile struct { + volatile bool DemodFinished; +// volatile bool LoadmodFinished; +} Flags = { 0 }; + +typedef enum { + /* Demod */ + DEMOD_DATA_BIT, + DEMOD_PARITY_BIT, + LOADMOD_FDT, + +} StateType; + +///////////////////////////////////////////////// +// Reader->Card Direction Traffic +///////////////////////////////////////////////// + +void ReaderSniffInit(void) +{ + /* Initialize some global vars and start looking out for reader commands */ + Flags.DemodFinished = 0; + +// ReaderStartDemod(); + + CodecBufferPtr = CodecBuffer; + ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; + DataRegister = 0; + SampleRegister = 0; + SampleIdxRegister = 0; + BitCount = 0; + StateRegister = DEMOD_DATA_BIT; + + + /* Configure sampling-timer free running and sync to first modulation-pause. */ + CODEC_TIMER_SAMPLING.CNT = 0; // Reset the timer count + CODEC_TIMER_SAMPLING.PER = SAMPLE_RATE_SYSTEM_CYCLES - 1; // Set Period regisiter + CODEC_TIMER_SAMPLING.CCD = 0xFFFF; /* CCD Interrupt is not active! */ + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_DIV1_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_HI_gc; + + /* Start looking out for modulation pause via interrupt. */ + CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT1IF_bm; + CODEC_DEMOD_IN_PORT.INT1MASK = CODEC_DEMOD_IN_MASK0; + +// ISO14443ACodecInit(); +} + + +// Find first pause and start sampling +ISR(PORTB_INT1_vect) { +// LED_PORT.OUTSET = LED_RED; + /* This is the first edge of the first modulation-pause after StartDemod. + * Now we have time to start + * demodulating beginning from one bit-width after this edge. */ + + /* Sampling timer has been preset to sample-rate and has automatically synced + * to THIS first modulation pause. Thus after exactly one bit-width from here, + * an OVF is generated. We want to start sampling with the next bit and use the + * XYZBUF mechanism of the xmega to automatically double the sampling rate on the + * next overflow. For this we have to temporarily deactivate the automatical alignment + * in order to catch next overflow event for updating the BUF registers. + * We want to sample the demodulated data stream in the first quarter of the half-bit + * where the pulsed miller encoded is located. */ + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES/2 - 1; /* Half bit width */ + CODEC_TIMER_SAMPLING.CCDBUF = SAMPLE_RATE_SYSTEM_CYCLES/8 - 14 - 1; /* Compensate for DIGFILT and ISR prolog */ + + /* Setup Frame Delay Timer and wire to EVSYS. Frame delay time is + * measured from last change in RF field, therefore we use + * the event channel 1 (end of modulation pause) as the restart event. + * The preliminary frame delay time chosen here is irrelevant, because + * the correct FDT gets set automatically after demodulation. */ + +// CODEC_TIMER_LOADMOD.CNT = 0; +// CODEC_TIMER_LOADMOD.PER = 0xFFFF; +//// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODEND_EVSEL; +//// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; +//// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; +//// CODEC_TIMER_LOADMOD.CTRLA = CODEC_TIMER_CARRIER_CLKSEL; +// +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = 0; + + /* Disable this interrupt */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; +} + +// Sampling with timer and demod +ISR(TCD0_CCD_vect) { + /* This interrupt gets called twice for every bit to sample it. */ + uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; + + /* Shift sampled bit into sampling register */ + SampleRegister = (SampleRegister << 1) | (!SamplePin ? 0x01 : 0x00); + + if (SampleIdxRegister) { + SampleIdxRegister = 0; + /* Analyze the sampling register after 2 samples. */ + if ((SampleRegister & 0x07) == 0x07) { + /* No carrier modulation for 3 sample points. EOC! */ + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + + /* By this time, the FDT timer is aligned to the last modulation + * edge of the reader. So we disable the auto-synchronization and + * let it count the frame delay time in the background, and generate + * an interrupt once it has reached the FDT. */ + // Do not activate loadmod +// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = 0; + +// if (SampleRegister & 0x08) { +// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV1 - 40; /* compensate for ISR prolog */ +// } else { +// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV0 - 40; /* compensate for ISR prolog */ +// } + + StateRegister = LOADMOD_FDT; + +// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; +// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_HI_gc; + + /* Determine if we did not receive a multiple of 8 bits. + * If this is the case, right-align the remaining data and + * store it into the buffer. */ + uint8_t RemainingBits = BitCount % 8; + if (RemainingBits != 0) { + uint8_t NewDataRegister = DataRegister; + + while (RemainingBits++ < 8) { + /* Pad with zeroes to right-align. */ + NewDataRegister >>= 1; + } + + /* TODO: Prevent buffer overflow */ + *CodecBufferPtr = NewDataRegister; + } + + /* Signal, that we have finished sampling */ + Flags.DemodFinished = 1; + } else { + /* Otherwise, we check the two sample bits from the bit before. */ + uint8_t BitSample = SampleRegister & 0xC; + uint8_t Bit = 0; + + if (BitSample != (0x0 << 2)) { + /* We have a valid bit. decode and process it. */ + if (BitSample & (0x1 << 2)) { + /* 01 sequence or 11 sequence -> This is a zero bit */ + Bit = 0; + } else { + /* 10 sequence -> This is a one bit */ + Bit = 1; + } + + if (StateRegister == DEMOD_DATA_BIT) { + /* This is a data bit, so shift it into the data register and + * hold a local copy of it. */ + uint8_t NewDataRegister = DataRegister >> 1; + NewDataRegister |= (Bit ? 0x80 : 0x00); + DataRegister = NewDataRegister; + + /* Update bitcount */ + uint16_t NewBitCount = ++BitCount; + if ((NewBitCount & 0x07) == 0) { + /* We have reached a byte boundary! Store the data register. */ + /* TODO: Prevent buffer overflow */ + *CodecBufferPtr++ = NewDataRegister; + + /* Store bit for determining FDT at EOC and enable parity + * handling on next bit. */ + StateRegister = DEMOD_PARITY_BIT; + } + + } else if (StateRegister == DEMOD_PARITY_BIT) { + /* This is a parity bit. Store it */ + *ParityBufferPtr++ = Bit; + StateRegister = DEMOD_DATA_BIT; + } else { + /* Should never Happen (TM) */ + } + } else { + /* 00 sequence. -> No valid data yet. This also occurs if we just started + * sampling and have sampled less than 2 bits yet. Thus ignore. */ + } + } + } else { + /* On odd sample position just sample. */ + SampleIdxRegister = ~SampleIdxRegister; + } + + /* Make sure the sampling timer gets automatically aligned to the + * modulation pauses by using the RESTART event. + * This can be understood as a "poor mans PLL" and makes sure that we are + * never too far out the bit-grid while sampling. */ + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; +} + + + + +INLINE void ReaderSniffDeInit(void) +{ + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + + Flags.DemodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + + +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; + +} + + + + + +///////////////////////////////////////////////// // Card->Reader Direction Traffic +///////////////////////////////////////////////// + INLINE void CardSniffInit(void) { - + TestSniff14443ACodecInit(); } INLINE void CardSniffDeinit(void) @@ -27,22 +277,20 @@ INLINE void CardSniffDeinit(void) Reader14443ACodecDeInit(); } -// Reader->Card Direction Traffic -INLINE void ReaderSniffInit(void) -{ - ISO14443ACodecInit(); -} - -INLINE void ReaderSniffDeInit(void) -{ - ISO14443ACodecDeInit(); -} void Sniff14443ACodecInit(void) { + Flags.DemodFinished = 0; + SniffEnable = true; TrafficSource = TRAFFIC_READER; + + // Common Codec Register settings + CodecInitCommon(); + // Enable demodulator power + CodecSetDemodPower(true); + // Start with sniffing Reader->Card direction traffic // Card -> Reader traffic sniffing interrupt will be enbaled // when Reader-> Card direction sniffing finished @@ -58,12 +306,47 @@ void Sniff14443ACodecDeInit(void) SniffEnable = false; CardSniffDeinit(); ReaderSniffDeInit(); - } + + void Sniff14443ACodecTask(void) { + if (TrafficSource == TRAFFIC_READER){ - ISO14443ACodecTask(); + if (Flags.DemodFinished) { + Flags.DemodFinished = 0; + /* Reception finished. Process the received bytes */ + uint16_t DemodBitCount = BitCount; + + if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + // For logging data + LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); + LEDHook(LED_CODEC_RX, LED_PULSE); + + if(SniffEnable == true){ + // TODO: Start interrupt for finding Card -> Reader direction traffic + + ReaderSniffDeInit(); + CardSniffInit(); + +// ISO14443ACodecDeInit(); + +// TestSniff14443ACodecInit(); + TrafficSource = TRAFFIC_CARD; + return; + } + } +// +// /* No data to be processed. Disable loadmodding and start listening again */ +// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; +// CODEC_TIMER_LOADMOD.INTCTRLA = 0; + + ReaderSniffInit(); + + } + + + } else{ Reader14443ACodecTask(); } @@ -72,3 +355,4 @@ void Sniff14443ACodecTask(void) } + From c526ab3035c86cbbcb2ee583f81f62cfd4ad73ad Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 11 Jul 2018 02:36:02 +0100 Subject: [PATCH 09/26] Separate Card->Reader code, works for only one round of traffic Buggy commit. Maybe fix the event channel and reinit the timer when switching (cherry picked from commit a43869a) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 397 +++++++++++++++++- 1 file changed, 392 insertions(+), 5 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 0ab899c..d8617ef 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -20,6 +20,10 @@ #define ISO14443A_MIN_BITS_PER_FRAME 7 +// Card to reader +#define ISO14443A_PICC_TO_PCD_FDT_PRESCALER TC_CLKSEL_DIV8_gc // please change ISO14443A_PICC_TO_PCD_MIN_FDT when changing this +#define ISO14443A_RX_MINIMUM_BITCOUNT 4 + /* Define pseudo variables to use fast register access. This is useful for global vars */ #define DataRegister Codec8Reg0 @@ -32,13 +36,23 @@ #define CodecBufferPtr CodecPtrRegister1 #define ParityBufferPtr CodecPtrRegister2 + +#define BitCountUp GPIOR7 +#define CodecBufferIdx GPIOR8 + bool SniffEnable; enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; // volatile bool LoadmodFinished; + volatile bool Start; + volatile bool RxDone; + volatile bool RxPending; + } Flags = { 0 }; +static volatile uint16_t RxPendingSince; + typedef enum { /* Demod */ @@ -48,6 +62,14 @@ typedef enum { } StateType; + +static volatile enum { + STATE_IDLE, + STATE_MILLER_SEND, + STATE_MILLER_EOF, + STATE_FDT +} State; + ///////////////////////////////////////////////// // Reader->Card Direction Traffic ///////////////////////////////////////////////// @@ -267,17 +289,262 @@ INLINE void ReaderSniffDeInit(void) // Card->Reader Direction Traffic ///////////////////////////////////////////////// +INLINE void Insert0(void) +{ + SampleRegister >>= 1; + if (++BitCount % 8) + return; + *CodecBufferPtr++ = SampleRegister; +} + +INLINE void Insert1(void) +{ + SampleRegister = (SampleRegister >> 1) | 0x80; + if (++BitCount % 8) + return; + *CodecBufferPtr++ = SampleRegister; +} + +// This interrupt find Card -> Reader SOC +ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before +{ +// LED_PORT.OUTSET=LED_RED; + + ACA.AC0CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt + // enable the pause-finding timer + CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_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_CCB_VECT) // pause found +{ + + + uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL; + CODEC_TIMER_TIMESTAMPS.CNT = 0; + + /* This needs to be done only on the first call, + * but doing this only on a condition means wasting time, so we do it every time. */ + CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_DIV4_gc; + + switch (tmp) // decide how many half bit periods have been modulations + { + case 0 ... 48: // 32 ticks is one half of a bit period + return; + + case 49 ... 80: // 64 ticks are a full bit period + Insert1(); + Insert0(); + return; + + case 81 ... 112: // 96 ticks are 3 half bit periods + if (BitCount & 1) + { + Insert1(); + Insert1(); + Insert0(); + } else { + Insert1(); + Insert0(); + Insert0(); + } + return; + + default: // every value over 96 + 16 (tolerance) is considered to be 4 half bit periods + Insert1(); + Insert1(); + Insert0(); + Insert0(); + return; + } + return; +} +// EOC of Card->Reader found +ISR(TCD1_CCB_vect) // EOC found +{ +// Reader14443A_EOC(); + + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; + CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; + ACA.AC0CTRL &= ~AC_ENABLE_bm; + + if (BitCount & 1) + { + if (SampleRegister & 0x80) + Insert0(); + else + Insert1(); + } + + if (BitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + Flags.RxDone = true; + Flags.RxPending = false; + + // set up timer that forces the minimum frame delay time from PICC to PCD + CODEC_TIMER_LOADMOD.PER = 0xFFFF; + CODEC_TIMER_LOADMOD.CNT = 0; + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLD = 0; + CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; + + State = STATE_FDT; + +} +//// End of Card-> reader communication and enter frame delay time +//void Reader14443A_EOC(void) +//{ +// +// +//} + + INLINE void CardSniffInit(void) { - TestSniff14443ACodecInit(); + + //////////////////////////// + // 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; + CodecBufferPtr = CodecBuffer; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister = 0x00; + +// Flags.Start = false; +// Flags.RxPending = false; + Flags.RxDone = false; + /////////////////////////// + + Flags.Start = true; + // reset for future use +// CodecBufferIdx = 0; +// BitCountUp = 0; + + Flags.RxPending = true; + +// StartDemod(); + + /* + * 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.AC0CTRL = 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.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_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.CCB = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC1 INT + EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + CODEC_DEMOD_IN_PORT.INTCTRL = 0; + + +// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; +// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; +// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; +// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; +// PORTE.OUTTGL = PIN3_bm; + + // CODEC_TIMER_SAMPLING_CCC_vect + + + /* 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. */ + ACA.AC1CTRL = 0; + ACA.STATUS = AC_AC0IF_bm; + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + +// RxPendingSince = SystemGetSysTick(); + + +// State = STATE_IDLE; +// PORTE.OUTTGL = PIN3_bm; + + //Flags.RxPending = true; + + //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); + //Reader14443A_EOC(); + } INLINE void CardSniffDeinit(void) { - Reader14443ACodecDeInit(); + // CodecSetDemodPower(false); + // CodecReaderFieldStop(); + CODEC_TIMER_SAMPLING.CTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + + + + EVSYS.CH2MUX = 0; // on every ACA_AC1 INT + EVSYS.CH2CTRL = 0; + ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; + + + + Flags.RxDone = false; + Flags.RxPending = false; + Flags.Start = false; + +// Reader14443ACodecDeInit(); } +///////////////////////////////////////////////// +// Init and deInit, task, functions for this codec +///////////////////////////////////////////////// void Sniff14443ACodecInit(void) { @@ -342,13 +609,133 @@ void Sniff14443ACodecTask(void) // CODEC_TIMER_LOADMOD.INTCTRLA = 0; ReaderSniffInit(); - } + } + + else // Card->Reader Task + { + + // 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 (Flags.RxDone && BitCount > 0) // decode the raw received data + { + + if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) + { + BitCount = 0; + } else { + uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; + memcpy(TmpCodecBuffer, CodecBuffer, (BitCount + 7) / 8); + + CodecBufferPtr = CodecBuffer; + uint16_t BitCountTmp = 2, TotalBitCount = BitCount; + BitCount = 0; + + 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; + TmpCodecBuffer[BitCountTmp / 8] >>= 2; + switch (Bit) + { + case 0b10: + Insert1(); + break; + + case 0b01: + Insert0(); + break; + + case 0b00: // EOC + breakflag = true; + break; + + default: + // error, should not happen, TODO handle this + break; + } + BitCountTmp += 2; + } + if (BitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + +// BitCount = removeParityBits(CodecBuffer, BitCount); + + LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); + + Flags.RxPending=true; + + +// if (SniffEnable) +// { + +// LED_PORT.OUTCLR = LED_RED; + CardSniffDeinit(); + ReaderSniffInit(); +// Reader14443ACodecDeInit(); +// ISO14443ACodecInit(); + TrafficSource = TRAFFIC_READER; + + return; +// } + } + + } + Flags.Start = false; + Flags.RxDone = false; + + /* Call application with received data */ + BitCount = ApplicationProcess(CodecBuffer, BitCount); + + // Application have data to be sent +// if (false)//BitCount > 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); // 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 +// } + } +// Reader14443ACodecTask(); - } else{ - Reader14443ACodecTask(); } // ISO14443ACodecDeInit(); // Reader14443ACodecTask(); From cd321aff3d48b6244fc9204ee6722622470f4f2e Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 11 Jul 2018 10:59:43 +0100 Subject: [PATCH 10/26] Event Channel and PORTB int1 bug fix: 1. Use event CH2 for timer resetting 2. Can not sniff the second round of traffic due to the PORTB int1 was disabled in CardSniffInit(). This is reenabled in ReaderSniffInit (cherry picked from commit 24b87e2) --- Firmware/Chameleon-Mini/Codec/Codec.h | 5 +++ .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 43 +++++++++++++------ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 1e530bc..29daa91 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -146,6 +146,9 @@ INLINE void CodecInitCommon(void) EVSYS.CH0MUX = CODEC_DEMOD_IN_EVMUX0; EVSYS.CH1MUX = CODEC_DEMOD_IN_EVMUX1; + EVSYS.CH2MUX = CODEC_DEMOD_IN_EVMUX0; + + /* Configure loadmod pin configuration and use a virtual port configuration * for single instruction cycle access */ CODEC_LOADMOD_PORT.DIRSET = CODEC_LOADMOD_MASK; @@ -187,6 +190,8 @@ INLINE void CodecInitCommon(void) /* Configure Analog Comparator 1 to detect SOC */ ACA.AC1MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC1CTRL = CODEC_AC_DEMOD_SETTINGS; + + } INLINE void CodecSetSubcarrier(SubcarrierModType ModType, uint16_t Divider) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index d8617ef..22fd65e 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -76,6 +76,22 @@ static volatile enum { void ReaderSniffInit(void) { + + // Common Codec Register settings +// CodecInitCommon(); + + + // Configure interrupt for demod + // This was disabled in CardSniffInit() + CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; + + + // Enable demodulator power +// CodecSetDemodPower(true); + + + TrafficSource = TRAFFIC_READER; + /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; @@ -408,6 +424,7 @@ ISR(TCD1_CCB_vect) // EOC found INLINE void CardSniffInit(void) { + TrafficSource = TRAFFIC_CARD; //////////////////////////// // Same as reader init @@ -530,6 +547,7 @@ INLINE void CardSniffDeinit(void) EVSYS.CH2MUX = 0; // on every ACA_AC1 INT EVSYS.CH2CTRL = 0; + ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; @@ -548,10 +566,9 @@ INLINE void CardSniffDeinit(void) void Sniff14443ACodecInit(void) { - Flags.DemodFinished = 0; +// Flags.DemodFinished = 0; - SniffEnable = true; - TrafficSource = TRAFFIC_READER; +// SniffEnable = true; // Common Codec Register settings CodecInitCommon(); @@ -570,9 +587,10 @@ void Sniff14443ACodecInit(void) void Sniff14443ACodecDeInit(void) { - SniffEnable = false; +// SniffEnable = false; CardSniffDeinit(); ReaderSniffDeInit(); + CodecSetDemodPower(false); } @@ -590,18 +608,17 @@ void Sniff14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); - if(SniffEnable == true){ - // TODO: Start interrupt for finding Card -> Reader direction traffic +// if(SniffEnable == true){ + // TODO: Start interrupt for finding Card -> Reader direction traffic - ReaderSniffDeInit(); - CardSniffInit(); + ReaderSniffDeInit(); + CardSniffInit(); // ISO14443ACodecDeInit(); // TestSniff14443ACodecInit(); - TrafficSource = TRAFFIC_CARD; - return; - } + return; +// } } // // /* No data to be processed. Disable loadmodding and start listening again */ @@ -691,10 +708,12 @@ void Sniff14443ACodecTask(void) // LED_PORT.OUTCLR = LED_RED; CardSniffDeinit(); +// TrafficSource = TRAFFIC_READER; ReaderSniffInit(); +// Sniff14443ACodecInit(); +// ReaderSniffInit(); // Reader14443ACodecDeInit(); // ISO14443ACodecInit(); - TrafficSource = TRAFFIC_READER; return; // } From 686691f30ce7675236c0ffb86c4ed9e27d89b90a Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 02:01:53 +0100 Subject: [PATCH 11/26] Remove experimental code in Reader14443-2A.c, make sniffing code independent form Reader14443-2A.c and ISO14443-2A.c (cherry picked from commit 16f4fb1) --- Firmware/Chameleon-Mini/Codec/Codec.h | 2 - .../Chameleon-Mini/Codec/Reader14443-2A.c | 233 ++++-------------- .../Chameleon-Mini/Codec/Reader14443-2A.h | 1 - .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 1 - 4 files changed, 53 insertions(+), 184 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 29daa91..34b8e34 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -190,8 +190,6 @@ INLINE void CodecInitCommon(void) /* Configure Analog Comparator 1 to detect SOC */ ACA.AC1MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC1CTRL = CODEC_AC_DEMOD_SETTINGS; - - } INLINE void CodecSetSubcarrier(SubcarrierModType ModType, uint16_t Divider) diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index cb52073..d9cabbe 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -50,7 +50,6 @@ 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; @@ -67,11 +66,9 @@ void Reader14443ACodecInit(void) { Flags.RxDone = false; } - - void Reader14443ACodecDeInit(void) { -// CodecSetDemodPower(false); - // CodecReaderFieldStop(); + CodecSetDemodPower(false); + CodecReaderFieldStop(); CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = 0; @@ -101,7 +98,6 @@ INLINE void Insert1(void) // 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; @@ -130,13 +126,10 @@ INLINE void Reader14443A_EOC(void) CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; State = STATE_FDT; - - } INLINE void BufferToSequence(void) { - uint16_t count = BitCount; if (count > BITS_PER_BYTE * CODEC_BUFFER_SIZE / 2) // todo is this correct? return; @@ -188,11 +181,9 @@ INLINE void BufferToSequence(void) // 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. */ @@ -204,7 +195,6 @@ ISR (TCD0_CCC_vect) SampleRegister = 0x00; RxPendingSince = SystemGetSysTick(); - Flags.RxPending = true; // reset for future use @@ -219,7 +209,6 @@ ISR (TCD0_CCC_vect) // 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; @@ -236,13 +225,10 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCA_VECT) // EOC found // 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 @@ -251,8 +237,6 @@ ISR(ACA_AC1_vect) // this interrupt either finds the SOC or gets triggered befor // 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; @@ -293,71 +277,23 @@ ISR(CODEC_TIMER_LOADMOD_CCA_VECT) // pause found return; } -static void StartDemod(void){ - - - /* - * 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) { - - // 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 && 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; @@ -399,27 +335,9 @@ void Reader14443ACodecTask(void) } if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); - -// BitCount = removeParityBits(CodecBuffer, BitCount); - + LEDHook(LED_CODEC_RX, LED_PULSE); LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); - - Flags.RxPending=true; - - - if (SniffEnable) - { - - LED_PORT.OUTCLR = LED_RED; - Reader14443ACodecDeInit(); - Sniff14443ACodecInit(); -// ISO14443ACodecInit(); - TrafficSource = TRAFFIC_READER; - - return; - } } - } Flags.Start = false; Flags.RxDone = false; @@ -427,11 +345,44 @@ void Reader14443ACodecTask(void) /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - // Application have data to be sent - if (false)//BitCount > 0) + if (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. + */ - StartDemod(); + /* 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; LEDHook(LED_CODEC_TX, LED_PULSE); LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); @@ -443,15 +394,7 @@ void Reader14443ACodecTask(void) CodecBufferPtr = CodecBuffer; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCBIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_HI_gc; - _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 + _delay_loop_1(85); } } } @@ -462,7 +405,7 @@ void Reader14443ACodecStart(void) BitCount = 0; Flags.Start = true; -// CodecReaderFieldStart(); + CodecReaderFieldStart(); } void Reader14443ACodecReset(void) @@ -471,75 +414,5 @@ 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; - CodecBufferPtr = CodecBuffer; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister = 0x00; - -// Flags.Start = false; -// Flags.RxPending = false; - Flags.RxDone = false; - /////////////////////////// - - Flags.Start = true; - // reset for future use -// CodecBufferIdx = 0; -// BitCountUp = 0; - - Flags.RxPending = true; - - StartDemod(); - -// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; -// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; -// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; -// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; -// PORTE.OUTTGL = PIN3_bm; - - // CODEC_TIMER_SAMPLING_CCC_vect - - - /* 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. */ - ACA.STATUS = AC_AC1IF_bm; - ACA.AC1CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - - RxPendingSince = SystemGetSysTick(); - - -// State = STATE_IDLE; -// PORTE.OUTTGL = PIN3_bm; - - //Flags.RxPending = true; - - //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); - //Reader14443A_EOC(); - -} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h index a96fff2..e9a2c1e 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.h @@ -15,7 +15,6 @@ void Reader14443ACodecInit(void); void Reader14443ACodecDeInit(void); void Reader14443ACodecTask(void); -void TestSniff14443ACodecInit(void); /* Application Interface */ void Reader14443ACodecStart(void); diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 22fd65e..23b04d1 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -40,7 +40,6 @@ #define BitCountUp GPIOR7 #define CodecBufferIdx GPIOR8 -bool SniffEnable; enum RCTraffic TrafficSource; static volatile struct { From 56d5525beb5a0a690d9520846093d918ae232dcd Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 02:11:03 +0100 Subject: [PATCH 12/26] Remove redundancy comments in SniffISO14443-2A.c (cherry picked from commit b95dfda) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 174 +----------------- 1 file changed, 7 insertions(+), 167 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 23b04d1..dd1e573 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -4,6 +4,7 @@ // modified form ISO14443-2A.c and Reader14443-2A.c // +// TODO: implement pending since to automatically reset the sniffing after a period of no traffic #include "SniffISO14443-2A.h" #include "Reader14443-2A.h" @@ -76,26 +77,15 @@ static volatile enum { void ReaderSniffInit(void) { - // Common Codec Register settings -// CodecInitCommon(); - - // Configure interrupt for demod // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; - - // Enable demodulator power -// CodecSetDemodPower(true); - - TrafficSource = TRAFFIC_READER; /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; -// ReaderStartDemod(); - CodecBufferPtr = CodecBuffer; ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; DataRegister = 0; @@ -124,7 +114,6 @@ void ReaderSniffInit(void) // Find first pause and start sampling ISR(PORTB_INT1_vect) { -// LED_PORT.OUTSET = LED_RED; /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start * demodulating beginning from one bit-width after this edge. */ @@ -141,22 +130,6 @@ ISR(PORTB_INT1_vect) { CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES/2 - 1; /* Half bit width */ CODEC_TIMER_SAMPLING.CCDBUF = SAMPLE_RATE_SYSTEM_CYCLES/8 - 14 - 1; /* Compensate for DIGFILT and ISR prolog */ - /* Setup Frame Delay Timer and wire to EVSYS. Frame delay time is - * measured from last change in RF field, therefore we use - * the event channel 1 (end of modulation pause) as the restart event. - * The preliminary frame delay time chosen here is irrelevant, because - * the correct FDT gets set automatically after demodulation. */ - -// CODEC_TIMER_LOADMOD.CNT = 0; -// CODEC_TIMER_LOADMOD.PER = 0xFFFF; -//// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODEND_EVSEL; -//// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; -//// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; -//// CODEC_TIMER_LOADMOD.CTRLA = CODEC_TIMER_CARRIER_CLKSEL; -// -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = 0; - /* Disable this interrupt */ CODEC_DEMOD_IN_PORT.INT1MASK = 0; } @@ -177,26 +150,10 @@ ISR(TCD0_CCD_vect) { CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - /* By this time, the FDT timer is aligned to the last modulation - * edge of the reader. So we disable the auto-synchronization and - * let it count the frame delay time in the background, and generate - * an interrupt once it has reached the FDT. */ - // Do not activate loadmod -// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = 0; - -// if (SampleRegister & 0x08) { -// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV1 - 40; /* compensate for ISR prolog */ -// } else { -// CODEC_TIMER_LOADMOD.PER = ISO14443A_FRAME_DELAY_PREV0 - 40; /* compensate for ISR prolog */ -// } + // FDT timer (CODEC_TIMER_LOADMOD) is diabled StateRegister = LOADMOD_FDT; -// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; -// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_HI_gc; - /* Determine if we did not receive a multiple of 8 bits. * If this is the case, right-align the remaining data and * store it into the buffer. */ @@ -287,19 +244,10 @@ INLINE void ReaderSniffDeInit(void) CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - - -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = TC_OVFINTLVL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTFLAGS = TC0_OVFIF_bm; - } - - ///////////////////////////////////////////////// // Card->Reader Direction Traffic ///////////////////////////////////////////////// @@ -337,8 +285,6 @@ ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered befor // if the half bit duration is not modulated, then add 0 to buffer ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found { - - uint8_t tmp = CODEC_TIMER_TIMESTAMPS.CNTL; CODEC_TIMER_TIMESTAMPS.CNT = 0; @@ -376,13 +322,10 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found Insert0(); return; } - return; } // EOC of Card->Reader found ISR(TCD1_CCB_vect) // EOC found { -// Reader14443A_EOC(); - CODEC_TIMER_LOADMOD.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; @@ -413,50 +356,29 @@ ISR(TCD1_CCB_vect) // EOC found State = STATE_FDT; } -//// End of Card-> reader communication and enter frame delay time -//void Reader14443A_EOC(void) -//{ -// -// -//} INLINE void CardSniffInit(void) { TrafficSource = TRAFFIC_CARD; - //////////////////////////// - // Same as reader init /* Initialize common peripherals and start listening - * for incoming data. */ + * 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; + // No need to implement FDT, timer disabled 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; CodecBufferPtr = CodecBuffer; // use GPIOR for faster access BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly SampleRegister = 0x00; -// Flags.Start = false; -// Flags.RxPending = false; Flags.RxDone = false; - /////////////////////////// - Flags.Start = true; // reset for future use // CodecBufferIdx = 0; @@ -464,8 +386,6 @@ INLINE void CardSniffInit(void) Flags.RxPending = true; -// StartDemod(); - /* * Prepare for Manchester decoding. * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal @@ -503,16 +423,6 @@ INLINE void CardSniffInit(void) CODEC_DEMOD_IN_PORT.INTCTRL = 0; - -// CODEC_TIMER_SAMPLING.PER = 5*SAMPLE_RATE_SYSTEM_CYCLES - 1; -// CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; -// CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; -// CODEC_TIMER_SAMPLING.PERBUF = SAMPLE_RATE_SYSTEM_CYCLES - 1; -// PORTE.OUTTGL = PIN3_bm; - - // CODEC_TIMER_SAMPLING_CCC_vect - - /* 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. */ @@ -521,16 +431,6 @@ INLINE void CardSniffInit(void) ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; // RxPendingSince = SystemGetSysTick(); - - -// State = STATE_IDLE; -// PORTE.OUTTGL = PIN3_bm; - - //Flags.RxPending = true; - - //LogEntry(LOG_INFO_CODEC_TX_DATA_W_PARITY, "Codec Sniff Start", 18); - //Reader14443A_EOC(); - } INLINE void CardSniffDeinit(void) @@ -565,23 +465,14 @@ INLINE void CardSniffDeinit(void) void Sniff14443ACodecInit(void) { -// Flags.DemodFinished = 0; - -// SniffEnable = true; - // Common Codec Register settings CodecInitCommon(); // Enable demodulator power CodecSetDemodPower(true); // Start with sniffing Reader->Card direction traffic - // Card -> Reader traffic sniffing interrupt will be enbaled - // when Reader-> Card direction sniffing finished - // See ISO14443-2A.c ISO14443ACodecTask() ReaderSniffInit(); - // Also configure Interrupt settings for Reader function -// Reader14443ACodecInit(); } void Sniff14443ACodecDeInit(void) @@ -607,24 +498,13 @@ void Sniff14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); -// if(SniffEnable == true){ - // TODO: Start interrupt for finding Card -> Reader direction traffic - ReaderSniffDeInit(); CardSniffInit(); -// ISO14443ACodecDeInit(); - -// TestSniff14443ACodecInit(); return; -// } } -// -// /* No data to be processed. Disable loadmodding and start listening again */ -// CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; -// CODEC_TIMER_LOADMOD.INTCTRLA = 0; - - ReaderSniffInit(); + // Get nothing, Start sniff again + ReaderSniffInit(); } @@ -701,21 +581,11 @@ void Sniff14443ACodecTask(void) Flags.RxPending=true; - -// if (SniffEnable) -// { - -// LED_PORT.OUTCLR = LED_RED; + // Disable card sniffing and enable reader sniffing CardSniffDeinit(); -// TrafficSource = TRAFFIC_READER; ReaderSniffInit(); -// Sniff14443ACodecInit(); -// ReaderSniffInit(); -// Reader14443ACodecDeInit(); -// ISO14443ACodecInit(); return; -// } } } @@ -725,38 +595,8 @@ void Sniff14443ACodecTask(void) /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - // Application have data to be sent -// if (false)//BitCount > 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); // 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 -// } } -// Reader14443ACodecTask(); - } -// ISO14443ACodecDeInit(); -// Reader14443ACodecTask(); } From 2fa4a94fb9cd09372921cf9d062e4d83522ec841 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 13:45:46 +0100 Subject: [PATCH 13/26] name Interrupt vectors (cherry picked from commit 8d15036) --- Firmware/Chameleon-Mini/Codec/Codec.h | 5 +++++ Firmware/Chameleon-Mini/Codec/Reader14443-2A.c | 2 +- Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 34b8e34..09dee73 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -39,6 +39,7 @@ #define CODEC_DEMOD_IN_EVMUX0 EVSYS_CHMUX_PORTB_PIN1_gc #define CODEC_DEMOD_IN_EVMUX1 EVSYS_CHMUX_PORTB_PIN2_gc #define CODEC_DEMOD_IN_INT0_VECT PORTB_INT0_vect +#define CODEC_DEMOD_IN_INT1_VECT PORTB_INT1_vect #define CODEC_LOADMOD_PORT PORTC #define CODEC_LOADMOD_MASK PIN6_bm #define CODEC_CARRIER_IN_PORT PORTC @@ -58,6 +59,8 @@ #define CODEC_TIMER_SAMPLING TCD0 #define CODEC_TIMER_SAMPLING_CCA_VECT TCD0_CCA_vect #define CODEC_TIMER_SAMPLING_CCB_VECT TCD0_CCB_vect +#define CODEC_TIMER_SAMPLING_CCC_VECT TCD0_CCC_vect +#define CODEC_TIMER_SAMPLING_CCD_VECT TCD0_CCD_vect #define CODEC_TIMER_LOADMOD TCE0 #define CODEC_TIMER_LOADMOD_OVF_VECT TCE0_OVF_vect #define CODEC_TIMER_LOADMOD_CCA_VECT TCE0_CCA_vect @@ -81,6 +84,8 @@ #define CODEC_THRESHOLD_CALIBRATE_STEPS 16 #define CODEC_TIMER_TIMESTAMPS TCD1 #define CODEC_TIMER_TIMESTAMPS_CCA_VECT TCD1_CCA_vect +#define CODEC_TIMER_TIMESTAMPS_CCB_VECT TCD1_CCB_vect + #define CODEC_BUFFER_SIZE 256 diff --git a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c index d9cabbe..1bea53b 100644 --- a/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/Reader14443-2A.c @@ -179,7 +179,7 @@ INLINE void BufferToSequence(void) CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); } // Frame Delay Time PCD to PICC ends -ISR (TCD0_CCC_vect) +ISR (CODEC_TIMER_SAMPLING_CCC_VECT) { CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCCIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCCINTLVL_OFF_gc; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index dd1e573..b7200a9 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -113,7 +113,7 @@ void ReaderSniffInit(void) // Find first pause and start sampling -ISR(PORTB_INT1_vect) { +ISR(CODEC_DEMOD_IN_INT1_VECT) { /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start * demodulating beginning from one bit-width after this edge. */ @@ -135,7 +135,7 @@ ISR(PORTB_INT1_vect) { } // Sampling with timer and demod -ISR(TCD0_CCD_vect) { +ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* This interrupt gets called twice for every bit to sample it. */ uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; @@ -324,7 +324,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found } } // EOC of Card->Reader found -ISR(TCD1_CCB_vect) // EOC found +ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found { CODEC_TIMER_LOADMOD.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; From 6f020e492fc3002420e4f7aa021a1dd134e6dfa3 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 13 Jul 2018 17:30:06 +0100 Subject: [PATCH 14/26] Remove unused flags Add timeout for resetting to Reader->Card sniffing when no data get from Card->Reader sniffing (cherry picked from commit 6e88ae7) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 104 ++++++++---------- 1 file changed, 43 insertions(+), 61 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index b7200a9..a6883f6 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -45,11 +45,7 @@ enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; -// volatile bool LoadmodFinished; - volatile bool Start; volatile bool RxDone; - volatile bool RxPending; - } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -77,6 +73,7 @@ static volatile enum { void ReaderSniffInit(void) { + LED_PORT.OUTCLR = LED_RED; // Configure interrupt for demod // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; @@ -172,7 +169,8 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; - } else { + } + else { /* Otherwise, we check the two sample bits from the bit before. */ uint8_t BitSample = SampleRegister & 0xC; uint8_t Bit = 0; @@ -182,7 +180,8 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { if (BitSample & (0x1 << 2)) { /* 01 sequence or 11 sequence -> This is a zero bit */ Bit = 0; - } else { + } + else { /* 10 sequence -> This is a one bit */ Bit = 1; } @@ -206,19 +205,23 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { StateRegister = DEMOD_PARITY_BIT; } - } else if (StateRegister == DEMOD_PARITY_BIT) { + } + else if (StateRegister == DEMOD_PARITY_BIT) { /* This is a parity bit. Store it */ *ParityBufferPtr++ = Bit; StateRegister = DEMOD_DATA_BIT; - } else { + } + else { /* Should never Happen (TM) */ } - } else { + } + else { /* 00 sequence. -> No valid data yet. This also occurs if we just started * sampling and have sampled less than 2 bits yet. Thus ignore. */ } } - } else { + } + else { /* On odd sample position just sample. */ SampleIdxRegister = ~SampleIdxRegister; } @@ -271,8 +274,6 @@ INLINE void Insert1(void) // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { -// LED_PORT.OUTSET=LED_RED; - ACA.AC0CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; @@ -303,8 +304,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found return; case 81 ... 112: // 96 ticks are 3 half bit periods - if (BitCount & 1) - { + if (BitCount & 1) { Insert1(); Insert1(); Insert0(); @@ -332,8 +332,7 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; ACA.AC0CTRL &= ~AC_ENABLE_bm; - if (BitCount & 1) - { + if (BitCount & 1) { if (SampleRegister & 0x80) Insert0(); else @@ -343,7 +342,6 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); Flags.RxDone = true; - Flags.RxPending = false; // set up timer that forces the minimum frame delay time from PICC to PCD CODEC_TIMER_LOADMOD.PER = 0xFFFF; @@ -379,13 +377,10 @@ INLINE void CardSniffInit(void) SampleRegister = 0x00; Flags.RxDone = false; - Flags.Start = true; // reset for future use // CodecBufferIdx = 0; // BitCountUp = 0; - Flags.RxPending = true; - /* * Prepare for Manchester decoding. * The basic idea is to use two timers. The first one will be reset everytime the DEMOD signal @@ -418,7 +413,7 @@ INLINE void CardSniffInit(void) CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC1 INT + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; CODEC_DEMOD_IN_PORT.INTCTRL = 0; @@ -430,13 +425,12 @@ INLINE void CardSniffInit(void) ACA.STATUS = AC_AC0IF_bm; ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; -// RxPendingSince = SystemGetSysTick(); + RxPendingSince = SystemGetSysTick(); } INLINE void CardSniffDeinit(void) { - // CodecSetDemodPower(false); - // CodecReaderFieldStop(); + CODEC_TIMER_SAMPLING.CTRLA = 0; CODEC_TIMER_SAMPLING.INTCTRLB = 0; CODEC_TIMER_LOADMOD.CTRLA = 0; @@ -444,18 +438,14 @@ INLINE void CardSniffDeinit(void) - EVSYS.CH2MUX = 0; // on every ACA_AC1 INT + EVSYS.CH2MUX = 0; // on every ACA_AC0 INT EVSYS.CH2CTRL = 0; ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - - Flags.RxDone = false; - Flags.RxPending = false; - Flags.Start = false; - -// Reader14443ACodecDeInit(); +// Flags.RxPending = false; +// Flags.Start = false; } @@ -486,8 +476,8 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { - - if (TrafficSource == TRAFFIC_READER){ + // Reader->Card Task + if (TrafficSource == TRAFFIC_READER) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ @@ -506,26 +496,14 @@ void Sniff14443ACodecTask(void) // Get nothing, Start sniff again ReaderSniffInit(); } - - } - - else // Card->Reader Task + // Card->Reader Task + else { - - // 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)) - { - + // Receive finished + if (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; // } @@ -533,10 +511,10 @@ void Sniff14443ACodecTask(void) if (Flags.RxDone && BitCount > 0) // decode the raw received data { - if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) - { + if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { BitCount = 0; - } else { + } + else { uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; memcpy(TmpCodecBuffer, CodecBuffer, (BitCount + 7) / 8); @@ -548,12 +526,10 @@ void Sniff14443ACodecTask(void) TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored // Manchester Code ISO14443-2 8.2.5 - while (!breakflag && BitCountTmp < TotalBitCount) - { + while (!breakflag && BitCountTmp < TotalBitCount) { uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; TmpCodecBuffer[BitCountTmp / 8] >>= 2; - switch (Bit) - { + switch (Bit) { case 0b10: Insert1(); break; @@ -579,22 +555,28 @@ void Sniff14443ACodecTask(void) LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); - Flags.RxPending=true; - // Disable card sniffing and enable reader sniffing CardSniffDeinit(); ReaderSniffInit(); return; } - } - Flags.Start = false; Flags.RxDone = false; /* Call application with received data */ BitCount = ApplicationProcess(CodecBuffer, BitCount); - + } + else // Receive not finished yet, Continue waiting + { + // If Waiting for response time out + // Reset to reader sniffing + if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) ) { + Flags.RxDone = true; + // Disable card sniffing and enable reader sniffing + CardSniffDeinit(); + ReaderSniffInit(); + } } } } From cb49799de1d1d06fa93be590c74049603cadf6f6 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sat, 14 Jul 2018 18:52:48 +0100 Subject: [PATCH 15/26] Fix bug: ACA interrupt start after the card->Reader traffic start, so sometimes get not complete trace Another buffer used for store card->reader traffic is added, so that card->reader traffic sniffing can start right after the reader->Card trafic sniffing finished. (cherry picked from commit e074fcc) --- Firmware/Chameleon-Mini/Codec/Codec.c | 2 +- Firmware/Chameleon-Mini/Codec/Codec.h | 3 + .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 283 ++++++++++-------- 3 files changed, 162 insertions(+), 126 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.c b/Firmware/Chameleon-Mini/Codec/Codec.c index 56f2774..adfb60d 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.c +++ b/Firmware/Chameleon-Mini/Codec/Codec.c @@ -23,7 +23,7 @@ static volatile struct { } ReaderFieldFlags = { false }; uint8_t CodecBuffer[CODEC_BUFFER_SIZE]; - +uint8_t CodecBuffer2[CODEC_BUFFER_SIZE]; // the following three functions prevent sending data directly after turning on the reader field void CodecReaderFieldStart(void) // DO NOT CALL THIS FUNCTION INSIDE APPLICATION! { diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 09dee73..cdc82cd 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -99,6 +99,8 @@ #define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR4 & GPIOR5 */ #define CodecPtrRegister1 (*((volatile uint8_t**) &GPIOR8)) #define CodecPtrRegister2 (*((volatile uint8_t**) &GPIORA)) +#define CodecPtrRegister3 (*((volatile uint8_t**) &GPIORC)) + extern uint16_t Reader_FWT; @@ -110,6 +112,7 @@ typedef enum { } SubcarrierModType; extern uint8_t CodecBuffer[CODEC_BUFFER_SIZE]; +extern uint8_t CodecBuffer2[CODEC_BUFFER_SIZE]; INLINE void CodecInit(void) { ActiveConfiguration.CodecInitFunc(); diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index a6883f6..ddd4146 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -30,16 +30,20 @@ #define DataRegister Codec8Reg0 #define StateRegister Codec8Reg1 #define ParityRegister Codec8Reg2 -#define SampleIdxRegister Codec8Reg2 + +#define SampleIdxRegister GPIO4 #define SampleRegister Codec8Reg3 -#define BitSent CodecCount16Register1 +#define SampleRegister2 GPIO5 +//#define BitSent CodecCount16Register1 #define BitCount CodecCount16Register2 #define CodecBufferPtr CodecPtrRegister1 #define ParityBufferPtr CodecPtrRegister2 +#define CodecBufferPtr2 CodecPtrRegister3 -#define BitCountUp GPIOR7 -#define CodecBufferIdx GPIOR8 + +//#define BitCountUp GPIOR7 +//#define CodecBufferIdx GPIOR8 enum RCTraffic TrafficSource; @@ -65,12 +69,12 @@ static volatile enum { STATE_MILLER_EOF, STATE_FDT } State; - +uint16_t DemodBitCount; ///////////////////////////////////////////////// // Reader->Card Direction Traffic ///////////////////////////////////////////////// -void ReaderSniffInit(void) +INLINE void ReaderSniffInit(void) { LED_PORT.OUTCLR = LED_RED; @@ -78,8 +82,6 @@ void ReaderSniffInit(void) // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; - TrafficSource = TRAFFIC_READER; - /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; @@ -107,6 +109,116 @@ void ReaderSniffInit(void) // ISO14443ACodecInit(); } +INLINE void ReaderSniffDeInit(void) +{ + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + + Flags.DemodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; +} + +INLINE void CardSniffInit(void) +{ + /* Initialize common peripherals and start listening + * for incoming data. */ + + + // No need to implement FDT, timer disabled + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; + + CODEC_TIMER_LOADMOD.CTRLA = 0; + State = STATE_IDLE; + + CodecBufferPtr2 = CodecBuffer2; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + SampleRegister2 = 0x00; + + Flags.RxDone = false; + // reset for future use +// CodecBufferIdx = 0; +// BitCountUp = 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. + */ + + // Comparator ADC + /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ + ACA.AC0CTRL = 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.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_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.CCB = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT + EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; + + CODEC_DEMOD_IN_PORT.INTCTRL = 0; + + /* 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. */ + ACA.AC1CTRL = 0; + ACA.STATUS = AC_AC0IF_bm; + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + + RxPendingSince = SystemGetSysTick(); + PORTE.OUTSET = PIN3_bm; + + +} + +INLINE void CardSniffDeinit(void) +{ + PORTE.OUTCLR = PIN3_bm; + + + CODEC_TIMER_SAMPLING.CTRLA = 0; + CODEC_TIMER_SAMPLING.INTCTRLB = 0; + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + + + + EVSYS.CH2MUX = 0; // on every ACA_AC0 INT + EVSYS.CH2CTRL = 0; + ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; + ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; + + Flags.RxDone = false; +// Flags.RxPending = false; +// Flags.Start = false; + + +} + // Find first pause and start sampling @@ -169,6 +281,23 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; + DemodBitCount = BitCount; + + /* Gracefully shutdown codec */ + CODEC_DEMOD_IN_PORT.INT1MASK = 0; + +// Flags.DemodFinished = 0; + + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; + CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; + + +// ReaderSniffDeInit(); + CardSniffInit(); + return; + } else { /* Otherwise, we check the two sample bits from the bit before. */ @@ -236,18 +365,7 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { -INLINE void ReaderSniffDeInit(void) -{ - /* Gracefully shutdown codec */ - CODEC_DEMOD_IN_PORT.INT1MASK = 0; - Flags.DemodFinished = 0; - - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; - CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; -} @@ -257,18 +375,18 @@ INLINE void ReaderSniffDeInit(void) INLINE void Insert0(void) { - SampleRegister >>= 1; + SampleRegister2 >>= 1; if (++BitCount % 8) return; - *CodecBufferPtr++ = SampleRegister; + *CodecBufferPtr2++ = SampleRegister2; } INLINE void Insert1(void) { - SampleRegister = (SampleRegister >> 1) | 0x80; + SampleRegister2 = (SampleRegister2 >> 1) | 0x80; if (++BitCount % 8) return; - *CodecBufferPtr++ = SampleRegister; + *CodecBufferPtr2++ = SampleRegister2; } // This interrupt find Card -> Reader SOC @@ -333,14 +451,14 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found ACA.AC0CTRL &= ~AC_ENABLE_bm; if (BitCount & 1) { - if (SampleRegister & 0x80) + if (SampleRegister2 & 0x80) Insert0(); else Insert1(); } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); Flags.RxDone = true; // set up timer that forces the minimum frame delay time from PICC to PCD @@ -356,97 +474,6 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found } -INLINE void CardSniffInit(void) -{ - TrafficSource = TRAFFIC_CARD; - - /* Initialize common peripherals and start listening - * for incoming data. */ - - - // No need to implement FDT, timer disabled - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; - - CODEC_TIMER_LOADMOD.CTRLA = 0; - State = STATE_IDLE; - - CodecBufferPtr = CodecBuffer; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister = 0x00; - - Flags.RxDone = false; - // reset for future use -// CodecBufferIdx = 0; -// BitCountUp = 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. - */ - - // Comparator ADC - /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ - ACA.AC0CTRL = 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.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_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.CCB = 160; - CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; - CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; - - /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT - EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; - - CODEC_DEMOD_IN_PORT.INTCTRL = 0; - - /* 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. */ - ACA.AC1CTRL = 0; - ACA.STATUS = AC_AC0IF_bm; - ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - - RxPendingSince = SystemGetSysTick(); -} - -INLINE void CardSniffDeinit(void) -{ - - CODEC_TIMER_SAMPLING.CTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - - - - EVSYS.CH2MUX = 0; // on every ACA_AC0 INT - EVSYS.CH2CTRL = 0; - ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; - ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - - Flags.RxDone = false; -// Flags.RxPending = false; -// Flags.Start = false; -} ///////////////////////////////////////////////// @@ -455,12 +482,14 @@ INLINE void CardSniffDeinit(void) void Sniff14443ACodecInit(void) { + PORTE.DIRSET= PIN3_bm; // Common Codec Register settings CodecInitCommon(); // Enable demodulator power CodecSetDemodPower(true); // Start with sniffing Reader->Card direction traffic + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); } @@ -476,24 +505,25 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { + // Reader->Card Task if (TrafficSource == TRAFFIC_READER) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ - uint16_t DemodBitCount = BitCount; +// uint16_t DemodBitCount = BitCount; if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { // For logging data LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); - ReaderSniffDeInit(); - CardSniffInit(); + TrafficSource = TRAFFIC_CARD; return; } // Get nothing, Start sniff again + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); } } @@ -503,7 +533,7 @@ void Sniff14443ACodecTask(void) // if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) // return; // Receive finished - if (Flags.RxDone) { + if (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; // } @@ -516,9 +546,9 @@ void Sniff14443ACodecTask(void) } else { uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer, (BitCount + 7) / 8); + memcpy(TmpCodecBuffer, CodecBuffer2, (BitCount + 7) / 8); - CodecBufferPtr = CodecBuffer; + CodecBufferPtr2 = CodecBuffer2; uint16_t BitCountTmp = 2, TotalBitCount = BitCount; BitCount = 0; @@ -549,14 +579,15 @@ void Sniff14443ACodecTask(void) BitCountTmp += 2; } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer[BitCount / 8] = SampleRegister >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); // BitCount = removeParityBits(CodecBuffer, BitCount); - LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer, (BitCount + 7) / 8); + LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); return; @@ -565,7 +596,7 @@ void Sniff14443ACodecTask(void) Flags.RxDone = false; /* Call application with received data */ - BitCount = ApplicationProcess(CodecBuffer, BitCount); + BitCount = ApplicationProcess(CodecBuffer2, BitCount); } else // Receive not finished yet, Continue waiting { @@ -575,10 +606,12 @@ void Sniff14443ACodecTask(void) Flags.RxDone = true; // Disable card sniffing and enable reader sniffing CardSniffDeinit(); + TrafficSource = TRAFFIC_READER; ReaderSniffInit(); } } } + } From bf41815dbd042f65f3c1ffe610e1e499802c4135 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 16 Jul 2018 17:35:57 +0100 Subject: [PATCH 16/26] Sniffing Code Optimization Remove code related to FDT in sniffing mode Remove some redundant variables (cherry picked from commit 7254eb2) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 320 +++++++----------- .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 1 - 2 files changed, 125 insertions(+), 196 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index ddd4146..ca3ab4b 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -1,10 +1,10 @@ // // Created by Zitai Chen on 05/07/2018. -// Some interrupt handling vect -// modified form ISO14443-2A.c and Reader14443-2A.c +// Sniffing Function of ISO14443-2A cards +// Wors in both direction: PCD->PICC, PICC->PCD, +// modified from ISO14443-2A.c and Reader14443-2A.c // -// TODO: implement pending since to automatically reset the sniffing after a period of no traffic #include "SniffISO14443-2A.h" #include "Reader14443-2A.h" @@ -17,34 +17,27 @@ /* Sampling is done using internal clock, synchronized to the field modulation. * For that we need to convert the bit rate for the internal clock. */ -#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) - +#define SAMPLE_RATE_SYSTEM_CYCLES ((uint16_t) (((uint64_t) F_CPU * ISO14443A_BIT_RATE_CYCLES) / CODEC_CARRIER_FREQ) ) #define ISO14443A_MIN_BITS_PER_FRAME 7 // Card to reader #define ISO14443A_PICC_TO_PCD_FDT_PRESCALER TC_CLKSEL_DIV8_gc // please change ISO14443A_PICC_TO_PCD_MIN_FDT when changing this -#define ISO14443A_RX_MINIMUM_BITCOUNT 4 - +#define ISO14443A_RX_MINIMUM_BITCOUNT 4 /* Define pseudo variables to use fast register access. This is useful for global vars */ #define DataRegister Codec8Reg0 #define StateRegister Codec8Reg1 #define ParityRegister Codec8Reg2 -#define SampleIdxRegister GPIO4 -#define SampleRegister Codec8Reg3 -#define SampleRegister2 GPIO5 -//#define BitSent CodecCount16Register1 +#define SampleIdxRegister Codec8Reg3 +#define ReaderSampleR GPIOR4 +#define CardSampleR GPIOR5 #define BitCount CodecCount16Register2 -#define CodecBufferPtr CodecPtrRegister1 +#define ReaderBufferPtr CodecPtrRegister1 #define ParityBufferPtr CodecPtrRegister2 -#define CodecBufferPtr2 CodecPtrRegister3 +#define CardBufferPtr CodecPtrRegister3 - -//#define BitCountUp GPIOR7 -//#define CodecBufferIdx GPIOR8 - enum RCTraffic TrafficSource; static volatile struct { @@ -53,23 +46,16 @@ static volatile struct { } Flags = { 0 }; static volatile uint16_t RxPendingSince; - typedef enum { - /* Demod */ - DEMOD_DATA_BIT, + DEMOD_DATA_BIT, /* Demod */ DEMOD_PARITY_BIT, - LOADMOD_FDT, - } StateType; - -static volatile enum { - STATE_IDLE, - STATE_MILLER_SEND, - STATE_MILLER_EOF, - STATE_FDT -} State; uint16_t DemodBitCount; + +INLINE void CardSniffInit(void); +INLINE void CardSniffDeinit(void); + ///////////////////////////////////////////////// // Reader->Card Direction Traffic ///////////////////////////////////////////////// @@ -79,16 +65,15 @@ INLINE void ReaderSniffInit(void) LED_PORT.OUTCLR = LED_RED; // Configure interrupt for demod - // This was disabled in CardSniffInit() CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; /* Initialize some global vars and start looking out for reader commands */ Flags.DemodFinished = 0; - CodecBufferPtr = CodecBuffer; + ReaderBufferPtr = CodecBuffer; ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; DataRegister = 0; - SampleRegister = 0; + ReaderSampleR = 0; SampleIdxRegister = 0; BitCount = 0; StateRegister = DEMOD_DATA_BIT; @@ -106,13 +91,12 @@ INLINE void ReaderSniffInit(void) /* Start looking out for modulation pause via interrupt. */ CODEC_DEMOD_IN_PORT.INTFLAGS = PORT_INT1IF_bm; CODEC_DEMOD_IN_PORT.INT1MASK = CODEC_DEMOD_IN_MASK0; - -// ISO14443ACodecInit(); } INLINE void ReaderSniffDeInit(void) { /* Gracefully shutdown codec */ CODEC_DEMOD_IN_PORT.INT1MASK = 0; + CODEC_DEMOD_IN_PORT.INTCTRL = 0; Flags.DemodFinished = 0; @@ -122,104 +106,6 @@ INLINE void ReaderSniffDeInit(void) CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; } -INLINE void CardSniffInit(void) -{ - /* Initialize common peripherals and start listening - * for incoming data. */ - - - // No need to implement FDT, timer disabled - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCBINTLVL_OFF_gc; - - CODEC_TIMER_LOADMOD.CTRLA = 0; - State = STATE_IDLE; - - CodecBufferPtr2 = CodecBuffer2; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly - SampleRegister2 = 0x00; - - Flags.RxDone = false; - // reset for future use -// CodecBufferIdx = 0; -// BitCountUp = 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. - */ - - // Comparator ADC - /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ - ACA.AC0CTRL = 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.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; - CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_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.CCB = 160; - CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; - CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; - - /* Use the event system for resetting the pause-detecting timer. */ - EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT - EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_gc; - - CODEC_DEMOD_IN_PORT.INTCTRL = 0; - - /* 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. */ - ACA.AC1CTRL = 0; - ACA.STATUS = AC_AC0IF_bm; - ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; - - RxPendingSince = SystemGetSysTick(); - PORTE.OUTSET = PIN3_bm; - - -} - -INLINE void CardSniffDeinit(void) -{ - PORTE.OUTCLR = PIN3_bm; - - - CODEC_TIMER_SAMPLING.CTRLA = 0; - CODEC_TIMER_SAMPLING.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLA = 0; - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - - - - EVSYS.CH2MUX = 0; // on every ACA_AC0 INT - EVSYS.CH2CTRL = 0; - ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; - ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - - Flags.RxDone = false; -// Flags.RxPending = false; -// Flags.Start = false; - - -} - - // Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT1_VECT) { @@ -249,19 +135,23 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { uint8_t SamplePin = CODEC_DEMOD_IN_PORT.IN & CODEC_DEMOD_IN_MASK; /* Shift sampled bit into sampling register */ - SampleRegister = (SampleRegister << 1) | (!SamplePin ? 0x01 : 0x00); + ReaderSampleR = (ReaderSampleR << 1) | (!SamplePin ? 0x01 : 0x00); if (SampleIdxRegister) { SampleIdxRegister = 0; /* Analyze the sampling register after 2 samples. */ - if ((SampleRegister & 0x07) == 0x07) { + if ((ReaderSampleR & 0x07) == 0x07) { /* No carrier modulation for 3 sample points. EOC! */ + + // Shutdown the Reader->Card Sniffing, + // disable the sampling timer + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - - // FDT timer (CODEC_TIMER_LOADMOD) is diabled - - StateRegister = LOADMOD_FDT; + CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; + CODEC_DEMOD_IN_PORT.INTCTRL = 0; // Disable CODEC_DEMOD_IN_PORT interrupt + // CTRLD already disabled in CODEC_DEMOD_IN_INT1_VECT, + // so no need to disable it again it here /* Determine if we did not receive a multiple of 8 bits. * If this is the case, right-align the remaining data and @@ -276,32 +166,22 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { } /* TODO: Prevent buffer overflow */ - *CodecBufferPtr = NewDataRegister; + *ReaderBufferPtr = NewDataRegister; } /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; DemodBitCount = BitCount; - /* Gracefully shutdown codec */ - CODEC_DEMOD_IN_PORT.INT1MASK = 0; - -// Flags.DemodFinished = 0; - - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; - CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; - CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; - CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; - - -// ReaderSniffDeInit(); + // Start Card->Reader Sniffing without waiting for the complete of CodecTask + // Otherwise some bit will not be captured CardSniffInit(); return; } else { /* Otherwise, we check the two sample bits from the bit before. */ - uint8_t BitSample = SampleRegister & 0xC; + uint8_t BitSample = ReaderSampleR & 0xC; uint8_t Bit = 0; if (BitSample != (0x0 << 2)) { @@ -327,7 +207,7 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { if ((NewBitCount & 0x07) == 0) { /* We have reached a byte boundary! Store the data register. */ /* TODO: Prevent buffer overflow */ - *CodecBufferPtr++ = NewDataRegister; + *ReaderBufferPtr++ = NewDataRegister; /* Store bit for determining FDT at EOC and enable parity * handling on next bit. */ @@ -362,31 +242,102 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_RESTART_gc | CODEC_TIMER_MODSTART_EVSEL; } - - - - - - - ///////////////////////////////////////////////// // Card->Reader Direction Traffic ///////////////////////////////////////////////// +INLINE void CardSniffInit(void) +{ + /* Initialize common peripherals and start listening + * for incoming data. */ + + CardBufferPtr = CodecBuffer2; // use GPIOR for faster access + BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + CardSampleR = 0x00; + + Flags.RxDone = false; + + /* + * 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.AC0CTRL = 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.CCB = 95; // with 27.12 MHz this is 3/4 of a half bit width + CODEC_TIMER_LOADMOD.INTCTRLA = 0; + CODEC_TIMER_LOADMOD.INTFLAGS = TC1_CCBIF_bm; + CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCBINTLVL_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.CCB = 160; + CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; + CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + + /* Use the event system for resetting the pause-detecting timer. */ + EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT + EVSYS.CH2CTRL = EVSYS_DIGFILT_1SAMPLE_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. */ + ACA.AC1CTRL = 0; + ACA.STATUS = AC_AC0IF_bm; + ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; + + RxPendingSince = SystemGetSysTick(); + PORTE.OUTSET = PIN3_bm; + + +} + +INLINE void CardSniffDeinit(void) +{ + PORTE.OUTCLR = PIN3_bm; + + CODEC_TIMER_LOADMOD.CTRLA = 0; + CODEC_TIMER_LOADMOD.INTCTRLB = 0; + + // Disable event system CH2 + EVSYS.CH2MUX = 0; + EVSYS.CH2CTRL = 0; + // Reset ACA AC0 to default setting + ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; + ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; + + Flags.RxDone = false; +} + + + INLINE void Insert0(void) { - SampleRegister2 >>= 1; + CardSampleR >>= 1; if (++BitCount % 8) return; - *CodecBufferPtr2++ = SampleRegister2; + *CardBufferPtr++ = CardSampleR; } INLINE void Insert1(void) { - SampleRegister2 = (SampleRegister2 >> 1) | 0x80; + CardSampleR = (CardSampleR >> 1) | 0x80; if (++BitCount % 8) return; - *CodecBufferPtr2++ = SampleRegister2; + *CardBufferPtr++ = CardSampleR; } // This interrupt find Card -> Reader SOC @@ -444,38 +395,28 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found // EOC of Card->Reader found ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found { - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; + // Disable LOADMOD Timer + CODEC_TIMER_LOADMOD.INTCTRLB = 0; // Disable Interrupt + CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; // Disable Clock + CODEC_TIMER_LOADMOD.CTRLD = 0; // Disable connection to event channel + CODEC_TIMER_TIMESTAMPS.INTCTRLB = 0; CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; ACA.AC0CTRL &= ~AC_ENABLE_bm; if (BitCount & 1) { - if (SampleRegister2 & 0x80) + if (CardSampleR & 0x80) Insert0(); else Insert1(); } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); Flags.RxDone = true; - // set up timer that forces the minimum frame delay time from PICC to PCD - CODEC_TIMER_LOADMOD.PER = 0xFFFF; - CODEC_TIMER_LOADMOD.CNT = 0; - CODEC_TIMER_LOADMOD.INTCTRLA = 0; - CODEC_TIMER_LOADMOD.INTCTRLB = 0; - CODEC_TIMER_LOADMOD.CTRLD = 0; - CODEC_TIMER_LOADMOD.CTRLA = ISO14443A_PICC_TO_PCD_FDT_PRESCALER; - - State = STATE_FDT; - } - - - ///////////////////////////////////////////////// // Init and deInit, task, functions for this codec ///////////////////////////////////////////////// @@ -505,13 +446,11 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { - // Reader->Card Task if (TrafficSource == TRAFFIC_READER) { if (Flags.DemodFinished) { Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ -// uint16_t DemodBitCount = BitCount; if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { // For logging data @@ -530,14 +469,8 @@ void Sniff14443ACodecTask(void) // Card->Reader Task else { -// if (CodecIsReaderToBeRestarted() || !CodecIsReaderFieldReady()) -// return; // Receive finished - if (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 (Flags.RxDone) { if (Flags.RxDone && BitCount > 0) // decode the raw received data { @@ -548,7 +481,7 @@ void Sniff14443ACodecTask(void) uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; memcpy(TmpCodecBuffer, CodecBuffer2, (BitCount + 7) / 8); - CodecBufferPtr2 = CodecBuffer2; + CardBufferPtr = CodecBuffer2; uint16_t BitCountTmp = 2, TotalBitCount = BitCount; BitCount = 0; @@ -579,7 +512,7 @@ void Sniff14443ACodecTask(void) BitCountTmp += 2; } if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[BitCount / 8] = SampleRegister2 >> (8 - (BitCount % 8)); + CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); // BitCount = removeParityBits(CodecBuffer, BitCount); @@ -613,6 +546,3 @@ void Sniff14443ACodecTask(void) } } - - - diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h index 44d50c8..b8616b0 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -9,7 +9,6 @@ #include "Codec.h" #include "Terminal/CommandLine.h" -extern bool SniffEnable; extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; /* Codec Interface */ void Sniff14443ACodecInit(void); From 2a3b5c51ef2871bf5cb2af93ae6bca5f1f4abce2 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 16 Jul 2018 18:27:16 +0100 Subject: [PATCH 17/26] Add new log type for sniffing log (cherry picked from commit e63396e) --- Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c | 6 +++--- Firmware/Chameleon-Mini/Log.h | 8 ++++++++ Software/Chameleon/Log.py | 6 ++++++ Software/chamlog.py | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index ca3ab4b..6d4b996 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -454,7 +454,7 @@ void Sniff14443ACodecTask(void) if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { // For logging data - LogEntry(LOG_INFO_CODEC_RX_DATA, CodecBuffer, (DemodBitCount+7)/8); + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); TrafficSource = TRAFFIC_CARD; @@ -515,8 +515,8 @@ void Sniff14443ACodecTask(void) CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); // BitCount = removeParityBits(CodecBuffer, BitCount); - - LogEntry(LOG_INFO_CODEC_RX_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); + LEDHook(LED_CODEC_RX, LED_PULSE); + LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); diff --git a/Firmware/Chameleon-Mini/Log.h b/Firmware/Chameleon-Mini/Log.h index ce0bbfd..3fd3a31 100644 --- a/Firmware/Chameleon-Mini/Log.h +++ b/Firmware/Chameleon-Mini/Log.h @@ -23,6 +23,14 @@ typedef enum { LOG_INFO_CODEC_RX_DATA_W_PARITY = 0x42, ///< Currently active codec received data. LOG_INFO_CODEC_TX_DATA_W_PARITY = 0x43, ///< Currently active codec sent data. + LOG_INFO_CODEC_SNI_READER_DATA = 0x44, //< Sniffing codec receive data from reader + LOG_INFO_CODEC_SNI_READER_DATA_W_PARITY = 0x45, //< Sniffing codec receive data from reader + + LOG_INFO_CODEC_SNI_CARD_DATA = 0x46, //< Sniffing codec receive data from card + LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY = 0x47, //< Sniffing codec receive data from card + + + /* App */ LOG_INFO_APP_CMD_READ = 0x80, ///< Application processed read command. LOG_INFO_APP_CMD_WRITE = 0x81, ///< Application processed write command. diff --git a/Software/Chameleon/Log.py b/Software/Chameleon/Log.py index bcf7a24..0614e1b 100644 --- a/Software/Chameleon/Log.py +++ b/Software/Chameleon/Log.py @@ -25,6 +25,12 @@ eventTypes = { 0x42: { 'name': 'CODEC RX W/PARITY', 'decoder': binaryDecoder }, 0x43: { 'name': 'CODEC TX W/PARITY', 'decoder': binaryDecoder }, + 0x44: { 'name': 'CODEC RX SNI READER', 'decoder': binaryDecoder }, + 0x45: { 'name': 'CODEC RX SNI READER W/PARITY', 'decoder': binaryDecoder }, + 0x46: { 'name': 'CODEC RX SNI CARD', 'decoder': binaryDecoder }, + 0x47: { 'name': 'CODEC RX SNI CARD W/PARITY', 'decoder': binaryDecoder }, + + 0x80: { 'name': 'APP READ', 'decoder': binaryDecoder }, 0x81: { 'name': 'APP WRITE', 'decoder': binaryDecoder }, 0x84: { 'name': 'APP INC', 'decoder': binaryDecoder }, diff --git a/Software/chamlog.py b/Software/chamlog.py index e73d503..76dd87e 100755 --- a/Software/chamlog.py +++ b/Software/chamlog.py @@ -19,7 +19,7 @@ def verboseLog(text): def formatText(log): formatString = '{timestamp:0>5d} ms <{deltaTimestamp:>+6d} ms>:' - formatString += '{eventName:<16} ({dataLength:<3} bytes) [{data}]\n' + formatString += '{eventName:<28} ({dataLength:<3} bytes)\t[{data}]\n' text = '' for logEntry in log: From 14a6bc3c74e2eda48ec327fe7ab98bf997507e01 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 17 Jul 2018 05:01:35 +0100 Subject: [PATCH 18/26] Fix bug, card traffic is not right when using logmode=memory Print log after a round finished Otherwise it will take too much cpu cycles then the card traffic sniffing may not start in time (cherry picked from commit 48c89f5) --- Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 6d4b996..feb110c 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -43,6 +43,7 @@ enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; volatile bool RxDone; + } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -453,12 +454,9 @@ void Sniff14443ACodecTask(void) /* Reception finished. Process the received bytes */ if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { - // For logging data - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); LEDHook(LED_CODEC_RX, LED_PULSE); TrafficSource = TRAFFIC_CARD; - return; } // Get nothing, Start sniff again @@ -516,6 +514,10 @@ void Sniff14443ACodecTask(void) // BitCount = removeParityBits(CodecBuffer, BitCount); LEDHook(LED_CODEC_RX, LED_PULSE); + // Print log after a round finished + // Otherwise it will take too much cpu cycles + // then the card traffic sniffing may not start in time + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); // Disable card sniffing and enable reader sniffing @@ -537,6 +539,10 @@ void Sniff14443ACodecTask(void) // Reset to reader sniffing if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) ) { Flags.RxDone = true; + + // If Card sniffing started but no data get + // Then the codec must have sniffed some reader raffic + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); TrafficSource = TRAFFIC_READER; From 7af4cc5ee138fafb34fa643255f1f0ccbeaee5ae Mon Sep 17 00:00:00 2001 From: chenzitai Date: Thu, 19 Jul 2018 14:08:57 +0100 Subject: [PATCH 19/26] Longer reader pending timeout according to ISO-14443-4 5.5 (cherry picked from commit 4347afc) --- Firmware/Chameleon-Mini/Codec/Codec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index cdc82cd..3833f1b 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -25,7 +25,7 @@ #define ISO14443A_BIT_RATE_CYCLES 128 #define ISO14443A_FRAME_DELAY_PREV1 1236 #define ISO14443A_FRAME_DELAY_PREV0 1172 -#define ISO14443A_RX_PENDING_TIMEOUT 1 // ms +#define ISO14443A_RX_PENDING_TIMEOUT 4 // ms /* Peripheral definitions */ #define CODEC_DEMOD_POWER_PORT PORTB From 396cc21be196782e2bed8263118668c5718486b8 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Sun, 22 Jul 2018 00:08:11 +0100 Subject: [PATCH 20/26] Start reader sniffing right after card sniffing finished. This fix the bug that the sniffing get wrong data when the time gap between card signal and reader signal is too small (cherry picked from commit 573cb49) --- Firmware/Chameleon-Mini/Codec/Codec.h | 2 +- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 120 ++++++++++++------ 2 files changed, 85 insertions(+), 37 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 3833f1b..23e39e9 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -96,7 +96,7 @@ #define Codec8Reg2 GPIOR2 #define Codec8Reg3 GPIOR3 #define CodecCount16Register1 (*((volatile uint16_t*) &GPIOR4)) /* GPIOR4 & GPIOR5 */ -#define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR4 & GPIOR5 */ +#define CodecCount16Register2 (*((volatile uint16_t*) &GPIOR6)) /* GPIOR6 & GPIOR7 */ #define CodecPtrRegister1 (*((volatile uint8_t**) &GPIOR8)) #define CodecPtrRegister2 (*((volatile uint8_t**) &GPIORA)) #define CodecPtrRegister3 (*((volatile uint8_t**) &GPIORC)) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index feb110c..2bb6e2d 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -43,6 +43,7 @@ enum RCTraffic TrafficSource; static volatile struct { volatile bool DemodFinished; volatile bool RxDone; + volatile bool CardStarted; // If card have send the first bit } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -52,7 +53,8 @@ typedef enum { DEMOD_PARITY_BIT, } StateType; -uint16_t DemodBitCount; +uint16_t ReaderBitCount; +uint16_t CardBitCount; INLINE void CardSniffInit(void); INLINE void CardSniffDeinit(void); @@ -63,8 +65,8 @@ INLINE void CardSniffDeinit(void); INLINE void ReaderSniffInit(void) { +// PORTE.OUTSET = PIN3_bm; - LED_PORT.OUTCLR = LED_RED; // Configure interrupt for demod CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; @@ -95,6 +97,8 @@ INLINE void ReaderSniffInit(void) } INLINE void ReaderSniffDeInit(void) { +// PORTE.OUTCLR = PIN3_bm; + /* Gracefully shutdown codec */ CODEC_DEMOD_IN_PORT.INT1MASK = 0; CODEC_DEMOD_IN_PORT.INTCTRL = 0; @@ -147,6 +151,8 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { // Shutdown the Reader->Card Sniffing, // disable the sampling timer + PORTE.OUTSET = PIN3_bm; + CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; @@ -172,11 +178,18 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { /* Signal, that we have finished sampling */ Flags.DemodFinished = 1; - DemodBitCount = BitCount; + ReaderBitCount = BitCount; + // If we are have got data // Start Card->Reader Sniffing without waiting for the complete of CodecTask // Otherwise some bit will not be captured - CardSniffInit(); + if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + CardSniffInit(); + } else{ + ReaderSniffInit(); + } + PORTE.OUTCLR = PIN3_bm; + return; } @@ -249,6 +262,10 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { INLINE void CardSniffInit(void) { + LED_PORT.OUTSET = LED_RED; + PORTE.OUTSET = PIN2_bm; + + /* Initialize common peripherals and start listening * for incoming data. */ @@ -268,6 +285,8 @@ INLINE void CardSniffInit(void) * bit halves had modulations since the last pause. */ + DACB.CH0DATA = GlobalSettings.ActiveSettingPtr->ReaderThreshold; // real threshold voltage can be calculated with ch0data * Vref / 0xFFF + // Comparator ADC /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; @@ -301,14 +320,16 @@ INLINE void CardSniffInit(void) ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; RxPendingSince = SystemGetSysTick(); - PORTE.OUTSET = PIN3_bm; + Flags.CardStarted = false; } INLINE void CardSniffDeinit(void) { - PORTE.OUTCLR = PIN3_bm; + PORTE.OUTCLR = PIN2_bm; + LED_PORT.OUTCLR = LED_RED; + CODEC_TIMER_LOADMOD.CTRLA = 0; CODEC_TIMER_LOADMOD.INTCTRLB = 0; @@ -320,7 +341,8 @@ INLINE void CardSniffDeinit(void) ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; - Flags.RxDone = false; +// Flags.RxDone = false; +// Flags.CardStarted = false; } @@ -341,6 +363,22 @@ INLINE void Insert1(void) *CardBufferPtr++ = CardSampleR; } +INLINE void TaskInsert0(void) +{ + CardSampleR >>= 1; + if (++CardBitCount % 8) + return; + *CardBufferPtr++ = CardSampleR; +} + +INLINE void TaskInsert1(void) +{ + CardSampleR = (CardSampleR >> 1) | 0x80; + if (++CardBitCount % 8) + return; + *CardBufferPtr++ = CardSampleR; +} + // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { @@ -348,7 +386,7 @@ ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered befor // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; - + Flags.CardStarted = true; } // Decode the Card -> Reader signal // according to the pause and modulated period @@ -414,7 +452,13 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); + + CardBitCount = BitCount; Flags.RxDone = true; + Flags.CardStarted = false; + + CardSniffDeinit(); + ReaderSniffInit(); } @@ -424,7 +468,7 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found void Sniff14443ACodecInit(void) { - PORTE.DIRSET= PIN3_bm; + PORTE.DIRSET= PIN3_bm | PIN2_bm; // Common Codec Register settings CodecInitCommon(); // Enable demodulator power @@ -433,6 +477,7 @@ void Sniff14443ACodecInit(void) // Start with sniffing Reader->Card direction traffic TrafficSource = TRAFFIC_READER; ReaderSniffInit(); + Flags.RxDone = false; } @@ -453,15 +498,15 @@ void Sniff14443ACodecTask(void) Flags.DemodFinished = 0; /* Reception finished. Process the received bytes */ - if (DemodBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { - LEDHook(LED_CODEC_RX, LED_PULSE); + if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { +// LEDHook(LED_CODEC_RX, LED_PULSE); TrafficSource = TRAFFIC_CARD; return; } // Get nothing, Start sniff again TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); +// ReaderSniffInit(); } } // Card->Reader Task @@ -469,19 +514,19 @@ void Sniff14443ACodecTask(void) { // Receive finished if (Flags.RxDone) { - if (Flags.RxDone && BitCount > 0) // decode the raw received data + if (Flags.RxDone && CardBitCount > 0) // decode the raw received data { - if (BitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { - BitCount = 0; + if (CardBitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { + CardBitCount = 0; } else { uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer2, (BitCount + 7) / 8); + memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); CardBufferPtr = CodecBuffer2; - uint16_t BitCountTmp = 2, TotalBitCount = BitCount; - BitCount = 0; + uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; + CardBitCount = 0; bool breakflag = false; TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored @@ -492,11 +537,11 @@ void Sniff14443ACodecTask(void) TmpCodecBuffer[BitCountTmp / 8] >>= 2; switch (Bit) { case 0b10: - Insert1(); + TaskInsert1(); break; case 0b01: - Insert0(); + TaskInsert0(); break; case 0b00: // EOC @@ -509,40 +554,43 @@ void Sniff14443ACodecTask(void) } BitCountTmp += 2; } - if (BitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); + if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); -// BitCount = removeParityBits(CodecBuffer, BitCount); - LEDHook(LED_CODEC_RX, LED_PULSE); +// BitCount = removeParityBits(CodecBuffer, CardBitCount); +// LEDHook(LED_CODEC_RX, LED_PULSE); // Print log after a round finished // Otherwise it will take too much cpu cycles // then the card traffic sniffing may not start in time - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); - LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (BitCount + 7) / 8); + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); + LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); - // Disable card sniffing and enable reader sniffing - CardSniffDeinit(); - TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); - - return; +// return; } } + + // Once Rx Finished, Switch to Reader sniffing, + // No matter if getting data or not +// CardSniffDeinit(); + // Disable card sniffing and enable reader sniffing + TrafficSource = TRAFFIC_READER; +// ReaderSniffInit(); + Flags.RxDone = false; /* Call application with received data */ - BitCount = ApplicationProcess(CodecBuffer2, BitCount); + CardBitCount = ApplicationProcess(CodecBuffer2, CardBitCount); } else // Receive not finished yet, Continue waiting { // If Waiting for response time out // Reset to reader sniffing - if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT + 1) ) { - Flags.RxDone = true; + if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT) && !Flags.CardStarted) { + Flags.RxDone = false; // If Card sniffing started but no data get // Then the codec must have sniffed some reader raffic - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (DemodBitCount+7)/8); + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); // Disable card sniffing and enable reader sniffing CardSniffDeinit(); TrafficSource = TRAFFIC_READER; From 59d8e1739dc41604945f40be167e6eb2eebeecd3 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Mon, 23 Jul 2018 16:29:04 +0100 Subject: [PATCH 21/26] Refactor state and flags in SniffISO14443-2A.c (cherry picked from commit f3dd397) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 194 +++++++----------- 1 file changed, 79 insertions(+), 115 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 2bb6e2d..2a20cf7 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -41,9 +41,11 @@ enum RCTraffic TrafficSource; static volatile struct { - volatile bool DemodFinished; - volatile bool RxDone; - volatile bool CardStarted; // If card have send the first bit + volatile bool ReaderDataAvaliable; + volatile bool CardDataAvaliable; +// volatile bool DemodFinished; +// volatile bool RxDone; +// volatile bool CardStarted; // If card have send the first bit } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -51,10 +53,13 @@ static volatile uint16_t RxPendingSince; typedef enum { DEMOD_DATA_BIT, /* Demod */ DEMOD_PARITY_BIT, + PCD_PICC_FDT, + PICC_FRAME, + } StateType; -uint16_t ReaderBitCount; -uint16_t CardBitCount; +static volatile uint16_t ReaderBitCount; +static volatile uint16_t CardBitCount; INLINE void CardSniffInit(void); INLINE void CardSniffDeinit(void); @@ -71,7 +76,6 @@ INLINE void ReaderSniffInit(void) CODEC_DEMOD_IN_PORT.INTCTRL = PORT_INT1LVL_HI_gc; /* Initialize some global vars and start looking out for reader commands */ - Flags.DemodFinished = 0; ReaderBufferPtr = CodecBuffer; ParityBufferPtr = &CodecBuffer[ISO14443A_BUFFER_PARITY_OFFSET]; @@ -103,8 +107,6 @@ INLINE void ReaderSniffDeInit(void) CODEC_DEMOD_IN_PORT.INT1MASK = 0; CODEC_DEMOD_IN_PORT.INTCTRL = 0; - Flags.DemodFinished = 0; - CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.CTRLD = TC_EVACT_OFF_gc; CODEC_TIMER_SAMPLING.INTCTRLB = TC_CCDINTLVL_OFF_gc; @@ -114,6 +116,8 @@ INLINE void ReaderSniffDeInit(void) // Find first pause and start sampling ISR(CODEC_DEMOD_IN_INT1_VECT) { + PORTE.OUTSET = PIN2_bm; + /* This is the first edge of the first modulation-pause after StartDemod. * Now we have time to start * demodulating beginning from one bit-width after this edge. */ @@ -150,8 +154,9 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { // Shutdown the Reader->Card Sniffing, // disable the sampling timer + PORTE.OUTCLR = PIN2_bm; + - PORTE.OUTSET = PIN3_bm; CODEC_TIMER_SAMPLING.CTRLA = TC_CLKSEL_OFF_gc; CODEC_TIMER_SAMPLING.INTFLAGS = TC0_CCDIF_bm; @@ -177,18 +182,17 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { } /* Signal, that we have finished sampling */ - Flags.DemodFinished = 1; ReaderBitCount = BitCount; // If we are have got data // Start Card->Reader Sniffing without waiting for the complete of CodecTask // Otherwise some bit will not be captured if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { + Flags.ReaderDataAvaliable = true; CardSniffInit(); } else{ ReaderSniffInit(); } - PORTE.OUTCLR = PIN3_bm; return; @@ -231,7 +235,7 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { } else if (StateRegister == DEMOD_PARITY_BIT) { /* This is a parity bit. Store it */ - *ParityBufferPtr++ = Bit; +// *ParityBufferPtr++ = Bit; StateRegister = DEMOD_DATA_BIT; } else { @@ -263,7 +267,6 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { INLINE void CardSniffInit(void) { LED_PORT.OUTSET = LED_RED; - PORTE.OUTSET = PIN2_bm; /* Initialize common peripherals and start listening @@ -273,7 +276,6 @@ INLINE void CardSniffInit(void) BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly CardSampleR = 0x00; - Flags.RxDone = false; /* * Prepare for Manchester decoding. @@ -306,7 +308,8 @@ INLINE void CardSniffInit(void) CODEC_TIMER_TIMESTAMPS.CCB = 160; CODEC_TIMER_TIMESTAMPS.INTCTRLA = 0; CODEC_TIMER_TIMESTAMPS.INTFLAGS = TC1_CCBIF_bm; // Clear interrupt flag - CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; +// CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_LO_gc; + CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCBINTLVL_HI_gc; /* Use the event system for resetting the pause-detecting timer. */ EVSYS.CH2MUX = EVSYS_CHMUX_ACA_CH0_gc; // on every ACA_AC0 INT @@ -320,14 +323,13 @@ INLINE void CardSniffInit(void) ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_INTLVL_HI_gc | AC_ENABLE_bm; RxPendingSince = SystemGetSysTick(); - Flags.CardStarted = false; + StateRegister = PCD_PICC_FDT; } INLINE void CardSniffDeinit(void) { - PORTE.OUTCLR = PIN2_bm; LED_PORT.OUTCLR = LED_RED; @@ -341,8 +343,6 @@ INLINE void CardSniffDeinit(void) ACA.AC0MUXCTRL = AC_MUXPOS_DAC_gc | AC_MUXNEG_PIN7_gc; ACA.AC0CTRL = CODEC_AC_DEMOD_SETTINGS; -// Flags.RxDone = false; -// Flags.CardStarted = false; } @@ -382,11 +382,12 @@ INLINE void TaskInsert1(void) // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { + ACA.AC0CTRL &= ~AC_INTLVL_HI_gc; // disable this interrupt // enable the pause-finding timer CODEC_TIMER_LOADMOD.CTRLD = TC_EVACT_RESTART_gc | TC_EVSEL_CH2_gc; CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_DIV1_gc; - Flags.CardStarted = true; + StateRegister = PICC_FRAME; } // Decode the Card -> Reader signal // according to the pause and modulated period @@ -407,6 +408,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found return; case 49 ... 80: // 64 ticks are a full bit period + // Insert 0 Insert1(); Insert0(); return; @@ -434,6 +436,7 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found // EOC of Card->Reader found ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found { + // Disable LOADMOD Timer CODEC_TIMER_LOADMOD.INTCTRLB = 0; // Disable Interrupt CODEC_TIMER_LOADMOD.CTRLA = TC_CLKSEL_OFF_gc; // Disable Clock @@ -450,12 +453,14 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found Insert1(); } + if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); CardBitCount = BitCount; - Flags.RxDone = true; - Flags.CardStarted = false; + if (BitCount >= ISO14443A_RX_MINIMUM_BITCOUNT * 2) { + Flags.CardDataAvaliable = true; + } CardSniffDeinit(); ReaderSniffInit(); @@ -468,6 +473,7 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found void Sniff14443ACodecInit(void) { + PORTE.DIRSET= PIN3_bm | PIN2_bm; // Common Codec Register settings CodecInitCommon(); @@ -477,7 +483,8 @@ void Sniff14443ACodecInit(void) // Start with sniffing Reader->Card direction traffic TrafficSource = TRAFFIC_READER; ReaderSniffInit(); - Flags.RxDone = false; + Flags.ReaderDataAvaliable = false; + Flags.CardDataAvaliable = false; } @@ -492,111 +499,68 @@ void Sniff14443ACodecDeInit(void) void Sniff14443ACodecTask(void) { - // Reader->Card Task - if (TrafficSource == TRAFFIC_READER) { - if (Flags.DemodFinished) { - Flags.DemodFinished = 0; - /* Reception finished. Process the received bytes */ - - if (ReaderBitCount >= ISO14443A_MIN_BITS_PER_FRAME) { -// LEDHook(LED_CODEC_RX, LED_PULSE); - - TrafficSource = TRAFFIC_CARD; - return; - } - // Get nothing, Start sniff again - TrafficSource = TRAFFIC_READER; -// ReaderSniffInit(); - } + PORTE.OUTSET = PIN3_bm; + if(Flags.ReaderDataAvaliable){ + Flags.ReaderDataAvaliable = false; + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); + ReaderBitCount = 0; } - // Card->Reader Task - else - { - // Receive finished - if (Flags.RxDone) { - if (Flags.RxDone && CardBitCount > 0) // decode the raw received data - { - if (CardBitCount < ISO14443A_RX_MINIMUM_BITCOUNT * 2) { - CardBitCount = 0; - } - else { - uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); + if (Flags.CardDataAvaliable){ + Flags.CardDataAvaliable = false; - CardBufferPtr = CodecBuffer2; - uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; - CardBitCount = 0; + uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; + memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); - bool breakflag = false; - TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored + CardBufferPtr = CodecBuffer2; + uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; + CardBitCount = 0; - // Manchester Code ISO14443-2 8.2.5 - while (!breakflag && BitCountTmp < TotalBitCount) { - uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; - TmpCodecBuffer[BitCountTmp / 8] >>= 2; - switch (Bit) { - case 0b10: - TaskInsert1(); - break; + bool breakflag = false; + TmpCodecBuffer[0] >>= 2; // with this (and BitCountTmp = 2), the SOC is ignored - case 0b01: - TaskInsert0(); - break; + // Manchester Code ISO14443-2 8.2.5 + while (!breakflag && BitCountTmp < TotalBitCount) { + uint8_t Bit = TmpCodecBuffer[BitCountTmp / 8] & 0x03; + TmpCodecBuffer[BitCountTmp / 8] >>= 2; + switch (Bit) { + case 0b10: + TaskInsert1(); + break; - case 0b00: // EOC - breakflag = true; - break; + case 0b01: + TaskInsert0(); + break; - default: - // error, should not happen, TODO handle this - break; - } - BitCountTmp += 2; - } - if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); + case 0b00: // EOC + breakflag = true; + break; + + default: + // error, should not happen, TODO handle this + break; + } + BitCountTmp += 2; + } + if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte + CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); // BitCount = removeParityBits(CodecBuffer, CardBitCount); // LEDHook(LED_CODEC_RX, LED_PULSE); - // Print log after a round finished - // Otherwise it will take too much cpu cycles - // then the card traffic sniffing may not start in time - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); + // Print log after a round finished + // Otherwise it will take too much cpu cycles + // then the card traffic sniffing may not start in time + LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); // return; - } - } - - // Once Rx Finished, Switch to Reader sniffing, - // No matter if getting data or not -// CardSniffDeinit(); - // Disable card sniffing and enable reader sniffing - TrafficSource = TRAFFIC_READER; -// ReaderSniffInit(); - - Flags.RxDone = false; - - /* Call application with received data */ - CardBitCount = ApplicationProcess(CodecBuffer2, CardBitCount); - } - else // Receive not finished yet, Continue waiting - { - // If Waiting for response time out - // Reset to reader sniffing - if ((SYSTICK_DIFF(RxPendingSince) > Reader_FWT) && !Flags.CardStarted) { - Flags.RxDone = false; - - // If Card sniffing started but no data get - // Then the codec must have sniffed some reader raffic - LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - // Disable card sniffing and enable reader sniffing - CardSniffDeinit(); - TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); - } - } } + + if(StateRegister == PCD_PICC_FDT && (SYSTICK_DIFF(RxPendingSince) > Reader_FWT)){ + CardSniffDeinit(); + ReaderSniffInit(); + } + PORTE.OUTCLR = PIN3_bm; + + } From 14e17381533e89cb599f8b42f588856d1c18c8cb Mon Sep 17 00:00:00 2001 From: chenzitai Date: Tue, 24 Jul 2018 00:43:06 +0100 Subject: [PATCH 22/26] Optimise the Card->Reader Manchester decoder in Sniffing to make it faster It now decode and sample in the same time, so the decode half bit sampling to Manchester in the CodecTask can be removed. This optimisation may also fix the bug that the CodecTask not finished after start of Reader->Card Sampling and make the reader->Card sampling not in perfect timing and cause the Reader ->Card Sniffed data to be wrong. Trace from oscilloscope for the Problem: ReaderSniffing Enable __________ _________ __| |____________________| |_________ CardSniffing Enable _____________ _______ ________________| |______________| Task __ ___---- _|__|__|__|___| |__|__|__|__|__|_| |__|__|__|__| "-" indicate the problem (cherry picked from commit a246b98) --- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 149 ++++++++---------- 1 file changed, 63 insertions(+), 86 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 2a20cf7..2552a8d 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -37,15 +37,9 @@ #define ParityBufferPtr CodecPtrRegister2 #define CardBufferPtr CodecPtrRegister3 - -enum RCTraffic TrafficSource; - static volatile struct { volatile bool ReaderDataAvaliable; volatile bool CardDataAvaliable; -// volatile bool DemodFinished; -// volatile bool RxDone; -// volatile bool CardStarted; // If card have send the first bit } Flags = { 0 }; static volatile uint16_t RxPendingSince; @@ -60,6 +54,7 @@ typedef enum { static volatile uint16_t ReaderBitCount; static volatile uint16_t CardBitCount; +static volatile uint16_t rawBitCount; INLINE void CardSniffInit(void); INLINE void CardSniffDeinit(void); @@ -273,7 +268,8 @@ INLINE void CardSniffInit(void) * for incoming data. */ CardBufferPtr = CodecBuffer2; // use GPIOR for faster access - BitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + rawBitCount = 1; // FALSCH todo the first modulation of the SOC is "found" implicitly + BitCount = 0; CardSampleR = 0x00; @@ -363,22 +359,6 @@ INLINE void Insert1(void) *CardBufferPtr++ = CardSampleR; } -INLINE void TaskInsert0(void) -{ - CardSampleR >>= 1; - if (++CardBitCount % 8) - return; - *CardBufferPtr++ = CardSampleR; -} - -INLINE void TaskInsert1(void) -{ - CardSampleR = (CardSampleR >> 1) | 0x80; - if (++CardBitCount % 8) - return; - *CardBufferPtr++ = CardSampleR; -} - // This interrupt find Card -> Reader SOC ISR(ACA_AC0_vect) // this interrupt either finds the SOC or gets triggered before { @@ -402,34 +382,68 @@ ISR(CODEC_TIMER_LOADMOD_CCB_VECT) // pause found * but doing this only on a condition means wasting time, so we do it every time. */ CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_DIV4_gc; + // Remember, LSB is send first + // If current raw bit count is odd, then the previous raw bit must be 0 switch (tmp) // decide how many half bit periods have been modulations { case 0 ... 48: // 32 ticks is one half of a bit period return; case 49 ... 80: // 64 ticks are a full bit period - // Insert 0 - Insert1(); - Insert0(); + // Got 01 + if(rawBitCount & 1){ + // 01 + 0 -> 0 10 + // 10 -> 1, last 0 is ignored + if(rawBitCount > 1) { + // Ignore SOC + Insert1(); + } + } else{ + // Current sampled bit count is even, decode directly + // 01 -> 0 + Insert0(); + } + rawBitCount += 2; return; case 81 ... 112: // 96 ticks are 3 half bit periods - if (BitCount & 1) { - Insert1(); - Insert1(); + if (rawBitCount & 1) { + // Current sampled bit count is odd + // Got 011 + // 011 + 0 -> 01 10 -> 01 + if(rawBitCount > 1) { + // Ignore SOC + Insert1(); + } Insert0(); } else { - Insert1(); - Insert0(); + // Even bit count + // Got 001 + // 001 -> 0 01, The last 0 is ignored + // 01 -> 0 Insert0(); } + rawBitCount += 3; + return; default: // every value over 96 + 16 (tolerance) is considered to be 4 half bit periods - Insert1(); - Insert1(); - Insert0(); - Insert0(); + // Got 00 11 + if(rawBitCount & 1){ + // 00 11 + 0 -> 0 01 10 + // 01 -> 0, 10 -> 1, Ignore last 0 + if(rawBitCount > 1) { + // Ignore SOC + Insert1(); + } + Insert0(); + } else { + // Should not happen + // If modulation is correct, + // there should not be a full bit period modulation in even bit count + } + rawBitCount += 4; + return; } } @@ -446,19 +460,21 @@ ISR(CODEC_TIMER_TIMESTAMPS_CCB_VECT) // EOC found CODEC_TIMER_TIMESTAMPS.CTRLA = TC_CLKSEL_OFF_gc; ACA.AC0CTRL &= ~AC_ENABLE_bm; - if (BitCount & 1) { - if (CardSampleR & 0x80) - Insert0(); - else - Insert1(); + // If finished in odd sample count + // There must been an incomplete decoded bit + // Since only EOC is no modulation in full bit period, and previous raw bit must be 0 + // so the last not modulated bit must be 1 + if (rawBitCount & 1) { + // The previous raw bit must be 0 + // 1 + 0 -> 10 -> 1 + Insert1(); } - if (BitCount % 8) // copy the last byte, if there is an incomplete byte CodecBuffer2[BitCount / 8] = CardSampleR >> (8 - (BitCount % 8)); CardBitCount = BitCount; - if (BitCount >= ISO14443A_RX_MINIMUM_BITCOUNT * 2) { + if (BitCount >= ISO14443A_RX_MINIMUM_BITCOUNT) { Flags.CardDataAvaliable = true; } @@ -481,11 +497,10 @@ void Sniff14443ACodecInit(void) CodecSetDemodPower(true); // Start with sniffing Reader->Card direction traffic - TrafficSource = TRAFFIC_READER; - ReaderSniffInit(); Flags.ReaderDataAvaliable = false; Flags.CardDataAvaliable = false; + ReaderSniffInit(); } void Sniff14443ACodecDeInit(void) @@ -503,56 +518,18 @@ void Sniff14443ACodecTask(void) if(Flags.ReaderDataAvaliable){ Flags.ReaderDataAvaliable = false; LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - ReaderBitCount = 0; +// ReaderBitCount = 0; } + if (Flags.CardDataAvaliable){ Flags.CardDataAvaliable = false; - uint8_t TmpCodecBuffer[CODEC_BUFFER_SIZE]; - memcpy(TmpCodecBuffer, CodecBuffer2, (CardBitCount + 7) / 8); +// CardBitCount = removeParityBits(CodecBuffer2,CardBitCount ); +// LEDHook(LED_CODEC_RX, LED_PULSE); - CardBufferPtr = CodecBuffer2; - uint16_t BitCountTmp = 2, TotalBitCount = CardBitCount; - CardBitCount = 0; - - 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; - TmpCodecBuffer[BitCountTmp / 8] >>= 2; - switch (Bit) { - case 0b10: - TaskInsert1(); - break; - - case 0b01: - TaskInsert0(); - break; - - case 0b00: // EOC - breakflag = true; - break; - - default: - // error, should not happen, TODO handle this - break; - } - BitCountTmp += 2; - } - if (CardBitCount % 8) // copy the last byte, if there is an incomplete byte - CodecBuffer2[CardBitCount / 8] = CardSampleR >> (8 - (CardBitCount % 8)); - -// BitCount = removeParityBits(CodecBuffer, CardBitCount); -// LEDHook(LED_CODEC_RX, LED_PULSE); - // Print log after a round finished - // Otherwise it will take too much cpu cycles - // then the card traffic sniffing may not start in time LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); -// return; } From 823602c721ca859a2671ac38c149ae8eb0d1884f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Wed, 25 Jul 2018 17:40:46 +0100 Subject: [PATCH 23/26] Add Framework for autocalibrate of Sniffing Mode (cherry picked from commit c8606be) --- .../Chameleon-Mini/Application/Application.h | 1 + .../Chameleon-Mini/Application/Sniff14443A.c | 48 +++++++++++++++++++ .../Chameleon-Mini/Application/Sniff14443A.h | 24 ++++++++++ .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 13 ++--- Firmware/Chameleon-Mini/Configuration.c | 10 ++-- Firmware/Chameleon-Mini/Makefile | 2 +- Firmware/Chameleon-Mini/Terminal/Commands.c | 28 ++++++++--- 7 files changed, 104 insertions(+), 22 deletions(-) create mode 100644 Firmware/Chameleon-Mini/Application/Sniff14443A.c create mode 100644 Firmware/Chameleon-Mini/Application/Sniff14443A.h diff --git a/Firmware/Chameleon-Mini/Application/Application.h b/Firmware/Chameleon-Mini/Application/Application.h index 0b94960..1002d31 100644 --- a/Firmware/Chameleon-Mini/Application/Application.h +++ b/Firmware/Chameleon-Mini/Application/Application.h @@ -16,6 +16,7 @@ #include "MifareUltralight.h" #include "MifareClassic.h" #include "Reader14443A.h" +#include "Sniff14443A.h" /* Function wrappers */ INLINE void ApplicationInit(void) { diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c new file mode 100644 index 0000000..68512a7 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -0,0 +1,48 @@ +// +// Created by Zitai Chen on 25/07/2018. +// Application layer for sniffing +// Currently only support Autocalibrate +// + +#include +#include +#include "Sniff14443A.h" +Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; + +extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount); + static enum { + STATE_IDLE, + STATE_READER_DATA, + STATE_CARD_DATA +} SniffState = STATE_IDLE; + +void Sniff14443AAppInit(void){ + SniffState = STATE_IDLE; +} + +void Sniff14443AAppReset(void){ + SniffState = STATE_IDLE; + Sniff14443CurrentCommand = Sniff14443_Do_Nothing; +} +// Currently APPTask and AppTick is not being used +void Sniff14443AAppTask(void){/* Empty */} +void Sniff14443AAppTick(void){/* Empty */} + +void Sniff14443AAppTimeout(void){ + Sniff14443AAppReset(); +} + +uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ + switch (Sniff14443CurrentCommand){ + case Sniff14443_Do_Nothing: + return 0; + case Sniff14443_Autocalibrate: + // If received Reader WUPA + if(Buffer[0] == 0x26 || Buffer[0] == 0x54){ + LED_PORT.OUTSET = LED_RED; + } + break; + default: + return 0; + } +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.h b/Firmware/Chameleon-Mini/Application/Sniff14443A.h new file mode 100644 index 0000000..60f1c85 --- /dev/null +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.h @@ -0,0 +1,24 @@ +// +// Created by Zitai Chen on 25/07/2018. +// + +#ifndef CHAMELEON_MINI_SNIFF14443A_H +#define CHAMELEON_MINI_SNIFF14443A_H + +#include + +void Sniff14443AAppInit(void); +void Sniff14443AAppReset(void); +void Sniff14443AAppTask(void); +void Sniff14443AAppTick(void); +void Sniff14443AAppTimeout(void); + +uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount); + +typedef enum { + Sniff14443_Do_Nothing, + Sniff14443_Autocalibrate, +} Sniff14443Command; + +#endif //CHAMELEON_MINI_SNIFF14443A_H + diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index 2552a8d..fb2a51a 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -261,8 +261,6 @@ ISR(CODEC_TIMER_SAMPLING_CCD_VECT) { INLINE void CardSniffInit(void) { - LED_PORT.OUTSET = LED_RED; - /* Initialize common peripherals and start listening * for incoming data. */ @@ -326,8 +324,6 @@ INLINE void CardSniffInit(void) INLINE void CardSniffDeinit(void) { - LED_PORT.OUTCLR = LED_RED; - CODEC_TIMER_LOADMOD.CTRLA = 0; CODEC_TIMER_LOADMOD.INTCTRLB = 0; @@ -518,18 +514,17 @@ void Sniff14443ACodecTask(void) if(Flags.ReaderDataAvaliable){ Flags.ReaderDataAvaliable = false; LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); -// ReaderBitCount = 0; + ApplicationProcess(CodecBuffer, (ReaderBitCount+7)/8); + LEDHook(LED_CODEC_RX, LED_PULSE); } if (Flags.CardDataAvaliable){ Flags.CardDataAvaliable = false; - // CardBitCount = removeParityBits(CodecBuffer2,CardBitCount ); -// LEDHook(LED_CODEC_RX, LED_PULSE); - LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); - + LEDHook(LED_CODEC_RX, LED_PULSE); + ApplicationProcess(CodecBuffer2, (CardBitCount+7)/8); } diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index 5fda354..1fffdd0 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -191,11 +191,11 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .CodecInitFunc = Sniff14443ACodecInit, .CodecDeInitFunc = Sniff14443ACodecDeInit, .CodecTaskFunc = Sniff14443ACodecTask, - .ApplicationInitFunc = ApplicationInitDummy, - .ApplicationResetFunc = ApplicationResetDummy, - .ApplicationTaskFunc = ApplicationTaskDummy, - .ApplicationTickFunc = ApplicationTickDummy, - .ApplicationProcessFunc = ApplicationProcessDummy, + .ApplicationInitFunc = Sniff14443AAppInit, + .ApplicationResetFunc = Sniff14443AAppReset, + .ApplicationTaskFunc = Sniff14443AAppTask, + .ApplicationTickFunc = Sniff14443AAppTick, + .ApplicationProcessFunc = Sniff14443AAppProcess, .ApplicationGetUidFunc = ApplicationGetUidDummy, .ApplicationSetUidFunc = ApplicationSetUidDummy, .UidSize = 0, diff --git a/Firmware/Chameleon-Mini/Makefile b/Firmware/Chameleon-Mini/Makefile index 5870a2b..3824633 100644 --- a/Firmware/Chameleon-Mini/Makefile +++ b/Firmware/Chameleon-Mini/Makefile @@ -93,7 +93,7 @@ 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/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 += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) LUFA_PATH = ../LUFA CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -DFLASH_DATA_ADDR=$(FLASH_DATA_ADDR) -DFLASH_DATA_SIZE=$(FLASH_DATA_SIZE) -DSPM_HELPER_ADDR=$(SPM_HELPER_ADDR) -DBUILD_DATE=$(BUILD_DATE) -DCOMMIT_ID=\"$(COMMIT_ID)\" $(SETTINGS) diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index d4b26e9..c6307a8 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -2,6 +2,7 @@ #include "Commands.h" #include #include +#include #include "XModem.h" #include "../Settings.h" #include "../Chameleon-Mini.h" @@ -16,6 +17,7 @@ #include "../Codec/Codec.h" extern Reader14443Command Reader14443CurrentCommand; +extern Sniff14443Command Sniff14443CurrentCommand; extern const PROGMEM CommandEntryType CommandTable[]; @@ -629,15 +631,27 @@ CommandStatusIdType CommandGetField(char* OutMessage) CommandStatusIdType CommandExecAutocalibrate(char* OutMessage) { - if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER) + if (GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO14443A_READER){ + ApplicationReset(); + + Reader14443CurrentCommand = Reader14443_Autocalibrate; + Reader14443AAppInit(); + Reader14443ACodecStart(); + CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; + return TIMEOUT_COMMAND; + } + else if (GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO14443A_SNIFF){ + ApplicationReset(); + + Sniff14443CurrentCommand = Sniff14443_Autocalibrate; + Sniff14443AAppInit(); + CommandLinePendingTaskTimeout = &Sniff14443AAppTimeout; + return TIMEOUT_COMMAND; + } + else { return COMMAND_ERR_INVALID_USAGE_ID; - ApplicationReset(); + } - Reader14443CurrentCommand = Reader14443_Autocalibrate; - Reader14443AAppInit(); - Reader14443ACodecStart(); - CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; - return TIMEOUT_COMMAND; } CommandStatusIdType CommandExecClone(char *OutMessage) From 9c37cf758bd520d779e187229ceab35301a2dbf3 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Thu, 26 Jul 2018 02:28:03 +0100 Subject: [PATCH 24/26] Trace the Reader and card status in sniffing mode This will prepare for the autocalibrate of threshold If card selection fully detected, then the threshold is good, Otherwise it is not good. (cherry picked from commit f5c8485) --- .../Chameleon-Mini/Application/Sniff14443A.c | 127 ++++++++++++++++-- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 12 +- .../Chameleon-Mini/Codec/SniffISO14443-2A.h | 2 +- 3 files changed, 129 insertions(+), 12 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index 68512a7..e652834 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -7,22 +7,31 @@ #include #include #include "Sniff14443A.h" -Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; - +#include "Codec/SniffISO14443-2A.h" extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount); - static enum { + +Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; +bool selected = false; +static enum { STATE_IDLE, - STATE_READER_DATA, - STATE_CARD_DATA + STATE_REQA, + STATE_ATQA, + STATE_ANTICOLLI, + STATE_SELECT, + STATE_UID, + STATE_SAK, } SniffState = STATE_IDLE; + void Sniff14443AAppInit(void){ - SniffState = STATE_IDLE; + SniffState = STATE_REQA; + selected = false; } void Sniff14443AAppReset(void){ SniffState = STATE_IDLE; Sniff14443CurrentCommand = Sniff14443_Do_Nothing; + selected = false; } // Currently APPTask and AppTick is not being used void Sniff14443AAppTask(void){/* Empty */} @@ -32,16 +41,116 @@ void Sniff14443AAppTimeout(void){ Sniff14443AAppReset(); } +void reset2REQA(void){ + SniffState = STATE_REQA; + LED_PORT.OUTCLR = LED_RED; + selected = false; + // TODO: Mark the current threshold as fail and continue + +} uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ switch (Sniff14443CurrentCommand){ case Sniff14443_Do_Nothing: return 0; case Sniff14443_Autocalibrate: - // If received Reader WUPA - if(Buffer[0] == 0x26 || Buffer[0] == 0x54){ - LED_PORT.OUTSET = LED_RED; + switch (SniffState){ + case STATE_REQA: + // If received Reader REQA or WUPA + if (TrafficSource == TRAFFIC_READER && + (Buffer[0] == 0x26 || Buffer[0] == 0x54)) + { + SniffState = STATE_ATQA; + } else { + // Stay in this state, do noting + } + break; + case STATE_ATQA: + // ATQA: P RRRR XXXX P XXRX XXXX + if (TrafficSource == TRAFFIC_CARD && + BitCount == 2*9 && + (Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0 + (Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0 + (Buffer[2] & 0x01) == 0x00 && + checkParityBits(Buffer, BitCount)) + { + // Assume this is a good ATQA + SniffState = STATE_ANTICOLLI; + } else { + // If not ATQA, but REQA, then stay on this state, + // Reset to REQA, save the counter and reset the counter + if (TrafficSource == TRAFFIC_READER && + (Buffer[0] == 0x26 || Buffer[0] == 0x54)) { + } else { + // If not ATQA and not REQA then reset to REQA + reset2REQA(); + } + } + break; + case STATE_ANTICOLLI: + LED_PORT.OUTSET = LED_RED; + // SEL: 93/95/97 + if(TrafficSource == TRAFFIC_READER && + BitCount == 2*8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01) + { + SniffState = STATE_UID; + } else{ + reset2REQA(); + } + break; + case STATE_UID: + if(TrafficSource == TRAFFIC_CARD && + BitCount == 5*9 && + checkParityBits(Buffer, BitCount)) + { + SniffState = STATE_SELECT; + } else { + reset2REQA(); + } + break; + case STATE_SELECT: + + // SELECT: 9 bytes, SEL = 93/95/97, NVB=70 + if (TrafficSource == TRAFFIC_READER && + BitCount == 9*8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01 && + Buffer[1] == 0x70) + { + SniffState = STATE_SAK; + } else{ + // Not valid, reset + reset2REQA(); + } + break; + case STATE_SAK: + // SAK: 1Byte SAK + CRC + if(TrafficSource == TRAFFIC_CARD && + BitCount == 3*9 && + checkParityBits(Buffer, BitCount)) + { + if((Buffer[0] & 0x04) == 0x00){ + // UID complete, success SELECTED, + // TODO: Mark the current threshold as success and continue + // reset + SniffState = STATE_REQA; + selected = true; + LED_PORT.OUTCLR = LED_RED; + + } else { + // UID not complete, goto ANTICOLLI + SniffState = STATE_ANTICOLLI; + } + } else{ + reset2REQA(); + } + break; + default: + break; } break; + default: return 0; } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index fb2a51a..b58cc16 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -513,18 +513,26 @@ void Sniff14443ACodecTask(void) PORTE.OUTSET = PIN3_bm; if(Flags.ReaderDataAvaliable){ Flags.ReaderDataAvaliable = false; + LogEntry(LOG_INFO_CODEC_SNI_READER_DATA, CodecBuffer, (ReaderBitCount+7)/8); - ApplicationProcess(CodecBuffer, (ReaderBitCount+7)/8); + // Let the Application layer know where this data comes from LEDHook(LED_CODEC_RX, LED_PULSE); + + TrafficSource = TRAFFIC_READER; + ApplicationProcess(CodecBuffer, ReaderBitCount); } if (Flags.CardDataAvaliable){ Flags.CardDataAvaliable = false; + // CardBitCount = removeParityBits(CodecBuffer2,CardBitCount ); LogEntry(LOG_INFO_CODEC_SNI_CARD_DATA_W_PARITY, CodecBuffer2, (CardBitCount + 7) / 8); LEDHook(LED_CODEC_RX, LED_PULSE); - ApplicationProcess(CodecBuffer2, (CardBitCount+7)/8); + + // Let the Application layer know where this data comes from + TrafficSource = TRAFFIC_CARD; + ApplicationProcess(CodecBuffer2, CardBitCount); } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h index b8616b0..0e22d46 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.h @@ -9,7 +9,7 @@ #include "Codec.h" #include "Terminal/CommandLine.h" -extern enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; +enum RCTraffic {TRAFFIC_READER, TRAFFIC_CARD} TrafficSource; /* Codec Interface */ void Sniff14443ACodecInit(void); void Sniff14443ACodecDeInit(void); From 86d47110a97f18ebbffd3ac8d7ed79e1ce3bacc1 Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 27 Jul 2018 01:46:12 +0100 Subject: [PATCH 25/26] Basic auto calibrate for sniffing mode. Started from the smallest threshold and when the first good threshold is obtained, stop. May also need to extend the TIMEOUT to make this work. Need the reader reading all the timing when sniffing in order to auto calibrate (cherry picked from commit 2c3d5f5) --- .../Chameleon-Mini/Application/Sniff14443A.c | 102 ++++++++++-------- .../Chameleon-Mini/Codec/SniffISO14443-2A.c | 2 - 2 files changed, 57 insertions(+), 47 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index e652834..59f3ed7 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -11,7 +11,7 @@ extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount); Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing; -bool selected = false; +//bool selected = false; static enum { STATE_IDLE, STATE_REQA, @@ -22,16 +22,21 @@ static enum { STATE_SAK, } SniffState = STATE_IDLE; +static uint16_t tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; +static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / + CODEC_THRESHOLD_CALIBRATE_STEPS] = {0}; void Sniff14443AAppInit(void){ SniffState = STATE_REQA; - selected = false; + + tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; + CodecThresholdSet(tmp_th); } void Sniff14443AAppReset(void){ SniffState = STATE_IDLE; + Sniff14443CurrentCommand = Sniff14443_Do_Nothing; - selected = false; } // Currently APPTask and AppTick is not being used void Sniff14443AAppTask(void){/* Empty */} @@ -41,24 +46,31 @@ void Sniff14443AAppTimeout(void){ Sniff14443AAppReset(); } -void reset2REQA(void){ +INLINE void reset2REQA(void){ SniffState = STATE_REQA; LED_PORT.OUTCLR = LED_RED; - selected = false; - // TODO: Mark the current threshold as fail and continue + // Mark the current threshold as fail and continue + if(tmp_th < CODEC_THRESHOLD_CALIBRATE_MAX){ + Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = 0; + tmp_th = CodecThresholdIncrement(); + } else{ + // mark finish + } } uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ switch (Sniff14443CurrentCommand){ - case Sniff14443_Do_Nothing: + case Sniff14443_Do_Nothing: { return 0; - case Sniff14443_Autocalibrate: - switch (SniffState){ + } + case Sniff14443_Autocalibrate: { + + switch (SniffState) { case STATE_REQA: + LED_PORT.OUTCLR = LED_RED; // If received Reader REQA or WUPA if (TrafficSource == TRAFFIC_READER && - (Buffer[0] == 0x26 || Buffer[0] == 0x54)) - { + (Buffer[0] == 0x26 || Buffer[0] == 0x52)) { SniffState = STATE_ATQA; } else { // Stay in this state, do noting @@ -67,19 +79,18 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ case STATE_ATQA: // ATQA: P RRRR XXXX P XXRX XXXX if (TrafficSource == TRAFFIC_CARD && - BitCount == 2*9 && - (Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0 - (Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0 - (Buffer[2] & 0x01) == 0x00 && - checkParityBits(Buffer, BitCount)) - { + BitCount == 2 * 9 && + (Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0 + (Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0 + (Buffer[2] & 0x01) == 0x00 && + checkParityBits(Buffer, BitCount)) { // Assume this is a good ATQA SniffState = STATE_ANTICOLLI; } else { // If not ATQA, but REQA, then stay on this state, // Reset to REQA, save the counter and reset the counter if (TrafficSource == TRAFFIC_READER && - (Buffer[0] == 0x26 || Buffer[0] == 0x54)) { + (Buffer[0] == 0x26 || Buffer[0] == 0x52)) { } else { // If not ATQA and not REQA then reset to REQA reset2REQA(); @@ -87,23 +98,21 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ } break; case STATE_ANTICOLLI: - LED_PORT.OUTSET = LED_RED; // SEL: 93/95/97 - if(TrafficSource == TRAFFIC_READER && - BitCount == 2*8 && - (Buffer[0] & 0xf0) == 0x90 && - (Buffer[0] & 0x09) == 0x01) - { + if (TrafficSource == TRAFFIC_READER && + BitCount == 2 * 8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01) { SniffState = STATE_UID; - } else{ + + } else { reset2REQA(); } break; case STATE_UID: - if(TrafficSource == TRAFFIC_CARD && - BitCount == 5*9 && - checkParityBits(Buffer, BitCount)) - { + if (TrafficSource == TRAFFIC_CARD && + BitCount == 5 * 9 && + checkParityBits(Buffer, BitCount)) { SniffState = STATE_SELECT; } else { reset2REQA(); @@ -113,36 +122,39 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ // SELECT: 9 bytes, SEL = 93/95/97, NVB=70 if (TrafficSource == TRAFFIC_READER && - BitCount == 9*8 && - (Buffer[0] & 0xf0) == 0x90 && - (Buffer[0] & 0x09) == 0x01 && - Buffer[1] == 0x70) - { + BitCount == 9 * 8 && + (Buffer[0] & 0xf0) == 0x90 && + (Buffer[0] & 0x09) == 0x01 && + Buffer[1] == 0x70) { SniffState = STATE_SAK; - } else{ + } else { // Not valid, reset reset2REQA(); } break; case STATE_SAK: // SAK: 1Byte SAK + CRC - if(TrafficSource == TRAFFIC_CARD && - BitCount == 3*9 && - checkParityBits(Buffer, BitCount)) - { - if((Buffer[0] & 0x04) == 0x00){ + if (TrafficSource == TRAFFIC_CARD && + BitCount == 3 * 9 && + checkParityBits(Buffer, BitCount)) { + if ((Buffer[0] & 0x04) == 0x00) { // UID complete, success SELECTED, - // TODO: Mark the current threshold as success and continue + // Mark the current threshold as ok and finish // reset SniffState = STATE_REQA; - selected = true; - LED_PORT.OUTCLR = LED_RED; + LED_PORT.OUTSET = LED_RED; + Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] += 1; + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); + char tmpBuf[10]; + snprintf(tmpBuf, 10, "%4" PRIu16 ": ", tmp_th); + TerminalSendString(tmpBuf); + Sniff14443AAppReset(); } else { // UID not complete, goto ANTICOLLI SniffState = STATE_ANTICOLLI; } - } else{ + } else { reset2REQA(); } break; @@ -150,7 +162,7 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ break; } break; - + } default: return 0; } diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c index b58cc16..628eead 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO14443-2A.c @@ -281,8 +281,6 @@ INLINE void CardSniffInit(void) * bit halves had modulations since the last pause. */ - DACB.CH0DATA = GlobalSettings.ActiveSettingPtr->ReaderThreshold; // real threshold voltage can be calculated with ch0data * Vref / 0xFFF - // Comparator ADC /* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */ ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm; From daf51f28d77936d7a24c2d3a5eafd8786689443f Mon Sep 17 00:00:00 2001 From: chenzitai Date: Fri, 27 Jul 2018 17:12:53 +0100 Subject: [PATCH 26/26] Continue threshold searching from the last searched value or the current configured value (cherry picked from commit f3aa7b2) --- Firmware/Chameleon-Mini/Application/Sniff14443A.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff14443A.c b/Firmware/Chameleon-Mini/Application/Sniff14443A.c index 59f3ed7..bea898c 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff14443A.c +++ b/Firmware/Chameleon-Mini/Application/Sniff14443A.c @@ -28,9 +28,8 @@ static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIB void Sniff14443AAppInit(void){ SniffState = STATE_REQA; - - tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN; - CodecThresholdSet(tmp_th); + // Get current threshold and continue searching from here + tmp_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; } void Sniff14443AAppReset(void){ @@ -56,6 +55,7 @@ INLINE void reset2REQA(void){ tmp_th = CodecThresholdIncrement(); } else{ // mark finish + CommandLinePendingTaskFinished(COMMAND_INFO_FALSE, NULL); } } uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ @@ -145,10 +145,14 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){ LED_PORT.OUTSET = LED_RED; Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] += 1; CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); + // Send this threshold to terminal char tmpBuf[10]; snprintf(tmpBuf, 10, "%4" PRIu16 ": ", tmp_th); TerminalSendString(tmpBuf); + // Save value to EEPROM + SETTING_UPDATE(GlobalSettings.ActiveSettingPtr->ReaderThreshold); + Sniff14443AAppReset(); } else { // UID not complete, goto ANTICOLLI