Added LF frequency adjustments from d18c7db, cleaned up code,

typo fixes in iso14443a code, added the missing "tools" directory,
added initial elements for online/offline detection for commands.
This commit is contained in:
edouard@lafargue.name 2009-04-15 08:09:06 +00:00
parent 974ba9a205
commit 30f2a7d38f
16 changed files with 10914 additions and 161 deletions

View file

@ -87,8 +87,10 @@ void AcquireRawAdcSamples125k(BOOL at134khz)
memset(dest,0,n); memset(dest,0,n);
if(at134khz) { if(at134khz) {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
} else { } else {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
} }
@ -121,7 +123,7 @@ void AcquireRawAdcSamples125k(BOOL at134khz)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Read an ADC channel and block till it completes, then return the result // Read an ADC channel and block till it completes, then return the result
// in ADC units (0 to 1023). Also a routine to average sixteen samples and // in ADC units (0 to 1023). Also a routine to average 32 samples and
// return that. // return that.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static int ReadAdc(int ch) static int ReadAdc(int ch)
@ -152,6 +154,29 @@ static int AvgAdc(int ch)
return (a + 15) >> 5; return (a + 15) >> 5;
} }
/*
* Sweeps the useful LF range of the proxmark from
* 46.8kHz (divisor=255) to 600kHz (divisor=19) and
* reads the voltage in the antenna: the result is a graph
* which should clearly show the resonating frequency of your
* LF antenna ( hopefully around 90 if it is tuned to 125kHz!)
*/
void SweepLFrange()
{
BYTE *dest = (BYTE *)BigBuf;
int i;
// clear buffer
memset(BigBuf,0,sizeof(BigBuf));
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
for (i=255; i>19; i--) {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
SpinDelay(20);
dest[i] = (137500 * AvgAdc(4)) >> 18;
}
}
void MeasureAntennaTuning(void) void MeasureAntennaTuning(void)
{ {
@ -164,6 +189,7 @@ void MeasureAntennaTuning(void)
UsbCommand c; UsbCommand c;
// Let the FPGA drive the low-frequency antenna around 125 kHz. // Let the FPGA drive the low-frequency antenna around 125 kHz.
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
SpinDelay(20); SpinDelay(20);
vLf125 = AvgAdc(4); vLf125 = AvgAdc(4);
@ -172,6 +198,7 @@ void MeasureAntennaTuning(void)
vLf125 = (137500 * vLf125) >> 10; vLf125 = (137500 * vLf125) >> 10;
// Let the FPGA drive the low-frequency antenna around 134 kHz. // Let the FPGA drive the low-frequency antenna around 134 kHz.
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
SpinDelay(20); SpinDelay(20);
vLf134 = AvgAdc(4); vLf134 = AvgAdc(4);
@ -207,7 +234,7 @@ void SimulateTagLowFrequency(int period)
PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK); PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);
#define SHORT_COIL() LOW(GPIO_SSC_DOUT) #define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
i = 0; i = 0;
for(;;) { for(;;) {
@ -345,6 +372,7 @@ static void CmdHIDdemodFSK(void)
int m=0, n=0, i=0, idx=0, found=0, lastval=0; int m=0, n=0, i=0, idx=0, found=0, lastval=0;
DWORD hi=0, lo=0; DWORD hi=0, lo=0;
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
// Connect the A/D to the peak-detected low-frequency path. // Connect the A/D to the peak-detected low-frequency path.
@ -448,7 +476,7 @@ static void CmdHIDdemodFSK(void)
dest[i++]=dest[idx-1]; dest[i++]=dest[idx-1];
dest[i++]=dest[idx-1]; dest[i++]=dest[idx-1];
break; break;
// When a logic 0 is immediately followed by the start of the next transmisson // When a logic 0 is immediately followed by the start of the next transmisson
// (special pattern) a pattern of 4 bit duration lengths is created. // (special pattern) a pattern of 4 bit duration lengths is created.
case 4: case 4:
dest[i++]=dest[idx-1]; dest[i++]=dest[idx-1];
@ -573,20 +601,19 @@ void UsbPacketReceived(BYTE *packet, int len)
break; break;
case CMD_READER_ISO_15693: case CMD_READER_ISO_15693:
ReaderIso15693(c->ext1); ReaderIso15693(c->ext1);
break; break;
case CMD_SIMTAG_ISO_15693: case CMD_SIMTAG_ISO_15693:
SimTagIso15693(c->ext1); SimTagIso15693(c->ext1);
break; break;
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443: case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
AcquireRawAdcSamplesIso14443(c->ext1); AcquireRawAdcSamplesIso14443(c->ext1);
break; break;
case CMD_READER_ISO_14443a: case CMD_READER_ISO_14443a:
ReaderIso14443a(c->ext1); ReaderIso14443a(c->ext1);
break; break;
case CMD_SNOOP_ISO_14443: case CMD_SNOOP_ISO_14443:
@ -656,6 +683,14 @@ void UsbPacketReceived(BYTE *packet, int len)
LCDReset(); LCDReset();
break; break;
case CMD_SWEEP_LF:
SweepLFrange();
break;
case CMD_SET_LF_DIVISOR:
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);
break;
case CMD_LCD: case CMD_LCD:
LCDSend(c->ext1); LCDSend(c->ext1);
break; break;

View file

@ -19,6 +19,7 @@ extern BYTE ToSend[];
extern DWORD BigBuf[]; extern DWORD BigBuf[];
/// fpga.c /// fpga.c
void FpgaSendCommand(WORD cmd, WORD v);
void FpgaWriteConfWord(BYTE v); void FpgaWriteConfWord(BYTE v);
void FpgaDownloadAndGo(void); void FpgaDownloadAndGo(void);
void FpgaSetupSsc(void); void FpgaSetupSsc(void);
@ -26,6 +27,9 @@ void SetupSpi(int mode);
void FpgaSetupSscDma(BYTE *buf, int len); void FpgaSetupSscDma(BYTE *buf, int len);
void SetAdcMuxFor(int whichGpio); void SetAdcMuxFor(int whichGpio);
// Definitions for the FPGA commands.
#define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12)
// Definitions for the FPGA configuration word. // Definitions for the FPGA configuration word.
#define FPGA_MAJOR_MODE_LF_READER (0<<5) #define FPGA_MAJOR_MODE_LF_READER (0<<5)
#define FPGA_MAJOR_MODE_LF_SIMULATOR (1<<5) #define FPGA_MAJOR_MODE_LF_SIMULATOR (1<<5)

View file

@ -53,7 +53,7 @@ void SetupSpi(int mode)
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period) ( 1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
( 0 << 4) | // Bits per Transfer (8 bits) ( 8 << 4) | // Bits per Transfer (16 bits)
( 0 << 3) | // Chip Select inactive after transfer ( 0 << 3) | // Chip Select inactive after transfer
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0 ( 0 << 0); // Clock Polarity inactive state is logic 0
@ -185,15 +185,25 @@ void FpgaDownloadAndGo(void)
LED_D_OFF(); LED_D_OFF();
} }
//-----------------------------------------------------------------------------
// Send a 16 bit command/data pair to the FPGA.
// The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
// where C is the 4 bit command and D is the 12 bit data
//-----------------------------------------------------------------------------
void FpgaSendCommand(WORD cmd, WORD v)
{
SetupSpi(SPI_FPGA_MODE);
while ((SPI_STATUS & SPI_STATUS_TX_EMPTY) == 0); // wait for the transfer to complete
SPI_TX_DATA = SPI_CONTROL_LAST_TRANSFER | cmd | v; // send the data
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Write the FPGA setup word (that determines what mode the logic is in, read // Write the FPGA setup word (that determines what mode the logic is in, read
// vs. clone vs. etc.). // vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
// avoid changing this function's occurence everywhere in the source code.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void FpgaWriteConfWord(BYTE v) void FpgaWriteConfWord(BYTE v)
{ {
SetupSpi(SPI_FPGA_MODE); FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
while ((SPI_STATUS & SPI_STATUS_TX_EMPTY) == 0); // wait for the transfer to complete
SPI_TX_DATA = SPI_CONTROL_LAST_TRANSFER | v; // send the data
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <proxmark3.h> #include <proxmark3.h>
#include "apps.h" #include "apps.h"
#include "..\common\iso14443_crc.c" #include "../common/iso14443_crc.c"
//static void GetSamplesFor14443(BOOL weTx, int n); //static void GetSamplesFor14443(BOOL weTx, int n);

View file

@ -5,7 +5,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include <proxmark3.h> #include <proxmark3.h>
#include "apps.h" #include "apps.h"
#include "..\common\iso14443_crc.c" #include "../common/iso14443_crc.c"
typedef enum { typedef enum {
SEC_D = 1, SEC_D = 1,
@ -1686,7 +1686,7 @@ void ReaderIso14443a(DWORD parameter)
// OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in // OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in
// which case we need to make a cascade 2 request and select - this is a long UID // which case we need to make a cascade 2 request and select - this is a long UID
if (receivedAnswer[0] = 0x88) if (receivedAnswer[0] == 0x88)
{ {
// Do cascade level 2 stuff // Do cascade level 2 stuff
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////

View file

@ -1,3 +1,24 @@
################
## 2009/04/09 ##
################
winsrc/gui.cpp
Changes to PaintGraph to create X axis labels that are snapped to a power of two (useful when analysing low freq tags
with cycle times that are a power of two). Also small changes to keep the X axis labels fixed within the graph window
as the width of the graph window is resized.
armsrc/apps.h
New defines for FPGA commands FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR_REG
armsrc/appmain.c
armsrc/fpga.c
FpgaWriteConfWord(data) is now a special case of FpgaSendCommand(FPGA_CMD_SET_CONFREG, data) to avoid changing every
source file containing FpgaWriteConfWord()
fpga/fpga.v
Changes to the serial conf word, now takes a 4 bit command and 12 bit data code
fpga/lo_read.v
Significant changes to lo_read, it now can be configured with a divisor value to produce a configurable drive clock
for the antenna.
Recompiled FPGA code
################ ################
## 2009/04/09 ## ## 2009/04/09 ##
################ ################

View file

@ -21,7 +21,7 @@
`include "util.v" `include "util.v"
module fpga( module fpga(
spck, miso, mosi, ncs, spcki, miso, mosi, ncs,
pck0i, ck_1356meg, ck_1356megb, pck0i, ck_1356meg, ck_1356megb,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
adc_d, adc_clk, adc_noe, adc_d, adc_clk, adc_noe,
@ -29,7 +29,7 @@ module fpga(
cross_hi, cross_lo, cross_hi, cross_lo,
dbg dbg
); );
input spck, mosi, ncs; input spcki, mosi, ncs;
output miso; output miso;
input pck0i, ck_1356meg, ck_1356megb; input pck0i, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -40,11 +40,16 @@ module fpga(
input cross_hi, cross_lo; input cross_hi, cross_lo;
output dbg; output dbg;
//assign pck0 = pck0i;
IBUFG #(.IOSTANDARD("DEFAULT") ) pck0b( IBUFG #(.IOSTANDARD("DEFAULT") ) pck0b(
.O(pck0), .O(pck0),
.I(pck0i) .I(pck0i)
); );
//assign pck0 = pck0i; //assign spck = spcki;
IBUFG #(.IOSTANDARD("DEFAULT") ) spckb(
.O(spck),
.I(spcki)
);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// The SPI receiver. This sets up the configuration word, which the rest of // The SPI receiver. This sets up the configuration word, which the rest of
// the logic looks at to determine how to connect the A/D and the coil // the logic looks at to determine how to connect the A/D and the coil
@ -52,7 +57,8 @@ module fpga(
// to the configuration bits, for use below. // to the configuration bits, for use below.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
reg [7:0] conf_word_shift; reg [15:0] shift_reg;
reg [7:0] divisor;
reg [7:0] conf_word; reg [7:0] conf_word;
// We switch modes between transmitting to the 13.56 MHz tag and receiving // We switch modes between transmitting to the 13.56 MHz tag and receiving
@ -60,15 +66,18 @@ reg [7:0] conf_word;
// glitching, or else we will glitch the transmitted carrier. // glitching, or else we will glitch the transmitted carrier.
always @(posedge ncs) always @(posedge ncs)
begin begin
conf_word <= conf_word_shift; case(shift_reg[15:12])
4'b0001: conf_word <= shift_reg[7:0];
4'b0010: divisor <= shift_reg[7:0];
endcase
end end
always @(posedge spck) always @(posedge spck)
begin begin
if(~ncs) if(~ncs)
begin begin
conf_word_shift[7:1] <= conf_word_shift[6:0]; shift_reg[15:1] <= shift_reg[14:0];
conf_word_shift[0] <= mosi; shift_reg[0] <= mosi;
end end
end end
@ -110,7 +119,7 @@ lo_read lr(
lr_ssp_frame, lr_ssp_din, ssp_dout, lr_ssp_clk, lr_ssp_frame, lr_ssp_din, ssp_dout, lr_ssp_clk,
cross_hi, cross_lo, cross_hi, cross_lo,
lr_dbg, lr_dbg,
lo_is_125khz lo_is_125khz, divisor
); );
lo_simulate ls( lo_simulate ls(

View file

@ -1,6 +1,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// The way that we connect things in low-frequency read mode. In this case // The way that we connect things in low-frequency read mode. In this case
// we are generating the 134 kHz or 125 kHz carrier, and running the // we are generating the 134 kHz or 125 kHz carrier, and running the
// unmodulated carrier at that frequency. The A/D samples at that same rate, // unmodulated carrier at that frequency. The A/D samples at that same rate,
// and the result is serialized. // and the result is serialized.
// //
@ -14,7 +14,7 @@ module lo_read(
ssp_frame, ssp_din, ssp_dout, ssp_clk, ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo, cross_hi, cross_lo,
dbg, dbg,
lo_is_125khz lo_is_125khz, divisor
); );
input pck0, ck_1356meg, ck_1356megb; input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -25,6 +25,7 @@ module lo_read(
input cross_hi, cross_lo; input cross_hi, cross_lo;
output dbg; output dbg;
input lo_is_125khz; input lo_is_125khz;
input [7:0] divisor;
// The low-frequency RFID stuff. This is relatively simple, because most // The low-frequency RFID stuff. This is relatively simple, because most
// of the work happens on the ARM, and we just pass samples through. The // of the work happens on the ARM, and we just pass samples through. The
@ -38,65 +39,39 @@ module lo_read(
// 125 kHz by dividing by a further factor of (8*12*2), or ~134 kHz by // 125 kHz by dividing by a further factor of (8*12*2), or ~134 kHz by
// dividing by a factor of (8*11*2) (for 136 kHz, ~2% error, tolerable). // dividing by a factor of (8*11*2) (for 136 kHz, ~2% error, tolerable).
reg [3:0] pck_divider; reg [7:0] to_arm_shiftreg;
reg clk_lo; reg [7:0] pck_divider;
reg [6:0] ssp_divider;
reg ant_lo;
always @(posedge pck0) always @(posedge pck0)
begin begin
if(lo_is_125khz) if(pck_divider == 8'd0)
begin begin
if(pck_divider == 4'd11) pck_divider <= divisor[7:0];
begin ant_lo = !ant_lo;
pck_divider <= 4'd0; if(ant_lo == 1'b0)
clk_lo = !clk_lo; begin
end ssp_divider <= 7'b0011111;
else to_arm_shiftreg <= adc_d;
pck_divider <= pck_divider + 1; end
end end
else else
begin begin
if(pck_divider == 4'd10) pck_divider <= pck_divider - 1;
begin if(ssp_divider[6] == 1'b0)
pck_divider <= 4'd0; begin
clk_lo = !clk_lo; if (ssp_divider[1:0] == 1'b11) to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
end ssp_divider <= ssp_divider - 1;
else end
pck_divider <= pck_divider + 1; end
end
end end
reg [2:0] carrier_divider_lo;
always @(posedge clk_lo)
begin
carrier_divider_lo <= carrier_divider_lo + 1;
end
assign pwr_lo = carrier_divider_lo[2];
// This serializes the values returned from the A/D, and sends them out
// over the SSP.
reg [7:0] to_arm_shiftreg;
always @(posedge clk_lo)
begin
if(carrier_divider_lo == 3'b000)
to_arm_shiftreg <= adc_d;
else
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
end
assign ssp_clk = clk_lo;
assign ssp_frame = (carrier_divider_lo == 3'b001);
assign ssp_din = to_arm_shiftreg[7]; assign ssp_din = to_arm_shiftreg[7];
assign ssp_clk = pck_divider[1];
// The ADC converts on the falling edge, and our serializer loads when assign ssp_frame = ~ssp_divider[5];
// carrier_divider_lo == 3'b000.
assign adc_clk = ~carrier_divider_lo[2];
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
assign pwr_lo = ant_lo;
assign adc_clk = ~ant_lo;
assign dbg = adc_clk; assign dbg = adc_clk;
endmodule endmodule

View file

@ -1,5 +1,5 @@
`include "lo_read_org.v"
`include "lo_read.v" `include "lo_read.v"
/* /*
pck0 - input main 24Mhz clock (PLL / 4) pck0 - input main 24Mhz clock (PLL / 4)
[7:0] adc_d - input data from A/D converter [7:0] adc_d - input data from A/D converter
@ -29,6 +29,7 @@ module testbed_lo_read;
reg pck0; reg pck0;
reg [7:0] adc_d; reg [7:0] adc_d;
reg lo_is_125khz; reg lo_is_125khz;
reg [15:0] divisor;
wire pwr_lo; wire pwr_lo;
wire adc_clk; wire adc_clk;
@ -47,38 +48,61 @@ module testbed_lo_read;
wire cross_hi; wire cross_hi;
wire dbg; wire dbg;
lo_read #(5,200) dut( lo_read_org #(5,10) dut1(
.pck0(pck0), .pck0(pck0),
.ck_1356meg(ck_1356meg), .ck_1356meg(ack_1356meg),
.ck_1356megb(ck_1356megb), .ck_1356megb(ack_1356megb),
.pwr_lo(pwr_lo), .pwr_lo(apwr_lo),
.pwr_hi(pwr_hi), .pwr_hi(apwr_hi),
.pwr_oe1(pwr_oe1), .pwr_oe1(apwr_oe1),
.pwr_oe2(pwr_oe2), .pwr_oe2(apwr_oe2),
.pwr_oe3(pwr_oe3), .pwr_oe3(apwr_oe3),
.pwr_oe4(pwr_oe4), .pwr_oe4(apwr_oe4),
.adc_d(adc_d), .adc_d(adc_d),
.adc_clk(adc_clk), .adc_clk(adc_clk),
.ssp_frame(ssp_frame), .ssp_frame(assp_frame),
.ssp_din(ssp_din), .ssp_din(assp_din),
.ssp_dout(ssp_dout), .ssp_dout(assp_dout),
.ssp_clk(ssp_clk), .ssp_clk(assp_clk),
.cross_hi(cross_hi), .cross_hi(across_hi),
.cross_lo(cross_lo), .cross_lo(across_lo),
.dbg(dbg), .dbg(adbg),
.lo_is_125khz(lo_is_125khz) .lo_is_125khz(lo_is_125khz)
); );
integer idx, i; lo_read #(5,10) dut2(
.pck0(pck0),
.ck_1356meg(bck_1356meg),
.ck_1356megb(bck_1356megb),
.pwr_lo(bpwr_lo),
.pwr_hi(bpwr_hi),
.pwr_oe1(bpwr_oe1),
.pwr_oe2(bpwr_oe2),
.pwr_oe3(bpwr_oe3),
.pwr_oe4(bpwr_oe4),
.adc_d(adc_d),
.adc_clk(badc_clk),
.ssp_frame(bssp_frame),
.ssp_din(bssp_din),
.ssp_dout(bssp_dout),
.ssp_clk(bssp_clk),
.cross_hi(bcross_hi),
.cross_lo(bcross_lo),
.dbg(bdbg),
.lo_is_125khz(lo_is_125khz),
.divisor(divisor)
);
integer idx, i, adc_val=8;
// main clock // main clock
always #5 pck0 = !pck0; always #5 pck0 = !pck0;
//new A/D value available from ADC on positive edge
task crank_dut; task crank_dut;
begin begin
@(posedge adc_clk) ; @(posedge adc_clk) ;
adc_d = $random; adc_d = adc_val;
adc_val = (adc_val *2) + 53;
end end
endtask endtask
@ -87,19 +111,13 @@ module testbed_lo_read;
// init inputs // init inputs
pck0 = 0; pck0 = 0;
adc_d = 0; adc_d = 0;
lo_is_125khz = 1;
// simulate 4 A/D cycles at 134Khz divisor=255; //min 19, 95=125Khz, max 255
lo_is_125khz=0;
for (i = 0 ; i < 4 ; i = i + 1) begin
crank_dut;
end
// simulate 4 A/D cycles at 125Khz // simulate 4 A/D cycles at 125Khz
lo_is_125khz=1; for (i = 0 ; i < 8 ; i = i + 1) begin
for (i = 0 ; i < 4 ; i = i + 1) begin
crank_dut; crank_dut;
end end
$finish; $finish;
end end
endmodule // main endmodule // main

View file

@ -44,6 +44,8 @@ typedef struct {
#define CMD_SIMULATE_TAG_125K 0x0207 #define CMD_SIMULATE_TAG_125K 0x0207
#define CMD_HID_DEMOD_FSK 0x0208 // ## New command: demodulate HID tag ID #define CMD_HID_DEMOD_FSK 0x0208 // ## New command: demodulate HID tag ID
#define CMD_HID_SIM_TAG 0x0209 // ## New command: simulate HID tag by ID #define CMD_HID_SIM_TAG 0x0209 // ## New command: simulate HID tag by ID
#define CMD_SET_LF_DIVISOR 0x020A
#define CMD_SWEEP_LF 0x020B
// For the 13.56 MHz tags // For the 13.56 MHz tags
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
@ -58,7 +60,6 @@ typedef struct {
#define CMD_SNOOP_ISO_14443a 0x0383 // ## New snoop command #define CMD_SNOOP_ISO_14443a 0x0383 // ## New snoop command
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 // ## New command: Simulate tag 14443a #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 // ## New command: Simulate tag 14443a
#define CMD_READER_ISO_14443a 0x0385 // ## New command to act like a 14443a reader #define CMD_READER_ISO_14443a 0x0385 // ## New command to act like a 14443a reader
#define CMD_SIMULATE_MIFARE_CARD 0x0386 #define CMD_SIMULATE_MIFARE_CARD 0x0386
// For measurements of the antenna tuning // For measurements of the antenna tuning
@ -67,5 +68,6 @@ typedef struct {
// For direct FPGA control // For direct FPGA control
#define CMD_FPGA_MAJOR_MODE_OFF 0x0500 // ## FPGA Control #define CMD_FPGA_MAJOR_MODE_OFF 0x0500 // ## FPGA Control
#define CMD_TEST 0x0501
#endif #endif

18
tools/merge-srec.pl Normal file
View file

@ -0,0 +1,18 @@
# merge the code that initially executes out of flash with the RAM image
($flashFile, $ramFile) = @ARGV;
open(FLASH, $flashFile) or die "$flashFile: $!\n";
while(<FLASH>) {
print if /^S3/;
}
open(RAM, $ramFile) or die "$ramFile: $!\n";
while(<RAM>) {
if(/^S3(..)(........)(.*)/) {
$addr = sprintf('%08X', hex($2) - 0x00200000 + 0x200);
print "S3$1$addr$3\n";
}
}

39
tools/rbt2c.pl Normal file
View file

@ -0,0 +1,39 @@
#!/usr/bin/perl
# This tool converts a Xilinx xxx.rbt FPGA bitstream to a table that will
# compile as C source code. The output format is DWORDs, MSB first.
print "// Generated by rbt2c.pl, do not edit!\n\n";
for(1..7) {
chomp($_ = <>);
print "//// $_\n";
}
print <<EOT;
#include <proxmark3.h>
const DWORD FpgaImage[] = {
EOT
while(<>) {
chomp;
$v = 0;
for $b (split(//, $_)) {
$v <<= 1;
if($b eq '1') {
$v |= 1;
} elsif($b ne '0') {
die;
}
}
printf("\t0x%08x,\n", $v);
}
print <<EOT;
};
const DWORD FpgaImageLen = sizeof(FpgaImage) / sizeof(FpgaImage[0]);
EOT

35
tools/srecswap.pl Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/perl
# endian-swap S records; we need this because the JTAG tools we're using
# expect the memory image in byte-swapped format
#
# Jonathan Westhues, April 2004
if(@ARGV == 0) {
die "usage: $0 file-to-endian-swap.s19 > out.s19\n";
}
while(<>) {
chomp;
if(/^S0/) {
next;
}
if(/^S7/) {
print "$_\n";
next;
}
if(not /^S3(..)(........)(.*)(..)$/) {
die "bad S record at line $.\n";
}
$data = $3;
$checksum = $4;
print "S3$1$2";
while($data =~ m#(..)(..)(..)(..)#g) {
print "$4$3$2$1";
}
print "$checksum\n";
}

View file

@ -1598,6 +1598,7 @@ static void Cmdaskdemod(char *str) {
* routine, feel free to improve... * routine, feel free to improve...
* *
* 1st argument: clock rate (as number of samples per clock rate) * 1st argument: clock rate (as number of samples per clock rate)
* Typical values can be 64, 32, 128...
*/ */
static void Cmdmanchesterdemod(char *str) { static void Cmdmanchesterdemod(char *str) {
int i; int i;
@ -1605,18 +1606,23 @@ static void Cmdmanchesterdemod(char *str) {
int lastval; int lastval;
int lc = 0; int lc = 0;
int bitidx = 0; int bitidx = 0;
int bitidx2; int bit2idx = 0;
sscanf(str, "%i", &clock); sscanf(str, "%i", &clock);
int tolerance = clock/4; int tolerance = clock/4;
/* Holds the decoded bitstream. */ /* Holds the decoded bitstream: each clock period contains 2 bits */
int BitStream[MAX_GRAPH_TRACE_LEN*2]; /* later simplified to 1 bit after manchester decoding. */
int BitStream2[MAX_GRAPH_TRACE_LEN]; /* Add 10 bits to allow for noisy / uncertain traces without aborting */
/* int BitStream[GraphTraceLen*2/clock+10]; */
/* But it does not work if compiling on WIndows: therefore we just allocate a */
/* large array */
int BitStream[MAX_GRAPH_TRACE_LEN];
/* Detect first transition */ /* Detect first transition */
/* Lo-Hi (arbitrary) */ /* Lo-Hi (arbitrary) */
for(i=1;i<GraphTraceLen;i++) { for(i=1;i<GraphTraceLen;i++) {
if (GraphBuffer[i-1]<GraphBuffer[i]) { if (GraphBuffer[i-1]<GraphBuffer[i]) {
lastval = i; lastval = i;
@ -1626,18 +1632,24 @@ static void Cmdmanchesterdemod(char *str) {
} }
/* Then detect duration between 2 successive transitions */ /* Then detect duration between 2 successive transitions */
/* At this stage, GraphTrace is either 0 or 1 */
for(bitidx = 1 ;i<GraphTraceLen;i++) { for(bitidx = 1 ;i<GraphTraceLen;i++) {
if (GraphBuffer[i-1] != GraphBuffer[i]) { if (GraphBuffer[i-1] != GraphBuffer[i]) {
lc = i-lastval; lc = i-lastval;
lastval = i; lastval = i;
// Error check: if bitidx becomes too large, we do not
// have a Manchester encoded bitstream or the clock is really
// wrong!
if (bitidx > (GraphTraceLen*2/clock+8) ) {
PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
return;
}
// Then switch depending on lc length: // Then switch depending on lc length:
// Tolerance is 1/4 of clock rate (arbitrary) // Tolerance is 1/4 of clock rate (arbitrary)
if ((lc-clock/2) < tolerance) { if (abs(lc-clock/2) < tolerance) {
// Short pulse // Short pulse : either "1" or "0"
BitStream[bitidx++]=GraphBuffer[i-1]; BitStream[bitidx++]=GraphBuffer[i-1];
} else if ((lc-clock) < tolerance) { } else if (abs(lc-clock) < tolerance) {
// Long pulse // Long pulse: either "11" or "00"
BitStream[bitidx++]=GraphBuffer[i-1]; BitStream[bitidx++]=GraphBuffer[i-1];
BitStream[bitidx++]=GraphBuffer[i-1]; BitStream[bitidx++]=GraphBuffer[i-1];
} else { } else {
@ -1649,39 +1661,41 @@ static void Cmdmanchesterdemod(char *str) {
} }
// At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
for (bitidx2 = 0; bitidx2<bitidx; bitidx2 += 2) { // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
if ((BitStream[bitidx2] == 0) && (BitStream[bitidx2+1] == 1)) { // to stop output at the final bitidx2 value, not bitidx
BitStream2[bitidx2/2] = 1; for (i = 0; i < bitidx; i += 2) {
} else if ((BitStream[bitidx2] == 1) && (BitStream[bitidx2+1] == 0)) { if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
BitStream2[bitidx2/2] = 0; BitStream[bit2idx++] = 1;
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
BitStream[bit2idx++] = 0;
} else { } else {
// We cannot end up in this state, this means we are unsynchronized, // We cannot end up in this state, this means we are unsynchronized,
// move up 1 bit: // move up 1 bit:
bitidx2++; i++;
PrintToScrollback("Unsynchronized, resync..."); PrintToScrollback("Unsynchronized, resync...");
PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)"); PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
} }
} }
PrintToScrollback("Manchester decoded bitstream \n---------"); PrintToScrollback("Manchester decoded bitstream \n---------");
// Now output the bitstream to the scrollback by line of 16 bits // Now output the bitstream to the scrollback by line of 16 bits
for (i = 0; i<bitidx/2; i+=16) { for (i = 0; i < (bit2idx-16); i+=16) {
PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i", PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
BitStream2[i], BitStream[i],
BitStream2[i+1], BitStream[i+1],
BitStream2[i+2], BitStream[i+2],
BitStream2[i+3], BitStream[i+3],
BitStream2[i+4], BitStream[i+4],
BitStream2[i+5], BitStream[i+5],
BitStream2[i+6], BitStream[i+6],
BitStream2[i+7], BitStream[i+7],
BitStream2[i+8], BitStream[i+8],
BitStream2[i+9], BitStream[i+9],
BitStream2[i+10], BitStream[i+10],
BitStream2[i+11], BitStream[i+11],
BitStream2[i+12], BitStream[i+12],
BitStream2[i+13], BitStream[i+13],
BitStream2[i+14], BitStream[i+14],
BitStream2[i+15]); BitStream[i+15]);
} }
} }
@ -1805,6 +1819,32 @@ static void CmdLcd(char *str)
static void CmdTest(char *str) static void CmdTest(char *str)
{ {
} }
/*
* Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
* 600kHz.
*/
static void CmdSetDivisor(char *str)
{
UsbCommand c;
c.cmd = CMD_SET_LF_DIVISOR;
c.ext1 = atoi(str);
if (( c.ext1<0) || (c.ext1>255)) {
PrintToScrollback("divisor must be between 19 and 255");
} else {
SendCommand(&c, FALSE);
PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));
}
}
static void CmdSweepLF(char *str)
{
UsbCommand c;
c.cmd = CMD_SWEEP_LF;
SendCommand(&c, FALSE);
}
typedef void HandlerFunction(char *cmdline); typedef void HandlerFunction(char *cmdline);
@ -1863,6 +1903,8 @@ static struct {
"lcdreset", CmdLcdReset, "Hardware reset LCD", "lcdreset", CmdLcdReset, "Hardware reset LCD",
"lcd", CmdLcd, "Send command/data to LCD", "lcd", CmdLcd, "Send command/data to LCD",
"test", CmdTest, "Placeholder command for testing new code", "test", CmdTest, "Placeholder command for testing new code",
"setlfdivisor", CmdSetDivisor, "Drive LF antenna at 12Mhz/(divisor+1)",
"sweeplf", CmdSweepLF, "Sweep through LF freq range and store results in buffer",
"quit", CmdQuit, "quit program" "quit", CmdQuit, "quit program"
}; };

View file

@ -64,6 +64,7 @@ void ExecCmd(char *cmd)
} }
int CommandFinished; int CommandFinished;
int offset = 64;
static void ResizeCommandWindow(void) static void ResizeCommandWindow(void)
{ {
@ -122,8 +123,8 @@ static void PaintGraph(HDC hdc)
SelectObject(hdc, WhitePen); SelectObject(hdc, WhitePen);
MoveToEx(hdc, r.left + 40, r.top, NULL); MoveToEx(hdc, r.left + offset, r.top, NULL);
LineTo(hdc, r.left + 40, r.bottom); LineTo(hdc, r.left + offset, r.bottom);
int zeroHeight = r.top + (r.bottom - r.top) / 2; int zeroHeight = r.top + (r.bottom - r.top) / 2;
SelectObject(hdc, GreyPen); SelectObject(hdc, GreyPen);
@ -131,7 +132,7 @@ static void PaintGraph(HDC hdc)
LineTo(hdc, r.right, zeroHeight); LineTo(hdc, r.right, zeroHeight);
int startMax = int startMax =
(GraphTraceLen - (int)((r.right - r.left - 40) / GraphPixelsPerPoint)); (GraphTraceLen - (int)((r.right - r.left - offset) / GraphPixelsPerPoint));
if(startMax < 0) { if(startMax < 0) {
startMax = 0; startMax = 0;
} }
@ -151,7 +152,7 @@ static void PaintGraph(HDC hdc)
if(fabs((double)GraphBuffer[i]) > absYMax) { if(fabs((double)GraphBuffer[i]) > absYMax) {
absYMax = (int)fabs((double)GraphBuffer[i]); absYMax = (int)fabs((double)GraphBuffer[i]);
} }
int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint); int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint);
if(x > r.right) { if(x > r.right) {
break; break;
} }
@ -163,12 +164,15 @@ static void PaintGraph(HDC hdc)
SetBkColor(hdc, RGB(0, 0, 0)); SetBkColor(hdc, RGB(0, 0, 0));
// number of points that will be plotted // number of points that will be plotted
int span = (int)((r.right - r.left) / GraphPixelsPerPoint); double span = (int)((r.right - r.left) / GraphPixelsPerPoint);
// one label every 100 pixels, let us say
int labels = (r.right - r.left - 40) / 100; // one label every offset pixels, let us say
int labels = (r.right - r.left - offset) / offset;
if(labels <= 0) labels = 1; if(labels <= 0) labels = 1;
int pointsPerLabel = span / labels; // round to nearest power of 2
int pointsPerLabel = (int)(log(span / labels)/log(2.0));
if(pointsPerLabel <= 0) pointsPerLabel = 1; if(pointsPerLabel <= 0) pointsPerLabel = 1;
pointsPerLabel = (int)pow(2.0,pointsPerLabel);
int yMin = INT_MAX; int yMin = INT_MAX;
int yMax = INT_MIN; int yMax = INT_MIN;
@ -179,7 +183,7 @@ static void PaintGraph(HDC hdc)
if(i >= GraphTraceLen) { if(i >= GraphTraceLen) {
break; break;
} }
int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint); int x = offset + (int)((i - GraphStart)*GraphPixelsPerPoint);
if(x > r.right + GraphPixelsPerPoint) { if(x > r.right + GraphPixelsPerPoint) {
break; break;
} }
@ -212,8 +216,8 @@ static void PaintGraph(HDC hdc)
if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) { if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {
SelectObject(hdc, WhitePen); SelectObject(hdc, WhitePen);
MoveToEx(hdc, x, zeroHeight - 3, NULL); MoveToEx(hdc, x, zeroHeight - 8, NULL);
LineTo(hdc, x, zeroHeight + 3); LineTo(hdc, x, zeroHeight + 8);
char str[100]; char str[100];
sprintf(str, "+%d", (i - GraphStart)); sprintf(str, "+%d", (i - GraphStart));
@ -244,9 +248,9 @@ static void PaintGraph(HDC hdc)
} }
char str[100]; char str[100];
sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f]", sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f] zoom=%.3f",
GraphStart, yMax, yMin, yMean, n, GraphTraceLen, GraphStart, yMax, yMin, yMean, n, GraphTraceLen,
CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor); CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor, GraphPixelsPerPoint);
TextOut(hdc, 50, r.bottom - 20, str, strlen(str)); TextOut(hdc, 50, r.bottom - 20, str, strlen(str));
} }
@ -277,28 +281,28 @@ static LRESULT CALLBACK
case WM_KEYDOWN: case WM_KEYDOWN:
switch(wParam) { switch(wParam) {
case VK_DOWN: case VK_DOWN:
if(GraphPixelsPerPoint <= 50) { if(GraphPixelsPerPoint <= 8) {
GraphPixelsPerPoint *= 2; GraphPixelsPerPoint *= 2;
} }
break; break;
case VK_UP: case VK_UP:
if(GraphPixelsPerPoint >= 0.02) { if(GraphPixelsPerPoint >= 0.01) {
GraphPixelsPerPoint /= 2; GraphPixelsPerPoint /= 2;
} }
break; break;
case VK_RIGHT: case VK_RIGHT:
if(GraphPixelsPerPoint < 20) { if(GraphPixelsPerPoint < 16) {
GraphStart += (int)(20 / GraphPixelsPerPoint); GraphStart += (int)(16 / GraphPixelsPerPoint);
} else { } else {
GraphStart++; GraphStart++;
} }
break; break;
case VK_LEFT: case VK_LEFT:
if(GraphPixelsPerPoint < 20) { if(GraphPixelsPerPoint < 16) {
GraphStart -= (int)(20 / GraphPixelsPerPoint); GraphStart -= (int)(16 / GraphPixelsPerPoint);
} else { } else {
GraphStart--; GraphStart--;
} }
@ -314,7 +318,7 @@ nopaint:
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN: { case WM_RBUTTONDOWN: {
int x = LOWORD(lParam); int x = LOWORD(lParam);
x -= 40; x -= offset;
x = (int)(x / GraphPixelsPerPoint); x = (int)(x / GraphPixelsPerPoint);
x += GraphStart; x += GraphStart;
if(msg == WM_LBUTTONDOWN) { if(msg == WM_LBUTTONDOWN) {