+ hi = lo = size = idx = 0;
+ clk = invert = errCnt = 0;
+ }
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ DbpString("Stopped");
+ if (ledcontrol) LED_A_OFF();
+}
+
+void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
+{
+ uint8_t *dest = BigBuf_get_addr();
+ int idx=0;
+ uint32_t code=0, code2=0;
+ uint8_t version=0;
+ uint8_t facilitycode=0;
+ uint16_t number=0;
+ uint8_t crc = 0;
+ uint16_t calccrc = 0;
+
+ //clear read buffer
+ BigBuf_Clear_keep_EM();
+
+ // Configure to go in 125Khz listen mode
+ LFSetupFPGAForADC(95, true);
+
+ while(!BUTTON_PRESS() && !usb_poll_validate_length()) {
+ WDT_HIT();
+ if (ledcontrol) LED_A_ON();
+ DoAcquisition_default(-1,true);
+ //fskdemod and get start index
+ WDT_HIT();
+ idx = IOdemodFSK(dest, BigBuf_max_traceLen());
+ if (idx<0) continue;
+ //valid tag found
+
+ //Index map
+ //0 10 20 30 40 50 60
+ //| | | | | | |
+ //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
+ //-----------------------------------------------------------------------------
+ //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11
+ //
+ //Checksum:
+ //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11
+ //preamble F0 E0 01 03 B6 75
+ // How to calc checksum,
+ // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6
+ // F0 + E0 + 01 + 03 + B6 = 28A
+ // 28A & FF = 8A
+ // FF - 8A = 75
+ // Checksum: 0x75
+ //XSF(version)facility:codeone+codetwo
+ //Handle the data
+ // if(findone){ //only print binary if we are doing one
+ // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
+ // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
+ // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
+ // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
+ // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
+ // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
+ // Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
+ // }
+ code = bytebits_to_byte(dest+idx,32);
+ code2 = bytebits_to_byte(dest+idx+32,32);
+ version = bytebits_to_byte(dest+idx+27,8); //14,4
+ facilitycode = bytebits_to_byte(dest+idx+18,8);
+ number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
+
+ crc = bytebits_to_byte(dest+idx+54,8);
+ for (uint8_t i=1; i<6; ++i)
+ calccrc += bytebits_to_byte(dest+idx+9*i,8);
+ calccrc &= 0xff;
+ calccrc = 0xff - calccrc;
+
+ char *crcStr = (crc == calccrc) ? "ok":"!crc";
+
+ Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]",version,facilitycode,number,code,code2, crc, crcStr);
+ // if we're only looking for one tag
+ if (findone){
+ if (ledcontrol) LED_A_OFF();
+ *high=code;
+ *low=code2;
+ break;
+ }
+ code=code2=0;
+ version=facilitycode=0;
+ number=0;
+ idx=0;
+
+ WDT_HIT();
+ }
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ DbpString("Stopped");
+ if (ledcontrol) LED_A_OFF();
+}
+
+/*------------------------------
+ * T5555/T5557/T5567/T5577 routines
+ *------------------------------
+ * NOTE: T55x7/T5555 configuration register definitions moved to protocols.h
+ *
+ * Relevant communication times in microsecond
+ * To compensate antenna falling times shorten the write times
+ * and enlarge the gap ones.
+ * Q5 tags seems to have issues when these values changes.
+ */
+
+#define START_GAP 50*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc)
+#define WRITE_GAP 20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc)
+#define WRITE_0 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc)
+#define WRITE_1 54*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550
+#define READ_GAP 15*8
+
+// VALUES TAKEN FROM EM4x function: SendForward
+// START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle)
+// WRITE_GAP = 128; (16*8)
+// WRITE_1 = 256 32*8; (32*8)
+
+// These timings work for 4469/4269/4305 (with the 55*8 above)
+// WRITE_0 = 23*8 , 9*8
+
+// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
+// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
+// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
+// T0 = TIMER_CLOCK1 / 125000 = 192
+// 1 Cycle = 8 microseconds(us) == 1 field clock
+
+// new timer:
+// = 1us = 1.5ticks
+// 1fc = 8us = 12ticks
+void TurnReadLFOn(uint32_t delay) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+
+ // measure antenna strength.
+ //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
+
+ // Give it a bit of time for the resonant antenna to settle.
+ WaitUS(delay);
+}
+
+// Write one bit to card
+void T55xxWriteBit(int bit) {
+ if (!bit)
+ TurnReadLFOn(WRITE_0);
+ else
+ TurnReadLFOn(WRITE_1);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(WRITE_GAP);
+}
+
+// Send T5577 reset command then read stream (see if we can identify the start of the stream)
+void T55xxResetRead(void) {
+ LED_A_ON();
+ //clear buffer now so it does not interfere with timing later
+ BigBuf_Clear_keep_EM();
+
+ // Set up FPGA, 125kHz
+ LFSetupFPGAForADC(95, true);
+
+ // Trigger T55x7 in mode.
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(START_GAP);
+
+ // reset tag - op code 00
+ T55xxWriteBit(0);
+ T55xxWriteBit(0);
+
+ // Turn field on to read the response
+ TurnReadLFOn(READ_GAP);
+
+ // Acquisition
+ doT55x7Acquisition(BigBuf_max_traceLen());
+
+ // Turn the field off
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
+ cmd_send(CMD_ACK,0,0,0,0,0);
+ LED_A_OFF();
+}
+
+// Write one card block in page 0, no lock
+void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) {
+ LED_A_ON();
+ bool PwdMode = arg & 0x1;
+ uint8_t Page = (arg & 0x2)>>1;
+ uint32_t i = 0;
+
+ // Set up FPGA, 125kHz
+ LFSetupFPGAForADC(95, true);
+
+ // Trigger T55x7 in mode.
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(START_GAP);
+
+ // Opcode 10
+ T55xxWriteBit(1);
+ T55xxWriteBit(Page); //Page 0
+ if (PwdMode){
+ // Send Pwd
+ for (i = 0x80000000; i != 0; i >>= 1)
+ T55xxWriteBit(Pwd & i);
+ }
+ // Send Lock bit
+ T55xxWriteBit(0);
+
+ // Send Data
+ for (i = 0x80000000; i != 0; i >>= 1)
+ T55xxWriteBit(Data & i);
+
+ // Send Block number
+ for (i = 0x04; i != 0; i >>= 1)
+ T55xxWriteBit(Block & i);
+
+ // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550,
+ // so wait a little more)
+ TurnReadLFOn(20 * 1000);
+
+ //could attempt to do a read to confirm write took
+ // as the tag should repeat back the new block
+ // until it is reset, but to confirm it we would
+ // need to know the current block 0 config mode
+
+ // turn field off
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LED_A_OFF();
+}
+
+// Write one card block in page 0, no lock
+void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) {
+ T55xxWriteBlockExt(Data, Block, Pwd, arg);
+ cmd_send(CMD_ACK,0,0,0,0,0);
+}
+
+// Read one card block in page [page]
+void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) {
+ LED_A_ON();
+ bool PwdMode = arg0 & 0x1;
+ uint8_t Page = (arg0 & 0x2) >> 1;
+ uint32_t i = 0;
+ bool RegReadMode = (Block == 0xFF);
+
+ //clear buffer now so it does not interfere with timing later
+ BigBuf_Clear_keep_EM();
+
+ //make sure block is at max 7
+ Block &= 0x7;
+
+ // Set up FPGA, 125kHz to power up the tag
+ LFSetupFPGAForADC(95, true);
+ //SpinDelay(3);
+
+ // Trigger T55x7 Direct Access Mode with start gap
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(START_GAP);
+
+ // Opcode 1[page]
+ T55xxWriteBit(1);
+ T55xxWriteBit(Page); //Page 0
+
+ if (PwdMode){
+ // Send Pwd
+ for (i = 0x80000000; i != 0; i >>= 1)
+ T55xxWriteBit(Pwd & i);
+ }
+ // Send a zero bit separation
+ T55xxWriteBit(0);
+
+ // Send Block number (if direct access mode)
+ if (!RegReadMode)
+ for (i = 0x04; i != 0; i >>= 1)
+ T55xxWriteBit(Block & i);
+
+ // Turn field on to read the response
+ TurnReadLFOn(READ_GAP);
+
+ // Acquisition
+ doT55x7Acquisition(7679);
+
+ // Turn the field off
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
+ cmd_send(CMD_ACK,0,0,0,0,0);
+ LED_A_OFF();
+}
+
+void T55xxWakeUp(uint32_t Pwd){
+ LED_B_ON();
+ uint32_t i = 0;
+
+ // Set up FPGA, 125kHz
+ LFSetupFPGAForADC(95, true);
+
+ // Trigger T55x7 Direct Access Mode
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(START_GAP);
+
+ // Opcode 10
+ T55xxWriteBit(1);
+ T55xxWriteBit(0); //Page 0
+
+ // Send Pwd
+ for (i = 0x80000000; i != 0; i >>= 1)
+ T55xxWriteBit(Pwd & i);
+
+ // Turn and leave field on to let the begin repeating transmission
+ TurnReadLFOn(20*1000);
+}
+
+/*-------------- Cloning routines -----------*/
+void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) {
+ // write last block first and config block last (if included)
+ for (uint8_t i = numblocks+startblock; i > startblock; i--)
+ T55xxWriteBlockExt(blockdata[i-1], i-1, 0, 0);
+}
+
+// Copy HID id to card and setup block 0 config
+void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) {
+ uint32_t data[] = {0,0,0,0,0,0,0};
+ uint8_t last_block = 0;
+
+ if (longFMT){
+ // Ensure no more than 84 bits supplied
+ if (hi2 > 0xFFFFF) {
+ DbpString("Tags can only have 84 bits.");
+ return;
+ }
+ // Build the 6 data blocks for supplied 84bit ID
+ last_block = 6;
+ // load preamble (1D) & long format identifier (9E manchester encoded)
+ data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF);
+ // load raw id from hi2, hi, lo to data blocks (manchester encoded)
+ data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF);
+ data[3] = manchesterEncode2Bytes(hi >> 16);
+ data[4] = manchesterEncode2Bytes(hi & 0xFFFF);
+ data[5] = manchesterEncode2Bytes(lo >> 16);
+ data[6] = manchesterEncode2Bytes(lo & 0xFFFF);
+ } else {
+ // Ensure no more than 44 bits supplied
+ if (hi > 0xFFF) {
+ DbpString("Tags can only have 44 bits.");
+ return;
+ }
+ // Build the 3 data blocks for supplied 44bit ID
+ last_block = 3;
+ // load preamble
+ data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF);
+ data[2] = manchesterEncode2Bytes(lo >> 16);
+ data[3] = manchesterEncode2Bytes(lo & 0xFFFF);