// HDX reads data in Half Duplex mode // first we energise the TAG for long enough that it charges up // then we use sniffer to read response // each bit is 16 ticks, a 1 is 124.2 KHz and a 0 is 134.2 KHz // activation frequency is 134.2 KHz (745 FCs)) BOOL hdx_get_uid(BYTE *response) { BYTE i; BYTE tmp[HDX_DATABITS]; // this is a work in progress, so until reading produces any data, return empty return FALSE; // energise tag & wait for wakeup period InitHWReaderClock(OC_TOGGLE_PULSE, 745 / 2L, 745, RWD_STATE_ACTIVE); Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); // switch off clock and switch to sniffer mode detect_init(); // read to temporary array for speed for(i= 0 ; i < HDX_DATABITS ; ++i) tmp[i]= read_external_clock_burst(16) / 1000L; // convert to binary based on freq +- 3 for(i= 0 ; i < HDX_DATABITS ; ++i) { if (tmp[i] >= 122 && tmp[i] <= 128) tmp[i]= 0x01; else if (tmp[i] >= 129 && tmp[i] <= 135) tmp[i]= 0x00; else return FALSE; } binarraytohex(response, tmp, HDX_DATABITS); return TRUE; }
// this routine accepts either binary arrays or binary strings BOOL rwd_send(unsigned char *command, unsigned int length, BOOL reset, BOOL block, BYTE initial_state, unsigned int fc, unsigned int sleep, unsigned int wake, unsigned int pw0, unsigned int pw1, unsigned int gap, unsigned int post_wait) { unsigned int i; RWD_Fc= fc; // convert FCs to OCM ticks RWD_Sleep_Period= sleep * 2; RWD_Wake_Period= wake * 2; RWD_Zero_Period= pw0 * 2; RWD_One_Period= pw1 * 2; RWD_Gap_Period= gap * 2; RWD_Post_Wait= post_wait * 2; if(!RWD_Zero_Period || !RWD_One_Period || !RWD_Gap_Period) return FALSE; // convert ascii string to bin if required if(command[0] == '0' || command[0] == '1') { if(!binstringtobinarray(RWD_Command_Buff, command)) return FALSE; } else memcpy(RWD_Command_Buff, command, length); RWD_Command_Buff[length]= '*'; RWD_Command_ThisBit= RWD_Command_Buff; // start clock and wait for TAG to wake if not already running // this is needed in case a non-resetting RWD command is issued before any other action has woken tag if(mGetLED_Clock() == mLED_OFF) { RWD_State= RWD_STATE_INACTIVE; InitHWReaderClock(OC_TOGGLE_PULSE, RWD_Fc / 2L, RWD_Fc, RWD_State); if(!reset) Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } if(reset) RWD_State= RWD_STATE_GO_TO_SLEEP; else RWD_State= initial_state; // see if ISR has flagged RWD command finished if(block) while(RWD_State != RWD_STATE_ACTIVE) ; return TRUE; }
void read_PSK1_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us, unsigned int min_pulse_us) { // point globals at data for ISR EMU_Data= data; HW_Bits= bits; PSK_Min_Pulse= min_pulse_us; PSK_Read_Error= FALSE; memset(EMU_Data, '\0', bits); // stop USB interfering USBMaskInterrupts(); // start clock if not already running if(!mGetLED_Clock() == mLED_ON) { InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE); // give reader time to wake up and settle Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } // reset timer for timeout GetTimer_us(RESET); // align ourselves to reader's bit period by finding start of a pulse while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return; while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return; // reset timer for external timeouts GetTimer_us(RESET); // start ISR to read PSK data InitHWReaderISR(CONVERT_TO_TICKS(period) * ticks - 1L, TRUE); }
// h/w clock reader - initialise data pointers for ISR and start timers // timer2 creates clock output for external reader // timer4 reads data bit values // period_us == clock for reader // ticks == clock periods per bit // bits == number of bits to read // oneshot must be set if we are reading data in response to RWD, so no repeating stream BOOL read_ASK_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us, BOOL oneshot) { unsigned long dwell, time; BYTE count; Manchester_Error= FALSE; // if we're manchester or bi-phase encoding, we want to clock twice as fast so we can read both halves of the bit if(RFIDlerConfig.Manchester || RFIDlerConfig.BiPhase) { ticks /= 2; HW_Bits= (unsigned long) bits * 2; } else HW_Bits= (unsigned long) bits; // point globals at data for ISR EMU_Data= data; memset(EMU_Data, '\0', bits); // stop USB interfering USBMaskInterrupts(); // start clock if not already running if(!mGetLED_Clock() == mLED_ON) { InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE); // give reader time to wake up and settle Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } // align ourselves to reader's bit period by waiting until the end of a pulse GetTimer_us(RESET); count= READER_DATA; while(count == READER_DATA) if(GetTimer_us(NO_RESET) > timeout_us) return FALSE; // convert to ticks period= CONVERT_TO_TICKS(period); // biphase cannot auto-align when it detects a half-bit error, so we must align // on a full bit before we start if(!oneshot && RFIDlerConfig.BiPhase) { dwell= period * ticks * 2; count= 0; while((time= get_reader_gap(timeout_us))) { if(!time || count == 255) return; else if(approx(time, dwell, 10)) break; ++count; } } // wait for half the bit period so we sample mid-tick, not just as bit is toggling dwell= ((period * ticks) / 2L); GetTimer_ticks(RESET); //DEBUG_PIN_2= HIGH; while(GetTimer_ticks(NO_RESET) < dwell) ; // reset timer for external timeouts GetTimer_us(RESET); //DEBUG_PIN_2= LOW; // re-start reader ISR to read this bit if required InitHWReaderISR(period * ticks - 1L, TRUE); return TRUE; }
BOOL read_FSK_HW_clock(unsigned int period, unsigned int ticks, BYTE *data, unsigned int bits, unsigned int timeout_us) { unsigned int gaplength; // point globals at data for ISR EMU_Data= data; HW_Bits= bits; memset(EMU_Data, '\0', bits); // stop USB interfering USBMaskInterrupts(); // start clock if not already running if(!mGetLED_Clock() == mLED_ON) { InitHWReaderClock(OC_TOGGLE_PULSE, period / 2L, period, RWD_STATE_ACTIVE); // give reader time to wake up and settle Delay_us((RFIDlerConfig.FrameClock * RFIDlerConfig.RWD_Wake_Period) / 100); } // reset timer for timeout GetTimer_us(RESET); // align ourselves to reader's bit period by finding the end of a pulse train. // we can do this by measuring the gaps. when they become significantly different // sized (more than 25%), we have just switched frequency. // find the start of a pulse while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; // reset timer so we can meausure gap period GetTimer_us(RESET); while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; gaplength= GetTimer_us(RESET); // now look for a gap that doesn't match while(42) { while(READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; GetTimer_us(TRUE); while(!READER_DATA) if(timeout_us) if (GetTimer_us(NO_RESET) > timeout_us) return FALSE; if(!approx(GetTimer_us(NO_RESET), gaplength, FSK_TOLERANCE)) break; } // reset timer for external timeouts GetTimer_us(RESET); // start ISR to read FSK data InitHWReaderISR(CONVERT_TO_TICKS(period) * ticks - 1L, TRUE); return TRUE; }