]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
ISO15693 device side improvements (#652)
authorpwpiwi <pwpiwi@users.noreply.github.com>
Wed, 15 Aug 2018 12:03:20 +0000 (14:03 +0200)
committerGitHub <noreply@github.com>
Wed, 15 Aug 2018 12:03:20 +0000 (14:03 +0200)
* ISO15693 device side improvements
* increase accuracy by doubling the sample frequency (hi_read_rx_xcorr.v)
* adjust armsrc/iso15693.c and client/cmdhf15.c accordingly
* use more accurate approximation for sqrt(ci^2 + cq^2)
* improve EOF detection (was often mistaken for Logic0, resulting in "error, uneven octet! (extra bits!)")
* hi_read_r_xcorr.v: avoid overflows during accumulation and truncation
* explicitely cast unsigned ADC samples to signed

armsrc/iso15693.c
client/cmdhf15.c
fpga/fpga_hf.bit
fpga/hi_read_rx_xcorr.v

index 1f0b8193c0cf96ab76b31941bcb99ed94194aae0..ad6f5cfc0e6b684d2b186e498aab06f85642702b 100644 (file)
 #define AddCrc(data,datalen)  Iso15693AddCrc(data,datalen)
 #define sprintUID(target,uid)  Iso15693sprintUID(target,uid)
 
-int DEBUG=0;
+// approximate amplitude=sqrt(ci^2+cq^2) 
+#define AMPLITUDE(ci, cq) (MAX(ABS(ci), ABS(cq)) + (MIN(ABS(ci), ABS(cq))>>1))
+
+static int DEBUG = 0;
 
 
 // ---------------------------
@@ -303,13 +306,9 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
 
 // NOW READ RESPONSE
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
-       //spindelay(60);        // greg - experiment to get rid of some of the 0 byte/failed reads
        c = 0;
        getNext = false;
        for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0x43;
-               }
                if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
                        int8_t b;
                        b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
@@ -319,11 +318,11 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               uint8_t r = ABS(b) + ABS(prev);
+                               uint8_t r = AMPLITUDE(b, prev);
 
-                               dest[c++] = (uint8_t)r;
+                               dest[c++] = r;
 
-                               if(c >= 2000) {
+                               if(c >= 4000) {
                                        break;
                                }
                        } else {
@@ -341,12 +340,10 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
        int i, j;
        int max = 0, maxPos=0;
 
-       int skip = 4;
-
-       //      if(GraphTraceLen < 1000) return;        // THIS CHECKS FOR A BUFFER TO SMALL
+       int skip = 2;
 
        // First, correlate for SOF
-       for(i = 0; i < 100; i++) {
+       for(i = 0; i < 200; i++) {  // usually, SOF is found around i = 60
                int corr = 0;
                for(j = 0; j < arraylen(FrameSOF); j += skip) {
                        corr += FrameSOF[j]*dest[i+(j/skip)];
@@ -356,7 +353,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
                        maxPos = i;
                }
        }
-               // Dbprintf("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
+       if (DEBUG) Dbprintf("SOF at %d, correlation %d", maxPos, max/(arraylen(FrameSOF)/skip));
 
        int k = 0; // this will be our return value
 
@@ -370,10 +367,15 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
                memset(outBuf, 0, sizeof(outBuf));
                uint8_t mask = 0x01;
                for(;;) {
-                       int corr0 = 0, corr1 = 0, corrEOF = 0;
+                       int corr0 = 0, corr00 = 0, corr01 = 0, corr1 = 0, corrEOF = 0;
                        for(j = 0; j < arraylen(Logic0); j += skip) {
                                corr0 += Logic0[j]*dest[i+(j/skip)];
                        }
+                       corr01 = corr00 = corr0;
+                       for(j = 0; j < arraylen(Logic0); j += skip) {
+                               corr00 += Logic0[j]*dest[i+arraylen(Logic0)/skip+(j/skip)];
+                               corr01 += Logic1[j]*dest[i+arraylen(Logic0)/skip+(j/skip)];
+                       }
                        for(j = 0; j < arraylen(Logic1); j += skip) {
                                corr1 += Logic1[j]*dest[i+(j/skip)];
                        }
@@ -381,11 +383,14 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
                                corrEOF += FrameEOF[j]*dest[i+(j/skip)];
                        }
                        // Even things out by the length of the target waveform.
+                       corr00 *= 2;
+                       corr01 *= 2;
                        corr0 *= 4;
                        corr1 *= 4;
        
-                       if(corrEOF > corr1 && corrEOF > corr0) {
-                               // Dbprintf("EOF at %d", i);
+                       if(corrEOF > corr1 && corrEOF > corr00 && corrEOF > corr01) {
+                               if (DEBUG) Dbprintf("EOF at %d, correlation %d (corr01: %d, corr00: %d, corr1: %d, corr0: %d)", 
+                                       i, corrEOF, corr01, corr00, corr1, corr0);
                                break;
                        } else if(corr1 > corr0) {
                                i += arraylen(Logic1)/skip;
@@ -398,7 +403,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
                                k++;
                                mask = 0x01;
                        }
-                       if((i+(int)arraylen(FrameEOF)) >= 2000) {
+                       if((i+(int)arraylen(FrameEOF)/skip) >= 4000) {
                                DbpString("ran off end!");
                                break;
                        }
@@ -446,9 +451,6 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
        c = 0;
        getNext = false;
        for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0x43;
-               }
                if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
                        int8_t b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
 
@@ -457,11 +459,11 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               uint8_t r = ABS(b) + ABS(prev);
+                               uint8_t r = AMPLITUDE(b, prev);
 
-                               dest[c++] = (uint8_t)r;
+                               dest[c++] = r;
 
-                               if(c >= 20000) {
+                               if(c >= BIGBUF_SIZE) {
                                        break;
                                }
                        } else {
@@ -479,12 +481,10 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
        int i, j;
        int max = 0, maxPos=0;
 
-       int skip = 4;
-
-//     if(GraphTraceLen < 1000) return;        // THIS CHECKS FOR A BUFFER TO SMALL
+       int skip = 2;
 
        // First, correlate for SOF
-       for(i = 0; i < 19000; i++) {
+       for(i = 0; i < 38000; i++) {
                int corr = 0;
                for(j = 0; j < arraylen(FrameSOF); j += skip) {
                        corr += FrameSOF[j]*dest[i+(j/skip)];
@@ -494,7 +494,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
                        maxPos = i;
                }
        }
-//     DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
+       if (DEBUG) Dbprintf("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
 
        int k = 0; // this will be our return value
 
@@ -508,10 +508,15 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
                memset(outBuf, 0, sizeof(outBuf));
                uint8_t mask = 0x01;
                for(;;) {
-                       int corr0 = 0, corr1 = 0, corrEOF = 0;
+                       int corr0 = 0, corr00 = 0, corr01 = 0, corr1 = 0, corrEOF = 0;
                        for(j = 0; j < arraylen(Logic0); j += skip) {
                                corr0 += Logic0[j]*dest[i+(j/skip)];
                        }
+                       corr01 = corr00 = corr0;
+                       for(j = 0; j < arraylen(Logic0); j += skip) {
+                               corr00 += Logic0[j]*dest[i+arraylen(Logic0)/skip+(j/skip)];
+                               corr01 += Logic1[j]*dest[i+arraylen(Logic0)/skip+(j/skip)];
+                       }
                        for(j = 0; j < arraylen(Logic1); j += skip) {
                                corr1 += Logic1[j]*dest[i+(j/skip)];
                        }
@@ -519,11 +524,14 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
                                corrEOF += FrameEOF[j]*dest[i+(j/skip)];
                        }
                        // Even things out by the length of the target waveform.
+                       corr00 *= 2;
+                       corr01 *= 2;
                        corr0 *= 4;
                        corr1 *= 4;
        
-                       if(corrEOF > corr1 && corrEOF > corr0) {
-       //                      DbpString("EOF at %d", i);
+                       if(corrEOF > corr1 && corrEOF > corr00 && corrEOF > corr01) {
+                               if (DEBUG) Dbprintf("EOF at %d, correlation %d (corr01: %d, corr00: %d, corr1: %d, corr0: %d)", 
+                                       i, corrEOF, corr01, corr00, corr1, corr0);
                                break;
                        } else if(corr1 > corr0) {
                                i += arraylen(Logic1)/skip;
@@ -536,7 +544,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
                                k++;
                                mask = 0x01;
                        }
-                       if((i+(int)arraylen(FrameEOF)) >= 2000) {
+                       if((i+(int)arraylen(FrameEOF)/skip) >= BIGBUF_SIZE) {
                                DbpString("ran off end!");
                                break;
                        }
@@ -602,10 +610,6 @@ void AcquireRawAdcSamplesIso15693(void)
                                break;
                        }
                }
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
-                       (void)r;
-               }
                WDT_HIT();
        }
 
@@ -614,9 +618,6 @@ void AcquireRawAdcSamplesIso15693(void)
        c = 0;
        getNext = false;
        for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0x43;
-               }
                if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
                        int8_t b;
                        b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
@@ -626,11 +627,11 @@ void AcquireRawAdcSamplesIso15693(void)
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               uint8_t r = ABS(b) + ABS(prev);
+                               uint8_t r = AMPLITUDE(b, prev);
 
-                               dest[c++] = (uint8_t)r;
+                               dest[c++] = r;
 
-                               if(c >= 2000) {
+                               if(c >= 4000) {
                                        break;
                                }
                        } else {
@@ -668,9 +669,6 @@ void RecordRawAdcSamplesIso15693(void)
        c = 0;
        getNext = false;
        for(;;) {
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-                       AT91C_BASE_SSC->SSC_THR = 0x43;
-               }
                if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
                        int8_t b;
                        b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
@@ -680,11 +678,11 @@ void RecordRawAdcSamplesIso15693(void)
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               uint8_t r = ABS(b) + ABS(prev);
+                               uint8_t r = AMPLITUDE(b, prev);
 
-                               dest[c++] = (uint8_t)r;
+                               dest[c++] = r;
 
-                               if(c >= 7000) {
+                               if(c >= 14000) {
                                        break;
                                }
                        } else {
@@ -836,7 +834,7 @@ int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv)
        if (init) Iso15693InitReader();
 
        int answerLen=0;
-       uint8_t *answer = BigBuf_get_addr() + 3660;
+       uint8_t *answer = BigBuf_get_addr() + 4000;
        if (recv != NULL) memset(answer, 0, 100);
 
        if (!speed) {
@@ -957,7 +955,7 @@ void ReaderIso15693(uint32_t parameter)
 
        int answerLen1 = 0;
        int answerLen2 = 0;
-       int answerLen3 = 0;
+       // int answerLen3 = 0;
        int i = 0;
        int samples = 0;
        int tsamples = 0;
@@ -967,11 +965,11 @@ void ReaderIso15693(uint32_t parameter)
 
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
 
-       uint8_t *answer1 = BigBuf_get_addr() + 3660;
-       uint8_t *answer2 = BigBuf_get_addr() + 3760;
-       uint8_t *answer3 = BigBuf_get_addr() + 3860;
+       uint8_t *answer1 = BigBuf_get_addr() + 4000;
+       uint8_t *answer2 = BigBuf_get_addr() + 4100;
+       // uint8_t *answer3 = BigBuf_get_addr() + 4200;
        // Blank arrays
-       memset(answer1, 0x00, 300);
+       memset(answer1, 0x00, 200);
 
        SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
        // Setup SSC
@@ -1025,21 +1023,21 @@ void ReaderIso15693(uint32_t parameter)
                        TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
 
 
-       Dbprintf("%d octets read from SELECT request:", answerLen2);
-       DbdecodeIso15693Answer(answerLen2,answer2);
-       Dbhexdump(answerLen2,answer2,true);
+       // Dbprintf("%d octets read from SELECT request:", answerLen2);
+       // DbdecodeIso15693Answer(answerLen2,answer2);
+       // Dbhexdump(answerLen2,answer2,true);
 
-       Dbprintf("%d octets read from XXX request:", answerLen3);
-       DbdecodeIso15693Answer(answerLen3,answer3);
-       Dbhexdump(answerLen3,answer3,true);
+       // Dbprintf("%d octets read from XXX request:", answerLen3);
+       // DbdecodeIso15693Answer(answerLen3,answer3);
+       // Dbhexdump(answerLen3,answer3,true);
 
        // read all pages
        if (answerLen1>=12 && DEBUG) {
                i=0;                    
                while (i<32) {  // sanity check, assume max 32 pages
                        BuildReadBlockRequest(TagUID,i);
-             TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  
-         answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
+                       TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  
+                       answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
                        if (answerLen2>0) {
                                Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2);
                                DbdecodeIso15693Answer(answerLen2,answer2);
@@ -1073,7 +1071,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid)
 
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
 
-       uint8_t *buf = BigBuf_get_addr() + 3660;
+       uint8_t *buf = BigBuf_get_addr() + 4000;
        memset(buf, 0x00, 100);
        
        SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
@@ -1177,7 +1175,7 @@ void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8
 
        if (recv) { 
                LED_B_ON();
-    cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48);
+               cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48);
                LED_B_OFF();    
                
                if (DEBUG) {
index 08cc3b154bec50ff3f01baf4dcce1964f3597c01..b6a84c1cf4d196abb5bd73a42431ae3f12361dad 100644 (file)
@@ -268,7 +268,7 @@ static char* TagErrorStr(uint8_t error) {
                case 0x02: return "The command is not recognised";
                case 0x03: return "The option is not supported.";
                case 0x0f: return "Unknown error.";
-               case 0x10: return "The specified block is not available (doesnt exist).";
+               case 0x10: return "The specified block is not available (doesn't exist).";
                case 0x11: return "The specified block is already -locked and thus cannot be locked again";
                case 0x12: return "The specified block is locked and its content cannot be changed.";
                case 0x13: return "The specified block was not successfully programmed.";
@@ -286,12 +286,12 @@ int CmdHF15Demod(const char *Cmd)
        int i, j;
        int max = 0, maxPos = 0;
 
-       int skip = 4;
+       int skip = 2;
 
-       if (GraphTraceLen < 1000) return 0;
+       if (GraphTraceLen < 2000) return 0;
 
        // First, correlate for SOF
-       for (i = 0; i < 100; i++) {
+       for (i = 0; i < 200; i++) {
                int corr = 0;
                for (j = 0; j < arraylen(FrameSOF); j += skip) {
                        corr += FrameSOF[j] * GraphBuffer[i + (j / skip)];
@@ -310,23 +310,30 @@ int CmdHF15Demod(const char *Cmd)
        memset(outBuf, 0, sizeof(outBuf));
        uint8_t mask = 0x01;
        for (;;) {
-               int corr0 = 0, corr1 = 0, corrEOF = 0;
-               for (j = 0; j < arraylen(Logic0); j += skip) {
-                       corr0 += Logic0[j] * GraphBuffer[i + (j / skip)];
-               }
-               for (j = 0; j < arraylen(Logic1); j += skip) {
-                       corr1 += Logic1[j] * GraphBuffer[i + (j / skip)];
-               }
-               for (j = 0; j < arraylen(FrameEOF); j += skip) {
-                       corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)];
-               }
-               // Even things out by the length of the target waveform.
-               corr0 *= 4;
-               corr1 *= 4;
-               
-               if (corrEOF > corr1 && corrEOF > corr0) {
-                       PrintAndLog("EOF at %d", i);
-                       break;
+                       int corr0 = 0, corr00 = 0, corr01 = 0, corr1 = 0, corrEOF = 0;
+                       for(j = 0; j < arraylen(Logic0); j += skip) {
+                               corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];
+                       }
+                       corr01 = corr00 = corr0;
+                       for(j = 0; j < arraylen(Logic0); j += skip) {
+                               corr00 += Logic0[j]*GraphBuffer[i+arraylen(Logic0)/skip+(j/skip)];
+                               corr01 += Logic1[j]*GraphBuffer[i+arraylen(Logic0)/skip+(j/skip)];
+                       }
+                       for(j = 0; j < arraylen(Logic1); j += skip) {
+                               corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];
+                       }
+                       for(j = 0; j < arraylen(FrameEOF); j += skip) {
+                               corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];
+                       }
+                       // Even things out by the length of the target waveform.
+                       corr00 *= 2;
+                       corr01 *= 2;
+                       corr0 *= 4;
+                       corr1 *= 4;
+       
+                       if(corrEOF > corr1 && corrEOF > corr00 && corrEOF > corr01) {
+                               PrintAndLog("EOF at %d", i);
+                               break;
                } else if (corr1 > corr0) {
                        i += arraylen(Logic1) / skip;
                        outBuf[k] |= mask;
index 229151dfbf50cb8de730a85446ccbc18407e8474..939ba93a54ce00e9425a1156d3900f1af58c4c8e 100644 (file)
Binary files a/fpga/fpga_hf.bit and b/fpga/fpga_hf.bit differ
index 433d6736f1814c0f3cc529e807f8cfb70ed3c1eb..f637abf2012350f364e15d2606428bf6aca89311 100644 (file)
@@ -27,22 +27,12 @@ assign pwr_hi = ck_1356megb & (~snoop);
 assign pwr_oe1 = 1'b0;
 assign pwr_oe3 = 1'b0;
 assign pwr_oe4 = 1'b0;
+// Unused.
+assign pwr_lo = 1'b0;
+assign pwr_oe2 = 1'b0;
+
+assign adc_clk = ck_1356megb;  // sample frequency is 13,56 MHz
 
-reg [2:0] fc_div;
-always @(negedge ck_1356megb)
-    fc_div <= fc_div + 1;
-
-(* clock_signal = "yes" *) reg adc_clk;                                // sample frequency, always 16 * fc
-always @(ck_1356megb, xcorr_is_848, xcorr_quarter_freq, fc_div)
-       if (xcorr_is_848 & ~xcorr_quarter_freq)                 // fc = 847.5 kHz, standard ISO14443B
-               adc_clk <= ck_1356megb;
-       else if (~xcorr_is_848 & ~xcorr_quarter_freq)   // fc = 423.75 kHz 
-               adc_clk <= fc_div[0];
-       else if (xcorr_is_848 & xcorr_quarter_freq)             // fc = 211.875 kHz
-               adc_clk <= fc_div[1];
-       else                                                                                    // fc = 105.9375 kHz
-               adc_clk <= fc_div[2];
-               
 // When we're a reader, we just need to do the BPSK demod; but when we're an
 // eavesdropper, we also need to pick out the commands sent by the reader,
 // using AM. Do this the same way that we do it for the simulated tag.
@@ -69,15 +59,27 @@ begin
     end
 end
 
-// Let us report a correlation every 4 subcarrier cycles, or 4*16=64 samples,
-// so we need a 6-bit counter.
+
+// Let us report a correlation every 64 samples. I.e.
+// one Q/I pair after 4 subcarrier cycles for the 848kHz subcarrier,
+// one Q/I pair after 2 subcarrier cycles for the 424kHz subcarriers,
+// one Q/I pair for each subcarrier cyle for the 212kHz subcarrier.
+// We need a 6-bit counter for the timing.
 reg [5:0] corr_i_cnt;
-// And a couple of registers in which to accumulate the correlations.
-// We would add at most 32 times the difference between unmodulated and modulated signal. It should
+always @(negedge adc_clk)
+begin
+       corr_i_cnt <= corr_i_cnt + 1;
+end            
+
+// And a couple of registers in which to accumulate the correlations. From the 64 samples
+// we would add at most 32 times the difference between unmodulated and modulated signal. It should
 // be safe to assume that a tag will not be able to modulate the carrier signal by more than 25%.
 // 32 * 255 * 0,25 = 2040, which can be held in 11 bits. Add 1 bit for sign.
-reg signed [11:0] corr_i_accum;
-reg signed [11:0] corr_q_accum;
+// Temporary we might need more bits. For the 212kHz subcarrier we could possible add 32 times the
+// maximum signal value before a first subtraction would occur. 32 * 255 = 8160 can be held in 13 bits. 
+// Add one bit for sign -> need 14 bit registers but final result will fit into 12 bits.
+reg signed [13:0] corr_i_accum;
+reg signed [13:0] corr_q_accum;
 // we will report maximum 8 significant bits
 reg signed [7:0] corr_i_out;
 reg signed [7:0] corr_q_out;
@@ -86,12 +88,29 @@ reg ssp_clk;
 reg ssp_frame;
 
 
-always @(negedge adc_clk)
-begin
-       corr_i_cnt <= corr_i_cnt + 1;
-end            
-               
+// The subcarrier reference signals
+reg subcarrier_I;
+reg subcarrier_Q;
 
+always @(corr_i_cnt or xcorr_is_848 or xcorr_quarter_freq)
+begin
+       if (xcorr_is_848 & ~xcorr_quarter_freq)                         // 848 kHz
+               begin
+                       subcarrier_I = ~corr_i_cnt[3];
+                       subcarrier_Q = ~(corr_i_cnt[3] ^ corr_i_cnt[2]);
+               end
+       else if (xcorr_is_848 & xcorr_quarter_freq)                     // 212 kHz      
+               begin
+                       subcarrier_I = ~corr_i_cnt[5];
+                       subcarrier_Q = ~(corr_i_cnt[5] ^ corr_i_cnt[4]);
+               end
+       else
+               begin                                                                                   // 424 kHz
+                       subcarrier_I = ~corr_i_cnt[4];
+                       subcarrier_Q = ~(corr_i_cnt[4] ^ corr_i_cnt[3]);
+               end
+end
+       
 // ADC data appears on the rising edge, so sample it on the falling edge
 always @(negedge adc_clk)
 begin
@@ -103,36 +122,60 @@ begin
         if(snoop)
         begin
                        // Send 7 most significant bits of tag signal (signed), plus 1 bit reader signal
-            corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev};
-            corr_q_out <= {corr_q_accum[11:5], after_hysteresis_prev};
+                       if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) 
+                               corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev};
+                       else // truncate to maximum value
+                               if (corr_i_accum[13] == 1'b0)
+                                       corr_i_out <= {7'b0111111, after_hysteresis_prev_prev};
+                               else
+                                       corr_i_out <= {7'b1000000, after_hysteresis_prev_prev};
+                       if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111) 
+                               corr_q_out <= {corr_q_accum[11:5], after_hysteresis_prev};
+                       else // truncate to maximum value
+                               if (corr_q_accum[13] == 1'b0)
+                                       corr_q_out <= {7'b0111111, after_hysteresis_prev};
+                               else
+                                       corr_q_out <= {7'b1000000, after_hysteresis_prev};
                        after_hysteresis_prev_prev <= after_hysteresis;
         end
         else
         begin
-            // 8 bits of tag signal
-            corr_i_out <= corr_i_accum[11:4];
-            corr_q_out <= corr_q_accum[11:4];
+            // Send 8 bits of tag signal
+                       if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) 
+                               corr_i_out <= corr_i_accum[11:4];
+                       else // truncate to maximum value
+                               if (corr_i_accum[13] == 1'b0)
+                                       corr_i_out <= 8'b01111111;
+                               else
+                                       corr_i_out <= 8'b10000000;
+                       if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111) 
+                               corr_q_out <= corr_q_accum[11:4];
+                       else // truncate to maximum value
+                               if (corr_q_accum[13] == 1'b0)
+                                       corr_q_out <= 8'b01111111;
+                               else
+                                       corr_q_out <= 8'b10000000;
         end
-
-        corr_i_accum <= adc_d;
-        corr_q_accum <= adc_d;
+               // Initialize next correlation. 
+               // Both I and Q reference signals are high when corr_i_nct == 0. Therefore need to accumulate.
+        corr_i_accum <= $signed({1'b0,adc_d});
+        corr_q_accum <= $signed({1'b0,adc_d});
     end
     else
     begin
-        if(corr_i_cnt[3])
-            corr_i_accum <= corr_i_accum - adc_d;
+        if (subcarrier_I)
+            corr_i_accum <= corr_i_accum + $signed({1'b0,adc_d});
         else
-            corr_i_accum <= corr_i_accum + adc_d;
+            corr_i_accum <= corr_i_accum - $signed({1'b0,adc_d});
 
-        if(corr_i_cnt[3] == corr_i_cnt[2])                     // phase shifted by pi/2
-            corr_q_accum <= corr_q_accum + adc_d;
+        if (subcarrier_Q)
+            corr_q_accum <= corr_q_accum + $signed({1'b0,adc_d});
         else
-            corr_q_accum <= corr_q_accum - adc_d;
+            corr_q_accum <= corr_q_accum - $signed({1'b0,adc_d});
 
     end
 
-    // The logic in hi_simulate.v reports 4 samples per bit. We report two
-    // (I, Q) pairs per bit, so we should do 2 samples per pair.
+       // for each Q/I pair report two reader signal samples when sniffing
     if(corr_i_cnt == 6'd32)
         after_hysteresis_prev <= after_hysteresis;
 
@@ -167,8 +210,4 @@ assign ssp_din = corr_i_out[7];
 
 assign dbg = corr_i_cnt[3];
 
-// Unused.
-assign pwr_lo = 1'b0;
-assign pwr_oe2 = 1'b0;
-
 endmodule
Impressum, Datenschutz