From 38d49097f981240a0664319a1ff9a9c104bca86b Mon Sep 17 00:00:00 2001 From: Yann GASCUEL <34003959+lnv42@users.noreply.github.com> Date: Fri, 4 Mar 2022 09:45:12 +0100 Subject: [PATCH] iso15 sniffing: intragrate 2SC sniffing in same FPGA mode switching Fpgamode while sniffing with FpgaWriteConfWord() was sometimes too long so the tag answer start was lost. Now, (only with FPGA_BITSTREAM_HF_15) with "FPGA_HF_READER_MODE_SNIFF_AMPLITUDE | FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ": the amplitude is shrank from its 2 LSB bits and those 2 bits are now used to return the current frequency. From my tests, this 2 bits reduction does not affect quality of 1SC sniffing, but it may have slightly reduced the receiving range. FPGA FSK decoding code is also improved. --- armsrc/fpgaloader.c | 4 +- armsrc/fpgaloader.h | 9 +- armsrc/iso15693.c | 27 +-- fpga-xc2s30/Makefile | 2 +- fpga-xc2s30/fpga_hf_15.bit | Bin 42178 -> 42178 bytes fpga-xc2s30/fpga_hf_15.v | 36 ++- fpga-xc2s30/hi_reader_15.v | 443 +++++++++++++++++++++++++++++++++++++ 7 files changed, 469 insertions(+), 52 deletions(-) create mode 100644 fpga-xc2s30/hi_reader_15.v diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index ab8d57f7d..80d793b82 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -162,7 +162,9 @@ void FpgaSetupSsc(uint16_t fpga_mode) { // 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync // pulse, no output sync - if ((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER && (FpgaGetCurrent() == FPGA_BITSTREAM_HF || FpgaGetCurrent() == FPGA_BITSTREAM_HF_15)) { + if (((fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_READER || + (fpga_mode & FPGA_MAJOR_MODE_MASK) == FPGA_MAJOR_MODE_HF_FSK_READER) && + (FpgaGetCurrent() == FPGA_BITSTREAM_HF || FpgaGetCurrent() == FPGA_BITSTREAM_HF_15)) { AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); } else { AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 897031042..6069d3257 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -106,14 +106,7 @@ thres| x x x x x x x x #define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<4) #define FPGA_HF_READER_SUBCARRIER_424_KHZ (1<<4) #define FPGA_HF_READER_SUBCARRIER_212_KHZ (2<<4) - -#define FPGA_HF_FSK_READER_OUTPUT_1695_KHZ (0<<0) -#define FPGA_HF_FSK_READER_OUTPUT_848_KHZ (1<<0) -#define FPGA_HF_FSK_READER_OUTPUT_424_KHZ (2<<0) -#define FPGA_HF_FSK_READER_OUTPUT_212_KHZ (3<<0) - -#define FPGA_HF_FSK_READER_NOPOWER (0<<4) -#define FPGA_HF_FSK_READER_WITHPOWER (1<<4) +#define FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ (3<<4) // Options for the HF simulated tag, how to modulate #define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index c41760e24..919040d0e 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1269,10 +1269,10 @@ void AcquireRawAdcSamplesIso15693(void) { // Returns: true if we received a EOF // false if we are still waiting for some more //============================================================================= -#define DEBUG 0 -#define FREQ_IS_484(f) (f >= 26 && f <= 30) -#define FREQ_IS_424(f) (f >= 30 && f <= 34) -#define FREQ_IS_0(f) (f <= 24 || f >= 36) +//#define DEBUG 1 +#define FREQ_IS_484(f) ((f & 1) == 1) //(f >= 26 && f <= 30) +#define FREQ_IS_424(f) ((f & 2) == 2) //(f >= 30 && f <= 34) +#define FREQ_IS_0(f) ((f & 3) == 0) // (f <= 24 || f >= 36) #define SEOF_COUNT(c, s) ((s) ? (c >= 11 && c <= 13) : (c >= 44 && c <= 52)) #define LOGIC_COUNT(c, s) ((s) ? (c >= 3 && c <= 6) : (c >= 13 && c <= 21)) #define MAX_COUNT(c, s) ((s) ? (c >= 13) : (c >= 52)) @@ -1320,7 +1320,7 @@ static void DecodeTagFSKInit(DecodeTagFSK_t *DecodeTag, uint8_t *data, uint16_t // Performances of this function are crutial for stability // as it is called in real time for every samples -static int inline __attribute__((always_inline)) Handle15693FSKSamplesFromTag(uint8_t freq, DecodeTagFSK_t *DecodeTag, bool recv_speed) +static int RAMFUNC Handle15693FSKSamplesFromTag(uint8_t freq, DecodeTagFSK_t *DecodeTag, bool recv_speed, int samples) { switch(DecodeTag->state) { case STATE_FSK_BEFORE_SOF: @@ -1546,7 +1546,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH] = {0}; DecodeReaderInit(&dreader, cmd, sizeof(cmd), jam_search_len, jam_search_string); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE | FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ); LED_D_OFF(); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -1639,10 +1639,6 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { DecodeTagFSKReset(&dtagfsk); reader_is_active = false; expect_tag_answer = true; - if (expect_fsk_answer) - { - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_FSK_READER | FPGA_HF_FSK_READER_OUTPUT_212_KHZ | FPGA_HF_FSK_READER_NOPOWER); - } } else if (Handle15693SampleFromReader(sniffdata & 0x01, &dreader)) { uint32_t eof_time = dma_start_time + (samples * 16) + 16 - DELAY_READER_TO_ARM_SNIFF; // end of EOF @@ -1662,11 +1658,6 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { DecodeTagFSKReset(&dtagfsk); reader_is_active = false; expect_tag_answer = true; - if (expect_fsk_answer) - { - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_FSK_READER | FPGA_HF_FSK_READER_OUTPUT_212_KHZ | FPGA_HF_FSK_READER_NOPOWER); - - } } else { reader_is_active = (dreader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4); } @@ -1676,7 +1667,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { if (!expect_fsk_answer) { - if (Handle15693SamplesFromTag(sniffdata >> 2, &dtag)) { + if (Handle15693SamplesFromTag((sniffdata >> 4) << 2, &dtag)) { uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF if (dtag.lastBit == SOF_PART2) { @@ -1700,7 +1691,7 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { } else { - if (Handle15693FSKSamplesFromTag(sniffdata >> 8, &dtagfsk, expect_fast_answer)) { + if (Handle15693FSKSamplesFromTag((sniffdata >> 2) & 0x3, &dtagfsk, expect_fast_answer, samples-fsksamples)) { uint32_t eof_time = dma_start_time + (samples * 16) - DELAY_TAG_TO_ARM_SNIFF; // end of EOF if (dtagfsk.lastBit == SOF) { eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS) @@ -1719,7 +1710,6 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { tag_is_active = false; expect_fsk_answer = false; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); } else if (Handle15693FSKSamplesFromTag(sniffdata & 0xFF, &dtagfsk, expect_fast_answer)) { @@ -1741,7 +1731,6 @@ void SniffIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { tag_is_active = false; expect_fsk_answer = false; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNIFF_AMPLITUDE); } else { tag_is_active = (dtagfsk.state >= STATE_FSK_RECEIVING_DATA_484); } diff --git a/fpga-xc2s30/Makefile b/fpga-xc2s30/Makefile index 59eaf8b79..d6f05c430 100644 --- a/fpga-xc2s30/Makefile +++ b/fpga-xc2s30/Makefile @@ -22,7 +22,7 @@ fpga_felica.ngc: fpga_felica.v fpga.ucf xst_felica.scr util.v hi_simulate.v hi_r $(info [-] XST $@) $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_felica.scr -fpga_hf_15.ngc: fpga_hf_15.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_reader.v hi_iso14443a.v hi_sniffer.v hi_get_trace.v hi_read_fsk.v +fpga_hf_15.ngc: fpga_hf_15.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_reader_15.v hi_iso14443a.v hi_sniffer.v hi_get_trace.v $(Q)$(RM) $@ $(info [-] XST $@) $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf_15.scr diff --git a/fpga-xc2s30/fpga_hf_15.bit b/fpga-xc2s30/fpga_hf_15.bit index 916d843407f2a40f6ee2bb01a94b9ce0827359a0..678e746c48393129982605bf251edeb50880c306 100644 GIT binary patch literal 42178 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�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 literal 42178 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 oq!DQ9jlb95X_Dd%z@a9|kp~Hd;N0a>-!*8l(j diff --git a/fpga-xc2s30/fpga_hf_15.v b/fpga-xc2s30/fpga_hf_15.v index 59118ef33..d5c2138d6 100644 --- a/fpga-xc2s30/fpga_hf_15.v +++ b/fpga-xc2s30/fpga_hf_15.v @@ -46,6 +46,7 @@ `define FPGA_HF_READER_SUBCARRIER_848_KHZ 0 `define FPGA_HF_READER_SUBCARRIER_424_KHZ 1 `define FPGA_HF_READER_SUBCARRIER_212_KHZ 2 +`define FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ 3 `define FPGA_HF_FSK_READER_OUTPUT_1695_KHZ 0 `define FPGA_HF_FSK_READER_OUTPUT_848_KHZ 1 @@ -74,14 +75,13 @@ `define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect `define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag -`include "hi_reader.v" +`include "hi_reader_15.v" `include "hi_simulate.v" //`include "hi_iso14443a.v" `include "hi_sniffer.v" `include "util.v" // `include "hi_flite.v" `include "hi_get_trace.v" -`include "hi_read_fsk.v" module fpga_hf_15( input spck, output miso, input mosi, input ncs, @@ -221,15 +221,6 @@ hi_get_trace gt( gt_ssp_frame, gt_ssp_din, gt_ssp_clk ); -// 110 - HF Read FSK -hi_read_fsk hrf( - ck_1356meg, - hrf_pwr_lo, hrf_pwr_hi, hrf_pwr_oe1, hrf_pwr_oe2, hrf_pwr_oe3, hrf_pwr_oe4, - adc_d, hrf_adc_clk, - hrf_ssp_frame, hrf_ssp_din, hrf_ssp_clk, - subcarrier_frequency, minor_mode -); - // Major modes: // 000 -- HF reader; subcarrier frequency and modulation depth selectable // 001 -- HF simulated tag @@ -237,21 +228,20 @@ hi_read_fsk hrf( // 011 -- HF sniff // 100 -- HF ISO18092 FeliCa // 101 -- HF get trace -// 110 -- HF Read FSK +// 110 -- unused // 111 -- FPGA_MAJOR_MODE_OFF // 000 001 010 011 100 101 110 111 - -mux8 mux_ssp_clk (major_mode, ssp_clk, hr_ssp_clk, hs_ssp_clk, 1'b0, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, hrf_ssp_clk, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, hr_ssp_din, hs_ssp_din, 1'b0, he_ssp_din, hfl_ssp_din, gt_ssp_din, hrf_ssp_din, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, hr_ssp_frame, hs_ssp_frame, 1'b0, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, hrf_ssp_frame, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, hr_pwr_oe1, hs_pwr_oe1, 1'b0, he_pwr_oe1, hfl_pwr_oe1, 1'b0, hrf_pwr_oe1, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, hr_pwr_oe2, hs_pwr_oe2, 1'b0, he_pwr_oe2, hfl_pwr_oe2, 1'b0, hrf_pwr_oe2, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, hr_pwr_oe3, hs_pwr_oe3, 1'b0, he_pwr_oe3, hfl_pwr_oe3, 1'b0, hrf_pwr_oe3, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, hr_pwr_oe4, hs_pwr_oe4, 1'b0, he_pwr_oe4, hfl_pwr_oe4, 1'b0, hrf_pwr_oe4, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, hr_pwr_lo, hs_pwr_lo, 1'b0, he_pwr_lo, hfl_pwr_lo, 1'b0, hrf_pwr_lo, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, hr_pwr_hi, hs_pwr_hi, 1'b0, he_pwr_hi, hfl_pwr_hi, 1'b0, hrf_pwr_hi, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, hr_adc_clk, hs_adc_clk, 1'b0, he_adc_clk, hfl_adc_clk, 1'b0, hrf_adc_clk, 1'b0); +mux8 mux_ssp_clk (major_mode, ssp_clk, hr_ssp_clk, hs_ssp_clk, 1'b0, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, hr_ssp_din, hs_ssp_din, 1'b0, he_ssp_din, hfl_ssp_din, gt_ssp_din, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, hr_ssp_frame, hs_ssp_frame, 1'b0, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, 1'b0, 1'b0); +mux8 mux_pwr_oe1 (major_mode, pwr_oe1, hr_pwr_oe1, hs_pwr_oe1, 1'b0, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe2 (major_mode, pwr_oe2, hr_pwr_oe2, hs_pwr_oe2, 1'b0, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe3 (major_mode, pwr_oe3, hr_pwr_oe3, hs_pwr_oe3, 1'b0, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_oe4 (major_mode, pwr_oe4, hr_pwr_oe4, hs_pwr_oe4, 1'b0, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, hr_pwr_lo, hs_pwr_lo, 1'b0, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0, 1'b0); +mux8 mux_pwr_hi (major_mode, pwr_hi, hr_pwr_hi, hs_pwr_hi, 1'b0, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0, 1'b0); +mux8 mux_adc_clk (major_mode, adc_clk, hr_adc_clk, hs_adc_clk, 1'b0, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0, 1'b0); mux8 mux_dbg (major_mode, dbg, hr_dbg, hs_dbg, 1'b0, he_dbg, hfl_dbg, 1'b0, 1'b0, 1'b0); // In all modes, let the ADC's outputs be enabled. diff --git a/fpga-xc2s30/hi_reader_15.v b/fpga-xc2s30/hi_reader_15.v new file mode 100644 index 000000000..28b8a7cae --- /dev/null +++ b/fpga-xc2s30/hi_reader_15.v @@ -0,0 +1,443 @@ +//----------------------------------------------------------------------------- +// +// copied from hi_reader.v by Jonathan Westhues, April 2006 +// modified to add support for iso15 2sc mode by lnv42, Feb 2022 +//----------------------------------------------------------------------------- + +module hi_reader( + ck_1356meg, + pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, + adc_d, adc_clk, + ssp_frame, ssp_din, ssp_dout, ssp_clk, + dbg, + subcarrier_frequency, minor_mode +); + input ck_1356meg; + output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; + input [7:0] adc_d; + output adc_clk; + input ssp_dout; + output ssp_frame, ssp_din, ssp_clk; + output dbg; + input [1:0] subcarrier_frequency; + input [3:0] minor_mode; + +assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz + +// 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. +reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev; +reg [11:0] has_been_low_for; +always @(negedge adc_clk) +begin + if (& adc_d[7:0]) after_hysteresis <= 1'b1; + else if (~(| adc_d[7:0])) after_hysteresis <= 1'b0; + + if (after_hysteresis) + begin + has_been_low_for <= 12'd0; + end + else + begin + if (has_been_low_for == 12'd4095) + begin + has_been_low_for <= 12'd0; + after_hysteresis <= 1'b1; + end + else + has_been_low_for <= has_been_low_for + 1; + end +end + + +// 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; +always @(negedge adc_clk) +begin + corr_i_cnt <= corr_i_cnt + 1; +end + + +reg [1:0] fskout = 2'd0; +reg last0 = 1'b0; + +reg [7:0] avg = 8'd0; +reg [127:0] avg128 = 128'd0; +reg [7:0] diff16 = 8'd0; +reg [7:0] diff28 = 8'd0; +reg [7:0] diff32 = 8'd0; + +reg [11:0] match16 = 12'd0; +reg [11:0] match32 = 12'd0; +reg [11:0] match28 = 12'd0; + +always @(negedge adc_clk) +begin + if (corr_i_cnt[0] == 1'b0) // every 2 clock + begin + avg = adc_d[7:1]; + end + else + begin + avg = avg + adc_d[7:1]; + if (corr_i_cnt[0] == 1'b1) // every 2 clock + begin + if (avg > avg128[63:56]) + diff16 = avg - avg128[63:56]; + else + diff16 = avg128[63:56] - avg; + + if (avg > avg128[111:104]) + diff28 = avg - avg128[111:104]; + else + diff28 = avg128[111:104] - avg; + + if (avg > avg128[127:120]) + diff32 = avg - avg128[127:120]; + else + diff32 = avg128[127:120] - avg; + + avg128[127:8] = avg128[119:0]; + avg128[7:0] = avg; + + + if (corr_i_cnt[4:1] == 4'b0000) // every 32 clock (8*4) + begin + match16 = diff16; + match28 = diff28; + match32 = diff32; + end + else + begin + match16 = match16 + diff16; + match28 = match28 + diff28; + match32 = match32 + diff32; + + if (corr_i_cnt[4:1] == 4'b1111) // every 32 clock (8*4) + begin + last0 = (fskout == 2'b0); + if (match16 < 12'd64 && last0) + fskout = 2'b00; // not yet started + else if ((match16 | match28 | match32) == 12'b0) + fskout = 2'b00; // signal likely ended + else if (((match16 <= match28 + 12'd16) && (match16 <= match32+ 12'd16)) || + (match28 <= 12'd16 && match32 <= 12'd16)) + begin + if (!last0) + fskout = 2'b11; // 16 match better than 28 or 32 but already started + end + else + begin + if (match28 < match32) + begin + diff28 = match32 - match28; + diff16 = match16 - match28; + if (diff28*2 > diff16) + fskout = 2'b01; + else if (!last0) + begin + fskout = 2'b01; + end + end + else //if (match32 <= match28) + begin + diff32 = match28 - match32; + diff16 = match16 - match32; + if (diff32*2 > diff16) + fskout = 2'b10; + else if (!last0) + begin + fskout = 2'b10; + end + end + end + end + end + end + end +end + + +// 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. +// 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; + + +// the amplitude of the subcarrier is sqrt(ci^2 + cq^2). +// approximate by amplitude = max(|ci|,|cq|) + 1/2*min(|ci|,|cq|) +reg [13:0] corr_amplitude, abs_ci, abs_cq, max_ci_cq; +reg [12:0] min_ci_cq_2; // min_ci_cq / 2 + +always @(*) +begin + if (corr_i_accum[13] == 1'b0) + abs_ci <= corr_i_accum; + else + abs_ci <= -corr_i_accum; + + if (corr_q_accum[13] == 1'b0) + abs_cq <= corr_q_accum; + else + abs_cq <= -corr_q_accum; + + if (abs_ci > abs_cq) + begin + max_ci_cq <= abs_ci; + min_ci_cq_2 <= abs_cq / 2; + end + else + begin + max_ci_cq <= abs_cq; + min_ci_cq_2 <= abs_ci / 2; + end + + corr_amplitude <= max_ci_cq + min_ci_cq_2; + +end + + +// The subcarrier reference signals +reg subcarrier_I; +reg subcarrier_Q; + +always @(*) +begin + if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_848_KHZ) + begin + subcarrier_I = ~corr_i_cnt[3]; + subcarrier_Q = ~(corr_i_cnt[3] ^ corr_i_cnt[2]); + end + else if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_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 + // These are the correlators: we correlate against in-phase and quadrature + // versions of our reference signal, and keep the (signed) results or the + // resulting amplitude to send out later over the SSP. + if (corr_i_cnt == 6'd0) + begin + if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE) + begin + if (subcarrier_frequency == `FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ) + begin + // send amplitude + 2 bits fsk (2sc) signal + 2 bits reader signal + corr_i_out <= corr_amplitude[13:6]; + corr_q_out <= {corr_amplitude[5:2], fskout, after_hysteresis_prev_prev, after_hysteresis_prev}; + end + else + begin + // send amplitude plus 2 bits reader signal + corr_i_out <= corr_amplitude[13:6]; + corr_q_out <= {corr_amplitude[5:0], after_hysteresis_prev_prev, after_hysteresis_prev}; + end + end + else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ) + begin + // Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal + 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}; + + // Send 7 most significant bits of quadrature phase tag signal (signed), plus 1 bit reader signal + 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}; + end + else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE) + begin + // send amplitude + corr_i_out <= {2'b00, corr_amplitude[13:8]}; + corr_q_out <= corr_amplitude[7:0]; + end + else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_IQ) + begin + // Send 8 bits of in phase 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; + + // Send 8 bits of quadrature phase tag signal + 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 + + // for each Q/I pair report two reader signal samples when sniffing. Store the 1st. + after_hysteresis_prev_prev <= after_hysteresis; + + // 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 (subcarrier_I) + corr_i_accum <= corr_i_accum + $signed({1'b0, adc_d}); + else + corr_i_accum <= corr_i_accum - $signed({1'b0, adc_d}); + + if (subcarrier_Q) + corr_q_accum <= corr_q_accum + $signed({1'b0, adc_d}); + else + corr_q_accum <= corr_q_accum - $signed({1'b0, adc_d}); + end + + // for each Q/I pair report two reader signal samples when sniffing. Store the 2nd. + if (corr_i_cnt == 6'd32) + after_hysteresis_prev <= after_hysteresis; + + // Then the result from last time is serialized and send out to the ARM. + // We get one report each cycle, and each report is 16 bits, so the + // ssp_clk should be the adc_clk divided by 64/16 = 4. + // ssp_clk frequency = 13,56MHz / 4 = 3.39MHz + + if (corr_i_cnt[1:0] == 2'b00) + begin + // Don't shift if we just loaded new data, obviously. + if (corr_i_cnt != 6'd0) + begin + corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]}; + corr_q_out[7:1] <= corr_q_out[6:0]; + end + end + +end + + +// ssp clock and frame signal for communication to and from ARM +// _____ _____ _____ _ +// ssp_clk | |_____| |_____| |_____| +// _____ +// ssp_frame ___| |____________________________ +// ___________ ___________ ___________ _ +// ssp_d_in X___________X___________X___________X_ +// +// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... +// + +reg ssp_clk; +reg ssp_frame; + +always @(negedge adc_clk) +begin + if (corr_i_cnt[1:0] == 2'b00) + ssp_clk <= 1'b1; + + if (corr_i_cnt[1:0] == 2'b10) + ssp_clk <= 1'b0; + + // set ssp_frame signal for corr_i_cnt = 1..3 + // (send one frame with 16 Bits) + if (corr_i_cnt == 6'd1) + ssp_frame <= 1'b1; + + if (corr_i_cnt == 6'd3) + ssp_frame <= 1'b0; +end + + +assign ssp_din = corr_i_out[7]; + + +// a jamming signal +reg jam_signal; +reg [3:0] jam_counter; + +always @(negedge adc_clk) +begin + if (corr_i_cnt == 6'd0) + begin + jam_counter <= jam_counter + 1; + jam_signal <= jam_counter[1] ^ jam_counter[3]; + end +end + +// Antenna drivers +reg pwr_hi, pwr_oe4; + +always @(*) +begin + if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) + begin + pwr_hi = ck_1356meg; + pwr_oe4 = ssp_dout; + end + else if (minor_mode == `FPGA_HF_READER_MODE_SEND_FULL_MOD) + begin + pwr_hi = ck_1356meg & ~ssp_dout; + pwr_oe4 = 1'b0; + end + else if (minor_mode == `FPGA_HF_READER_MODE_SEND_JAM) + begin + pwr_hi = ck_1356meg & jam_signal; + pwr_oe4 = 1'b0; + end + else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ + || minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE + || minor_mode == `FPGA_HF_READER_MODE_SNIFF_PHASE) + begin // all off + pwr_hi = 1'b0; + pwr_oe4 = 1'b0; + end + else // receiving from tag + begin + pwr_hi = ck_1356meg; + pwr_oe4 = 1'b0; + end +end + +// always on +assign pwr_oe1 = 1'b0; +assign pwr_oe3 = 1'b0; + +// Unused. +assign pwr_lo = 1'b0; +assign pwr_oe2 = 1'b0; + +// Debug Output +assign dbg = corr_i_cnt[3]; + +endmodule