ADD: 'lf cotag read' - COTAG can be read now.

This commit is contained in:
iceman1001 2017-02-02 15:32:21 +01:00
parent 4401050bcc
commit 5f5b83b743
9 changed files with 232 additions and 41 deletions

View file

@ -1017,7 +1017,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]);
break;
case CMD_COTAG:
Cotag();
Cotag(c->arg[0]);
break;
#endif

View file

@ -98,7 +98,7 @@ void T55xxWakeUp(uint32_t Pwd);
void TurnReadLFOn(uint32_t delay);
void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode);
void Cotag();
void Cotag(uint32_t arg0);
/// iso14443b.h
void SimulateIso14443bTag(uint32_t pupi);

View file

@ -799,7 +799,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
WDT_HIT();
if (ledcontrol) LED_A_ON();
DoAcquisition_default(-1,true);
DoAcquisition_default(0, true);
// FSK demodulator
size = 50*128*2; //big enough to catch 2 sequences of largest format
idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
@ -1740,18 +1740,36 @@ void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode
LED_D_OFF();
}
void Cotag() {
/*
Reading a COTAG.
COTAG needs the reader to send a startsequence and the card has an extreme slow datarate.
because of this, we can "sample" the data signal but we interpreate it to Manchester direct.
READER START SEQUENCE:
burst 800 us, gap 2.2 msecs
burst 3.6 msecs gap 2.2 msecs
burst 800 us gap 2.2 msecs
pulse 3.6 msecs
This triggers a COTAG tag to response
*/
void Cotag(uint32_t arg0) {
#define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); }
//#define WAIT2200 { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2200); }
#define ON(x) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
LED_A_ON();
#define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
uint8_t rawsignal = arg0 & 0xF;
LED_A_ON();
// Switching to LF image on FPGA. This might empty BigBuff
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
//clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
// Set up FPGA, 132kHz to power up the tag
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Set up FPGA, 132kHz to power up the tag
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
@ -1761,27 +1779,20 @@ void Cotag() {
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc();
// start a 1.5ticks is 1us
// start clock - 1.5ticks is 1us
StartTicks();
//send start pulse
//send COTAG start pulse
ON(740) OFF
ON(3330) OFF
ON(740) OFF
ON(1000)
/*
ON(800) OFF
ON(3600) OFF
ON(800) OFF
ON(1000)
burst 800 us, gap 2.2 msecs
burst 3.6 msecs gap 2.2 msecs
burst 800 us gap 2.2 msecs
pulse 3.6 msecs
*/
DoAcquisition_config(FALSE);
switch(rawsignal) {
case 0: doCotagAcquisition(50000); break;
case 1: doCotagAcquisitionManchester(); break;
case 2: DoAcquisition_config(TRUE); break;
}
// Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off

View file

@ -20,7 +20,7 @@ sample_config config = { 1, 8, 1, 95, 0 } ;
void printConfig() {
Dbprintf("LF Sampling config: ");
Dbprintf(" [q] divisor: %d ", config.divisor);
Dbprintf(" [q] divisor: %d (%d KHz)", config.divisor, 12000 / (config.divisor+1));
Dbprintf(" [b] bps: %d ", config.bits_per_sample);
Dbprintf(" [d] decimation: %d ", config.decimation);
Dbprintf(" [a] averaging: %s ", (config.averaging) ? "Yes" : "No");
@ -140,7 +140,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
while(!BUTTON_PRESS() && !usb_poll_validate_length() ) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x00; //0x43;
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
@ -310,4 +310,122 @@ void doT55x7Acquisition(size_t sample_size) {
}
}
}
/**
* acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384
* and is Manchester?, we directly gather the manchester data into bigbuff
**/
#define COTAG_T1 384
#define COTAG_T2 (COTAG_T1>>1)
#define COTAG_ONE_THRESHOLD 128+30
#define COTAG_ZERO_THRESHOLD 128-30
void doCotagAcquisition(size_t sample_size) {
uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size )
bufsize = sample_size;
dest[0] = 0;
uint8_t sample = 0, firsthigh = 0, firstlow = 0;
uint16_t i = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) ) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
// find first peak
if ( !firsthigh ) {
if (sample < COTAG_ONE_THRESHOLD)
continue;
firsthigh = 1;
}
if ( !firstlow ){
if (sample > COTAG_ZERO_THRESHOLD )
continue;
firstlow = 1;
}
++i;
if ( sample > COTAG_ONE_THRESHOLD)
dest[i] = 255;
else if ( sample < COTAG_ZERO_THRESHOLD)
dest[i] = 0;
else
dest[i] = dest[i-1];
}
}
}
uint32_t doCotagAcquisitionManchester() {
uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > 320 )
bufsize = 320;
dest[0] = 0;
uint8_t sample = 0, firsthigh = 0, firstlow = 0;
uint16_t sample_counter = 0, period = 0;
uint8_t curr = 0, prev = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) ) {
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = 0x43;
LED_D_ON();
}
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
// find first peak
if ( !firsthigh ) {
if (sample < COTAG_ONE_THRESHOLD)
continue;
firsthigh = 1;
}
if ( !firstlow ){
if (sample > COTAG_ZERO_THRESHOLD )
continue;
firstlow = 1;
}
// set sample 255, 0, or previous
if ( sample > COTAG_ONE_THRESHOLD){
prev = curr;
curr = 1;
}
else if ( sample < COTAG_ZERO_THRESHOLD) {
prev = curr;
curr = 0;
}
else {
curr = prev;
}
// full T1 periods,
if ( period > 0 ) {
--period;
continue;
}
dest[sample_counter] = curr;
++sample_counter;
period = COTAG_T1;
}
}
return sample_counter;
}

View file

@ -11,7 +11,14 @@
typedef struct BitstreamOut BitstreamOut;
/**
* acquisition of T55x7 LF signal. Similart to other LF, but adjusted with @marshmellows thresholds
* acquisition of Cotag LF signal. Similar to other LF, since the Cotag has such long datarate RF/384
* and is Manchester?, we directly gather the manchester data into bigbuff
**/
void doCotagAcquisition(size_t sample_size);
uint32_t doCotagAcquisitionManchester(void);
/**
* acquisition of T55x7 LF signal. Similar to other LF, but adjusted with @marshmellows thresholds
* the data is collected in BigBuf.
**/
void doT55x7Acquisition(size_t sample_size);

View file

@ -222,10 +222,11 @@ int CmdSetDivisor(const char *Cmd)
PrintAndLog("divisor must be between 19 and 255");
return 1;
}
// 12 000 000 (12Mhz)
//
clearCommandBuffer();
SendCommand(&c);
PrintAndLog("Divisor set, expected freq=%dHz", 12000000 / (c.arg[0]+1));
PrintAndLog("Divisor set, expected %.1f KHz", ((double)12000 / (c.arg[0]+1)) );
return 0;
}

View file

@ -11,26 +11,78 @@
static int CmdHelp(const char *Cmd);
int usage_lf_cotag_read(void){
PrintAndLog("Usage: lf COTAG read [h] <signaldata>");
PrintAndLog("Options:");
PrintAndLog(" h : This help");
PrintAndLog(" <0|1|2> : 0 - HIGH/LOW signal; maxlength bigbuff");
PrintAndLog(" : 1 - translation of HI/LO into bytes with manchester 0,1");
PrintAndLog(" : 2 - raw signal; maxlength bigbuff");
PrintAndLog("");
PrintAndLog("Sample:");
PrintAndLog(" lf cotag read 0");
PrintAndLog(" lf cotag read 1");
return 0;
}
int CmdCOTAGDemod(const char *Cmd) {
return 0;
}
// When reading a COTAG.
// 0 = HIGH/LOW signal - maxlength bigbuff
// 1 = translation for HI/LO into bytes with manchester 0,1 - length 300
// 2 = raw signal - maxlength bigbuff
int CmdCOTAGRead(const char *Cmd) {
// if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_cotag_read();
CmdLFSetConfig("q 89");
if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_cotag_read();
uint8_t bits[320] = {0};
uint32_t rawsignal = 0;
sscanf(Cmd, "%u", &rawsignal);
UsbCommand c = {CMD_COTAG, {0, 0, 0}};
UsbCommand c = {CMD_COTAG, {rawsignal, 0, 0}};
clearCommandBuffer();
SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) {
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 7000) ) {
PrintAndLog("command execution time out");
return 1;
return 1;
}
getSamples("", true);
switch ( rawsignal ){
case 0:
case 2: {
CmdPlot("");
CmdGrid("384");
getSamples("", true); break;
}
case 1: {
GetFromBigBuf(bits, sizeof(bits), 0);
UsbCommand response;
if ( !WaitForResponseTimeout(CMD_ACK, &response, 500) ) {
PrintAndLog("timeout while waiting for reply.");
return 1;
}
size_t size = sizeof(bits);
int err = manrawdecode(bits, &size, 1);
if (err){
PrintAndLog("DEBUG: Error - COTAG too many errors: %d", err);
return 0;
}
PrintAndLog("%s", sprint_bin(bits, size));
setDemodBuf(bits, sizeof(bits), 0);
// CmdCOTAGDemod();
break;
}
}
return 0;
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"read", CmdCOTAGRead, 0, "Attempt to read and extract tag data"},
{"demod", CmdCOTAGDemod, 1, "Tries to decode a COTAG signal"},
{"read", CmdCOTAGRead, 0, "Attempt to read and extract tag data"},
{NULL, NULL, 0, NULL}
};

View file

@ -21,5 +21,7 @@
int CmdLFCOTAG(const char *Cmd);
int CmdCOTAGRead(const char *Cmd);
int CmdCOTAGDemod(const char *Cmd);
int usage_lf_cotag_read(void);
#endif

View file

@ -350,9 +350,9 @@ int askdemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr
//take 10 and 01 and manchester decode
//run through 2 times and take least errCnt
int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert){
uint16_t bitnum = 0, MaxBits = 512, errCnt = 0;
int errCnt = 0, bestErr = 1000;
uint16_t bitnum = 0, MaxBits = 512, bestRun = 0;
size_t i, k;
uint16_t bestErr = 1000, bestRun = 0;
if (*size < 16) return -1;
//find correct start position [alignment]
for (k=0; k < 2; ++k){