]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
CHG: extracted some timers functionality, to get unified access to a timer/clock...
authoriceman1001 <iceman@iuse.se>
Wed, 21 Sep 2016 17:03:32 +0000 (19:03 +0200)
committericeman1001 <iceman@iuse.se>
Wed, 21 Sep 2016 17:03:32 +0000 (19:03 +0200)
armsrc/Makefile
armsrc/legicrf.c
armsrc/legicrf.h
armsrc/ticks.c [new file with mode: 0644]
armsrc/ticks.h [new file with mode: 0644]
armsrc/util.c
armsrc/util.h
client/cmdhflegic.c
common/crc.c
common/crc.h

index 7986dd7f8581a68e9f83d11879d3fb670a698baa..bfc5cbf213c7b2bec6ba7d05a74f8bdccfe4a656 100644 (file)
@@ -50,7 +50,8 @@ THUMBSRC = start.c \
        util.c \
        string.c \
        usb_cdc.c \
-       cmd.c
+       cmd.c \
+       ticks.c
 
 # These are to be compiled in ARM mode
 ARMSRC = fpgaloader.c \
index 2883bdfc0a98f59fb84ae2dfd0471e341e48cef8..e8a2e1aab0616f2b9dcb485ebefa85f4a6025fd7 100644 (file)
@@ -7,7 +7,6 @@
 //-----------------------------------------------------------------------------
 // LEGIC RF simulation code
 //-----------------------------------------------------------------------------
-
 #include "legicrf.h"
 
 static struct legic_frame {
@@ -73,7 +72,7 @@ static void setup_timer(void) {
 //#define RWD_TIME_0 90      /* RWD_TIME_PAUSE off, 40us on = 60us */
 //#define RWD_TIME_PAUSE 30  /* 20us */
 
-// testing calculating in ticks instead of (us) microseconds.
+// testing calculating in (us) microseconds.
 #define        RWD_TIME_1 120          // READER_TIME_PAUSE 20us off, 80us on = 100us  80 * 1.5 == 120ticks
 #define RWD_TIME_0 60          // READER_TIME_PAUSE 20us off, 40us on = 60us   40 * 1.5 == 60ticks 
 #define RWD_TIME_PAUSE 30      // 20us == 20 * 1.5 == 30ticks */
@@ -107,36 +106,17 @@ uint32_t sendFrameStop = 0;
 #ifndef COIL_PULSE
 # define COIL_PULSE(x)  { \
                SHORT_COIL; \
-               Wait(RWD_TIME_PAUSE); \
+               WaitTicks(RWD_TIME_PAUSE); \
                OPEN_COIL; \
-               Wait((x)); \
+               WaitTicks((x)); \
        }
 #endif
-#ifndef GET_TICKS
-# define GET_TICKS AT91C_BASE_TC0->TC_CV
-#endif
 
 // ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. 
 // Historically it used to be FREE_BUFFER_SIZE, which was 2744.
 #define LEGIC_CARD_MEMSIZE 1024
 static uint8_t* cardmem;
 
-static void Wait(uint32_t time){
-       if ( time == 0 ) return;
-       time += GET_TICKS;      
-       while (GET_TICKS < time);
-}
-// Starts Clock and waits until its reset
-static void Reset(AT91PS_TC clock){
-       clock->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       while(clock->TC_CV > 1) ;
-}
-
-// Starts Clock and waits until its reset
-static void ResetClock(void){
-       Reset(timer);
-}
-
 static void frame_append_bit(struct legic_frame * const f, int bit) {
        // Overflow, won't happen
    if (f->bits >= 31) return;
@@ -166,8 +146,7 @@ static void frame_clean(struct legic_frame * const f) {
 */
 
 /* Generate Keystream */
-static uint32_t get_key_stream(int skip, int count)
-{
+uint32_t get_key_stream(int skip, int count) {
        uint32_t key = 0;
        int i;
 
@@ -175,7 +154,7 @@ static uint32_t get_key_stream(int skip, int count)
        legic_prng_bc += prng_timer->TC_CV;
 
        // reset the prng timer.
-       Reset(prng_timer);
+       ResetTimer(prng_timer);
 
        /* If skip == -1, forward prng time based */
        if(skip == -1) {
@@ -209,7 +188,7 @@ static uint32_t get_key_stream(int skip, int count)
 /* Send a frame in tag mode, the FPGA must have been set up by
  * LegicRfSimulate
  */
-static void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt) {
+void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt) {
        /* Bitbang the response */
        LOW(GPIO_SSC_DOUT);
        AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
@@ -222,7 +201,7 @@ static void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt) {
        }
 
        /* Wait for the frame start */
-       Wait( TAG_FRAME_WAIT );
+       WaitUS( TAG_FRAME_WAIT );
 
        uint8_t bit = 0;
        for(int i = 0; i < bits; i++) {
@@ -235,7 +214,7 @@ static void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt) {
                else
                        LOW(GPIO_SSC_DOUT);
                  
-               Wait(100);
+               WaitUS(100);
    }
    LOW(GPIO_SSC_DOUT);
 }
@@ -243,7 +222,7 @@ static void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt) {
 /* Send a frame in reader mode, the FPGA must have been set up by
  * LegicRfReader
  */
-static void frame_sendAsReader(uint32_t data, uint8_t bits){
+void frame_sendAsReader(uint32_t data, uint8_t bits){
 
        uint32_t starttime = GET_TICKS, send = 0;
        uint16_t mask = 1;
@@ -298,14 +277,13 @@ static void frame_sendAsReader(uint32_t data, uint8_t bits){
 static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) {
 
        frame_clean(f);
+       if ( bits > 32 ) return;
        
-       uint8_t i = 0, edges = 0;       
+       uint8_t i = bits, edges = 0;    
        uint16_t lsfr = 0;
        uint32_t the_bit = 1, next_bit_at = 0, data;
        int old_level = 0, level = 0;
 
-       if(bits > 32) bits = 32;
-
        AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN;
        AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN;
        
@@ -320,14 +298,14 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) {
        data = lsfr;
        
        //FIXED time between sending frame and now listening frame. 330us
-       Wait( TAG_FRAME_WAIT - ( GET_TICKS - sendFrameStop ) );
-       //Wait( TAG_FRAME_WAIT );
+       //WaitTicks( GET_TICKS - sendFrameStop - TAG_FRAME_WAIT);
+       WaitTicks( 490 );
 
        uint32_t starttime = GET_TICKS;
        
        next_bit_at =  GET_TICKS + TAG_BIT_PERIOD;
        
-       for( i = 0; i < bits; i++) {
+       while ( i-- ){
                edges = 0;
                while  ( GET_TICKS < next_bit_at) {
 
@@ -341,7 +319,7 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) {
                next_bit_at += TAG_BIT_PERIOD;
                
                // We expect 42 edges  == ONE
-               if(edges > 20 && edges < 64)
+               if(edges > 30 && edges < 64)
                        data ^= the_bit;
 
                the_bit <<= 1;  
@@ -370,12 +348,12 @@ static void frame_receiveAsReader(struct legic_frame * const f, uint8_t bits) {
 
 // Setup pm3 as a Legic Reader
 static uint32_t setup_phase_reader(uint8_t iv) {
-
+       
        // Switch on carrier and let the tag charge for 1ms
        HIGH(GPIO_SSC_DOUT);
-       SpinDelay(300);
+       WaitUS(300);    
        
-       ResetUSClock();
+       ResetTicks();
        
        // no keystream yet
        legic_prng_init(0);
@@ -389,8 +367,8 @@ static uint32_t setup_phase_reader(uint8_t iv) {
        frame_receiveAsReader(&current_frame, 6);
 
        // fixed delay before sending ack.
-       Wait(360);  // 240us = 360tick
-       legic_prng_forward(2);  //240us / 100 == 2.4 iterations
+       WaitTicks(387);  // 244us
+       legic_prng_forward(3);  //240us / 100 == 2.4 iterations
        
        // Send obsfuscated acknowledgment frame.
        // 0x19 = 0x18 MIM22, 0x01 LSB READCMD 
@@ -402,17 +380,13 @@ static uint32_t setup_phase_reader(uint8_t iv) {
                default: break;
        }
        return current_frame.data;
-
-       // fixed delay after setup phase.
-       Wait(375); // 260us == 375 ticks
-       legic_prng_forward(2);// 260us / 100 == 2.6 iterations
 }
 
-static void LegicCommonInit(void) {    
+static void LegicCommonInit(void) {
+
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
        SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
-       FpgaSetupSsc();
 
        /* Bitbang the transmitter */
        LOW(GPIO_SSC_DOUT);
@@ -427,14 +401,15 @@ static void LegicCommonInit(void) {
        set_tracing(TRUE);
        crc_init(&legic_crc, 4, 0x19 >> 1, 0x5, 0);
        
-       StartCountUS();
+       StartTicks();
 }
 
 // Switch off carrier, make sure tag is reset
 static void switch_off_tag_rwd(void) {
        LOW(GPIO_SSC_DOUT);
-       SpinDelay(10);
+       WaitUS(200);
        WDT_HIT();
+       Dbprintf("Exit Switch_off_tag_rwd");
 }
 
 // calculate crc4 for a legic READ command 
@@ -451,6 +426,15 @@ static uint32_t legic4Crc(uint8_t legicCmd, uint16_t byte_index, uint8_t value,
 
 int legic_read_byte(int byte_index, int cmd_sz) {
 
+       // (us)| ticks
+       // -------------
+       // 330 | 495
+       // 460 | 690
+       // 258 | 387
+       // 244 | 366
+       WaitTicks(332); 
+       legic_prng_forward(2); // 460 / 100 = 4.6  iterations
+
        uint8_t byte = 0, crc = 0, calcCrc = 0;
        uint32_t cmd = (byte_index << 1) | LEGIC_READ;
 
@@ -466,9 +450,8 @@ int legic_read_byte(int byte_index, int cmd_sz) {
                return -1;
        }
 
-       Wait(690);  // 460us == 690ticks
-       legic_prng_forward(4); // 460 / 100 = 4.6  iterations
-       
+
+//     legic_prng_forward(2); // 460 / 100 = 4.6  iterations
        return byte;
 }
 
@@ -504,7 +487,7 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) {
 
     legic_prng_forward(2); /* we wait anyways */
        
-       Wait(TAG_FRAME_WAIT);
+       WaitUS(TAG_FRAME_WAIT);
        
        frame_sendAsReader(cmd, cmd_sz);
   
@@ -516,7 +499,7 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) {
     int t, old_level = 0, edges = 0;
     int next_bit_at = 0;
 
-       Wait(TAG_FRAME_WAIT);
+       WaitUS(TAG_FRAME_WAIT);
 
     for( t = 0; t < 80; ++t) {
         edges = 0;
@@ -532,13 +515,13 @@ int legic_write_byte(uint8_t byte, uint16_t addr, uint8_t addr_sz) {
                        int t = timer->TC_CV;
                        int c = t / TAG_BIT_PERIOD;
                        
-                       ResetClock();
+                       ResetTimer(timer);
                        legic_prng_forward(c);
                return 0;
         }
     }
 
-       ResetClock();
+       ResetTimer(timer);
        return -1;
 }
 
@@ -802,7 +785,7 @@ static void frame_handle_tag(struct legic_frame const * const f)
         LED_C_ON();
         
                // Reset prng timer
-               Reset(prng_timer);
+               ResetTimer(prng_timer);
                
         legic_prng_init(f->data);
         frame_send_tag(0x3d, 6, 1); /* 0x3d^0x26 = 0x1B */
@@ -812,8 +795,8 @@ static void frame_handle_tag(struct legic_frame const * const f)
         legic_prng_iv = f->data;
  
  
-               ResetClock();
-               Wait(280);
+               ResetTimer(timer);
+               WaitUS(280);
         return;
    }
 
@@ -824,8 +807,8 @@ static void frame_handle_tag(struct legic_frame const * const f)
       if((f->bits == 6) && (f->data == xored)) {
          legic_state = STATE_CON;
 
-                ResetClock();
-                Wait(200);
+                ResetTimer(timer);
+                WaitUS(200);
          return;
 
         } else {
@@ -851,9 +834,9 @@ static void frame_handle_tag(struct legic_frame const * const f)
 
          frame_send_tag(hash | data, 12, 1);
 
-                ResetClock();
+                ResetTimer(timer);
          legic_prng_forward(2);
-                Wait(180);
+                WaitUS(180);
          return;
       }
    }
@@ -1004,10 +987,6 @@ void LegicRfSimulate(int phase, int frame, int reqresp)
        LEDsoff();
 }
 
-//-----------------------------------------------------------------------------
-//-----------------------------------------------------------------------------
-
-
 //-----------------------------------------------------------------------------
 // Code up a string of octets at layer 2 (including CRC, we don't generate
 // that here) so that they can be transmitted to the reader. Doesn't transmit
index 4e3177ee6fc4b905de423bce5b554231a6c49c45..2008f5b9771bf3b3165d6d5ccea9ffb79053d68c 100644 (file)
@@ -17,6 +17,7 @@
 #include "string.h"            
 #include "legic_prng.h"        // legic PRNG impl
 #include "crc.h"               // legic crc-4
+#include "ticks.h"             // timers
 
 #define LEGIC_READ 0x01
 #define LEGIC_WRITE 0x00
@@ -26,6 +27,10 @@ extern int  LegicRfReader(int offset, int bytes, int iv);
 extern void LegicRfWriter(int offset, int bytes, int iv);
 extern void LegicRfRawWriter(int address, int data, int iv);
 
+uint32_t get_key_stream(int skip, int count);
+void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt);
+void frame_sendAsReader(uint32_t data, uint8_t bits);
+
 int ice_legic_select_card();
 void ice_legic_setup();
 
diff --git a/armsrc/ticks.c b/armsrc/ticks.c
new file mode 100644 (file)
index 0000000..43b006f
--- /dev/null
@@ -0,0 +1,235 @@
+//-----------------------------------------------------------------------------
+// Jonathan Westhues, Sept 2005
+// Iceman, Sept 2016
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Timers, Clocks functions used in LF or Legic where you would need detailed time.
+//-----------------------------------------------------------------------------
+
+#include "ticks.h"
+
+// attempt at high resolution microsecond timer
+// beware: timer counts in 21.3uS increments (1024/48Mhz)
+void SpinDelayUs(int us) {
+       int ticks = (48 * us) >> 10;
+
+       // Borrow a PWM unit for my real-time clock
+       AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
+       
+       // 48 MHz / 1024 gives 46.875 kHz
+       AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
+       AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
+       AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
+
+       uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
+
+       for(;;) {
+               uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
+               if (now == (uint16_t)(start + ticks))
+                       return;
+
+               WDT_HIT();
+       }
+}
+
+void SpinDelay(int ms) {
+  // convert to uS and call microsecond delay function
+       SpinDelayUs(ms*1000);
+}
+//  -------------------------------------------------------------------------
+//  timer lib
+//  -------------------------------------------------------------------------
+//  test procedure:
+//
+//     ti = GetTickCount();
+//     SpinDelay(1000);
+//     ti = GetTickCount() - ti;
+//     Dbprintf("timer(1s): %d t=%d", ti, GetTickCount());
+
+void StartTickCount() {
+       // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz.
+       // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register.
+    uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff;                // = 16 * main clock frequency (16MHz) / slow clock frequency
+       // set RealTimeCounter divider to count at 1kHz:
+       AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf);
+       // note: worst case precision is approx 2.5%
+}
+
+/*
+* Get the current count.
+*/
+uint32_t RAMFUNC GetTickCount(){
+       return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2;
+}
+
+//  -------------------------------------------------------------------------
+//  microseconds timer 
+//  -------------------------------------------------------------------------
+void StartCountUS() {
+       AT91C_BASE_PMC->PMC_PCER |= (1 << 12) | (1 << 13) | (1 << 14);
+       AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
+
+       // fast clock
+       // tick=1.5mks
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
+       AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 
+                                                               AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
+                                                               AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
+       AT91C_BASE_TC0->TC_RA = 1;
+       AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
+       
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable  
+       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
+       
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TCB->TCB_BCR = 1;
+       
+       while (AT91C_BASE_TC1->TC_CV >= 1);
+}
+
+uint32_t RAMFUNC GetCountUS(){
+       //return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
+       //  By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
+       return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV * 2) / 3); 
+}
+void ResetUSClock(void) {      
+       //enable clock of timer and software trigger
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       while (AT91C_BASE_TC1->TC_CV >= 1);
+}
+// attempt at high resolution microsecond timer
+// beware: timer counts in 21.3uS increments (1024/48Mhz)
+void SpinDelayCountUs(uint32_t us) {
+       if (us < 8) return;
+       us += GetCountUS();     
+       while ( GetCountUS() < us ){}
+}
+// static uint32_t GlobalUsCounter = 0;
+// uint32_t RAMFUNC GetDeltaCountUS(){
+       // uint32_t g_cnt = GetCountUS();
+       // uint32_t g_res = g_cnt - GlobalUsCounter;
+       // GlobalUsCounter = g_cnt;
+       // return g_res;
+// }
+//  -------------------------------------------------------------------------
+//  Timer for iso14443 commands. Uses ssp_clk from FPGA 
+//  -------------------------------------------------------------------------
+void StartCountSspClk() {
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2);  // Enable Clock to all timers
+       AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1               // XC0 Clock = TIOA1
+                                                       | AT91C_TCB_TC1XC1S_NONE                // XC1 Clock = none
+                                                       | AT91C_TCB_TC2XC2S_TIOA0;              // XC2 Clock = TIOA0
+
+       // configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs:
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;                               // disable TC1
+       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz
+                                                       | AT91C_TC_CPCSTOP                              // Stop clock on RC compare
+                                                       | AT91C_TC_EEVTEDG_RISING               // Trigger on rising edge of Event
+                                                       | AT91C_TC_EEVT_TIOB                    // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
+                                                       | AT91C_TC_ENETRG                               // Enable external trigger event
+                                                       | AT91C_TC_WAVESEL_UP                   // Upmode without automatic trigger on RC compare
+                                                       | AT91C_TC_WAVE                                 // Waveform Mode
+                                                       | AT91C_TC_AEEVT_SET                    // Set TIOA1 on external event
+                                                       | AT91C_TC_ACPC_CLEAR;                  // Clear TIOA1 on RC Compare
+       AT91C_BASE_TC1->TC_RC = 0x04;                                                   // RC Compare value = 0x04
+
+       // use TC0 to count TIOA1 pulses
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;                               // disable TC0
+       AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0                              // TC0 clock = XC0 clock = TIOA1
+                                                       | AT91C_TC_WAVE                                 // Waveform Mode
+                                                       | AT91C_TC_WAVESEL_UP                   // just count
+                                                       | AT91C_TC_ACPA_CLEAR                   // Clear TIOA0 on RA Compare
+                                                       | AT91C_TC_ACPC_SET;                    // Set TIOA0 on RC Compare
+       AT91C_BASE_TC0->TC_RA = 1;                                                              // RA Compare value = 1; pulse width to TC2
+       AT91C_BASE_TC0->TC_RC = 0;                                                              // RC Compare value = 0; increment TC2 on overflow
+
+       // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk)
+       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS;                               // disable TC2  
+       AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2                              // TC2 clock = XC2 clock = TIOA0
+                                                       | AT91C_TC_WAVE                                 // Waveform Mode
+                                                       | AT91C_TC_WAVESEL_UP;                  // just count
+
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;                               // enable and reset TC0
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;                               // enable and reset TC1
+       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;                               // enable and reset TC2
+
+       // synchronize the counter with the ssp_frame signal. 
+       // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present 
+       while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME));   // wait for ssp_frame to go high (start of frame)
+       while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME);              // wait for ssp_frame to be low
+       while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK));     // wait for ssp_clk to go high
+
+       // note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame
+       // it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge
+       AT91C_BASE_TCB->TCB_BCR = 1;                                                    // assert Sync (set all timers to 0 on next active clock edge)
+       // at the next (3rd) ssp_clk rising edge, TC1 will be reset (and not generate a clock signal to TC0)
+       // at the next (4th) ssp_clk rising edge, TC0 (the low word of our counter) will be reset. From now on,
+       // whenever the last three bits of our counter go 0, we can be sure to be in the middle of a frame transfer.
+       // (just started with the transfer of the 4th Bit).
+
+       // The high word of the counter (TC2) will not reset until the low word (TC0) overflows. 
+       // Therefore need to wait quite some time before we can use the counter.
+       while (AT91C_BASE_TC2->TC_CV >= 1);
+}
+void ResetSspClk(void) {       
+       //enable clock of timer and software trigger
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+}
+
+uint32_t RAMFUNC GetCountSspClk(){
+
+       uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV;
+       if ((tmp_count & 0x0000ffff) == 0)  //small chance that we may have missed an increment in TC2
+               return (AT91C_BASE_TC2->TC_CV << 16);
+       return tmp_count;
+}
+
+
+void StartTicks(void){
+       //initialization of the timer
+       AT91C_BASE_PMC->PMC_PCER |= (1 << 12) | (1 << 13) | (1 << 14);
+       AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
+
+       // fast clock TC0
+       // tick=1.5mks
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
+       AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK;  //clock at 48/32 MHz
+       
+       // Enable and reset timer
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TCB->TCB_BCR = 1;
+       // wait until timer becomes zero.
+       while (AT91C_BASE_TC0->TC_CV > 1);
+}
+// Wait - Spindelay in ticks.
+// if called with a high number, this will trigger the WDT...
+void WaitTicks(uint32_t ticks){
+       if ( ticks == 0 ) return;
+       ticks += GET_TICKS;     
+       while (GET_TICKS < ticks);
+}
+// Wait / Spindelay in us (microseconds) 
+// 1us = 1.5ticks.
+void WaitUS(uint16_t us){
+       if ( us == 0 ) return;
+       WaitTicks(  (uint32_t)(us * 1.5) );
+}
+void WaitMS(uint16_t ms){
+       if (ms == 0) return;
+       WaitTicks( (uint32_t)(ms * 1500) );
+}
+// Starts Clock and waits until its reset
+void ResetTicks(){
+       ResetTimer(AT91C_BASE_TC0);
+}
+void ResetTimer(AT91PS_TC timer){
+       timer->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       while(timer->TC_CV > 1) ;
+}
diff --git a/armsrc/ticks.h b/armsrc/ticks.h
new file mode 100644 (file)
index 0000000..050cb6a
--- /dev/null
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------------
+// Jonathan Westhues, Aug 2005
+// Iceman, Sept 2016
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Timers, Clocks functions used in LF or Legic where you would need detailed time.
+//-----------------------------------------------------------------------------
+
+#ifndef __TICKS_H
+#define __TICKS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "common.h"
+#include "apps.h"
+#include "proxmark3.h"
+
+#ifndef GET_TICKS
+# define GET_TICKS AT91C_BASE_TC0->TC_CV
+#endif
+
+void SpinDelay(int ms);
+void SpinDelayUs(int us);
+
+void StartTickCount(void);
+uint32_t RAMFUNC GetTickCount(void);
+
+void StartCountUS(void);
+uint32_t RAMFUNC GetCountUS(void);
+void ResetUSClock(void);
+void SpinDelayCountUs(uint32_t us);
+//uint32_t RAMFUNC GetDeltaCountUS(void);
+
+void StartCountSspClk();
+void ResetSspClk(void);
+uint32_t RAMFUNC GetCountSspClk();
+
+extern void StartTicks(void);
+extern void WaitTicks(uint32_t ticks);
+extern void WaitUS(uint16_t us);
+extern void WaitMS(uint16_t ms);
+extern void ResetTicks();
+extern void ResetTimer(AT91PS_TC timer);
+#endif
\ No newline at end of file
index be6170d36ae282479f71fed2fa4cc02044696172..1716a1134ba9b266e69b5bef660bb3d15979a4e2 100644 (file)
@@ -233,35 +233,6 @@ int BUTTON_HELD(int ms) {
        return BUTTON_ERROR;
 }
 
-// attempt at high resolution microsecond timer
-// beware: timer counts in 21.3uS increments (1024/48Mhz)
-void SpinDelayUs(int us) {
-       int ticks = (48 * us) >> 10;
-
-       // Borrow a PWM unit for my real-time clock
-       AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
-       
-       // 48 MHz / 1024 gives 46.875 kHz
-       AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
-       AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
-       AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
-
-       uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-
-       for(;;) {
-               uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
-               if (now == (uint16_t)(start + ticks))
-                       return;
-
-               WDT_HIT();
-       }
-}
-
-void SpinDelay(int ms) {
-  // convert to uS and call microsecond delay function
-       SpinDelayUs(ms*1000);
-}
-
 /* Similar to FpgaGatherVersion this formats stored version information
  * into a string representation. It takes a pointer to the struct version_information,
  * verifies the magic properties, then stores a formatted string, prefixed by
@@ -295,158 +266,3 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
        strncat(dst, v->buildtime, len - strlen(dst) - 1);
        strncat(dst, "\n", len - strlen(dst) - 1);
 }
-
-//  -------------------------------------------------------------------------
-//  timer lib
-//  -------------------------------------------------------------------------
-//  test procedure:
-//
-//     ti = GetTickCount();
-//     SpinDelay(1000);
-//     ti = GetTickCount() - ti;
-//     Dbprintf("timer(1s): %d t=%d", ti, GetTickCount());
-
-void StartTickCount() {
-       // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz.
-       // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register.
-    uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff;                // = 16 * main clock frequency (16MHz) / slow clock frequency
-       // set RealTimeCounter divider to count at 1kHz:
-       AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf);
-       // note: worst case precision is approx 2.5%
-}
-
-/*
-* Get the current count.
-*/
-uint32_t RAMFUNC GetTickCount(){
-       return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2;
-}
-
-//  -------------------------------------------------------------------------
-//  microseconds timer 
-//  -------------------------------------------------------------------------
-void StartCountUS() {
-       AT91C_BASE_PMC->PMC_PCER |= (0x1 << 12) | (0x1 << 13) | (0x1 << 14);
-//     AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC1XC1S_TIOA0;
-       AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
-
-       // fast clock
-       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
-       AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz)/32 -- tick=1.5mks
-                                                               AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
-                                                               AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
-       AT91C_BASE_TC0->TC_RA = 1;
-       AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
-       
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable  
-       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0
-       
-       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       AT91C_BASE_TCB->TCB_BCR = 1;
-       
-       while (AT91C_BASE_TC1->TC_CV >= 1);
-}
-
-uint32_t RAMFUNC GetCountUS(){
-       //return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
-       //  By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
-       return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV * 2) / 3); 
-}
-void ResetUSClock(void) {      
-       //enable clock of timer and software trigger
-       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       while (AT91C_BASE_TC1->TC_CV >= 1);
-}
-// attempt at high resolution microsecond timer
-// beware: timer counts in 21.3uS increments (1024/48Mhz)
-void SpinDelayCountUs(uint32_t us) {
-       if (us < 8) return;
-       us += GetCountUS();     
-       while ( GetCountUS() < us ){}
-}
-// static uint32_t GlobalUsCounter = 0;
-
-// uint32_t RAMFUNC GetDeltaCountUS(){
-       // uint32_t g_cnt = GetCountUS();
-       // uint32_t g_res = g_cnt - GlobalUsCounter;
-       // GlobalUsCounter = g_cnt;
-       // return g_res;
-// }
-
-
-//  -------------------------------------------------------------------------
-//  Timer for iso14443 commands. Uses ssp_clk from FPGA 
-//  -------------------------------------------------------------------------
-void StartCountSspClk() {
-       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2);  // Enable Clock to all timers
-       AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1               // XC0 Clock = TIOA1
-                                                       | AT91C_TCB_TC1XC1S_NONE                // XC1 Clock = none
-                                                       | AT91C_TCB_TC2XC2S_TIOA0;              // XC2 Clock = TIOA0
-
-       // configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs:
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;                               // disable TC1
-       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz
-                                                       | AT91C_TC_CPCSTOP                              // Stop clock on RC compare
-                                                       | AT91C_TC_EEVTEDG_RISING               // Trigger on rising edge of Event
-                                                       | AT91C_TC_EEVT_TIOB                    // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
-                                                       | AT91C_TC_ENETRG                               // Enable external trigger event
-                                                       | AT91C_TC_WAVESEL_UP                   // Upmode without automatic trigger on RC compare
-                                                       | AT91C_TC_WAVE                                 // Waveform Mode
-                                                       | AT91C_TC_AEEVT_SET                    // Set TIOA1 on external event
-                                                       | AT91C_TC_ACPC_CLEAR;                  // Clear TIOA1 on RC Compare
-       AT91C_BASE_TC1->TC_RC = 0x04;                                                   // RC Compare value = 0x04
-
-       // use TC0 to count TIOA1 pulses
-       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;                               // disable TC0
-       AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0                              // TC0 clock = XC0 clock = TIOA1
-                                                       | AT91C_TC_WAVE                                 // Waveform Mode
-                                                       | AT91C_TC_WAVESEL_UP                   // just count
-                                                       | AT91C_TC_ACPA_CLEAR                   // Clear TIOA0 on RA Compare
-                                                       | AT91C_TC_ACPC_SET;                    // Set TIOA0 on RC Compare
-       AT91C_BASE_TC0->TC_RA = 1;                                                              // RA Compare value = 1; pulse width to TC2
-       AT91C_BASE_TC0->TC_RC = 0;                                                              // RC Compare value = 0; increment TC2 on overflow
-
-       // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk)
-       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS;                               // disable TC2  
-       AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2                              // TC2 clock = XC2 clock = TIOA0
-                                                       | AT91C_TC_WAVE                                 // Waveform Mode
-                                                       | AT91C_TC_WAVESEL_UP;                  // just count
-
-       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;                               // enable and reset TC0
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;                               // enable and reset TC1
-       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;                               // enable and reset TC2
-
-       // synchronize the counter with the ssp_frame signal. 
-       // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present 
-       while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME));   // wait for ssp_frame to go high (start of frame)
-       while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME);              // wait for ssp_frame to be low
-       while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK));     // wait for ssp_clk to go high
-
-       // note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame
-       // it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge
-       AT91C_BASE_TCB->TCB_BCR = 1;                                                    // assert Sync (set all timers to 0 on next active clock edge)
-       // at the next (3rd) ssp_clk rising edge, TC1 will be reset (and not generate a clock signal to TC0)
-       // at the next (4th) ssp_clk rising edge, TC0 (the low word of our counter) will be reset. From now on,
-       // whenever the last three bits of our counter go 0, we can be sure to be in the middle of a frame transfer.
-       // (just started with the transfer of the 4th Bit).
-
-       // The high word of the counter (TC2) will not reset until the low word (TC0) overflows. 
-       // Therefore need to wait quite some time before we can use the counter.
-       while (AT91C_BASE_TC2->TC_CV >= 1);
-}
-void ResetSspClk(void) {       
-       //enable clock of timer and software trigger
-       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-       AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
-}
-
-uint32_t RAMFUNC GetCountSspClk(){
-       uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV;
-       if ((tmp_count & 0x0000ffff) == 0)  //small chance that we may have missed an increment in TC2
-               return (AT91C_BASE_TC2->TC_CV << 16);
-       return tmp_count;
-}
-
index 3ff70dd4a44fba4b1d33567e081f705567a65939..d323529226e71993d9518e2a1dd97264a1b30d1f 100644 (file)
@@ -18,6 +18,7 @@
 #include "apps.h"
 #include "BigBuf.h"
 #include "proxmark3.h"
+#include "ticks.h"
 
 #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
 
@@ -51,25 +52,10 @@ void rol(uint8_t *data, const size_t len);
 void lsl (uint8_t *data, size_t len);
 int32_t le24toh (uint8_t data[3]);
 
-void SpinDelay(int ms);
-void SpinDelayUs(int us);
 void LED(int led, int ms);
 void LEDsoff();
 int BUTTON_CLICKED(int ms);
 int BUTTON_HELD(int ms);
 void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
 
-void StartTickCount();
-uint32_t RAMFUNC GetTickCount();
-
-void StartCountUS();
-uint32_t RAMFUNC GetCountUS();
-void ResetUSClock(void);
-void SpinDelayCountUs(uint32_t us);
-//uint32_t RAMFUNC GetDeltaCountUS();
-
-void StartCountSspClk();
-void ResetSspClk(void);
-uint32_t RAMFUNC GetCountSspClk();
-
 #endif
index 2cfb286ea90acac200de0eab914ccafaa8cca59c..b52034dc046d5d85b3ebd36dac01b5dec3174ff3 100644 (file)
@@ -404,13 +404,15 @@ int CmdLegicRFRead(const char *Cmd) {
        PrintAndLog("Current IV: 0x%02x", IV);
        
        // get some  prng bytes from 
-       uint8_t temp[12];
+       uint8_t temp[32];
        legic_prng_init(IV);
-       for ( uint8_t j = 0; j < sizeof(temp); ++j)
-               temp[j] = legic_prng_get_bits(8);
-
-       PrintAndLog("PRNG: %s", sprint_hex(temp, sizeof(temp)));
-       
+       for ( uint8_t j = 0; j < sizeof(temp); ++j) {
+               temp[j] = legic_prng_get_bit(1);
+               legic_prng_forward(1);
+               //PrintAndLog("PRNG: %s", sprint_hex(temp, sizeof(temp)));
+       }
+       PrintAndLog("PRNG: %s", sprint_bin(temp, sizeof(temp)));
+               
        UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, IV}};
        clearCommandBuffer();
        SendCommand(&c);
index 72e6f0248751001e44210e412cabcc76ad5370d4..2f11f5f45f6c97386ffb6a595b014b05bd7a3e3b 100644 (file)
@@ -43,6 +43,8 @@ void crc_update(crc_t *crc, uint32_t indata, int data_width){
        crc->state ^= indata << (crc->order - data_width);
        
        for( uint8_t bit = data_width; bit > 0; --bit) {
+               
+               
                 // Try to divide the current data bit.
                if (crc->state & crc->topbit)
                        crc->state = (crc->state << 1) ^ crc->polynom;
@@ -51,6 +53,22 @@ void crc_update(crc_t *crc, uint32_t indata, int data_width){
        }
 }
 
+void crc_update2(crc_t *crc, uint32_t data, int data_width)
+{
+       if (crc->refin) data = reflect(data, data_width);
+       
+       int i;
+       for(i=0; i<data_width; i++) {
+               int oldstate = crc->state;
+               crc->state = crc->state >> 1;
+               if( (oldstate^data) & 1 ) {
+                       crc->state ^= crc->polynom;
+               }
+               data >>= 1;
+       }
+}
+
+
 uint32_t crc_finish(crc_t *crc) {
        uint32_t val = crc->state;
        if (crc->refout) val = reflect(val, crc->order);
@@ -83,6 +101,14 @@ uint32_t CRC8Maxim(uint8_t *buff, size_t size) {
 }
 
 // width=4  poly=0xC, reversed poly=0x7  init=0x5   refin=true  refout=true  xorout=0x0000  check=  name="CRC-4/LEGIC"
+uint32_t CRC4Legic(uint8_t *cmd, size_t size) {
+       crc_t crc;
+       crc_init_ref(&crc, 4, 0x19 >> 1, 0x5, 0, TRUE, TRUE);
+       crc_update2(&crc, 1, 1); /* CMD_READ */
+       crc_update2(&crc, cmd[0], 8);
+       crc_update2(&crc, cmd[1], 8);
+       return reflect(crc_finish(&crc), 4);    
+}
 // width=8  poly=0x63, reversed poly=0x8D  init=0x55  refin=true  refout=true  xorout=0x0000  check=0xC6  name="CRC-8/LEGIC"
 // the CRC needs to be reversed before returned.
 uint32_t CRC8Legic(uint8_t *buff, size_t size) {
index d7314379badffb487eea673f8011cf3d1dd77562..56f0435794cc1460df09accdd899dde18340641b 100644 (file)
@@ -44,6 +44,7 @@ extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_v
  * data_width lower-most bits are used).
  */
 extern void crc_update(crc_t *crc, uint32_t data, int data_width);
+extern void crc_update2(crc_t *crc, uint32_t data, int data_width);
 
 /* Clean the crc state, e.g. reset it to initial_value */
 extern void crc_clear(crc_t *crc);
Impressum, Datenschutz