2  * LEGIC RF simulation code 
   4  * (c) 2009 Henryk Plötz <henryk@ploetzli.ch> 
  14 static struct legic_frame 
{ 
  20 static void setup_timer(void) 
  22         /* Set up Timer 1 to use for measuring time between pulses. Since we're bit-banging 
  23          * this it won't be terribly accurate but should be good enough. 
  25         AT91C_BASE_PMC
->PMC_PCER 
= (1 << AT91C_ID_TC1
); 
  26         timer 
= AT91C_BASE_TC1
; 
  27         timer
->TC_CCR 
= AT91C_TC_CLKDIS
; 
  28         timer
->TC_CMR 
= TC_CMR_TCCLKS_TIMER_CLOCK3
; 
  29         timer
->TC_CCR 
= AT91C_TC_CLKEN 
| AT91C_TC_SWTRG
; 
  31 /* At TIMER_CLOCK3 (MCK/32) */ 
  32 #define RWD_TIME_1 150     /* RWD_TIME_PAUSE off, 80us on = 100us */ 
  33 #define RWD_TIME_0 90      /* RWD_TIME_PAUSE off, 40us on = 60us */ 
  34 #define RWD_TIME_PAUSE 30  /* 20us */ 
  35 #define RWD_TIME_FUZZ 20   /* rather generous 13us, since the peak detector + hysteresis fuzz quite a bit */ 
  36 #define TAG_TIME_BIT 150   /* 100us for every bit */ 
  37 #define TAG_TIME_WAIT 490  /* time from RWD frame end to tag frame start, experimentally determined */ 
  41 #define FUZZ_EQUAL(value, target, fuzz) ((value) > ((target)-(fuzz)) && (value) < ((target)+(fuzz))) 
  43 /* Send a frame in reader mode, the FPGA must have been set up by 
  46 static void frame_send_rwd(uint16_t data
, int bits
) 
  49         timer
->TC_CCR 
= AT91C_TC_CLKEN 
| AT91C_TC_SWTRG
; 
  50         while(timer
->TC_CV 
> 1) ; /* Wait till the clock has reset */ 
  53         for(i
=0; i
<bits
; i
++) { 
  54                 int starttime 
= timer
->TC_CV
; 
  55                 int pause_end 
= starttime 
+ RWD_TIME_PAUSE
, bit_end
; 
  60                         bit_end 
= starttime 
+ RWD_TIME_1
; 
  62                         bit_end 
= starttime 
+ RWD_TIME_0
; 
  65                 /* RWD_TIME_PAUSE time off, then some time on, so that the complete bit time is 
  66                  * RWD_TIME_x, where x is the bit to be transmitted */ 
  67                 AT91C_BASE_PIOA
->PIO_CODR 
= GPIO_SSC_DOUT
; 
  68                 while(timer
->TC_CV 
< pause_end
) ; 
  69                 AT91C_BASE_PIOA
->PIO_SODR 
= GPIO_SSC_DOUT
; 
  70                 while(timer
->TC_CV 
< bit_end
) ; 
  74                 /* One final pause to mark the end of the frame */ 
  75                 int pause_end 
= timer
->TC_CV 
+ RWD_TIME_PAUSE
; 
  76                 AT91C_BASE_PIOA
->PIO_CODR 
= GPIO_SSC_DOUT
; 
  77                 while(timer
->TC_CV 
< pause_end
) ; 
  78                 AT91C_BASE_PIOA
->PIO_SODR 
= GPIO_SSC_DOUT
; 
  81         /* Reset the timer, to measure time until the start of the tag frame */ 
  82         timer
->TC_CCR 
= AT91C_TC_SWTRG
; 
  83         while(timer
->TC_CV 
> 1) ; /* Wait till the clock has reset */ 
  86 /* Receive a frame from the card in reader emulation mode, the FPGA and 
  87  * timer must have been set up by LegicRfReader and frame_send_rwd. 
  89  * The LEGIC RF protocol from card to reader does not include explicit 
  90  * frame start/stop information or length information. The reader must 
  91  * know beforehand how many bits it wants to receive. (Notably: a card 
  92  * sending a stream of 0-bits is indistinguishable from no card present.) 
  94  * Receive methodology: There is a fancy correlator in hi_read_rx_xcorr, but 
  95  * I'm not smart enough to use it. Instead I have patched hi_read_tx to output 
  96  * the ADC signal with hysteresis on SSP_DIN. Bit-bang that signal and look 
  97  * for edges. Count the edges in each bit interval. If they are approximately 
  98  * 0 this was a 0-bit, if they are approximately equal to the number of edges 
  99  * expected for a 212kHz subcarrier, this was a 1-bit. For timing we use the 
 100  * timer that's still running from frame_send_rwd in order to get a synchronization 
 101  * with the frame that we just sent. 
 103  * FIXME: Because we're relying on the hysteresis to just do the right thing  
 104  * the range is severely reduced (and you'll probably also need a good antenna). 
 105  * So this should be fixed some time in the future for a proper receiver.  
 107 static void frame_receive_rwd(struct legic_frame 
* const f
, int bits
) 
 109         uint16_t the_bit 
= 1;  /* Use a bitmask to save on shifts */ 
 111         int i
, old_level
=0, edges
=0; 
 112         int next_bit_at 
= TAG_TIME_WAIT
; 
 118         AT91C_BASE_PIOA
->PIO_ODR 
= GPIO_SSC_DIN
; 
 119         AT91C_BASE_PIOA
->PIO_PER 
= GPIO_SSC_DIN
; 
 121         while(timer
->TC_CV 
< next_bit_at
) ; 
 122         next_bit_at 
+= TAG_TIME_BIT
; 
 124         for(i
=0; i
<bits
; i
++) { 
 126                 while(timer
->TC_CV 
< next_bit_at
) { 
 127                         int level 
= (AT91C_BASE_PIOA
->PIO_PDSR 
& GPIO_SSC_DIN
); 
 128                         if(level 
!= old_level
) 
 132                 next_bit_at 
+= TAG_TIME_BIT
; 
 134                 if(edges 
> 20 && edges 
< 60) { /* expected are 42 edges */ 
 145         /* Reset the timer, to synchronize the next frame */ 
 146         timer
->TC_CCR 
= AT91C_TC_SWTRG
; 
 147         while(timer
->TC_CV 
> 1) ; /* Wait till the clock has reset */ 
 150 static void frame_clean(struct legic_frame 
* const f
) 
 156 static uint16_t perform_setup_phase_rwd(void) 
 159         /* Switch on carrier and let the tag charge for 1ms */ 
 160         AT91C_BASE_PIOA
->PIO_SODR 
= GPIO_SSC_DOUT
; 
 163         frame_send_rwd(0x55, 7); 
 164         frame_clean(¤t_frame
); 
 165         frame_receive_rwd(¤t_frame
, 6); 
 166         while(timer
->TC_CV 
< 387) ; /* ~ 258us */ 
 167         frame_send_rwd(0x019, 6); 
 169         return current_frame
.data 
^ 0x26; 
 172 static void switch_off_tag_rwd(void) 
 174         /* Switch off carrier, make sure tag is reset */ 
 175         AT91C_BASE_PIOA
->PIO_CODR 
= GPIO_SSC_DOUT
; 
 181 void LegicRfReader(void) 
 183         SetAdcMuxFor(GPIO_MUXSEL_HIPKD
); 
 185         FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX
); 
 187         /* Bitbang the transmitter */ 
 188         AT91C_BASE_PIOA
->PIO_CODR 
= GPIO_SSC_DOUT
; 
 189         AT91C_BASE_PIOA
->PIO_OER 
= GPIO_SSC_DOUT
; 
 190         AT91C_BASE_PIOA
->PIO_PER 
= GPIO_SSC_DOUT
; 
 194         memset(BigBuf
, 0, 1024); 
 196         int byte_index 
= 0, card_size 
= 0, command_size 
= 0; 
 197         uint16_t command_obfuscation 
= 0x57, response_obfuscation 
= 0; 
 198         uint16_t tag_type 
= perform_setup_phase_rwd(); 
 199         switch_off_tag_rwd(); 
 204                 DbpString("MIM 256 card found, reading card ..."); 
 207                 response_obfuscation 
= 0x52; 
 210                 DbpString("MIM 1024 card found, reading card ..."); 
 213                 response_obfuscation 
= 0xd4; 
 216                 DbpString("No or unknown card found, aborting"); 
 222         while(!BUTTON_PRESS() && (byte_index
<card_size
)) { 
 223                 if(perform_setup_phase_rwd() != tag_type
) { 
 224                         DbpString("Card removed, aborting"); 
 225                         switch_off_tag_rwd(); 
 230                 while(timer
->TC_CV 
< 387) ; /* ~ 258us */ 
 231                 frame_send_rwd(command_obfuscation 
^ (byte_index
<<1), command_size
); 
 232                 frame_clean(¤t_frame
); 
 233                 frame_receive_rwd(¤t_frame
, 8); 
 234                 ((uint8_t*)BigBuf
)[byte_index
] = (current_frame
.data 
^ response_obfuscation
) & 0xff; 
 236                 switch_off_tag_rwd(); 
 240                 if(byte_index 
& 0x04) LED_C_ON(); else LED_C_OFF(); 
 246                 if(card_size 
== 256) { 
 247                         DbpString("Card read, use hexsamples 256 to view results"); 
 248                 } else if(card_size 
== 1024) { 
 249                         DbpString("Card read, use hexsamples 1024 to view results");