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

This commit is contained in:
iceman1001 2017-02-02 15:32:21 +01:00
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]); CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]);
break; break;
case CMD_COTAG: case CMD_COTAG:
Cotag(); Cotag(c->arg[0]);
break; break;
#endif #endif

View file

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

View file

@ -799,7 +799,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
WDT_HIT(); WDT_HIT();
if (ledcontrol) LED_A_ON(); if (ledcontrol) LED_A_ON();
DoAcquisition_default(-1,true); DoAcquisition_default(0, true);
// FSK demodulator // FSK demodulator
size = 50*128*2; //big enough to catch 2 sequences of largest format size = 50*128*2; //big enough to catch 2 sequences of largest format
idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo); 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(); 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 OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); }
//#define WAIT2200 { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2200); } #define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
#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(); 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 //clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
// Set up FPGA, 132kHz to power up the tag // Set up FPGA, 132kHz to power up the tag
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); 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. // Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc(); FpgaSetupSsc();
// start a 1.5ticks is 1us // start clock - 1.5ticks is 1us
StartTicks(); StartTicks();
//send start pulse //send COTAG start pulse
ON(740) OFF ON(740) OFF
ON(3330) OFF ON(3330) OFF
ON(740) OFF ON(740) OFF
ON(1000) ON(1000)
/* switch(rawsignal) {
ON(800) OFF case 0: doCotagAcquisition(50000); break;
ON(3600) OFF case 1: doCotagAcquisitionManchester(); break;
ON(800) OFF case 2: DoAcquisition_config(TRUE); break;
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);
// Turn the field off // Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // 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() { void printConfig() {
Dbprintf("LF Sampling config: "); 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(" [b] bps: %d ", config.bits_per_sample);
Dbprintf(" [d] decimation: %d ", config.decimation); Dbprintf(" [d] decimation: %d ", config.decimation);
Dbprintf(" [a] averaging: %s ", (config.averaging) ? "Yes" : "No"); 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() ) { while(!BUTTON_PRESS() && !usb_poll_validate_length() ) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { 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(); LED_D_ON();
} }
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { 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; 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. * the data is collected in BigBuf.
**/ **/
void doT55x7Acquisition(size_t sample_size); 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"); PrintAndLog("divisor must be between 19 and 255");
return 1; return 1;
} }
// 12 000 000 (12Mhz)
//
clearCommandBuffer(); clearCommandBuffer();
SendCommand(&c); 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; return 0;
} }

View file

@ -11,26 +11,78 @@
static int CmdHelp(const char *Cmd); 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) { int CmdCOTAGRead(const char *Cmd) {
// if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_cotag_read(); if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_cotag_read();
CmdLFSetConfig("q 89"); 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(); clearCommandBuffer();
SendCommand(&c); SendCommand(&c);
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { if ( !WaitForResponseTimeout(CMD_ACK, NULL, 7000) ) {
PrintAndLog("command execution time out"); 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; return 0;
} }
static command_t CommandTable[] = { static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"}, {"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} {NULL, NULL, 0, NULL}
}; };

View file

@ -21,5 +21,7 @@
int CmdLFCOTAG(const char *Cmd); int CmdLFCOTAG(const char *Cmd);
int CmdCOTAGRead(const char *Cmd); int CmdCOTAGRead(const char *Cmd);
int CmdCOTAGDemod(const char *Cmd);
int usage_lf_cotag_read(void);
#endif #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 //take 10 and 01 and manchester decode
//run through 2 times and take least errCnt //run through 2 times and take least errCnt
int manrawdecode(uint8_t * BitStream, size_t *size, uint8_t invert){ 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; size_t i, k;
uint16_t bestErr = 1000, bestRun = 0;
if (*size < 16) return -1; if (*size < 16) return -1;
//find correct start position [alignment] //find correct start position [alignment]
for (k=0; k < 2; ++k){ for (k=0; k < 2; ++k){