X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/f97d4e2378e04397b3c884d10acb79725dee4e06..4118b74dc8834bd2f45002ca6b781ce7cfae6d0c:/armsrc/lfops.c diff --git a/armsrc/lfops.c b/armsrc/lfops.c index d29ec375..79d59bf9 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -14,8 +14,15 @@ #include "hitag2.h" #include "crc16.h" #include "string.h" +#include "lfdemod.h" -// split into two routines so we can avoid timing issues after sending commands // + +/** +* Does the sample acquisition. If threshold is specified, the actual sampling +* is not commenced until the threshold has been reached. +* @param trigger_threshold - the threshold +* @param silent - is true, now outputs are made. If false, dbprints the status +*/ void DoAcquisition125k_internal(int trigger_threshold,bool silent) { uint8_t *dest = (uint8_t *)BigBuf; @@ -46,12 +53,21 @@ void DoAcquisition125k_internal(int trigger_threshold,bool silent) } } +/** +* Perform sample aquisition. +*/ void DoAcquisition125k(int trigger_threshold) { DoAcquisition125k_internal(trigger_threshold, false); } -//void SetupToAcquireRawAdcSamples(int divisor) +/** +* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream +* if not already loaded, sets divisor and starts up the antenna. +* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz +* 0 or 95 ==> 125 KHz +* +**/ void LFSetupFPGAForADC(int divisor, bool lf_field) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -71,46 +87,46 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) // Now set up the SSC to get the ADC samples that are now streaming at us. FpgaSetupSsc(); } - +/** +* Initializes the FPGA, and acquires the samples. +**/ void AcquireRawAdcSamples125k(int divisor) { LFSetupFPGAForADC(divisor, true); // Now call the acquisition routine DoAcquisition125k_internal(-1,false); } +/** +* Initializes the FPGA for snoop-mode, and acquires the samples. +**/ + void SnoopLFRawAdcSamples(int divisor, int trigger_threshold) { LFSetupFPGAForADC(divisor, false); - DoAcquisition125k(trigger_threshold, false); -} - - + DoAcquisition125k(trigger_threshold); } void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, uint8_t *command) { - int at134khz; /* Make sure the tag is reset */ FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelay(2500); + + int divisor_used = 95; // 125 KHz // see if 'h' was specified + if (command[strlen((char *) command) - 1] == 'h') - at134khz = TRUE; - else - at134khz = FALSE; + divisor_used = 88; // 134.8 KHz - if (at134khz) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - // Give it a bit of time for the resonant antenna to settle. SpinDelay(50); + // And a little more time for the tag to fully power up SpinDelay(2000); @@ -122,10 +138,7 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); - if (at134khz) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); LED_D_ON(); @@ -137,10 +150,7 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); SpinDelayUs(delay_off); - if (at134khz) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor_used); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); @@ -621,237 +631,213 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol) LED_A_OFF(); } -size_t fsk_demod(uint8_t * dest, size_t size) -{ - uint32_t last_transition = 0; - uint32_t idx = 1; - - // we don't care about actual value, only if it's more or less than a - // threshold essentially we capture zero crossings for later analysis - uint8_t threshold_value = 127; - - // sync to first lo-hi transition, and threshold - - //Need to threshold first sample - if(dest[0] < threshold_value) dest[0] = 0; - else dest[0] = 1; - - size_t numBits = 0; - // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8) - // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere - // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10 - for(idx = 1; idx < size; idx++) { - // threshold current value - if (dest[idx] < threshold_value) dest[idx] = 0; - else dest[idx] = 1; - - // Check for 0->1 transition - if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition - - if (idx-last_transition < 9) { - dest[numBits]=1; - } else { - dest[numBits]=0; - } - last_transition = idx; - numBits++; - } - } - return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0 -} - - -size_t aggregate_bits(uint8_t *dest,size_t size, uint8_t h2l_crossing_value,uint8_t l2h_crossing_value, uint8_t maxConsequtiveBits ) -{ - uint8_t lastval=dest[0]; - uint32_t idx=0; - size_t numBits=0; - uint32_t n=1; - - for( idx=1; idx < size; idx++) { - - if (dest[idx]==lastval) { - n++; - continue; - } - //if lastval was 1, we have a 1->0 crossing - if ( dest[idx-1] ) { - n=(n+1) / h2l_crossing_value; - } else {// 0->1 crossing - n=(n+1) / l2h_crossing_value; - } - if (n == 0) n = 1; - - if(n < maxConsequtiveBits) - { - memset(dest+numBits, dest[idx-1] , n); - numBits += n; - } - n=0; - lastval=dest[idx]; - }//end for - - return numBits; - -} -// loop to capture raw HID waveform then FSK demodulate the TAG ID from it +// loop to get raw HID waveform then FSK demodulate the TAG ID from it void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol) { uint8_t *dest = (uint8_t *)BigBuf; - size_t size=0,idx=0; //, found=0; + size_t size=0; //, found=0; uint32_t hi2=0, hi=0, lo=0; + // Configure to go in 125Khz listen mode + LFSetupFPGAForADC(95, true); while(!BUTTON_PRESS()) { - // Configure to go in 125Khz listen mode - LFSetupFPGAForADC(0, true) - WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition125k_internal(true); + DoAcquisition125k_internal(-1,true); size = sizeof(BigBuf); - + if (size < 2000) continue; // FSK demodulator - size = fsk_demod(dest, size); - WDT_HIT(); - - // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns - // 1->0 : fc/8 in sets of 6 - // 0->1 : fc/10 in sets of 5 - size = aggregate_bits(dest,size, 6,5,5); + int bitLen = HIDdemodFSK(dest,size,&hi2,&hi,&lo); + WDT_HIT(); + if (bitLen>0 && lo>0){ // final loop, go over previously decoded manchester data and decode into usable tag ID // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0 - uint8_t frame_marker_mask[] = {1,1,1,0,0,0}; - int numshifts = 0; - idx = 0; - while( idx + sizeof(frame_marker_mask) < size) { - // search for a start of frame marker - if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0) - { // frame marker found - idx+=sizeof(frame_marker_mask); - - while(dest[idx] != dest[idx+1] && idx < size-2) - { // Keep going until next frame marker (or error) - // Shift in a bit. Start by shifting high registers - hi2 = (hi2<<1)|(hi>>31); - hi = (hi<<1)|(lo>>31); - //Then, shift in a 0 or one into low - if (dest[idx] && !dest[idx+1]) // 1 0 - lo=(lo<<1)|0; - else // 0 1 - lo=(lo<<1)| - 1; - numshifts ++; - idx += 2; - } - //Dbprintf("Num shifts: %d ", numshifts); - // Hopefully, we read a tag and hit upon the next frame marker - if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0) - { - if (hi2 != 0){ - Dbprintf("TAG ID: %x%08x%08x (%d)", - (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + if (hi2 != 0){ //extra large HID tags + Dbprintf("TAG ID: %x%08x%08x (%d)", + (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + }else { //standard HID tags <38 bits + //Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd + uint8_t bitlen = 0; + uint32_t fc = 0; + uint32_t cardnum = 0; + if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used + uint32_t lo2=0; + lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit + uint8_t idx3 = 1; + while(lo2>1){ //find last bit set to 1 (format len bit) + lo2=lo2>>1; + idx3++; + } + bitlen =idx3+19; + fc =0; + cardnum=0; + if(bitlen==26){ + cardnum = (lo>>1)&0xFFFF; + fc = (lo>>17)&0xFF; + } + if(bitlen==37){ + cardnum = (lo>>1)&0x7FFFF; + fc = ((hi&0xF)<<12)|(lo>>20); + } + if(bitlen==34){ + cardnum = (lo>>1)&0xFFFF; + fc= ((hi&1)<<15)|(lo>>17); } - else { - Dbprintf("TAG ID: %x%08x (%d)", - (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + if(bitlen==35){ + cardnum = (lo>>1)&0xFFFFF; + fc = ((hi&1)<<11)|(lo>>21); } } - - // reset - hi2 = hi = lo = 0; - numshifts = 0; - }else - { - idx++; + else { //if bit 38 is not set then 37 bit format is used + bitlen= 37; + fc =0; + cardnum=0; + if(bitlen==37){ + cardnum = (lo>>1)&0x7FFFF; + fc = ((hi&0xF)<<12)|(lo>>20); + } + } + //Dbprintf("TAG ID: %x%08x (%d)", + // (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); + Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", + (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, + (unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum); } + if (findone){ + if (ledcontrol) LED_A_OFF(); + return; + } + // reset + hi2 = hi = lo = 0; } WDT_HIT(); - - } + //SpinDelay(50); + } DbpString("Stopped"); if (ledcontrol) LED_A_OFF(); } -uint32_t bytebits_to_byte(uint8_t* src, int numbits) -{ - uint32_t num = 0; - for(int i = 0 ; i < numbits ; i++) - { - num = (num << 1) | (*src); - src++; - } - return num; -} - - -void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) +void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol) { uint8_t *dest = (uint8_t *)BigBuf; - size_t size=0, idx=0; - uint32_t code=0, code2=0; - + size_t size=0; //, found=0; + int bitLen=0; + int clk=0, invert=0, errCnt=0; + uint64_t lo=0; + // Configure to go in 125Khz listen mode + LFSetupFPGAForADC(95, true); while(!BUTTON_PRESS()) { - // Configure to go in 125Khz listen mode - LFSetupFPGAForADC(0, true); - WDT_HIT(); if (ledcontrol) LED_A_ON(); - DoAcquisition125k_internal(true); + DoAcquisition125k_internal(-1,true); size = sizeof(BigBuf); - + if (size < 2000) continue; // FSK demodulator - size = fsk_demod(dest, size); + //int askmandemod(uint8_t *BinStream,uint32_t *BitLen,int *clk, int *invert); + bitLen=size; + //Dbprintf("DEBUG: Buffer got"); + errCnt = askmandemod(dest,&bitLen,&clk,&invert); //HIDdemodFSK(dest,size,&hi2,&hi,&lo); + //Dbprintf("DEBUG: ASK Got"); WDT_HIT(); - // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns - // 1->0 : fc/8 in sets of 7 - // 0->1 : fc/10 in sets of 6 - size = aggregate_bits(dest, size, 7,6,13); + if (errCnt>=0){ + lo = Em410xDecode(dest,bitLen); + //Dbprintf("DEBUG: EM GOT"); + //printEM410x(lo); + if (lo>0){ + Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",(uint32_t)(lo>>32),(uint32_t)lo,(uint32_t)(lo&0xFFFF),(uint32_t)((lo>>16LL) & 0xFF),(uint32_t)(lo & 0xFFFFFF)); + } + if (findone){ + if (ledcontrol) LED_A_OFF(); + return; + } + } else{ + //Dbprintf("DEBUG: No Tag"); + } + WDT_HIT(); + lo = 0; + clk=0; + invert=0; + errCnt=0; + size=0; + //SpinDelay(50); + } + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); +} +void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) +{ + uint8_t *dest = (uint8_t *)BigBuf; + size_t size=0; + int idx=0; + uint32_t code=0, code2=0; + uint8_t version=0; + uint8_t facilitycode=0; + uint16_t number=0; + // Configure to go in 125Khz listen mode + LFSetupFPGAForADC(95, true); + + while(!BUTTON_PRESS()) { WDT_HIT(); - - //Handle the data - uint8_t mask[] = {0,0,0,0,0,0,0,0,0,1}; - for( idx=0; idx < size - 64; idx++) { - - if ( memcmp(dest + idx, mask, sizeof(mask)) ) continue; - - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+8], dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+16],dest[idx+17],dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+24],dest[idx+25],dest[idx+26],dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35],dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44],dest[idx+45],dest[idx+46],dest[idx+47]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53],dest[idx+54],dest[idx+55]); - Dbprintf("%d%d%d%d%d%d%d%d",dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); - - code = bytebits_to_byte(dest+idx,32); - code2 = bytebits_to_byte(dest+idx+32,32); - - short version = bytebits_to_byte(dest+idx+14,4); - char unknown = bytebits_to_byte(dest+idx+19,8) ; - uint16_t number = bytebits_to_byte(dest+idx+36,9); - - Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,unknown,number,code,code2); - if (ledcontrol) LED_D_OFF(); - + if (ledcontrol) LED_A_ON(); + DoAcquisition125k_internal(-1,true); + size = sizeof(BigBuf); + //make sure buffer has data + if (size < 2000) continue; + //fskdemod and get start index + WDT_HIT(); + idx = IOdemodFSK(dest,size); + if (idx>0){ + //valid tag found + + //Index map + //0 10 20 30 40 50 60 + //| | | | | | | + //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 + //----------------------------------------------------------------------------- + //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 + // + //XSF(version)facility:codeone+codetwo + //Handle the data + if(findone){ //only print binary if we are doing one + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]); + Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]); + Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); + } + code = bytebits_to_byte(dest+idx,32); + code2 = bytebits_to_byte(dest+idx+32,32); + version = bytebits_to_byte(dest+idx+27,8); //14,4 + facilitycode = bytebits_to_byte(dest+idx+18,8) ; + number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9 + + Dbprintf("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2); // if we're only looking for one tag if (findone){ - LED_A_OFF(); + if (ledcontrol) LED_A_OFF(); + //LED_A_OFF(); return; - } - } + } + code=code2=0; + version=facilitycode=0; + number=0; + idx=0; + } WDT_HIT(); } DbpString("Stopped"); @@ -939,7 +925,8 @@ void T55xxWriteBit(int bit) // Write one card block in page 0, no lock void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode) { - unsigned int i; + //unsigned int i; //enio adjustment 12/10/14 + uint32_t i; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz @@ -984,8 +971,8 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode) { uint8_t *dest = (uint8_t *)BigBuf; - int m=0, i=0; - + //int m=0, i=0; //enio adjustment 12/10/14 + uint32_t m=0, i=0; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); m = sizeof(BigBuf); // Clear destination buffer before sending the command @@ -1445,78 +1432,81 @@ int DemodPCF7931(uint8_t **outBlocks) { for (bitidx = 0; i < GraphTraceLen; i++) { - if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin)) - { - lc = i - lastval; - lastval = i; - - // Switch depending on lc length: - // Tolerance is 1/8 of clock rate (arbitrary) - if (abs(lc-clock/4) < tolerance) { - // 16T0 - if((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ - i += (128+127+16+32+33+16)-1; - lastval = i; - pmc = 0; - block_done = 1; - } - else { - pmc = i; - } - } else if (abs(lc-clock/2) < tolerance) { - // 32TO - if((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ - i += (128+127+16+32+33)-1; - lastval = i; - pmc = 0; - block_done = 1; - } - else if(half_switch == 1) { - BitStream[bitidx++] = 0; - half_switch = 0; - } - else - half_switch++; - } else if (abs(lc-clock) < tolerance) { - // 64TO - BitStream[bitidx++] = 1; - } else { - // Error - warnings++; - if (warnings > 10) - { - Dbprintf("Error: too many detection errors, aborting."); - return 0; - } - } - - if(block_done == 1) { - if(bitidx == 128) { - for(j=0; j<16; j++) { - Blocks[num_blocks][j] = 128*BitStream[j*8+7]+ - 64*BitStream[j*8+6]+ - 32*BitStream[j*8+5]+ - 16*BitStream[j*8+4]+ - 8*BitStream[j*8+3]+ - 4*BitStream[j*8+2]+ - 2*BitStream[j*8+1]+ - BitStream[j*8]; - } - num_blocks++; - } - bitidx = 0; - block_done = 0; - half_switch = 0; - } - if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0; - else dir = 1; - } - if(bitidx==255) - bitidx=0; - warnings = 0; - if(num_blocks == 4) break; + if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin)) + { + lc = i - lastval; + lastval = i; + + // Switch depending on lc length: + // Tolerance is 1/8 of clock rate (arbitrary) + if (abs(lc-clock/4) < tolerance) { + // 16T0 + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33+16)-1; + lastval = i; + pmc = 0; + block_done = 1; + } + else { + pmc = i; + } + } else if (abs(lc-clock/2) < tolerance) { + // 32TO + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33)-1; + lastval = i; + pmc = 0; + block_done = 1; + } + else if(half_switch == 1) { + BitStream[bitidx++] = 0; + half_switch = 0; + } + else + half_switch++; + } else if (abs(lc-clock) < tolerance) { + // 64TO + BitStream[bitidx++] = 1; + } else { + // Error + warnings++; + if (warnings > 10) + { + Dbprintf("Error: too many detection errors, aborting."); + return 0; + } + } + + if(block_done == 1) { + if(bitidx == 128) { + for(j=0; j<16; j++) { + Blocks[num_blocks][j] = 128*BitStream[j*8+7]+ + 64*BitStream[j*8+6]+ + 32*BitStream[j*8+5]+ + 16*BitStream[j*8+4]+ + 8*BitStream[j*8+3]+ + 4*BitStream[j*8+2]+ + 2*BitStream[j*8+1]+ + BitStream[j*8]; + } + num_blocks++; + } + bitidx = 0; + block_done = 0; + half_switch = 0; + } + if(i < GraphTraceLen) + { + if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0; + else dir = 1; + } + } + if(bitidx==255) + bitidx=0; + warnings = 0; + if(num_blocks == 4) break; } memcpy(outBlocks, Blocks, 16*num_blocks); return num_blocks;