+
+// Initialize the proxmark as iso15k reader
+// (this might produces glitches that confuse some tags
+void Iso15693InitReader() {
+ LED_A_ON();
+ LED_B_ON();
+ LED_C_OFF();
+ LED_D_OFF();
+
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ // Setup SSC
+ // FpgaSetupSsc();
+
+ // Start from off (no field generated)
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ SpinDelay(10);
+
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaSetupSsc();
+
+ // Give the tags time to energize
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+ SpinDelay(250);
+
+ LED_A_ON();
+ LED_B_OFF();
+ LED_C_OFF();
+ LED_D_OFF();
+}
+
+///////////////////////////////////////////////////////////////////////
+// ISO 15693 Part 3 - Air Interface
+// This section basicly contains transmission and receiving of bits
+///////////////////////////////////////////////////////////////////////
+
+// Encode (into the ToSend buffers) an identify request, which is the first
+// thing that you must send to a tag to get a response.
+static void BuildIdentifyRequest(void)
+{
+ uint8_t cmd[5];
+
+ uint16_t crc;
+ // one sub-carrier, inventory, 1 slot, fast rate
+ // AFI is at bit 5 (1<<4) when doing an INVENTORY
+ cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);
+ // inventory command code
+ cmd[1] = 0x01;
+ // no mask
+ cmd[2] = 0x00;
+ //Now the CRC
+ crc = Crc(cmd, 3);
+ cmd[3] = crc & 0xff;
+ cmd[4] = crc >> 8;
+
+ CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+// uid is in transmission order (which is reverse of display order)
+static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
+{
+ uint8_t cmd[13];
+
+ uint16_t crc;
+ // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
+ // followed by teh block data
+ // one sub-carrier, inventory, 1 slot, fast rate
+ cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit
+ // READ BLOCK command code
+ cmd[1] = 0x20;
+ // UID may be optionally specified here
+ // 64-bit UID
+ cmd[2] = uid[0];
+ cmd[3] = uid[1];
+ cmd[4] = uid[2];
+ cmd[5] = uid[3];
+ cmd[6] = uid[4];
+ cmd[7] = uid[5];
+ cmd[8] = uid[6];
+ cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
+ // Block number to read
+ cmd[10] = blockNumber;//0x00;
+ //Now the CRC
+ crc = Crc(cmd, 11); // the crc needs to be calculated over 12 bytes
+ cmd[11] = crc & 0xff;
+ cmd[12] = crc >> 8;
+
+ CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+// Now the VICC>VCD responses when we are simulating a tag
+ static void BuildInventoryResponse( uint8_t *uid)
+{
+ uint8_t cmd[12];
+
+ uint16_t crc;
+ // one sub-carrier, inventory, 1 slot, fast rate
+ // AFI is at bit 5 (1<<4) when doing an INVENTORY
+ //(1 << 2) | (1 << 5) | (1 << 1);
+ cmd[0] = 0; //
+ cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
+ // 64-bit UID
+ cmd[2] = uid[7]; //0x32;
+ cmd[3] = uid[6]; //0x4b;
+ cmd[4] = uid[5]; //0x03;
+ cmd[5] = uid[4]; //0x01;
+ cmd[6] = uid[3]; //0x00;
+ cmd[7] = uid[2]; //0x10;
+ cmd[8] = uid[1]; //0x05;
+ cmd[9] = uid[0]; //0xe0;
+ //Now the CRC
+ crc = Crc(cmd, 10);
+ cmd[10] = crc & 0xff;
+ cmd[11] = crc >> 8;
+
+ CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+// Universal Method for sending to and recv bytes from a tag
+// init ... should we initialize the reader?
+// speed ... 0 low speed, 1 hi speed
+// **recv will return you a pointer to the received data
+// If you do not need the answer use NULL for *recv[]
+// return: lenght of received data
+int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv) {
+
+ int samples = 0;
+ int tsamples = 0;
+ int wait = 0;
+ int elapsed = 0;
+
+ LED_A_ON();
+ LED_B_ON();
+ LED_C_OFF();
+ LED_D_OFF();
+
+ if (init) Iso15693InitReader();
+
+ int answerLen=0;
+ uint8_t *answer = BigBuf_get_addr() + 3660;
+ if (recv != NULL) memset(answer, 0, 100);
+
+ if (!speed) {
+ // low speed (1 out of 256)
+ CodeIso15693AsReader256(send, sendlen);
+ } else {
+ // high speed (1 out of 4)
+ CodeIso15693AsReader(send, sendlen);
+ }
+
+ LED_A_ON();
+ LED_B_OFF();
+
+ TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
+ // Now wait for a response
+ if (recv!=NULL) {
+ LED_A_OFF();
+ LED_B_ON();
+ answerLen = GetIso15693AnswerFromTag(answer, 100, &samples, &elapsed) ;
+ *recv=answer;
+ }
+
+ LED_A_OFF();
+ LED_B_OFF();
+ LED_C_OFF();
+ LED_D_OFF();
+
+ return answerLen;
+}
+
+
+// --------------------------------------------------------------------
+// Debug Functions
+// --------------------------------------------------------------------
+
+// Decodes a message from a tag and displays its metadata and content
+#define DBD15STATLEN 48
+void DbdecodeIso15693Answer(int len, uint8_t *d) {
+ char status[DBD15STATLEN+1]={0};
+ uint16_t crc;
+
+ if (len>3) {
+ if (d[0]&(1<<3))
+ strncat(status,"ProtExt ",DBD15STATLEN);
+ if (d[0]&1) {
+ // error
+ strncat(status,"Error ",DBD15STATLEN);
+ switch (d[1]) {
+ case 0x01:
+ strncat(status,"01:notSupp",DBD15STATLEN);
+ break;
+ case 0x02:
+ strncat(status,"02:notRecog",DBD15STATLEN);
+ break;
+ case 0x03:
+ strncat(status,"03:optNotSupp",DBD15STATLEN);
+ break;
+ case 0x0f:
+ strncat(status,"0f:noInfo",DBD15STATLEN);
+ break;
+ case 0x10:
+ strncat(status,"10:dontExist",DBD15STATLEN);
+ break;
+ case 0x11:
+ strncat(status,"11:lockAgain",DBD15STATLEN);
+ break;
+ case 0x12:
+ strncat(status,"12:locked",DBD15STATLEN);
+ break;
+ case 0x13:
+ strncat(status,"13:progErr",DBD15STATLEN);
+ break;
+ case 0x14:
+ strncat(status,"14:lockErr",DBD15STATLEN);
+ break;
+ default:
+ strncat(status,"unknownErr",DBD15STATLEN);
+ }
+ strncat(status," ",DBD15STATLEN);
+ } else {
+ strncat(status,"NoErr ",DBD15STATLEN);
+ }
+
+ crc=Crc(d,len-2);
+ if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
+ strncat(status,"CrcOK",DBD15STATLEN);
+ else
+ strncat(status,"CrcFail!",DBD15STATLEN);
+
+ Dbprintf("%s",status);
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////
+// Functions called via USB/Client
+///////////////////////////////////////////////////////////////////////
+
+void SetDebugIso15693(uint32_t debug) {
+ DEBUG=debug;
+ Dbprintf("Iso15693 Debug is now %s",DEBUG?"on":"off");
+ return;
+}
+
+
+