-#if DEBUG_RA_VALUES || DEBUG_FRAME_CONTENTS
- int i = 0;
-#endif
- char frame[10];
- int frame_pos=0;
-
- DbpString("Starting Hitag2 emulator, press button to end");
- hitag2_init();
-
- /* Set up simulator mode, frequency divisor which will drive the FPGA
- * and analog mux selection.
- */
- FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
- FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
- SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
- RELAY_OFF();
-
- /* Set up Timer 1:
- * Capture mode, timer source MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
- * external trigger rising edge, load RA on rising edge of TIOA, load RB on rising
- * edge of TIOA. Assign PA15 to TIOA1 (peripheral B)
- */
-
- AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
- AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
- AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK |
- AT91C_TC_ETRGEDG_RISING |
- AT91C_TC_ABETRG |
- AT91C_TC_LDRA_RISING |
- AT91C_TC_LDRB_RISING;
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN |
- AT91C_TC_SWTRG;
-
- /* calculate the new value for the carrier period in terms of TC1 values */
- t0 = t0/2;
-
- int overflow = 0;
- while(!BUTTON_PRESS()) {
- WDT_HIT();
- if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
- int ra = AT91C_BASE_TC1->TC_RA;
- if((ra > t0*HITAG_T_EOF) | overflow) ra = t0*HITAG_T_EOF+1;
-#if DEBUG_RA_VALUES
- if(ra > 255 || overflow) ra = 255;
- ((char*)BigBuf)[i] = ra;
- i = (i+1) % 8000;
-#endif
-
- if(overflow || (ra > t0*HITAG_T_EOF) || (ra < t0*HITAG_T_0_MIN)) {
- /* Ignore */
- } else if(ra >= t0*HITAG_T_1_MIN ) {
- /* '1' bit */
- if(frame_pos < 8*sizeof(frame)) {
- frame[frame_pos / 8] |= 1<<( 7-(frame_pos%8) );
- frame_pos++;
- }
- } else if(ra >= t0*HITAG_T_0_MIN) {
- /* '0' bit */
- if(frame_pos < 8*sizeof(frame)) {
- frame[frame_pos / 8] |= 0<<( 7-(frame_pos%8) );
- frame_pos++;
- }
- }
-
- overflow = 0;
- LED_D_ON();
- } else {
- if(AT91C_BASE_TC1->TC_CV > t0*HITAG_T_EOF) {
- /* Minor nuisance: In Capture mode, the timer can not be
- * stopped by a Compare C. There's no way to stop the clock
- * in software, so we'll just have to note the fact that an
- * overflow happened and the next loaded timer value might
- * have wrapped. Also, this marks the end of frame, and the
- * still running counter can be used to determine the correct
- * time for the start of the reply.
- */
- overflow = 1;
-
- if(frame_pos > 0) {
- /* Have a frame, do something with it */
-#if DEBUG_FRAME_CONTENTS
- ((char*)BigBuf)[i++] = frame_pos;
- memcpy( ((char*)BigBuf)+i, frame, 7);
- i+=7;
- i = i % sizeof(BigBuf);
-#endif
- hitag_handle_frame(t0, frame_pos, frame);
- memset(frame, 0, sizeof(frame));
- }
- frame_pos = 0;
-
- }
- LED_D_OFF();
- }
- }
- DbpString("All done");
-}
-
-static void hitag_send_bit(int t0, int bit) {
- if(bit == 1) {
- /* Manchester: Loaded, then unloaded */
- LED_A_ON();
- SHORT_COIL();
- while(AT91C_BASE_TC1->TC_CV < t0*15);
- OPEN_COIL();
- while(AT91C_BASE_TC1->TC_CV < t0*31);
- LED_A_OFF();
- } else if(bit == 0) {
- /* Manchester: Unloaded, then loaded */
- LED_B_ON();
- OPEN_COIL();
- while(AT91C_BASE_TC1->TC_CV < t0*15);
- SHORT_COIL();
- while(AT91C_BASE_TC1->TC_CV < t0*31);
- LED_B_OFF();
- }
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset clock for the next bit */
-
-}
-static void hitag_send_frame(int t0, int frame_len, const char const * frame, int fdt)
-{
- OPEN_COIL();
- AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
-
- /* Wait for HITAG_T_WRESP carrier periods after the last reader bit,
- * not that since the clock counts since the rising edge, but T_wresp is
- * with respect to the falling edge, we need to wait actually (T_wresp - T_g)
- * periods. The gap time T_g varies (4..10).
- */
- while(AT91C_BASE_TC1->TC_CV < t0*(fdt-8));
-
- int saved_cmr = AT91C_BASE_TC1->TC_CMR;
- AT91C_BASE_TC1->TC_CMR &= ~AT91C_TC_ETRGEDG; /* Disable external trigger for the clock */
- AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset the clock and use it for response timing */
-
- int i;
- for(i=0; i<5; i++)
- hitag_send_bit(t0, 1); /* Start of frame */
-
- for(i=0; i<frame_len; i++) {
- hitag_send_bit(t0, !!(frame[i/ 8] & (1<<( 7-(i%8) ))) );
- }
-
- OPEN_COIL();
- AT91C_BASE_TC1->TC_CMR = saved_cmr;
-}
-
-/* Callback structure to cleanly separate tag emulation code from the radio layer. */
-static int hitag_cb(const char* response_data, const int response_length, const int fdt, void *cb_cookie)
-{
- hitag_send_frame(*(int*)cb_cookie, response_length, response_data, fdt);
- return 0;
-}
-/* Frame length in bits, frame contents in MSBit first format */
-static void hitag_handle_frame(int t0, int frame_len, char *frame)
-{
- hitag2_handle_command(frame, frame_len, hitag_cb, &t0);