From 621eb129764b90ac464d91b134f06291b01b082f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 12 Jan 2020 00:30:23 +0100 Subject: [PATCH] fix: lf simulation, wrong offsets in majormode --- armsrc/felica.c | 8 ++-- armsrc/fpgaloader.h | 80 ++++++++++++++++++++++------------ fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes fpga/fpga_lf.v | 104 ++++++++++++++++++++++++++++++++++++-------- 5 files changed, 144 insertions(+), 48 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index 91b58d97f..d42640532 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -337,7 +337,7 @@ static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) { } static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) { - uint8_t flags = FPGA_MAJOR_MODE_ISO18092; + uint8_t flags = FPGA_MAJOR_MODE_HF_ISO18092; if (power) flags |= FPGA_HF_ISO18092_FLAG_READER; if (highspeed) @@ -404,7 +404,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { Dbprintf("WaitForFelicaReply Start"); uint32_t c = 0; // power, no modulation - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); // clear RXRDY: @@ -471,7 +471,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) { AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | fpga_minor_mode); //20.4 ms generate field, start sending polling command afterwars. SpinDelay(100); @@ -720,7 +720,7 @@ void felica_sim_lite(uint64_t uid) { TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0); //switch back - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); FelicaFrameReset(); listenmode = true; diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index c91fb3315..90d020333 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -21,10 +21,35 @@ #define FPGA_BITSTREAM_LF 1 #define FPGA_BITSTREAM_HF 2 +/* + Communication between ARM / FPGA is done inside armsrc/fpgaloader.c (function FpgaSendCommand) + Send 16 bit command / data pair to FPGA + The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 + where + C is 4bit command + D is 12bit data + +-----+--------- frame layout -------------------- +bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +-----+------------------------------------------- +cmd | x x x x +major| x x x +opt | x x +divi | x x x x x x x x +thres| x x x x x x x x +-----+------------------------------------------- +*/ + // Definitions for the FPGA commands. -#define FPGA_CMD_SET_CONFREG (1<<12) -#define FPGA_CMD_SET_DIVISOR (2<<12) -#define FPGA_CMD_SET_USER_BYTE1 (3<<12) +// HF / LF +#define FPGA_CMD_SET_CONFREG (1<<12) // C + +// LF +#define FPGA_CMD_SET_DIVISOR (2<<12) // C +#define FPGA_CMD_SET_USER_BYTE1 (3<<12) // C + +// HF +#define FPGA_CMD_TRACE_ENABLE (2<<12) // C // Definitions for the FPGA configuration word. // LF @@ -32,32 +57,34 @@ #define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) #define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) #define FPGA_MAJOR_MODE_LF_ADC (3<<5) + // HF -#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) -#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) -#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) -#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) -#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) -#define FPGA_MAJOR_MODE_HF_FELICA (5<<5) +#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) // D +#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) // D +#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) // D +#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) // D +#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) // D +#define FPGA_MAJOR_MODE_HF_ISO18092 (5<<5) // D +#define FPGA_MAJOR_MODE_HF_GET_TRACE (6<<5) // D + // BOTH -#define FPGA_MAJOR_MODE_OFF_LF (6<<5) -#define FPGA_MAJOR_MODE_OFF (7<<5) +#define FPGA_MAJOR_MODE_OFF (7<<5) // D // Options for LF_READER -#define FPGA_LF_ADC_READER_FIELD (1<<0) +#define FPGA_LF_ADC_READER_FIELD 0x1 // Options for LF_EDGE_DETECT #define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 -#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) -#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) +#define FPGA_LF_EDGE_DETECT_READER_FIELD 0x1 +#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 0x2 // Options for the HF reader, tx to tag -#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) +#define FPGA_HF_READER_TX_SHALLOW_MOD 0x1 // Options for the HF reader, correlating against rx from tag -#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) -#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) -#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) +#define FPGA_HF_READER_RX_XCORR_848_KHZ 0x1 +#define FPGA_HF_READER_RX_XCORR_SNOOP 0x2 +#define FPGA_HF_READER_RX_XCORR_QUARTER 0x4 // Options for the HF simulated tag, how to modulate #define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 @@ -68,17 +95,16 @@ // no 848K // Options for ISO14443A -#define FPGA_HF_ISO14443A_SNIFFER (0<<0) -#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) -#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) -#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) -#define FPGA_HF_ISO14443A_READER_MOD (4<<0) +#define FPGA_HF_ISO14443A_SNIFFER 0x0 +#define FPGA_HF_ISO14443A_TAGSIM_LISTEN 0x1 +#define FPGA_HF_ISO14443A_TAGSIM_MOD 0x2 +#define FPGA_HF_ISO14443A_READER_LISTEN 0x3 +#define FPGA_HF_ISO14443A_READER_MOD 0x4 //options for Felica. -#define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000 -#define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module -#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect -#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag +#define FPGA_HF_ISO18092_FLAG_NOMOD 0x1 // 0001 disable modulation module +#define FPGA_HF_ISO18092_FLAG_424K 0x2 // 0010 should enable 414k mode (untested). No autodetect +#define FPGA_HF_ISO18092_FLAG_READER 0x4 // 0100 enables antenna power, to act as a reader instead of tag void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaWriteConfWord(uint8_t v); diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 7e3fc14e2223e60a37b3427515e38c4d3dd62f4b..ae66d510fa02ca3e7181036f0f8e2bf134ebf884 100644 GIT binary patch delta 33 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 diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 1df5394b6..da681321c 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -18,7 +18,7 @@ `define FPGA_MAJOR_MODE_LF_PASSTHRU 2 `define FPGA_MAJOR_MODE_LF_ADC 3 -// Options for LF_ADC +// Options for LF_READER `define FPGA_LF_ADC_READER_FIELD 1 // Options for LF_EDGE_DETECT @@ -50,32 +50,106 @@ module fpga_lf( // to the configuration bits, for use below. //----------------------------------------------------------------------------- +/* + Attempt to write up how its hooked up. Iceman 2020. + + Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() + Send 16 bit command / data pair to FPGA + The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 + where + C is 4bit command + D is 12bit data + + shift_reg receive this 16bit frame + + LF command + ---------- + shift_reg[15:12] == 4bit command + LF has three commands (FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR, FPGA_CMD_SET_EDGE_DETECT_THRESHOLD) + Current commands uses only 2bits. We have room for up to 4bits of commands total (7). + + LF data + ------- + shift_reg[11:0] == 12bit data + lf data is divided into MAJOR MODES and configuration values. + + The major modes uses 3bits (0,1,2,3,7 | 000, 001, 010, 011, 111) + 000 FPGA_MAJOR_MODE_LF_READER = Act as LF reader (modulate) + 001 FPGA_MAJOR_MODE_LF_EDGE_DETECT = Simulate LF + 010 FPGA_MAJOR_MODE_LF_PASSTHRU = Passthrough mode, CROSS_LO line connected to SSP_DIN. SSP_DOUT logic level controls if we modulate / listening + 011 FPGA_MAJOR_MODE_LF_ADC = refactor hitag2, clear ADC sampling + 111 FPGA_MAJOR_MODE_OFF = turn off sampling. + + Each one of this major modes can have options. Currently these two major modes uses options. + - FPGA_MAJOR_MODE_LF_READER + - FPGA_MAJOR_MODE_LF_EDGE_DETECT + + FPGA_MAJOR_MODE_LF_READER + ------------------------------------- + lf_field = 1bit (FPGA_LF_ADC_READER_FIELD) + + You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at + divisor = 8bits shift_reg[7:0] + + FPGA_MAJOR_MODE_LF_EDGE_DETECT + ------------------------------------------ + lf_ed_toggle_mode = 1bits + lf_ed_threshold = 8bits threshold defaults to 127 + + You can send FPGA_CMD_SET_EDGE_DETECT_THRESHOLD to set a custom threshold + lf_ed_threshold = 8bits threshold value. + + conf_word 12bits + conf_word[7:5] = 3bit major mode. + conf_word[0] = 1bit lf_field + conf_word[1] = 1bit lf_ed_toggle_mode + conf_word[7:0] = 8bit divisor + conf_word[7:0] = 8bit threshold + +-----+--------- frame layout -------------------- +bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +-----+------------------------------------------- +cmd | x x x x +major| x x x +opt | x x +divi | x x x x x x x x +thres| x x x x x x x x +-----+------------------------------------------- +*/ + reg [15:0] shift_reg; reg [7:0] divisor; -reg [8:0] conf_word; - -// threshold edge detect reg [7:0] lf_ed_threshold; +reg [11:0] conf_word; +wire [2:0] major_mode = conf_word[7:5]; +wire lf_field = conf_word[0]; +wire lf_ed_toggle_mode = conf_word[1]; + +// Handles cmd / data frame from ARM always @(posedge ncs) begin + // 4 bit command case (shift_reg[15:12]) `FPGA_CMD_SET_CONFREG: begin - conf_word <= shift_reg[8:0]; - if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) + // 12 bit data + conf_word <= shift_reg[11:0]; + if (shift_reg[7:5] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) begin - lf_ed_threshold <= 127; // default threshold + lf_ed_threshold <= 127; // default threshold end end + `FPGA_CMD_SET_DIVISOR: - divisor <= shift_reg[7:0]; + divisor <= shift_reg[7:0]; // 8bits + `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: - lf_ed_threshold <= shift_reg[7:0]; + lf_ed_threshold <= shift_reg[7:0]; // 8 bits endcase end -// +// Receive 16bits of data from ARM here. always @(posedge spck) begin if (~ncs) @@ -85,12 +159,6 @@ begin end end -wire [2:0] major_mode = conf_word[8:6]; - -// For the low-frequency configuration: -wire lf_field = conf_word[0]; -wire lf_ed_toggle_mode = conf_word[1]; // for lo_edge_detect - //----------------------------------------------------------------------------- // And then we instantiate the modules corresponding to each of the FPGA's // major modes, and use muxes to connect the outputs of the active mode to @@ -142,7 +210,9 @@ lo_adc la( // 001 -- LF edge detect (generic) // 010 -- LF passthrough // 011 -- LF ADC (read/write) -// 110 -- FPGA_MAJOR_MODE_OFF_LF (rdv40 specific) +// 100 -- unused +// 101 -- unused +// 110 -- unused // 111 -- FPGA_MAJOR_MODE_OFF // 000 001 010 011 100 101 110 111 mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0);