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)
This commit is contained in:
chenzitai
2018-08-15 22:48:44 +01:00
parent 59d8e1739d
commit 14e1738153
@@ -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;
}