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);
if(at134khz) {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
} else {
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
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
// 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.
//-----------------------------------------------------------------------------
static int ReadAdc(int ch)
@ -152,6 +154,29 @@ static int AvgAdc(int ch)
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)
{
@ -164,6 +189,7 @@ void MeasureAntennaTuning(void)
UsbCommand c;
// 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);
SpinDelay(20);
vLf125 = AvgAdc(4);
@ -172,6 +198,7 @@ void MeasureAntennaTuning(void)
vLf125 = (137500 * vLf125) >> 10;
// 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);
SpinDelay(20);
vLf134 = AvgAdc(4);
@ -207,7 +234,7 @@ void SimulateTagLowFrequency(int period)
PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
i = 0;
for(;;) {
@ -345,6 +372,7 @@ static void CmdHIDdemodFSK(void)
int m=0, n=0, i=0, idx=0, found=0, lastval=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);
// 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];
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.
case 4:
dest[i++]=dest[idx-1];
@ -573,20 +601,19 @@ void UsbPacketReceived(BYTE *packet, int len)
break;
case CMD_READER_ISO_15693:
ReaderIso15693(c->ext1);
ReaderIso15693(c->ext1);
break;
case CMD_SIMTAG_ISO_15693:
SimTagIso15693(c->ext1);
SimTagIso15693(c->ext1);
break;
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
AcquireRawAdcSamplesIso14443(c->ext1);
break;
case CMD_READER_ISO_14443a:
ReaderIso14443a(c->ext1);
ReaderIso14443a(c->ext1);
break;
case CMD_SNOOP_ISO_14443:
@ -656,6 +683,14 @@ void UsbPacketReceived(BYTE *packet, int len)
LCDReset();
break;
case CMD_SWEEP_LF:
SweepLFrange();
break;
case CMD_SET_LF_DIVISOR:
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->ext1);
break;
case CMD_LCD:
LCDSend(c->ext1);
break;

View file

@ -19,6 +19,7 @@ extern BYTE ToSend[];
extern DWORD BigBuf[];
/// fpga.c
void FpgaSendCommand(WORD cmd, WORD v);
void FpgaWriteConfWord(BYTE v);
void FpgaDownloadAndGo(void);
void FpgaSetupSsc(void);
@ -26,6 +27,9 @@ void SetupSpi(int mode);
void FpgaSetupSscDma(BYTE *buf, int len);
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.
#define FPGA_MAJOR_MODE_LF_READER (0<<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 << 16) | // Delay Before SPCK (1 MCK period)
( 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
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0
@ -185,15 +185,25 @@ void FpgaDownloadAndGo(void)
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
// 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)
{
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 | v; // send the data
FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
}
//-----------------------------------------------------------------------------

File diff suppressed because it is too large Load diff

View file

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

View file

@ -5,7 +5,7 @@
//-----------------------------------------------------------------------------
#include <proxmark3.h>
#include "apps.h"
#include "..\common\iso14443_crc.c"
#include "../common/iso14443_crc.c"
typedef enum {
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
// 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
///////////////////////////////////////////////////////////////////

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 ##
################

View file

@ -21,7 +21,7 @@
`include "util.v"
module fpga(
spck, miso, mosi, ncs,
spcki, miso, mosi, ncs,
pck0i, ck_1356meg, ck_1356megb,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
adc_d, adc_clk, adc_noe,
@ -29,7 +29,7 @@ module fpga(
cross_hi, cross_lo,
dbg
);
input spck, mosi, ncs;
input spcki, mosi, ncs;
output miso;
input pck0i, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -40,11 +40,16 @@ module fpga(
input cross_hi, cross_lo;
output dbg;
//assign pck0 = pck0i;
IBUFG #(.IOSTANDARD("DEFAULT") ) pck0b(
.O(pck0),
.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 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.
//-----------------------------------------------------------------------------
reg [7:0] conf_word_shift;
reg [15:0] shift_reg;
reg [7:0] divisor;
reg [7:0] conf_word;
// 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.
always @(posedge ncs)
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
always @(posedge spck)
begin
if(~ncs)
begin
conf_word_shift[7:1] <= conf_word_shift[6:0];
conf_word_shift[0] <= mosi;
shift_reg[15:1] <= shift_reg[14:0];
shift_reg[0] <= mosi;
end
end
@ -110,7 +119,7 @@ lo_read lr(
lr_ssp_frame, lr_ssp_din, ssp_dout, lr_ssp_clk,
cross_hi, cross_lo,
lr_dbg,
lo_is_125khz
lo_is_125khz, divisor
);
lo_simulate ls(

View file

@ -1,6 +1,6 @@
//-----------------------------------------------------------------------------
// 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,
// and the result is serialized.
//
@ -14,7 +14,7 @@ module lo_read(
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
lo_is_125khz
lo_is_125khz, divisor
);
input pck0, ck_1356meg, ck_1356megb;
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;
output dbg;
input lo_is_125khz;
input [7:0] divisor;
// 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
@ -38,65 +39,39 @@ module lo_read(
// 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).
reg [3:0] pck_divider;
reg clk_lo;
reg [7:0] to_arm_shiftreg;
reg [7:0] pck_divider;
reg [6:0] ssp_divider;
reg ant_lo;
always @(posedge pck0)
begin
if(lo_is_125khz)
begin
if(pck_divider == 4'd11)
begin
pck_divider <= 4'd0;
clk_lo = !clk_lo;
end
else
pck_divider <= pck_divider + 1;
end
else
begin
if(pck_divider == 4'd10)
begin
pck_divider <= 4'd0;
clk_lo = !clk_lo;
end
else
pck_divider <= pck_divider + 1;
end
if(pck_divider == 8'd0)
begin
pck_divider <= divisor[7:0];
ant_lo = !ant_lo;
if(ant_lo == 1'b0)
begin
ssp_divider <= 7'b0011111;
to_arm_shiftreg <= adc_d;
end
end
else
begin
pck_divider <= pck_divider - 1;
if(ssp_divider[6] == 1'b0)
begin
if (ssp_divider[1:0] == 1'b11) to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
ssp_divider <= ssp_divider - 1;
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];
// The ADC converts on the falling edge, and our serializer loads when
// carrier_divider_lo == 3'b000.
assign adc_clk = ~carrier_divider_lo[2];
assign ssp_clk = pck_divider[1];
assign ssp_frame = ~ssp_divider[5];
assign pwr_hi = 1'b0;
assign pwr_lo = ant_lo;
assign adc_clk = ~ant_lo;
assign dbg = adc_clk;
endmodule

View file

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

View file

@ -44,6 +44,8 @@ typedef struct {
#define CMD_SIMULATE_TAG_125K 0x0207
#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_SET_LF_DIVISOR 0x020A
#define CMD_SWEEP_LF 0x020B
// For the 13.56 MHz tags
#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_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_SIMULATE_MIFARE_CARD 0x0386
// For measurements of the antenna tuning
@ -67,5 +68,6 @@ typedef struct {
// For direct FPGA control
#define CMD_FPGA_MAJOR_MODE_OFF 0x0500 // ## FPGA Control
#define CMD_TEST 0x0501
#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...
*
* 1st argument: clock rate (as number of samples per clock rate)
* Typical values can be 64, 32, 128...
*/
static void Cmdmanchesterdemod(char *str) {
int i;
@ -1605,18 +1606,23 @@ static void Cmdmanchesterdemod(char *str) {
int lastval;
int lc = 0;
int bitidx = 0;
int bitidx2;
int bit2idx = 0;
sscanf(str, "%i", &clock);
int tolerance = clock/4;
/* Holds the decoded bitstream. */
int BitStream[MAX_GRAPH_TRACE_LEN*2];
int BitStream2[MAX_GRAPH_TRACE_LEN];
/* Holds the decoded bitstream: each clock period contains 2 bits */
/* later simplified to 1 bit after manchester decoding. */
/* 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 */
/* Lo-Hi (arbitrary) */
/* Lo-Hi (arbitrary) */
for(i=1;i<GraphTraceLen;i++) {
if (GraphBuffer[i-1]<GraphBuffer[i]) {
lastval = i;
@ -1626,18 +1632,24 @@ static void Cmdmanchesterdemod(char *str) {
}
/* Then detect duration between 2 successive transitions */
/* At this stage, GraphTrace is either 0 or 1 */
for(bitidx = 1 ;i<GraphTraceLen;i++) {
if (GraphBuffer[i-1] != GraphBuffer[i]) {
lc = i-lastval;
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:
// Tolerance is 1/4 of clock rate (arbitrary)
if ((lc-clock/2) < tolerance) {
// Short pulse
if (abs(lc-clock/2) < tolerance) {
// Short pulse : either "1" or "0"
BitStream[bitidx++]=GraphBuffer[i-1];
} else if ((lc-clock) < tolerance) {
// Long pulse
} else if (abs(lc-clock) < tolerance) {
// Long pulse: either "11" or "00"
BitStream[bitidx++]=GraphBuffer[i-1];
BitStream[bitidx++]=GraphBuffer[i-1];
} 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
for (bitidx2 = 0; bitidx2<bitidx; bitidx2 += 2) {
if ((BitStream[bitidx2] == 0) && (BitStream[bitidx2+1] == 1)) {
BitStream2[bitidx2/2] = 1;
} else if ((BitStream[bitidx2] == 1) && (BitStream[bitidx2+1] == 0)) {
BitStream2[bitidx2/2] = 0;
// Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
// to stop output at the final bitidx2 value, not bitidx
for (i = 0; i < bitidx; i += 2) {
if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
BitStream[bit2idx++] = 1;
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
BitStream[bit2idx++] = 0;
} else {
// We cannot end up in this state, this means we are unsynchronized,
// move up 1 bit:
bitidx2++;
i++;
PrintToScrollback("Unsynchronized, resync...");
PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
}
}
PrintToScrollback("Manchester decoded bitstream \n---------");
// 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",
BitStream2[i],
BitStream2[i+1],
BitStream2[i+2],
BitStream2[i+3],
BitStream2[i+4],
BitStream2[i+5],
BitStream2[i+6],
BitStream2[i+7],
BitStream2[i+8],
BitStream2[i+9],
BitStream2[i+10],
BitStream2[i+11],
BitStream2[i+12],
BitStream2[i+13],
BitStream2[i+14],
BitStream2[i+15]);
BitStream[i],
BitStream[i+1],
BitStream[i+2],
BitStream[i+3],
BitStream[i+4],
BitStream[i+5],
BitStream[i+6],
BitStream[i+7],
BitStream[i+8],
BitStream[i+9],
BitStream[i+10],
BitStream[i+11],
BitStream[i+12],
BitStream[i+13],
BitStream[i+14],
BitStream[i+15]);
}
}
@ -1805,6 +1819,32 @@ static void CmdLcd(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);
@ -1863,6 +1903,8 @@ static struct {
"lcdreset", CmdLcdReset, "Hardware reset LCD",
"lcd", CmdLcd, "Send command/data to LCD",
"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"
};

View file

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