// the license.
//-----------------------------------------------------------------------------
// Miscellaneous routines for low frequency tag operations.
-// Tags supported here so far are Texas Instruments (TI), HID
+// Tags supported here so far are Texas Instruments (TI), HID, EM4x05, EM410x
// Also routines for raw mode reading/simulating of LF waveform
//-----------------------------------------------------------------------------
*/
void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command)
{
+ // start timer
+ StartTicks();
- int divisor_used = 95; // 125 KHz
- // see if 'h' was specified
-
- if (command[strlen((char *) command) - 1] == 'h')
- divisor_used = 88; // 134.8 KHz
-
- sample_config sc = { 0,0,1, divisor_used, 0};
- setSamplingConfig(&sc);
- //clear read buffer
- BigBuf_Clear_keep_EM();
+ // use lf config settings
+ sample_config *sc = getSamplingConfig();
- /* Make sure the tag is reset */
+ // Make sure the tag is reset
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- SpinDelay(2500);
+ WaitMS(2500);
- LFSetupFPGAForADC(sc.divisor, 1);
+ // clear read buffer (after fpga bitstream loaded...)
+ BigBuf_Clear_keep_EM();
- // And a little more time for the tag to fully power up
- SpinDelay(2000);
+ // power on
+ LFSetupFPGAForADC(sc->divisor, 1);
+ // And a little more time for the tag to fully power up
+ WaitMS(2000);
+ // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods.
+ bool bitbang = delay_off == 0;
// now modulate the reader field
- while(*command != '\0' && *command != ' ') {
+
+ if (bitbang) {
+ // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly...
+ uint8_t hack_cnt = 7;
+ if (period_0 < hack_cnt || period_1 < hack_cnt) {
+ DbpString("Warning periods cannot be less than 7us in bit bang mode");
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LED_D_OFF();
+ return;
+ }
+
+ // hack2 needed--- it appears to take about 8-16us to turn the antenna back on
+ // leading to ~ 1 to 2 125khz samples extra in every off period
+ // so we should test for last 0 before next 1 and reduce period_0 by this extra amount...
+ // but is this time different for every antenna or other hw builds??? more testing needed
+
+ // prime cmd_len to save time comparing strings while modulating
+ int cmd_len = 0;
+ while(command[cmd_len] != '\0' && command[cmd_len] != ' ')
+ cmd_len++;
+
+ int counter = 0;
+ bool off = false;
+ for (counter = 0; counter < cmd_len; counter++) {
+ // if cmd = 0 then turn field off
+ if (command[counter] == '0') {
+ // if field already off leave alone (affects timing otherwise)
+ if (off == false) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LED_D_OFF();
+ off = true;
+ }
+ // note we appear to take about 7us to switch over (or run the if statements/loop...)
+ WaitUS(period_0-hack_cnt);
+ // else if cmd = 1 then turn field on
+ } else {
+ // if field already on leave alone (affects timing otherwise)
+ if (off) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+ LED_D_ON();
+ off = false;
+ }
+ // note we appear to take about 7us to switch over (or run the if statements/loop...)
+ WaitUS(period_1-hack_cnt);
+ }
+ }
+ } else { // old mode of cmd read using delay as off period
+ while(*command != '\0' && *command != ' ') {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LED_D_OFF();
+ WaitUS(delay_off);
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+ LED_D_ON();
+ if(*(command++) == '0') {
+ WaitUS(period_0);
+ } else {
+ WaitUS(period_1);
+ }
+ }
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF();
- SpinDelayUs(delay_off);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
- LED_D_ON();
- if(*(command++) == '0')
- SpinDelayUs(period_0);
- else
- SpinDelayUs(period_1);
+ WaitUS(delay_off);
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
}
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LED_D_OFF();
- SpinDelayUs(delay_off);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc.divisor);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
// now do the read
- DoAcquisition_config(false);
+ DoAcquisition_config(false, 0);
+
+ // Turn off antenna
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ // tell client we are done
+ cmd_send(CMD_ACK,0,0,0,0,0);
}
/* blank r/w tag data stream
int i;
uint8_t *tab = BigBuf_get_addr();
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+ //note FpgaDownloadAndGo destroys the bigbuf so be sure this is called before now...
+ //FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
i = 0;
for(;;) {
//wait until SSC_CLK goes HIGH
+ int ii = 0;
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
- if(BUTTON_PRESS() || (usb_poll_validate_length() )) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- DbpString("Stopped");
- return;
+ //only check every 1000th time (usb_poll_validate_length on some systems was too slow)
+ if ( ii == 1000 ) {
+ if (BUTTON_PRESS() || usb_poll_validate_length() ) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ DbpString("Stopped");
+ return;
+ }
+ ii=0;
}
WDT_HIT();
+ ii++;
}
if (ledcontrol)
LED_D_ON();
if (ledcontrol)
LED_D_OFF();
+ ii=0;
//wait until SSC_CLK goes LOW
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
- if(BUTTON_PRESS() || (usb_poll_validate_length() )) {
- DbpString("Stopped");
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- return;
+ //only check every 1000th time (usb_poll_validate_length on some systems was too slow)
+ if ( ii == 1000 ) {
+ if (BUTTON_PRESS() || usb_poll_validate_length() ) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ DbpString("Stopped");
+ return;
+ }
+ ii=0;
}
WDT_HIT();
+ ii++;
}
i++;
DbpString("Tags can only have 44 bits. - USE lf simfsk for larger tags");
return;
}
+ // set LF so we don't kill the bigbuf we are setting with simulation data.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
fc(0,&n);
// special start of frame marker containing invalid bit sequences
fc(8, &n); fc(8, &n); // invalid
uint8_t clk = arg2 & 0xFF;
uint8_t invert = (arg2 >> 8) & 1;
+ // set LF so we don't kill the bigbuf we are setting with simulation data.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
for (i=0; i<size; i++){
if (BitStream[i] == invert){
fcAll(fcLow, &n, clk, &modCnt);
uint8_t separator = arg2 & 1;
uint8_t invert = (arg2 >> 8) & 1;
+ // set LF so we don't kill the bigbuf we are setting with simulation data.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
if (encoding==2){ //biphase
uint8_t phase=0;
for (i=0; i<size; i++){
uint8_t carrier = arg1 & 0xFF;
uint8_t invert = arg2 & 0xFF;
uint8_t curPhase = 0;
+ // set LF so we don't kill the bigbuf we are setting with simulation data.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
for (i=0; i<size; i++){
if (BitStream[i] == curPhase){
pskSimBit(carrier, &n, clk, &curPhase, FALSE);
size_t size;
uint32_t hi2=0, hi=0, lo=0;
int idx=0;
+ int dummyIdx = 0;
// Configure to go in 125Khz listen mode
LFSetupFPGAForADC(95, true);
// FSK demodulator
//size = sizeOfBigBuff; //variable size will change after demod so re initialize it before use
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, &dummyIdx);
if (idx>0 && lo>0 && (size==96 || size==192)){
// go over previously decoded manchester data and decode into usable tag ID
{
uint8_t *dest = BigBuf_get_addr();
size_t size;
- int idx=0;
+ int idx=0, dummyIdx=0;
//clear read buffer
BigBuf_Clear_keep_EM();
// Configure to go in 125Khz listen mode
DoAcquisition_default(-1,true);
// FSK demodulator
size = 50*128*2; //big enough to catch 2 sequences of largest format
- idx = AWIDdemodFSK(dest, &size);
+ idx = AWIDdemodFSK(dest, &size, &dummyIdx);
if (idx<=0 || size!=96) continue;
// Index map
uint8_t version=0;
uint8_t facilitycode=0;
uint16_t number=0;
+ int dummyIdx=0;
//clear read buffer
BigBuf_Clear_keep_EM();
// Configure to go in 125Khz listen mode
DoAcquisition_default(-1,true);
//fskdemod and get start index
WDT_HIT();
- idx = IOdemodFSK(dest, BigBuf_max_traceLen());
+ idx = IOdemodFSK(dest, BigBuf_max_traceLen(), &dummyIdx);
if (idx<0) continue;
//valid tag found
TurnReadLFOn(READ_GAP);
// Acquisition
- DoPartialAcquisition(0, true, BigBuf_max_traceLen());
+ DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0);
// Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
// Acquisition
// Now do the acquisition
- DoPartialAcquisition(0, true, 12000);
+ DoPartialAcquisition(0, true, 12000, 0);
// Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
//Program the 7 data blocks for supplied 224bit UID
uint32_t data[] = {0, uid1, uid2, uid3, uid4, uid5, uid6, uid7};
// and the block 0 for Indala224 format
- //Config for Indala (RF/32;PSK1 with RF/2;Maxblock=7)
- data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (7 << T55x7_MAXBLOCK_SHIFT);
+ //Config for Indala (RF/32;PSK2 with RF/2;Maxblock=7)
+ data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT);
//TODO add selection of chip for Q5 or T55x7
- // data[0] = (((32-2)>>1)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 7 << T5555_MAXBLOCK_SHIFT;
+ // data[0] = (((32-2)>>1)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK2 | 7 << T5555_MAXBLOCK_SHIFT;
WriteT55xx(data, 0, 8);
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=7;Inverse data)
// T5567WriteBlock(0x603E10E2,0);
SendForward(fwd_bit_count);
WaitUS(400);
// Now do the acquisition
- DoPartialAcquisition(20, true, 6000);
+ DoPartialAcquisition(20, true, 6000, 1000);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_A_OFF();
WaitUS(6500);
//Capture response if one exists
- DoPartialAcquisition(20, true, 6000);
+ DoPartialAcquisition(20, true, 6000, 1000);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
LED_A_OFF();
switch(rawsignal) {
case 0: doCotagAcquisition(50000); break;
case 1: doCotagAcquisitionManchester(); break;
- case 2: DoAcquisition_config(TRUE); break;
+ case 2: DoAcquisition_config(true, 0); break;
}
// Turn the field off