uint16_t period_0 = periods >> 16;
uint16_t period_1 = periods & 0xFFFF;
- // 95 == 125 KHz 88 == 124.8 KHz
+ // 95 == 125 KHz 88 == 134.8 KHz
int divisor_used = (useHighFreq) ? 88 : 95;
sample_config sc = { 0,0,1, divisor_used, 0};
setSamplingConfig(&sc);
// now do the read
DoAcquisition_config(false);
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
/* blank r/w tag data stream
// if not provided a valid crc will be computed from the data and written.
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
{
- StartTicks();
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if(crc == 0) {
crc = update_crc16(crc, (idlo)&0xff);
// whether we're modulating the antenna (high)
// or listening to the antenna (low)
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
+ StartTicks();
+
LED_A_ON();
-
+
// steal this pin from the SSP and use it to control the modulation
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
// then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)
// finally end with 0x0300 (write frame)
// all data is sent lsb first
- // finish with 15ms programming time
+ // finish with 50ms programming time
// modulate antenna
HIGH(GPIO_SSC_DOUT);
int i = 0;
uint8_t *buf = BigBuf_get_addr();
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
+ //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
//FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
//FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE );
+
+ // set frequency, get values from 'lf config' command
+ sample_config *sc = getSamplingConfig();
+
+ if ( (sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255) )
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+ else if (sc->divisor == 0)
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+ else
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor);
+
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
// power on antenna
- // OPEN_COIL();
- // SpinDelay(50);
+ OPEN_COIL();
+ // charge time
+ WaitMS(50);
for(;;) {
WDT_HIT();
for (i=0; i<size; i++){
askSimBit(BitStream[i]^invert, &n, clk, encoding);
}
- if (encoding==0 && BitStream[0]==BitStream[size-1]){ //run a second set inverted (for biphase phase)
+ if (encoding==0 && BitStream[0]==BitStream[size-1]){ //run a second set inverted (for ask/raw || biphase phase)
for (i=0; i<size; i++){
askSimBit(BitStream[i]^invert^1, &n, clk, encoding);
}
WDT_HIT();
if (ledcontrol) LED_A_ON();
- DoAcquisition_default(-1,true);
+ DoAcquisition_default(0, true);
// FSK demodulator
size = 50*128*2; //big enough to catch 2 sequences of largest format
idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
if (ledcontrol) LED_A_OFF();
*high = hi;
*low = lo;
- goto OUT;
+ break;
}
// reset
}
hi2 = hi = lo = idx = 0;
WDT_HIT();
}
-OUT:
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Stopped");
if (ledcontrol) LED_A_OFF();
break;
}
if (findone)
- goto OUT;
+ break;
idx = 0;
WDT_HIT();
}
-OUT:
+
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Stopped");
if (ledcontrol) LED_A_OFF();
errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
if (errCnt){
- if (size>64){
+ if (size == 128){
Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)",
hi,
(uint32_t)(lo>>32),
if (ledcontrol) LED_A_OFF();
*high=lo>>32;
*low=lo & 0xFFFFFFFF;
- return;
+ break;
}
}
WDT_HIT();
hi = lo = size = idx = 0;
clk = invert = errCnt = 0;
}
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Stopped");
if (ledcontrol) LED_A_OFF();
}
if (ledcontrol) LED_A_OFF();
*high=code;
*low=code2;
- goto OUT;
+ break;
}
code=code2=0;
version=facilitycode=0;
WDT_HIT();
}
-OUT:
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Stopped");
if (ledcontrol) LED_A_OFF();
// Give it a bit of time for the resonant antenna to settle.
WaitUS(delay);
}
+void TurnReadLF_off(uint32_t delay) {
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitUS(delay);
+}
// Write one bit to card
void T55xxWriteBit(int bit) {
// Set up FPGA, 125kHz to power up the tag
LFSetupFPGAForADC(95, true);
- SpinDelay(3);
+ //SpinDelay(3);
// Trigger T55x7 Direct Access Mode with start gap
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
TurnReadLFOn(READ_GAP);
// Acquisition
- doT55x7Acquisition(12000);
+ doT55x7Acquisition(7679);
// Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
data[4] = manchesterEncode2Bytes(hi & 0xFFFF);
data[5] = manchesterEncode2Bytes(lo >> 16);
data[6] = manchesterEncode2Bytes(lo & 0xFFFF);
- } else {
+ } else {
// Ensure no more than 44 bits supplied
if (hi > 0xFFF) {
DbpString("Tags can only have 44 bits.");
data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT;
//TODO add selection of chip for Q5 or T55x7
- // data[0] = (((50-2)/2)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT;
+ // data[0] = (((50-2)>>1)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT;
LED_D_ON();
- // Program the data blocks for supplied ID
- // and the block 0 for HID format
WriteT55xx(data, 0, last_block+1);
-
LED_D_OFF();
-
- DbpString("DONE!");
}
void CopyIOtoT55x7(uint32_t hi, uint32_t lo) {
uint32_t data[] = {T55x7_BITRATE_RF_64 | T55x7_MODULATION_FSK2a | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo};
//TODO add selection of chip for Q5 or T55x7
//t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
- // data[0] = (64 << T5555_BITRATE_SHIFT) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT;
+ // data[0] = ( ((64-2)>>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT;
LED_D_ON();
// Program the data blocks for supplied ID
// and the block 0 config
WriteT55xx(data, 0, 3);
LED_D_OFF();
- DbpString("DONE!");
}
// Clone Indala 64-bit tag by UID to T55x7
// and the Config for Indala 64 format (RF/32;PSK1 with RF/2;Maxblock=2)
uint32_t data[] = { T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo};
//TODO add selection of chip for Q5 or T55x7
- // data[0] = (((32-2)/2)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
+ // data[0] = (((32-2)>>1)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;
WriteT55xx(data, 0, 3);
//Alternative config for Indala (Extended mode;RF/32;PSK1 with RF/2;Maxblock=2;Inverse data)
// T5567WriteBlock(0x603E1042,0);
- DbpString("DONE!");
}
// Clone Indala 224-bit tag by UID to T55x7
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7) {
//Config for Indala (RF/32;PSK1 with RF/2;Maxblock=7)
data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK1 | (7 << T55x7_MAXBLOCK_SHIFT);
//TODO add selection of chip for Q5 or T55x7
- // data[0] = (((32-2)/2)<<T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 7 << T5555_MAXBLOCK_SHIFT;
+ // data[0] = (((32-2)>>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_PSK1 | 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);
- DbpString("DONE!");
}
// clone viking tag to T55xx
void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) {
uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2};
//t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
- if (Q5) data[0] = (32 << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
+ if (Q5) data[0] = (((32-2)>>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT;
// Program the data blocks for supplied ID and the block 0 config
WriteT55xx(data, 0, 3);
LED_D_OFF();
}
data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT);
} else { //t5555 (Q5)
- clock = (clock-2)>>1; //n = (RF-2)/2
- data[0] = (clock << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT);
+ // t5555 (Q5) BITRATE = (RF-2)/2 (iceman)
+ data[0] = ( ((clock-2) >> 1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT);
}
WriteT55xx(data, 0, 3);
//-----------------------------------
// EM4469 / EM4305 routines
//-----------------------------------
-#define FWD_CMD_LOGIN 0xC //including the even parity, binary mirrored
+// Below given command set.
+// Commands are including the even parity, binary mirrored
+#define FWD_CMD_LOGIN 0xC
#define FWD_CMD_WRITE 0xA
#define FWD_CMD_READ 0x9
#define FWD_CMD_DISABLE 0x5
uint8_t i;
line_parity = 0;
- for(i=0;i<6;i++) {
+ for( i=0; i<6; i++ ) {
*forward_ptr++ = addr;
line_parity ^= addr;
addr >>= 1;
//====================================================================
void SendForward(uint8_t fwd_bit_count) {
+// iceman, 21.3us increments for the USclock verification.
+// 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead
+// 32FC * 8us == 256us / 21.3 == 12.018 steps. ok
+// 16FC * 8us == 128us / 21.3 == 6.009 steps. ok
+#ifndef EM_START_GAP
+#define EM_START_GAP 55*8
+#endif
+
fwd_write_ptr = forwardLink_data;
fwd_bit_sz = fwd_bit_count;
- LED_D_ON();
-
// Set up FPGA, 125kHz
LFSetupFPGAForADC(95, true);
// force 1st mod pulse (start gap must be longer for 4305)
fwd_bit_sz--; //prepare next bit modulation
fwd_write_ptr++;
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
- WaitUS(55*8); //55 cycles off (8us each)for 4305 // ICEMAN: problem with (us) clock is 21.3us increments
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
- WaitUS(16*8); //16 cycles on (8us each) // ICEMAN: problem with (us) clock is 21.3us increments
+
+ TurnReadLF_off(EM_START_GAP);
+ TurnReadLFOn(18*8);
- // now start writting
+ // now start writting with bitbanging the antenna.
while(fwd_bit_sz-- > 0) { //prepare next bit modulation
- if(((*fwd_write_ptr++) & 1) == 1)
- WaitUS(32*8); //32 cycles at 125Khz (8us each) // ICEMAN: problem with (us) clock is 21.3us increments
- else {
- //These timings work for 4469/4269/4305 (with the 55*8 above)
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
- WaitUS(16*8); //16-4 cycles off (8us each) // ICEMAN: problem with (us) clock is 21.3us increments
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);//field on
- WaitUS(16*8); //16 cycles on (8us each) // ICEMAN: problem with (us) clock is 21.3us increments
+ if(((*fwd_write_ptr++) & 1) == 1) {
+ WaitUS(32);
+ } else {
+ TurnReadLF_off(23*8);
+ TurnReadLFOn(16*8);
}
}
}
-void EM4xLogin(uint32_t Password) {
-
- uint8_t fwd_bit_count;
+void EM4xLogin(uint32_t pwd) {
+ uint8_t len;
forward_ptr = forwardLink_data;
- fwd_bit_count = Prepare_Cmd( FWD_CMD_LOGIN );
- fwd_bit_count += Prepare_Data( Password&0xFFFF, Password>>16 );
- SendForward(fwd_bit_count);
-
- //Wait for command to complete
- WaitMS(20);
+ len = Prepare_Cmd( FWD_CMD_LOGIN );
+ len += Prepare_Data( pwd & 0xFFFF, pwd >> 16 );
+ SendForward(len);
+ //WaitUS(20); // no wait for login command.
+ // should receive
+ // 0000 1010 ok.
+ // 0000 0001 fail
}
-void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
-
- uint8_t fwd_bit_count;
- uint8_t *dest = BigBuf_get_addr();
- uint16_t bufsize = BigBuf_max_traceLen(); // ICEMAN: this tries to fill up all tracelog space
- uint32_t i = 0;
+void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
- // Clear destination buffer before sending the command
+ LED_A_ON();
+ uint8_t len;
+
+ //clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
- //If password mode do login
- if (PwdMode == 1) EM4xLogin(Pwd);
+ /* should we read answer from Logincommand?
+ *
+ * should receive
+ * 0000 1010 ok.
+ * 0000 0001 fail
+ **/
+ if (usepwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
- fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
- fwd_bit_count += Prepare_Addr( Address );
+ len = Prepare_Cmd( FWD_CMD_READ );
+ len += Prepare_Addr( addr );
- SendForward(fwd_bit_count);
+ SendForward(len);
- // Now do the acquisition
- // ICEMAN, change to the one in lfsampling.c
- i = 0;
- for(;;) {
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
- AT91C_BASE_SSC->SSC_THR = 0x43;
- }
- if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
- dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
- ++i;
- if (i >= bufsize) break;
- }
- }
+ WaitUS(400);
+
+ DoPartialAcquisition(20, true, 6000);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
cmd_send(CMD_ACK,0,0,0,0,0);
- LED_D_OFF();
+ LED_A_OFF();
}
-void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
+void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) {
- uint8_t fwd_bit_count;
+ LED_A_ON();
+
+ bool usePwd = (flag & 0xF);
+ uint8_t addr = (flag >> 8) & 0xFF;
+ uint8_t len;
+
+ //clear buffer now so it does not interfere with timing later
+ BigBuf_Clear_ext(false);
- //If password mode do login
- if (PwdMode == 1) EM4xLogin(Pwd);
+ /* should we read answer from Logincommand?
+ *
+ * should receive
+ * 0000 1010 ok.
+ * 0000 0001 fail
+ **/
+ if (usePwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
- fwd_bit_count = Prepare_Cmd( FWD_CMD_WRITE );
- fwd_bit_count += Prepare_Addr( Address );
- fwd_bit_count += Prepare_Data( Data&0xFFFF, Data>>16 );
+ len = Prepare_Cmd( FWD_CMD_WRITE );
+ len += Prepare_Addr( addr );
+ len += Prepare_Data( data & 0xFFFF, data >> 16 );
+
+ SendForward(len);
- SendForward(fwd_bit_count);
+ //Wait 20ms for write to complete?
+ WaitMS(7);
- //Wait for write to complete
- WaitMS(20);
+ //Capture response if one exists
+ DoPartialAcquisition(20, true, 6000);
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ cmd_send(CMD_ACK,0,0,0,0,0);
+ LED_A_OFF();
+}
+
+/*
+Reading a COTAG.
+
+COTAG needs the reader to send a startsequence and the card has an extreme slow datarate.
+because of this, we can "sample" the data signal but we interpreate it to Manchester direct.
+
+READER START SEQUENCE:
+burst 800 us, gap 2.2 msecs
+burst 3.6 msecs gap 2.2 msecs
+burst 800 us gap 2.2 msecs
+pulse 3.6 msecs
+
+This triggers a COTAG tag to response
+*/
+void Cotag(uint32_t arg0) {
+#ifndef OFF
+# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); }
+#endif
+#ifndef ON
+# define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); }
+#endif
+ uint8_t rawsignal = arg0 & 0xF;
+
+ LED_A_ON();
+
+ // Switching to LF image on FPGA. This might empty BigBuff
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
+ //clear buffer now so it does not interfere with timing later
+ BigBuf_Clear_ext(false);
+
+ // Set up FPGA, 132kHz to power up the tag
+ FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+
+ // Connect the A/D to the peak-detected low-frequency path.
+ SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+ // Now set up the SSC to get the ADC samples that are now streaming at us.
+ FpgaSetupSsc();
+
+ // start clock - 1.5ticks is 1us
+ StartTicks();
+
+ //send COTAG start pulse
+ ON(740) OFF
+ ON(3330) OFF
+ ON(740) OFF
+ ON(1000)
+
+ switch(rawsignal) {
+ case 0: doCotagAcquisition(50000); break;
+ case 1: doCotagAcquisitionManchester(); break;
+ case 2: DoAcquisition_config(TRUE); break;
+ }
+
+ // Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
- LED_D_OFF();
+ cmd_send(CMD_ACK,0,0,0,0,0);
+ LED_A_OFF();
}
+
+/*
+* EM4305 support
+*/