//----------------------------------------------------------------------------- // Miscellaneous routines for low frequency tag operations. // Tags supported here so far are Texas Instruments (TI), HID // Also routines for raw mode reading/simulating of LF waveform // //----------------------------------------------------------------------------- #include #include "apps.h" #include "../common/crc16.c" void AcquireRawAdcSamples125k(BOOL at134khz) { if(at134khz) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } else { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Give it a bit of time for the resonant antenna to settle. SpinDelay(50); // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); // Now call the acquisition routine DoAcquisition125k(at134khz); } // split into two routines so we can avoid timing issues after sending commands // void DoAcquisition125k(BOOL at134khz) { BYTE *dest = (BYTE *)BigBuf; int n = sizeof(BigBuf); int i; memset(dest,0,n); i = 0; for(;;) { if(SSC_STATUS & (SSC_STATUS_TX_READY)) { SSC_TRANSMIT_HOLDING = 0x43; LED_D_ON(); } if(SSC_STATUS & (SSC_STATUS_RX_READY)) { dest[i] = (BYTE)SSC_RECEIVE_HOLDING; i++; LED_D_OFF(); if(i >= n) { break; } } } DbpIntegers(dest[0], dest[1], at134khz); } void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command) { BOOL at134khz; // see if 'h' was specified if(command[strlen((char *) command) - 1] == 'h') at134khz= TRUE; else at134khz= FALSE; if(at134khz) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } else { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } // Give it a bit of time for the resonant antenna to settle. SpinDelay(50); // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); // now modulate the reader field while(*command != '\0' && *command != ' ') { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); if(at134khz) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } else { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } LED_D_ON(); if(*(command++) == '0') SpinDelayUs(period_0); else SpinDelayUs(period_1); } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); if(at134khz) { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } else { FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); } // now do the read DoAcquisition125k(at134khz); } void AcquireTiType(void) { int i; // tag transmission is <20ms, sampling at 2M gives us 40K samples max // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS int n = 1250; // clear buffer DbpIntegers((DWORD)BigBuf, sizeof(BigBuf), 0x12345678); memset(BigBuf,0,sizeof(BigBuf)); // Set up the synchronous serial port PIO_DISABLE = (1<= n) return; } WDT_HIT(); } // return stolen pin to SSP PIO_DISABLE = (1<>8)&0xff); crc = update_crc16(crc, (idlo>>16)&0xff); crc = update_crc16(crc, (idlo>>24)&0xff); crc = update_crc16(crc, (idhi)&0xff); crc = update_crc16(crc, (idhi>>8)&0xff); crc = update_crc16(crc, (idhi>>16)&0xff); crc = update_crc16(crc, (idhi>>24)&0xff); } DbpString("Writing the following data to tag:"); DbpIntegers(idhi, idlo, crc); // TI tags charge at 134.2Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz // Place FPGA in passthrough mode, in this mode the CROSS_LO line // connects to SSP_DIN and the SSP_DOUT logic level controls // whether we're modulating the antenna (high) // or listening to the antenna (low) FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); LED_A_ON(); // steal this pin from the SSP and use it to control the modulation PIO_ENABLE = (1<>8 )&0xff ); WriteTIbyte( (idlo>>16)&0xff ); WriteTIbyte( (idlo>>24)&0xff ); WriteTIbyte( (idhi )&0xff ); WriteTIbyte( (idhi>>8 )&0xff ); WriteTIbyte( (idhi>>16)&0xff ); WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo WriteTIbyte( (crc )&0xff ); // crc lo WriteTIbyte( (crc>>8 )&0xff ); // crc hi WriteTIbyte(0x00); // write frame lo WriteTIbyte(0x03); // write frame hi PIO_OUTPUT_DATA_SET = (1<0xFFF) { DbpString("Tags can only have 44 bits."); return; } fc(0,&n); // special start of frame marker containing invalid bit sequences fc(8, &n); fc(8, &n); // invalid fc(8, &n); fc(10, &n); // logical 0 fc(10, &n); fc(10, &n); // invalid fc(8, &n); fc(10, &n); // logical 0 WDT_HIT(); // manchester encode bits 43 to 32 for (i=11; i>=0; i--) { if ((i%4)==3) fc(0,&n); if ((hi>>i)&1) { fc(10, &n); fc(8, &n); // low-high transition } else { fc(8, &n); fc(10, &n); // high-low transition } } WDT_HIT(); // manchester encode bits 31 to 0 for (i=31; i>=0; i--) { if ((i%4)==3) fc(0,&n); if ((lo>>i)&1) { fc(10, &n); fc(8, &n); // low-high transition } else { fc(8, &n); fc(10, &n); // high-low transition } } if (ledcontrol) LED_A_ON(); SimulateTagLowFrequency(n, ledcontrol); if (ledcontrol) LED_A_OFF(); } // loop to capture raw HID waveform then FSK demodulate the TAG ID from it void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) { BYTE *dest = (BYTE *)BigBuf; int m=0, n=0, i=0, idx=0, found=0, lastval=0; DWORD hi=0, lo=0; FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); // Connect the A/D to the peak-detected low-frequency path. SetAdcMuxFor(GPIO_MUXSEL_LOPKD); // Give it a bit of time for the resonant antenna to settle. SpinDelay(50); // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); for(;;) { WDT_HIT(); if (ledcontrol) LED_A_ON(); if(BUTTON_PRESS()) { DbpString("Stopped"); if (ledcontrol) LED_A_OFF(); return; } i = 0; m = sizeof(BigBuf); memset(dest,128,m); for(;;) { if(SSC_STATUS & (SSC_STATUS_TX_READY)) { SSC_TRANSMIT_HOLDING = 0x43; if (ledcontrol) LED_D_ON(); } if(SSC_STATUS & (SSC_STATUS_RX_READY)) { dest[i] = (BYTE)SSC_RECEIVE_HOLDING; // we don't care about actual value, only if it's more or less than a // threshold essentially we capture zero crossings for later analysis if(dest[i] < 127) dest[i] = 0; else dest[i] = 1; i++; if (ledcontrol) LED_D_OFF(); if(i >= m) { break; } } } // FSK demodulator // sync to first lo-hi transition for( idx=1; idx>1)&0xffff); /* if we're only looking for one tag */ if (findone) { *high = hi; *low = lo; return; } hi=0; lo=0; found=0; } } if (found) { if (dest[idx] && (!dest[idx+1]) ) { hi=(hi<<1)|(lo>>31); lo=(lo<<1)|0; } else if ( (!dest[idx]) && dest[idx+1]) { hi=(hi<<1)|(lo>>31); lo=(lo<<1)|1; } else { found=0; hi=0; lo=0; } idx++; } if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) ) { found=1; idx+=6; if (found && (hi|lo)) { DbpString("TAG ID"); DbpIntegers(hi, lo, (lo>>1)&0xffff); /* if we're only looking for one tag */ if (findone) { *high = hi; *low = lo; return; } hi=0; lo=0; found=0; } } } WDT_HIT(); } }