CHG: FeliCa implemenation by @satsuoni

This commit is contained in:
iceman1001 2017-10-20 20:27:44 +02:00
commit 4b63f940f1
20 changed files with 705 additions and 232 deletions

View file

@ -21,6 +21,7 @@ APP_CFLAGS = -DWITH_CRC \
-DWITH_ISO14443b \
-DWITH_ISO14443a \
-DWITH_ICLASS \
-DWITH_FELICA \
-DWITH_HFSNOOP \
-DWITH_HF_YOUNG \
-fno-strict-aliasing -ffunction-sections -fdata-sections
@ -45,6 +46,7 @@ SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c
SRC_ISO15693 = iso15693.c iso15693tools.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c epa.c
SRC_ISO14443b = iso14443b.c
SRC_FELICA = felica.c
SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c
SRC_EMV = tlv.c emvdataels.c emvutil.c emvcmd.c
@ -93,6 +95,7 @@ ARMSRC = fpgaloader.c \
$(SRC_ICLASS) \
$(SRC_EMV) \
$(SRC_CRC) \
$(SRC_FELICA) \
parity.c \
usb_cdc.c \
cmd.c \

View file

@ -766,6 +766,18 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break;
#endif
#ifdef WITH_FELICA
case CMD_FELICA_LITE_SIM:
HfSimLite(c->arg[0]);
break;
case CMD_FELICA_SNOOP:
HfSnoopISO18(c->arg[0], c->arg[1]);
break;
case CMD_FELICA_LITE_DUMP:
HfDumpFelicaLiteS();
break;
#endif
#ifdef WITH_ISO14443a
case CMD_SNOOP_ISO_14443a:
SniffIso14443a(c->arg[0]);

View file

@ -233,6 +233,11 @@ bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* d
// util.h
void HfSnoop(int , int);
//felica.c
extern void HfSnoopISO18(uint32_t samples, uint32_t triggers);
extern void HfSimLite(uint64_t uid);
extern void HfDumpFelicaLiteS();
//EMV functions
// emvcmd.h
extern void EMVTransaction(void);

View file

@ -85,4 +85,14 @@ extern void switch_off();
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
#define FPGA_HF_ISO14443A_READER_MOD (4<<0)
//options for Felica.
#define FPGA_MAJOR_MODE_ISO18092 (5<<5)
#define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) //disable modulation module
#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // should enable 414k mode (untested). No autodetect
#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // enables antenna power, to act as a reader instead of tag
#endif

View file

@ -745,6 +745,114 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
return tracepos;
}
void printFelica(uint16_t traceLen, uint8_t *trace)
{
PrintAndLog(" Gap | Src | Data | CRC | Annotation |");
PrintAndLog("--------|-----|---------------------------------|----------|-------------------|");
uint16_t tracepos=0;
//I am stripping SYNC
while(tracepos<traceLen)
{
if(tracepos+3>=traceLen) break;
uint16_t gap= (uint16_t)trace[tracepos+1]+((uint16_t)trace[tracepos]>>8);
uint16_t crc_ok=trace[tracepos+2];
tracepos+=3;
if(tracepos+3>=traceLen) break;
uint16_t len=trace[tracepos+2];
//printf("!!! %02x %02x %02x %02x %02x %02x %d",trace[tracepos+0],trace[tracepos+1],trace[tracepos+2],trace[tracepos+3],trace[tracepos+4],trace[tracepos+5],len);
tracepos+=3; //skip SYNC
if(tracepos+len+1>=traceLen) break;
uint8_t cmd=trace[tracepos];
uint8_t isResponse=cmd&1;
char line[32][110];
for (int j = 0; j < len+1 && j/8 < 32; j++)
{
snprintf(line[j/8]+(( j % 8) * 4), 110, " %02x ", trace[tracepos+j]);
}
char expbuf[50];
switch(cmd)
{
case FELICA_POLL_REQ:snprintf(expbuf,49,"Poll Req");break;
case FELICA_POLL_ACK :snprintf(expbuf,49,"Poll Resp");break;
case FELICA_REQSRV_REQ :snprintf(expbuf,49,"Request Srvc Req");break;
case FELICA_REQSRV_ACK :snprintf(expbuf,49,"Request Srv Resp");break;
case FELICA_RDBLK_REQ :snprintf(expbuf,49,"Read block(s) Req");break;
case FELICA_RDBLK_ACK :snprintf(expbuf,49,"Read block(s) Resp");break;
case FELICA_WRTBLK_REQ :snprintf(expbuf,49,"Write block(s) Req");break;
case FELICA_WRTBLK_ACK :snprintf(expbuf,49,"Write block(s) Resp");break;
case FELICA_SRCHSYSCODE_REQ :snprintf(expbuf,49,"Search syscode Req");break;
case FELICA_SRCHSYSCODE_ACK :snprintf(expbuf,49,"Search syscode Resp");break;
case FELICA_REQSYSCODE_REQ :snprintf(expbuf,49,"Request syscode Req");break;
case FELICA_REQSYSCODE_ACK :snprintf(expbuf,49,"Request syscode Resp");break;
case FELICA_AUTH1_REQ :snprintf(expbuf,49,"Auth1 Req");break;
case FELICA_AUTH1_ACK :snprintf(expbuf,49,"Auth1 Resp");break;
case FELICA_AUTH2_REQ :snprintf(expbuf,49,"Auth2 Req");break;
case FELICA_AUTH2_ACK :snprintf(expbuf,49,"Auth2 Resp");break;
case FELICA_RDSEC_REQ :snprintf(expbuf,49,"Secure read Req");break;
case FELICA_RDSEC_ACK :snprintf(expbuf,49,"Secure read Resp");break;
case FELICA_WRTSEC_REQ :snprintf(expbuf,49,"Secure write Req");break;
case FELICA_WRTSEC_ACK :snprintf(expbuf,49,"Secure write Resp");break;
case FELICA_REQSRV2_REQ :snprintf(expbuf,49,"Request Srvc v2 Req");break;
case FELICA_REQSRV2_ACK :snprintf(expbuf,49,"Request Srvc v2 Resp");break;
case FELICA_GETSTATUS_REQ :snprintf(expbuf,49,"Get status Req");break;
case FELICA_GETSTATUS_ACK :snprintf(expbuf,49,"Get status Resp");break;
case FELICA_OSVER_REQ :snprintf(expbuf,49,"Get OS Version Req");break;
case FELICA_OSVER_ACK :snprintf(expbuf,49,"Get OS Version Resp");break;
case FELICA_RESET_MODE_REQ :snprintf(expbuf,49,"Reset mode Req");break;
case FELICA_RESET_MODE_ACK :snprintf(expbuf,49,"Reset mode Resp");break;
case FELICA_AUTH1V2_REQ :snprintf(expbuf,49,"Auth1 v2 Req");break;
case FELICA_AUTH1V2_ACK :snprintf(expbuf,49,"Auth1 v2 Resp");break;
case FELICA_AUTH2V2_REQ :snprintf(expbuf,49,"Auth2 v2 Req");break;
case FELICA_AUTH2V2_ACK :snprintf(expbuf,49,"Auth2 v2 Resp");break;
case FELICA_RDSECV2_REQ :snprintf(expbuf,49,"Secure read v2 Req");break;
case FELICA_RDSECV2_ACK :snprintf(expbuf,49,"Secure read v2 Resp");break;
case FELICA_WRTSECV2_REQ :snprintf(expbuf,49,"Secure write v2 Req");break;
case FELICA_WRTSECV2_ACK :snprintf(expbuf,49,"Secure write v2 Resp");break;
case FELICA_UPDATE_RNDID_REQ :snprintf(expbuf,49,"Update IDr Req");break;
case FELICA_UPDATE_RNDID_ACK :snprintf(expbuf,49,"Update IDr Resp");break;
default: snprintf(expbuf,49,"Unknown");break;
}
int num_lines = MIN((len )/16 + 1, 16);
for (int j = 0; j < num_lines ; j++)
{
if (j == 0) {
PrintAndLog("%7d | %s |%-32s |%02x %02x %s| %s",
gap,
(isResponse ? "Tag" : "Rdr"),
line[j],
trace[tracepos+len],
trace[tracepos+len+1],
(crc_ok) ? "OK" : "NG",
expbuf);
} else {
PrintAndLog(" | |%-32s | | ",
line[j]);
}
}
tracepos+=len+1;
}
PrintAndLog("");
}
int usage_hf_list(){
PrintAndLog("List protocol data in trace buffer.");
PrintAndLog("Usage: hf list <protocol> [f][c]");
@ -863,6 +971,12 @@ int CmdHFList(const char *Cmd) {
PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
PrintAndLog("");
if(protocol==FELICA)
{
printFelica(traceLen,trace);
}
else
{
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
if ( protocol == ISO_14443A )
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
@ -882,7 +996,7 @@ int CmdHFList(const char *Cmd) {
while(tracepos < traceLen) {
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
}
}
free(trace);
return 0;
}

View file

@ -13,23 +13,44 @@ static int CmdHelp(const char *Cmd);
int usage_hf_felica_sim(void) {
PrintAndLog("\n Emulating ISO/18092 FeliCa tag \n");
PrintAndLog("usage: hf felica sim [h] t <type> u <uid> [v]");
PrintAndLog("usage: hf felica sim [h] t <type> [v]");
PrintAndLog("options: ");
PrintAndLog(" h : This help");
PrintAndLog(" t : 1 = FeliCa");
PrintAndLog(" : 2 = FeliCaS");
PrintAndLog(" : 2 = FeliCaLiteS");
PrintAndLog(" v : (Optional) Verbose");
PrintAndLog("samples:");
PrintAndLog(" hf felica sim t 1 u 11223344556677");
PrintAndLog(" hf felica sim t 1 ");
return 0;
}
int usage_hf_felica_sniff(void){
PrintAndLog("It get data from the field and saves it into command buffer.");
PrintAndLog("Buffer accessible from command 'hf list felica'");
PrintAndLog("Usage: hf felica sniff [c][r]");
PrintAndLog("c - triggered by first data from card");
PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
PrintAndLog("sample: hf felica sniff c r");
PrintAndLog("Usage: hf felica sniff <s > <t>");
PrintAndLog(" s samples to skip (decimal)");
PrintAndLog(" t triggers to skip (decimal)");
PrintAndLog("samples:");
PrintAndLog(" hf felica sniff s 1000");
return 0;
}
int usage_hf_felica_simlite(void) {
PrintAndLog("\n Emulating ISO/18092 FeliCa Lite tag \n");
PrintAndLog("usage: hf felica litesim [h] u <uid>");
PrintAndLog("options: ");
PrintAndLog(" h : This help");
PrintAndLog(" uid : UID in hexsymbol");
PrintAndLog("samples:");
PrintAndLog(" hf felica litesim 11223344556677");
return 0;
}
int usage_hf_felica_dumplite(void) {
PrintAndLog("\n Dump ISO/18092 FeliCa Lite tag \n");
PrintAndLog("usage: hf felica litedump [h]");
PrintAndLog("options: ");
PrintAndLog(" h : This help");
PrintAndLog("samples:");
PrintAndLog(" hf felica litedump");
return 0;
}
int usage_hf_felica_raw(void){
@ -66,13 +87,6 @@ int CmdHFFelicaReader(const char *Cmd) {
iso14a_card_select_t card;
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
/*
0: couldn't read
1: OK, with ATS
2: OK, no ATS
3: proprietary Anticollision
*/
uint64_t select_status = resp.arg[0];
if (select_status == 0) {
@ -81,10 +95,6 @@ int CmdHFFelicaReader(const char *Cmd) {
return 0;
}
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
return select_status;
}
@ -98,8 +108,8 @@ int CmdHFFelicaSim(const char *Cmd) {
int uidlen = 0;
bool verbose = false;
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch(param_getchar(Cmd, cmdp)) {
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (param_getchar(Cmd, cmdp)) {
case 'h':
case 'H':
return usage_hf_felica_sim();
@ -155,22 +165,211 @@ int CmdHFFelicaSim(const char *Cmd) {
return 0;
}
int CmdHFFelicaSniff(const char *Cmd) {
int param = 0;
uint8_t ctmp;
for (int i = 0; i < 2; i++) {
ctmp = param_getchar(Cmd, i);
if (ctmp == 'h' || ctmp == 'H') return usage_hf_felica_sniff();
if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
}
int CmdHFFelicaSniff(const char *Cmd) {
UsbCommand c = {CMD_FELICA_SNOOP, {param, 0, 0}};
uint8_t cmdp = 0;
uint64_t samples2skip = 0;
uint64_t triggers2skip = 0;
bool errors = false;
while(param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch(param_getchar(Cmd, cmdp)) {
case 'h':
case 'H':
return usage_hf_felica_sniff();
case 's':
case 'S':
samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp += 2;
break;
case 't':
case 'T':
triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp += 2;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
}
//Validations
if (errors || cmdp == 0) return usage_hf_felica_sniff();
UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}};
clearCommandBuffer();
SendCommand(&c);
return 0;
}
// uid hex
int CmdHFFelicaSimLite(const char *Cmd) {
uint64_t uid = param_get64ex(Cmd, 0, 0, 16);
if (!uid)
return usage_hf_felica_simlite();
UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} };
clearCommandBuffer();
SendCommand(&c);
return 0;
}
uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace,uint16_t tracelen) {
if (tracepos+19 >= tracelen)
return tracelen;
trace += tracepos;
uint8_t blocknum = trace[0];
uint8_t status1 = trace[1];
uint8_t status2 = trace[2];
char line[110] = {0};
for (int j = 0; j < 16; j++) {
snprintf(line+( j * 4),110, "%02x ", trace[j+3]);
}
PrintAndLog( "Block number %02x, status: %02x %02x",blocknum,status1, status2);
switch (blocknum) {
case 0x00: PrintAndLog( "S_PAD0: %s",line);break;
case 0x01: PrintAndLog( "S_PAD1: %s",line);break;
case 0x02: PrintAndLog( "S_PAD2: %s",line);break;
case 0x03: PrintAndLog( "S_PAD3: %s",line);break;
case 0x04: PrintAndLog( "S_PAD4: %s",line);break;
case 0x05: PrintAndLog( "S_PAD5: %s",line);break;
case 0x06: PrintAndLog( "S_PAD6: %s",line);break;
case 0x07: PrintAndLog( "S_PAD7: %s",line);break;
case 0x08: PrintAndLog( "S_PAD8: %s",line);break;
case 0x09: PrintAndLog( "S_PAD9: %s",line);break;
case 0x0a: PrintAndLog( "S_PAD10: %s",line);break;
case 0x0b: PrintAndLog( "S_PAD11: %s",line);break;
case 0x0c: PrintAndLog( "S_PAD12: %s",line);break;
case 0x0d: PrintAndLog( "S_PAD13: %s",line);break;
case 0x0E: {
uint32_t regA = trace[3] + (trace[4]>>8) + (trace[5]>>16) + (trace[6]>>24);
uint32_t regB = trace[7] + (trace[8]>>8) + (trace[9]>>16) + (trace[10]>>24);
line[0] = 0;
for (int j = 0; j < 8; j++)
snprintf(line+( j * 2),110, "%02x", trace[j+11]);
PrintAndLog( "REG: regA: %d regB: %d regC: %s ", regA, regB, line);
}
break;
case 0x80: PrintAndLog( "Random Challenge, WO: %s ", line); break;
case 0x81: PrintAndLog( "MAC, only set on dual read: %s ", line); break;
case 0x82: {
char idd[20];
char idm[20];
for (int j = 0; j < 8; j++)
snprintf(idd+( j * 2),20, "%02x", trace[j+3]);
for (int j = 0; j < 6; j++)
snprintf(idm+( j * 2),20, "%02x", trace[j+13]);
PrintAndLog( "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm);
}
break;
case 0x83: {
char idm[20];
char pmm[20];
for (int j = 0; j < 8; j++)
snprintf(idm+( j * 2),20, "%02x", trace[j+3]);
for (int j = 0; j < 8; j++)
snprintf(pmm+( j * 2),20, "%02x", trace[j+11]);
PrintAndLog( "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm);
}
break;
case 0x84: PrintAndLog( "SER_C: 0x%02x%02x ", trace[3], trace[4]); break;
case 0x85: PrintAndLog( "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break;
case 0x86: PrintAndLog( "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break;
case 0x87: PrintAndLog( "CK (card key), WO: %s ", line); break;
case 0x88: {
PrintAndLog( "Memory Configuration (MC):");
PrintAndLog( "MAC needed to write state: %s", trace[3+12]? "on" : "off");
//order might be off here...
PrintAndLog("Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) );
PrintAndLog("Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) );
PrintAndLog("Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) );
PrintAndLog( "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off");
PrintAndLog( "RF parameter: %02x", (trace[3+4] & 0x7) );
PrintAndLog( "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no");
PrintAndLog( "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no");
PrintAndLog("RW access for S_PAD : %s ", sprint_bin(trace+3, 2) );
}
break;
case 0x90: {
PrintAndLog( "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]);
}
break;
case 0x91: {
PrintAndLog( "MAC_A, RW (auth): %s ", line);
}
break;
case 0x92: {
PrintAndLog( "State:");
PrintAndLog( "Polling disabled: %s", trace[3+8] ? "yes" : "no");
PrintAndLog( "Authenticated: %s", trace[3] ? "yes" : "no");
}
break;
case 0xa0: {
PrintAndLog( "CRC of all bloacks match : %s", (trace[3+2]==0xff) ? "no" : "yes");
}
break;
default:
PrintAndLog( "INVALID %d: %s", blocknum, line);
break;
}
return tracepos+19;
}
int CmdHFFelicaDumpLite(const char *Cmd) {
//usage_hf_felica_dumplite();
UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}};
clearCommandBuffer();
SendCommand(&c);
uint16_t tracepos = 0;
uint8_t *trace;
trace = malloc(USB_CMD_DATA_SIZE);
if ( trace == NULL ) {
PrintAndLog("Cannot allocate memory for trace");
return 1;
}
// Query for the size of the trace
UsbCommand response;
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
if ( !WaitForResponseTimeout(CMD_ACK, &response, 4000) ) {
PrintAndLog("timeout while waiting for reply.");
return 1;
}
uint16_t traceLen = response.arg[2];
if (traceLen > USB_CMD_DATA_SIZE) {
uint8_t *p = realloc(trace, traceLen);
if (p == NULL) {
PrintAndLog("Cannot allocate memory for trace");
free(trace);
return 2;
}
trace = p;
GetFromBigBuf(trace, traceLen, 0);
WaitForResponse(CMD_ACK, NULL);
}
PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
while (tracepos < traceLen) {
tracepos = PrintFliteBlock(tracepos, trace, traceLen);
}
free(trace);
return 0;
}
int CmdHFFelicaCmdRaw(const char *cmd) {
UsbCommand c = {CMD_FELICA_COMMAND, {0, 0, 0}};
bool reply = 1;
@ -323,12 +522,15 @@ void waitCmdFelica(uint8_t iSelect) {
}
static command_t CommandTable[] = {
{"help", CmdHelp, 1, "This help"},
{"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"},
{"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"},
{"sim", CmdHFFelicaSim, 0, "<UID> -- Simulate ISO 18092/FeliCa tag"},
{"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"},
{"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"},
{"help", CmdHelp, 1, "This help"},
{"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"},
{"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"},
{"sim", CmdHFFelicaSim, 0, "<UID> -- Simulate ISO 18092/FeliCa tag"},
{"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"},
{"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"},
{"litesim", CmdHFFelicaSimLite, 0, "<NDEF2> - only reply to poll request"},
{"litedump", CmdHFFelicaDumpLite, 0, "Wait for and try dumping FelicaLite"},
{NULL, NULL, 0, NULL}
};

View file

@ -38,4 +38,9 @@ extern int usage_hf_felica_sniff(void);
extern int usage_hf_fFelica_raw(void);
void waitCmdFelica(uint8_t iSelect);
//temp
extern int CmdHFFelicaSimLite(const char *Cmd);
extern int CmdHFFelicaDumpLite(const char *Cmd);
#endif

View file

@ -436,6 +436,67 @@ uint32_t GetT55xxClockBit(uint32_t clock);
#define EM4x05_DISABLE_ALLOWED 1<<23
#define EM4x05_READER_TALK_FIRST 1<<24
#define FLITE_SERVICE_RO 0x000B
#define FLITE_SERVICE_RW 0x0009
#define FELICA_POLL_REQ 0x00
#define FELICA_POLL_ACK 0x01
#define FELICA_REQSRV_REQ 0x02
#define FELICA_REQSRV_ACK 0x03
#define FELICA_RDBLK_REQ 0x06
#define FELICA_RDBLK_ACK 0x07
#define FELICA_WRTBLK_REQ 0x08
#define FELICA_WRTBLK_ACK 0x09
#define FELICA_SRCHSYSCODE_REQ 0x0a
#define FELICA_SRCHSYSCODE_ACK 0x0b
#define FELICA_REQSYSCODE_REQ 0x0c
#define FELICA_REQSYSCODE_ACK 0x0d
#define FELICA_AUTH1_REQ 0x10
#define FELICA_AUTH1_ACK 0x11
#define FELICA_AUTH2_REQ 0x12
#define FELICA_AUTH2_ACK 0x13
#define FELICA_RDSEC_REQ 0x14
#define FELICA_RDSEC_ACK 0x15
#define FELICA_WRTSEC_REQ 0x16
#define FELICA_WRTSEC_ACK 0x17
#define FELICA_REQSRV2_REQ 0x32
#define FELICA_REQSRV2_ACK 0x33
#define FELICA_GETSTATUS_REQ 0x38
#define FELICA_GETSTATUS_ACK 0x39
#define FELICA_OSVER_REQ 0x3c
#define FELICA_OSVER_ACK 0x3d
#define FELICA_RESET_MODE_REQ 0x3e
#define FELICA_RESET_MODE_ACK 0x3f
#define FELICA_AUTH1V2_REQ 0x40
#define FELICA_AUTH1V2_ACK 0x41
#define FELICA_AUTH2V2_REQ 0x42
#define FELICA_AUTH2V2_ACK 0x43
#define FELICA_RDSECV2_REQ 0x44
#define FELICA_RDSECV2_ACK 0x45
#define FELICA_WRTSECV2_REQ 0x46
#define FELICA_WRTSECV2_ACK 0x47
#define FELICA_UPDATE_RNDID_REQ 0x4C
#define FELICA_UPDATE_RNDID_ACK 0x4D
// iclass / picopass chip config structures and shared routines
typedef struct {
uint8_t app_limit; //[8]

Binary file not shown.

View file

@ -18,6 +18,8 @@
`include "hi_simulate.v"
`include "hi_iso14443a.v"
`include "hi_sniffer.v"
`include "hi_flite.v"
//`include "hf_fmod.v"
`include "util.v"
module fpga_hf(
@ -73,7 +75,10 @@ wire hi_read_tx_shallow_modulation = conf_word[0];
wire hi_read_rx_xcorr_848 = conf_word[0];
// and whether to drive the coil (reader) or just short it (snooper)
wire hi_read_rx_xcorr_snoop = conf_word[1];
// divide subcarrier frequency by 4
wire hi_read_rx_xcorr_quarter = conf_word[2];
wire [1:0] hi_read_tx_speed= conf_word [2:1];
// For the high-frequency simulated tag: what kind of modulation to use.
wire [2:0] hi_simulate_mod_type = conf_word[2:0];
@ -90,8 +95,19 @@ hi_read_tx ht(
ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk,
cross_hi, cross_lo,
ht_dbg,
hi_read_tx_shallow_modulation
hi_read_tx_shallow_modulation,hi_read_tx_speed, 1'b1
);
/*hi_fmod hmf(
pck0, ck_1356meg, ck_1356megb,
hmf_pwr_lo, hmf_pwr_hi, hmf_pwr_oe1, hmf_pwr_oe2, hmf_pwr_oe3, hmf_pwr_oe4,
adc_d, ht_adc_clk,
hmf_ssp_frame, hmf_ssp_din, ssp_dout, hmf_ssp_clk,
cross_hi, cross_lo,
hmf_dbg,
hi_simulate_mod_type
);*/
hi_read_rx_xcorr hrxc(
pck0, ck_1356meg, ck_1356megb,
@ -100,7 +116,7 @@ hi_read_rx_xcorr hrxc(
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
cross_hi, cross_lo,
hrxc_dbg,
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
hi_simulate hs(
@ -133,6 +149,16 @@ hi_sniffer he(
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
hi_flite hfl(
pck0, ck_1356meg, ck_1356megb,
hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4,
adc_d, hfl_adc_clk,
hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk,
cross_hi, cross_lo,
hfl_dbg,
hi_simulate_mod_type
);
// Major modes:
// 000 -- HF reader, transmitting to tag; modulation depth selectable
@ -140,19 +166,34 @@ hi_sniffer he(
// 010 -- HF simulated tag
// 011 -- HF ISO14443-A
// 100 -- HF Snoop
// 101 -- HF demod test
// 110 -- Felica modulation, reusing HF reader
// 111 -- everything off
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, 1'b0, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, 1'b0, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, 1'b0, 1'b0, 1'b0);
//mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, hmf_ssp_clk, 1'b0);
//mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, hmf_ssp_din, 1'b0);
//mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, hmf_ssp_frame, 1'b0);
//mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, hmf_pwr_oe1, 1'b0);
//mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, hmf_pwr_oe2, 1'b0);
//mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, hmf_pwr_oe3, 1'b0);
//mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, hmf_pwr_oe4, 1'b0);
//mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, hmf_pwr_lo, 1'b0);
//mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, hmf_pwr_hi, 1'b0);
//mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, hmf_adc_clk, 1'b0);
//mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, hmf_dbg, 1'b0);
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0);
// In all modes, let the ADC's outputs be enabled.
assign adc_noe = 1'b0;

Binary file not shown.

View file

@ -103,7 +103,7 @@ lo_edge_detect le(
// Major modes:
// 000 -- LF reader (generic)
// 001 -- LF edge detect (generic)
// 010 -- LF passthru
// 010 -- LF passthrough
mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0);

Binary file not shown.

View file

@ -16,6 +16,7 @@
`include "hi_flite.v"
`include "util.v"
`include "hi_sniffer.v"
module fpga_nfc(
input spck, output miso, input mosi, input ncs,
@ -67,11 +68,11 @@ assign major_mode = conf_word[7:5];
// For the high-frequency receive correlator: frequency against which to
// correlate.
//wire hi_read_rx_xcorr_848 = conf_word[0];
wire hi_read_rx_xcorr_848 = conf_word[0];
// and whether to drive the coil (reader) or just short it (snooper)
//wire hi_read_rx_xcorr_snoop = conf_word[1];
wire hi_read_rx_xcorr_snoop = conf_word[1];
// divide subcarrier frequency by 4
//wire hi_read_rx_xcorr_quarter = conf_word[2];
wire hi_read_rx_xcorr_quarter = conf_word[2];
// For the high-frequency simulated tag: what kind of modulation to use.
wire [2:0] hi_simulate_mod_type = conf_word[2:0];
@ -81,6 +82,15 @@ wire [2:0] hi_simulate_mod_type = conf_word[2:0];
// major modes, and use muxes to connect the outputs of the active mode to
// the output pins.
//-----------------------------------------------------------------------------
hi_sniffer he(
pck0, ck_1356meg, ck_1356megb,
he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4,
adc_d, he_adc_clk,
he_ssp_frame, he_ssp_din, ssp_dout, he_ssp_clk,
cross_hi, cross_lo,
he_dbg,
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
hi_flite hfl(
@ -103,17 +113,17 @@ hi_flite hfl(
// 101 -- HF NFC demod, just to copy it for now
// 111 -- everything off
mux8 mux_ssp_clk (major_mode, ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_ssp_clk, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_ssp_din, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_ssp_frame, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe1, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe2, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe3, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_oe4, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_lo, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_pwr_hi, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_adc_clk, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, hfl_dbg, 1'b0, 1'b0);
mux8 mux_ssp_clk (major_mode, ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, he_ssp_clk, hfl_ssp_clk, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, he_ssp_din, hfl_ssp_din, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, he_ssp_frame, hfl_ssp_frame, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, 1'b0, 1'b0, 1'b0, 1'b0, hfl_dbg, hfl_dbg, 1'b0, 1'b0);
// In all modes, let the ADC's outputs be enabled.
assign adc_noe = 1'b0;

View file

@ -1,15 +1,11 @@
// Satsuoni, October 2017, Added FeliCa support
//
//this code demodulates and modulates signal as described in ISO/IEC 18092. That includes packets used for Felica, NFC Tag 3, etc. (which do overlap)
//simple envelope following algorithm is used (modification of fail0verflow LF one) is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave)
// only 212 kbps (fc/64) for now 414 is relatively straightforward...
// only 212 kbps (fc/64) for now 414 is relatively straightforward... though for reader, the selection has to come from ARM
// modulation waits for
//market sprocket -doesn't really mean anything ;)
`define SNIFFER 3'b000
`define TAGSIM_LISTEN 3'b001 //same as SNIFFER, really. demod does not distinguish tag from reader
`define TAGSIM_MODULATE 3'b010
`define TAGSIM_MOD_NODELAY 3'b011 //not implemented yet. for use with commands other than polling, which might require different timing, as per Felica standard
//redefining mod_type: bits 210: bit 2 - reader drive/power on/off, bit 1 - speed bit, 0:212, 1 -424 bit 0: listen or modulate
module hi_flite(
pck0, ck_1356meg, ck_1356megb,
@ -18,7 +14,8 @@ module hi_flite(
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
mod_type // maybe used
mod_type // used
);
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -28,15 +25,18 @@ module hi_flite(
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
input [2:0] mod_type; // maybe used.
input [2:0] mod_type; // used.
assign dbg=0;
// Most off, oe4 for modulation; No reader emulation (would presumably just require switching power on, but I am not sure)
assign pwr_hi = 1'b0;
wire power= mod_type[2];
wire speed= mod_type[1];
wire disabl= mod_type[0];
// Most off, oe4 for modulation;
// Trying reader emulation (would presumably just require switching power on, but I am not sure)
//;// 1'b0;
assign pwr_lo = 1'b0;
assign pwr_oe1 = 1'b0;
assign pwr_oe2 = 1'b0;
assign pwr_oe3 = 1'b0;
//512x64/fc -wait before ts0, 32768 ticks
@ -51,7 +51,7 @@ assign adc_clk = ck_1356meg;
`define ithrmin 91//-13'd8
`define ithrmax 160// 13'd8
`define min_bitdelay_212 8
//minimum values and corresponding thresholds
reg [8:0] curmin=`imin;
@ -76,9 +76,13 @@ reg did_sync=0;
`define bithalf_212 32 //half-bit length for 212 kbit
`define bitlen_212 64 //full-bit length for 212 kbit
`define bitmlen_212 63 //bit transition edge
`define bitmhalf_212 31 //mod flip
`define bithalf_424 16 //half-bit length for 212 kbit
`define bitmlen_424 31 //bit transition edge
wire [7:0]bithalf= speed ? `bithalf_424 : `bithalf_212;
wire [7:0]bitmlen= speed ? `bitmlen_424 : `bitmlen_212;
//ssp clock and current values
@ -98,57 +102,36 @@ reg [8:0] ssp_cnt=9'd0;
always @(posedge adc_clk)
ssp_cnt <= (ssp_cnt + 1);
reg getting_arm_data=1'b0;
reg [47:0] delayline=48'd0; //48-bit preamble delay line. Just push the data into it starting from first SYNC (1) bit coming from ARM Made this long to keep all ARM data received during preamble
reg [5:0] delay_read_ptr=6'd0; // this is supposed to count ARM delay in the buffer.
reg preamble=0; // whether we are sending preamble
//maybe change it so that ARM sends preamble as well.
//then: ready bits sent to ARM, 8 bits sent from ARM (all ones), then preamble (all zeros, presumably) - which starts modulation
always @(negedge adc_clk)
begin
//count fc/64 - transfer bits to ARM at the rate they are received
if(ssp_cnt[5:0] == 6'b000000)
if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed &&(ssp_cnt[4:0] == 5'b00000)))
begin
ssp_clk <= 1'b1;
// if(mod_type[2])
// begin
// ssp_din<=outp[0];//after_hysteresis;
//outp<={1'b0,outp[7:1]};
// end
// else
ssp_din <= curbit;
//sample ssp_dout?
if(mod_type==`TAGSIM_MODULATE||mod_type==`TAGSIM_MOD_NODELAY)
begin
delayline<={delayline[46:0],ssp_dout};
if ((~getting_arm_data) && ssp_dout)
begin
getting_arm_data <=1'b1;
delay_read_ptr<=delay_read_ptr+1;
end
else
begin
if (getting_arm_data & preamble)
begin
delay_read_ptr<=delay_read_ptr+1;
end
end
end
else
begin
getting_arm_data <=1'b0;
delay_read_ptr<=6'd0;
end
//sample ssp_dout
end
if(ssp_cnt[5:0] == 6'b100000)
if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000))
ssp_clk <= 1'b0;
//create frame pulses. TBH, I still don't know what they do exactly, but they are crucial for ARM->FPGA transfer. If the frame is in the beginning of the byte, transfer slows to a crawl for some reason
// took me a day to figure THAT out.
if(ssp_cnt[8:0] == 9'd31)
if(( (~speed) && (ssp_cnt[8:0] == 9'd31))||(speed && ssp_cnt[7:0] == 8'd15))
begin
ssp_frame <= 1'b1;
end
if(ssp_cnt[8:0] == 9'b1011111)
if(( (~speed) && (ssp_cnt[8:0] == 9'b1011111))||(speed &&ssp_cnt[7:0] == 8'b101111) )
begin
ssp_frame <= 1'b0;
end
@ -158,7 +141,7 @@ end
//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise)
reg ssp_din;
reg ssp_din;//= outp[0];
@ -168,28 +151,74 @@ reg prv =1'b1;
reg[7:0] mid=8'd128; //for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry.
//modulated coil. set to 1 to modulate low, 0 to keep signal high
reg mod_sig_coil=1'b0;
// set TAGSIM__MODULATE on ARM if we want to write... (frame would get lost if done mid-frame...)
// start sending over 1s on ssp->arm when we start sending preamble
reg counting_desync=1'b0; // are we counting bits since last frame?
reg sending=1'b0; // are we actively modulating?
reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes.
reg [11:0] bit_counts=12'd0;///for timeslots... only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those?
//reg [2:0]old_mod;
//always @(mod_type) //when moving from modulate_mode
//begin
//if (mod_type[2]==1&&old_mod[2]==0)
// bit_counts=0;
//old_mod=mod_type;
//end
//we need some way to flush bit_counts triggers on mod_type changes don't compile
reg dlay;
always @(negedge adc_clk) //every data ping?
begin
//envelope follow code...
////////////
if ((mod_type==`SNIFFER )||(mod_type==`TAGSIM_LISTEN))
//move the counter to the outside...
// if (adc_d>=curminthres||try_sync)
if(fccount==bitmlen)
begin
if((~try_sync)&&(adc_d<curminthres)&&disabl )
begin
fccount<=1;
end
else
begin
fccount<=0;
end
// if (counting_desync)
// begin
dlay<=ssp_dout;
if(bit_counts>768) // should be over ts0 now, without ARM interference... stop counting...
begin
bit_counts<=0;
// counting_desync<=0;
end
else
if((power))
bit_counts<=0;
else
bit_counts<=bit_counts+1;
// end
end
else
begin
if((~try_sync)&&(adc_d<curminthres) &&disabl)
begin
fccount<=1;
end
else
begin
fccount<=fccount+1;
end
end
if (adc_d>curmaxthres) //rising edge
begin
case (state)
0: begin
curmax <= adc_d>155? adc_d :155;
curmax <= adc_d>`imax? adc_d :`imax;
state <= 2;
end
1: begin
@ -214,7 +243,7 @@ begin
begin
case (state)
0: begin
curmin <=adc_d<96? adc_d :96;
curmin <=adc_d<`imin? adc_d :`imin;
state <=1;
end
1: begin
@ -224,7 +253,7 @@ begin
2: begin
curminthres <= ( (curmin>>1)+(curmin>>2)+(curmin>>4)+(curmax>>3)+(curmax>>4));
curmaxthres <= ( (curmax>>1)+(curmax>>2)+(curmax>>4)+(curmin>>3)+(curmin>>4));
curmin <=adc_d<96? adc_d :96;
curmin <=adc_d<`imin? adc_d :`imin;
state <=1;
end
default:
@ -235,7 +264,7 @@ begin
if (~try_sync ) //begin modulation, lower edge...
begin
try_sync <=1;
counting_desync<=1'b0;
//counting_desync<=1'b0;
fccount <= 1;
did_sync<=0;
curbit<=0;
@ -259,7 +288,7 @@ begin
if (tsinceedge>=(128))
begin
//we might need to start counting... assuming ARM wants to reply to the frame.
counting_desync<=1'b1;
// counting_desync<=1'b1;
bit_counts<=1;// i think? 128 is about 2 bits passed... but 1 also works
try_sync<=0;
did_sync<=0;//desync
@ -278,32 +307,13 @@ begin
end
end
//move the counter to the outside...
if (adc_d>=curminthres||try_sync)
if(fccount==`bitmlen_212)
begin
fccount<=0;
if (counting_desync)
begin
if(bit_counts>768) // should be over ts0 now, without ARM interference... stop counting...
begin
bit_counts<=0;
counting_desync<=0;
end
else
bit_counts<=bit_counts+1;
end
end
else
begin
fccount<=fccount+1;
end
if (try_sync && tsinceedge<128)
begin
//detect bits in their middle ssp sampling is in sync, so it would sample all bits in order
if (fccount==`bithalf_212)
if (fccount==bithalf)
begin
if ((~did_sync) && ((prv==1&&(mid>128))||(prv==0&&(mid<=128))))
begin
@ -336,7 +346,7 @@ begin
end
else
begin
if (fccount==`bitmlen_212)
if (fccount==bitmlen)
begin
// fccount <=0;
prv <=(mid>128)?1:0;
@ -367,61 +377,40 @@ begin
begin
end
sending <=0;
end //listen mode end
else
begin //sim mode start
//not sure how precise do the time slots have to be... is anything within Ts ok?
//keep counting until 576, just in case
if(fccount==`bitmlen_212)
begin
if (bit_counts==512) //
curbit<=1;
else
begin
if(bit_counts>512)
curbit<=mod_sig_coil;//delayline[delay_read_ptr];//bit_counts[0];
else
curbit<=0;
end
fccount<=0;
if (bit_counts<=576) //we don't need to count after that...
begin
bit_counts<=bit_counts+1;
if (bit_counts== 512) //should start sending from next tick... i think?
begin
sending <=1;
mod_sig_coil <=1;//modulate... down?
preamble<=1;
end
else
if (bit_counts== 559)
begin
preamble<=0;
end
end
if (sending)
begin //need next bit
if(preamble)
mod_sig_coil<=1;
else
mod_sig_coil<=~delayline[delay_read_ptr];
end
end
else
begin
fccount<=fccount+1;
if ((fccount==`bitmhalf_212)&&(sending)) //flip modulation mid-bit
begin
mod_sig_coil<=~mod_sig_coil;//flip
end
end
end //sim mode end
end
//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that
reg pwr_hi;
reg pwr_oe1;
reg pwr_oe2;
reg pwr_oe3;
reg pwr_oe4;
assign pwr_oe4 = mod_sig_coil & (mod_type == `TAGSIM_MODULATE)&sending;
wire mod=((fccount>=bithalf)^dlay)&(~disabl);
always @(ck_1356megb or ssp_dout or power or disabl or mod)
begin
if (power)
begin
pwr_hi <= ck_1356megb;
pwr_oe1 <= mod;
pwr_oe2 <= mod;
pwr_oe3 <= mod;
pwr_oe4 <= 1'b0;
end
else
begin
pwr_hi <= 1'b0;
pwr_oe1 <= 1'b0;
pwr_oe2 <= 1'b0;
pwr_oe3 <= 1'b0;
pwr_oe4 <= mod;
end
end
//assign pwr_oe4 = 1'b0;// mod_sig_coil & (modulate_mode)&sending & (~mod_type[2]);
//try shallow mod for reader?
//assign pwr_hi= (mod_type[2]) & ck_1356megb;
//assign pwr_oe1= 1'b0; //mod_sig_coil & (modulate_mode)&sending & (mod_type[2]);
//assign pwr_oe2 = 1'b0;// mod_sig_coil & (modulate_mode)&sending & (mod_type[2]);
//assign pwr_oe3 = 1'b0; //mod_sig_coil & (modulate_mode)&sending & (mod_type[2]);
endmodule

View file

@ -10,7 +10,7 @@ module hi_read_rx_xcorr(
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
xcorr_is_848, snoop
xcorr_is_848, snoop, xcorr_quarter_freq
);
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -20,7 +20,7 @@ module hi_read_rx_xcorr(
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
input xcorr_is_848, snoop;
input xcorr_is_848, snoop, xcorr_quarter_freq;
// Carrier is steady on through this, unless we're snooping.
assign pwr_hi = ck_1356megb & (~snoop);
@ -28,18 +28,20 @@ assign pwr_oe1 = 1'b0;
assign pwr_oe3 = 1'b0;
assign pwr_oe4 = 1'b0;
// Clock divider
reg [0:0] fc_divider;
reg [2:0] fc_div;
always @(negedge ck_1356megb)
fc_divider <= fc_divider + 1;
wire fc_div2 = fc_divider[0];
fc_div <= fc_div + 1;
reg adc_clk;
always @(ck_1356megb)
if (xcorr_is_848)
(* clock_signal = "yes" *) reg adc_clk; // sample frequency, always 16 * fc
always @(ck_1356megb, xcorr_is_848, xcorr_quarter_freq, fc_div)
if (xcorr_is_848 & ~xcorr_quarter_freq) // fc = 847.5 kHz
adc_clk <= ck_1356megb;
else
adc_clk <= fc_div2;
else if (~xcorr_is_848 & ~xcorr_quarter_freq) // fc = 424.25 kHz
adc_clk <= fc_div[0];
else if (xcorr_is_848 & xcorr_quarter_freq) // fc = 212.125 kHz
adc_clk <= fc_div[1];
else // fc = 106.0625 kHz
adc_clk <= fc_div[2];
// When we're a reader, we just need to do the BPSK demod; but when we're an
// eavesdropper, we also need to pick out the commands sent by the reader,
@ -71,8 +73,7 @@ end
// so we need a 6-bit counter.
reg [5:0] corr_i_cnt;
// And a couple of registers in which to accumulate the correlations.
// we would add at most 32 times adc_d, the result can be held in 13 bits.
// Need one additional bit because it can be negative as well
// we would add/sub at most 32 times adc_d, the signed result can be held in 14 bits.
reg signed [13:0] corr_i_accum;
reg signed [13:0] corr_q_accum;
reg signed [7:0] corr_i_out;

View file

@ -12,7 +12,7 @@ module hi_read_tx(
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
shallow_modulation
shallow_modulation, speed, power
);
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
@ -23,6 +23,8 @@ module hi_read_tx(
input cross_hi, cross_lo;
output dbg;
input shallow_modulation;
input [1:0] speed;
input power;
// The high-frequency stuff. For now, for testing, just bring out the carrier,
// and allow the ARM to modulate it over the SSP.
@ -32,6 +34,8 @@ reg pwr_oe2;
reg pwr_oe3;
reg pwr_oe4;
always @(ck_1356megb or ssp_dout or shallow_modulation)
begin
if (power)
begin
if(shallow_modulation)
begin
@ -50,6 +54,15 @@ begin
pwr_oe4 <= 1'b0;
end
end
else
begin
pwr_hi <= 1'b0;
pwr_oe1 <= 1'b0;
pwr_oe2 <= 1'b0;
pwr_oe3 <= 1'b0;
pwr_oe4 <= ~ssp_dout;
end
end
// Then just divide the 13.56 MHz clock down to produce appropriate clocks
// for the synchronous serial port.
@ -59,7 +72,7 @@ reg [6:0] hi_div_by_128;
always @(posedge ck_1356meg)
hi_div_by_128 <= hi_div_by_128 + 1;
assign ssp_clk = hi_div_by_128[6];
assign ssp_clk = speed[1]? (speed[0]? hi_div_by_128[3]: hi_div_by_128[4]) : (speed[0]? hi_div_by_128[5]: hi_div_by_128[6]);
reg [2:0] hi_byte_div;
@ -76,7 +89,7 @@ assign adc_clk = ck_1356meg;
reg after_hysteresis;
always @(negedge adc_clk)
begin
if(& adc_d[7:0]) after_hysteresis <= 1'b1;
if(& adc_d[7:4]) after_hysteresis <= 1'b1;
else if(~(| adc_d[7:0])) after_hysteresis <= 1'b0;
end

View file

@ -53,11 +53,6 @@ end
// Divide 13.56 MHz by 32 to produce the SSP_CLK
// The register is bigger to allow higher division factors of up to /128
// FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) // 0000
// FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) // 0001
// FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) // 0010
// FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) // 0100
// FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101
reg [10:0] ssp_clk_divider;
always @(posedge adc_clk)
@ -91,8 +86,8 @@ end
// Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
// this is arbitrary, because it's just a bitstream.
// One nasty issue, though: I can't make it work with both rx and tx at
// once. The phase wrt ssp_clk must be changed.
// TODO to find out why that is and make a better fix.
// once. The phase wrt ssp_clk must be changed. TODO to find out why
// that is and make a better fix.
reg [2:0] ssp_frame_divider_to_arm;
always @(posedge ssp_clk)
ssp_frame_divider_to_arm <= (ssp_frame_divider_to_arm + 1);

View file

@ -17,8 +17,11 @@ module hi_sniffer(
output dbg;
input xcorr_is_848, snoop, xcorr_quarter_freq; // not used.
// let's try hi-pass
// We are only snooping, all off.
assign pwr_hi = 1'b0;
assign pwr_hi = ck_1356megb & xcorr_quarter_freq;//1'b0;
assign pwr_lo = 1'b0;
assign pwr_oe1 = 1'b0;
assign pwr_oe2 = 1'b0;
@ -29,8 +32,12 @@ reg ssp_frame;
reg [7:0] adc_d_out = 8'd0;
reg [2:0] ssp_cnt = 3'd0;
assign adc_clk = ck_1356meg;
assign ssp_clk = ~ck_1356meg;
reg [12:0] avg=13'd0;
assign adc_clk = ck_1356megb;
assign ssp_clk = ~ck_1356megb;
always @(posedge ssp_clk)
begin
@ -41,7 +48,9 @@ begin
if(ssp_cnt[2:0] == 3'b000) // set frame length
begin
adc_d_out[7:0] <= adc_d;
// adc_d_out[7:0] <= (alias_buf>>>3) +8'd126;//( $signed(adc_d-adc_d_old)>1 | $signed(adc_d_old-adc_d)>1)? alias_buf+adc_d-adc_d_old:alias_buf; //alias_buf[11:3]+8'd126;//adc_d;
// adc_d_out[7:0]<=adc_d;
adc_d_out[7:0] <=adc_d;//-(avg>>3) +8'd126;
ssp_frame <= 1'b1;
end
else

View file

@ -171,6 +171,9 @@ typedef struct{
#define CMD_FELICA_SIMULATE_TAG 0x03A0
#define CMD_FELICA_SNOOP 0x03A1
#define CMD_FELICA_COMMAND 0x03A2
//temp
#define CMD_FELICA_LITE_DUMP 0x03AA
#define CMD_FELICA_LITE_SIM 0x03AB
// For measurements of the antenna tuning
#define CMD_MEASURE_ANTENNA_TUNING 0x0400