diff --git a/armsrc/felica.c b/armsrc/felica.c new file mode 100644 index 000000000..d06b4eeb0 --- /dev/null +++ b/armsrc/felica.c @@ -0,0 +1,658 @@ +#include "proxmark3.h" +#include "apps.h" +#include "BigBuf.h" +#include "util.h" +#include "usb_cdc.h" // for usb_poll_validate_length +#include "../common/protocols.h" + + + +//random service RW: 0x0009 +//random service RO: 0x000B + +//structure to hold outgoing NFC frame +static uint8_t frameSpace[MAX_FRAME_SIZE+4]; + +//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames +static struct { + enum { + STATE_UNSYNCD, + STATE_TRYING_SYNC, + STATE_GET_LENGTH, + STATE_GET_DATA, + STATE_GET_CRC, + STATE_FULL + } state; + + uint16_t shiftReg; //for synchronization and offset calculation + int posCnt; + uint8_t crc_ok; + int rem_len; + uint16_t len; + uint8_t byte_offset; + uint16_t rolling_crc; + uint8_t framebytes[260]; //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc + // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc +} NFCFrame; + +//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in +//bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in + +# define SYNC_16BIT 45645 + +static void ResetNFCFrame() { + NFCFrame.state = STATE_UNSYNCD; + NFCFrame.posCnt = 0; + NFCFrame.crc_ok = 0; + NFCFrame.byte_offset = 0; + NFCFrame.rolling_crc = 0; +} + +uint8_t reverse(uint8_t b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; +} + +//shift byte into frame, reversing it at the same time +static void shiftInByte(uint8_t bt) { + + for(int j=0; j < NFCFrame.byte_offset; j++) { + NFCFrame.framebytes[NFCFrame.posCnt] = ( NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); + bt >>= 1; + } + NFCFrame.posCnt++; + NFCFrame.rem_len--; + for(int j = NFCFrame.byte_offset; j<8; j++) { + NFCFrame.framebytes[NFCFrame.posCnt] = (NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); + bt >>= 1; + } +} + +//crc table - from lammertb/libcrc +static uint16_t crc_tabccitt[256]; +static uint8_t crc_tabccitt_init = 0; + +static void init_crcccitt_tab( void ) +{ + uint16_t i; + uint16_t j; + uint16_t crc; + uint16_t c; + + for (i=0; i<256; i++) { + + crc = 0; + c = i << 8; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ 0x1021; + else crc = crc << 1; + + c = c << 1; + } + + crc_tabccitt[i] = crc; + } + + crc_tabccitt_init = true; + +} + +static uint16_t update_crc_ccitt( uint16_t crc, unsigned char c ) +{ + //rely on prior init + //if ( ! crc_tabccitt_init ) init_crcccitt_tab(); + return (crc << 8) ^ crc_tabccitt[ ((crc >> 8) ^ (uint16_t) c) & 0x00FF ]; +} + +static void ProcessNFCByte(uint8_t bt) { + switch (NFCFrame.state) { + case STATE_UNSYNCD: { + //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case + if (bt > 0) { + NFCFrame.shiftReg = reverse(bt); + NFCFrame.state = STATE_TRYING_SYNC; + } + }; + break; + case STATE_TRYING_SYNC: + { + if(bt==0) + { + //desync + NFCFrame.shiftReg=bt; + NFCFrame.state=STATE_UNSYNCD; + } + else + { + for(int i=0;i<8;i++) + { + if(NFCFrame.shiftReg==SYNC_16BIT) + { //SYNC done! + NFCFrame.state=STATE_GET_LENGTH; + NFCFrame.framebytes[0]=0xb2; + NFCFrame.framebytes[1]=0x4d; //write SYNC + NFCFrame.byte_offset=i; + //shift in remaining byte, slowly... + for(int j=i;j<8;j++) + { + NFCFrame.framebytes[2]=(NFCFrame.framebytes[2]<<1)+(bt&1); + bt>>=1; + } + + NFCFrame.posCnt=2; + if(i==0) + break; + } + NFCFrame.shiftReg=(NFCFrame.shiftReg<<1)+(bt&1); + bt>>=1; + } + + //that byte was last byte of sync + if(NFCFrame.shiftReg==SYNC_16BIT) + { //Force SYNC on next byte + NFCFrame.state=STATE_GET_LENGTH; + NFCFrame.framebytes[0]=0xb2; + NFCFrame.framebytes[1]=0x4d; + NFCFrame.byte_offset=0; + NFCFrame.posCnt=1; + } + } + };break; + case STATE_GET_LENGTH: + { + + shiftInByte(bt); + NFCFrame.rem_len= NFCFrame.framebytes[2]-1; + NFCFrame.rolling_crc=update_crc_ccitt(0,NFCFrame.framebytes[2]); //start calculating CRC for later + NFCFrame.len= NFCFrame.framebytes[2]+4;//with crc and sync + NFCFrame.state=STATE_GET_DATA; + };break; + case STATE_GET_DATA: + { + shiftInByte(bt); + if(NFCFrame.byte_offset!=0) + NFCFrame.rolling_crc=update_crc_ccitt(NFCFrame.rolling_crc,NFCFrame.framebytes[NFCFrame.posCnt-1]); + else + NFCFrame.rolling_crc=update_crc_ccitt(NFCFrame.rolling_crc,NFCFrame.framebytes[NFCFrame.posCnt]); + + if(NFCFrame.rem_len<=0) + { + NFCFrame.state=STATE_GET_CRC; + NFCFrame.rem_len=2; + } + + + };break; + case STATE_GET_CRC: + { + shiftInByte(bt); + if(NFCFrame.rem_len<=0) + { + NFCFrame.crc_ok=((NFCFrame.rolling_crc&0xff)==NFCFrame.framebytes[NFCFrame.len-1]&&(NFCFrame.rolling_crc>>8)==NFCFrame.framebytes[NFCFrame.len-2]) ; + + NFCFrame.state=STATE_FULL; + NFCFrame.rem_len=0; + } + + };break; + case STATE_FULL: + { + //ignore byte. Don't forget to clear frame to receive next one... + + };break; + } +} + +void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { + if(!crc_tabccitt_init) + init_crcccitt_tab(); + + BigBuf_free(); BigBuf_Clear(); + + int remFrames = (samplesToSkip) ? samplesToSkip : 0; + + Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); + + LED_D_ON(); + // Select correct configs + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092|FPGA_HF_ISO18092_FLAG_NOMOD); + SpinDelay(100); + + //the frame bits are slow enough. + int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory + + uint8_t *dest = (uint8_t *)BigBuf_get_addr(); + uint8_t *destend = dest + n-2; + StartCountSspClk(); //for apx frame timing + + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + ResetNFCFrame(); + + int numbts=0; + + uint32_t endframe= GetCountSspClk(); + + while(dest <= destend) + { + WDT_HIT(); + if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) + { + uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + ProcessNFCByte(dist); + + if(NFCFrame.state==STATE_GET_LENGTH) //to be sure we are in frame + { + //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% + uint16_t distance=GetCountSspClk()-endframe-64+(NFCFrame.byte_offset>0?(8-NFCFrame.byte_offset):0); + *dest=distance>>8; + dest++; + *dest=(distance&0xff); + dest++; + } + if(NFCFrame.state==STATE_FULL) //crc NOT checked + { + endframe=GetCountSspClk(); + *dest=NFCFrame.crc_ok; //kind of wasteful + dest++; + for(int i=0;i=destend ) break; + + } + + remFrames--; + if (remFrames<=0) break; + if (dest>=destend ) break; + numbts+=NFCFrame.len; + ResetNFCFrame(); + } + } + if( BUTTON_PRESS()) break; + } + + //reset framing + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + set_tracelen(numbts); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations",BigBuf_get_traceLen()); + LED_D_OFF(); +} + +// poll-0: 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21, +// resp: 0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80,0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f, +// poll-1 (reply with available system codes - NFC Tag3 specs, IIRC): 0xb2,0x4d,0x06,0x00,0xff,0xff,0x01,0x00,0x3a,0x10 +// resp: 0xb2,0x4d,0x14,0x01, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0x0c,0xe2, +// page-req: 0xb2,0x4d,0x10,0x06, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x01, 0x0b,0x00, 0x01, 0x80,0x00, 0x2e,0xb3, +// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num) +// page-resp: 0xb2,0x4d,0x1d,0x07, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00, 0x00, 0x01, 0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23, 0xcb,0x6e, + +void SetcrcToFrame(uint8_t * framebf) { + //expect framebuf to be preset with len... + uint16_t crc = 0; + for(int i=2; i < 2 + framebf[2]; i++) { + crc = update_crc_ccitt(crc, framebf[i]); + } + framebf[2+framebf[2]] = (crc >> 8); + framebf[3+framebf[2]] = (crc & 0xff); +} + +//builds a readblock frame for felica lite(s). Felica standart has a different file system, AFAIK +// 8-byte ndef, number of blocks, blocks numbers +// number of blocks limited to 4 for FelicaLite(S) +static void BuildFliteRdblk(uint8_t* ndef, int blocknum,uint16_t * blocks ) +{ + if(blocknum>4||blocknum<=0) + { + Dbprintf("Invalid number of blocks, %d. Up to 4 are allowed.",blocknum); + } + int c=0,i=0; + frameSpace[c++]=0xb2; + frameSpace[c++]=0x4d; + c++; //set length later + frameSpace[c++]=FELICA_RDBLK_REQ; //command number + for(i=0;i<8;i++) //card IDm, from poll + frameSpace[c++]=ndef[i]; + + frameSpace[c++]=0x01; //number of services + frameSpace[c++]= (uint8_t)(((uint16_t)FLITE_SERVICE_RO)&0xff);//service code -big endian? + frameSpace[c++]= (uint8_t)(((uint16_t)FLITE_SERVICE_RO)>>8); + frameSpace[c++]=blocknum; //number of blocks + for(i=0;i=256) //3-byte block + { + frameSpace[c++]=0x00; + frameSpace[c++]=(blocks[i]>>8); //block number, little endian.... + frameSpace[c++]=(blocks[i]&0xff); + + } + else + { + frameSpace[c++]=0x80; + frameSpace[c++]=blocks[i]; + } + } + frameSpace[2]=c-2; //set length + SetcrcToFrame(frameSpace); +} + +//legacy, technically. +static int manch_tbl_fill = 0; +static uint8_t manch_tbl[16] = {0}; + +static void fillManch() { + for(uint8_t obs = 0; obs < 16; obs++) { + uint8_t res = 0; + uint8_t tmp = obs << 4; + for(int j=0; j<4; j++) { + res <<= 2; + if (tmp & 0x80) + res += 2; + else + res += 1; + tmp <<= 1; + } + manch_tbl[obs] = res; + } + manch_tbl_fill = 1; +} + +static void sendNFCToFPGA(uint8_t * frame, int len, uint32_t waitTill, uint8_t power, uint8_t highspeed) { + if(!manch_tbl_fill) + fillManch(); + + volatile uint32_t b; + + int c; + uint32_t ThisTransferTime = 0; + + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 |( power? FPGA_HF_ISO18092_FLAG_READER:0) |(highspeed?FPGA_HF_ISO18092_FLAG_424K:0) ); + + if (power) + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 |FPGA_HF_ISO18092_FLAG_READER |(highspeed>0) ); + else + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 ); + + if(waitTill>0) { + while( (ThisTransferTime = GetCountSspClk()) < waitTill) + WDT_HIT(); + } + + //preamble + for(c = 0; c < 6;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + c++; + } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; + } + + for(c = 0; c < len;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = frame[c]; + c++; + } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; + } + + while(!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; + AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay + + while(!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; + AT91C_BASE_SSC->SSC_THR = 0x00; //spin + + //disable + if (power) + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 |FPGA_HF_ISO18092_FLAG_READER | 1); + else + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | 1 ); +} + +//simulate NFC Tag3 card - for now only poll response works +// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 +void HfSimLite( uint64_t nfcid) { + + if(!crc_tabccitt_init) + init_crcccitt_tab(); + + if(!manch_tbl_fill) + fillManch(); + + uint8_t ndef[8]; + num_to_bytes(nfcid, 8, ndef); + + //NFC tag 3/ ISo technically. Many overlapping standards + DbpString("Felica Lite-S sim start"); + Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x",ndef[0],ndef[1],ndef[2],ndef[3],ndef[4],ndef[5],ndef[6],ndef[7]); + //prepare our 3 responses... + +#define R_POLL0_LEN 0x16 +#define R_POLL1_LEN 0x18 +#define R_READBLK_LEN 0x21 + + uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; + uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; + + int i; + uint8_t *curresp = 0; + int curlen = 0; + + //fill in blanks + for( i=0; i<8; i++) { + resp_poll0[i+4] = ndef[i]; + resp_poll1[i+4] = ndef[i]; + resp_readblk[i+4] = ndef[i]; + } + //calculate and set CRC + SetcrcToFrame(resp_poll0); + SetcrcToFrame(resp_poll1); + SetcrcToFrame(resp_readblk); + + // Select correct configs + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092|FPGA_HF_ISO18092_FLAG_NOMOD); + SpinDelay(100); + + //it might be possible to use MSB? + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + + ResetNFCFrame(); + StartCountSspClk(); // should work without now, this is mostly for debugging + + bool listenmode = true; + uint32_t frtm = GetCountSspClk(); + for(;;) { + WDT_HIT(); + + if (listenmode) { + //waiting for request... + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + + uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + frtm = GetCountSspClk(); + ProcessNFCByte(dist); + + if (NFCFrame.state==STATE_FULL) { + + if (NFCFrame.crc_ok) { + + if (NFCFrame.framebytes[2] == 6 && NFCFrame.framebytes[3] == 0) { + + //polling... there are two types of polling we answer to + if (NFCFrame.framebytes[6] == 0) { + curresp = resp_poll0; + curlen = R_POLL0_LEN; + listenmode = false; + } + if (NFCFrame.framebytes[6]==1) { + curresp = resp_poll1; + curlen = R_POLL1_LEN; + listenmode = true; + } + } + + if (NFCFrame.framebytes[2] > 5 && NFCFrame.framebytes[3] == 0x06) { + //we should rebuild it depending on page size, but... + //Let's see first + curresp = resp_readblk; + curlen = R_READBLK_LEN; + listenmode = false; + } + //clear frame + ResetNFCFrame(); + } else { + //frame invalid, clear it out to allow for the next one + ResetNFCFrame(); + } + } + } + } + if (!listenmode) { + //trying to answer... here to start answering immediately. + //this one is a bit finicky. Seems that being a bit late is better than earlier + sendNFCToFPGA(curresp, curlen, frtm+512, 0, 0); + + //switch back + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); + + ResetNFCFrame(); + listenmode = true; + curlen = 0; + curresp = NULL; + } + if( BUTTON_PRESS()) break; + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Felica Lite-S sim end"); +} + +int WaitForFelicaReply(int maxbytes) { + int bcnt = 0; + ResetNFCFrame(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 |FPGA_HF_ISO18092_FLAG_NOMOD|FPGA_HF_ISO18092_FLAG_READER); + + for (; bcnt < maxbytes; ) { + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + + ProcessNFCByte(dist); + bcnt++; + if (NFCFrame.state == STATE_FULL) { + if (NFCFrame.crc_ok) { + return 1; + } else { + Dbprintf("Got frame %d with wrong crc, crc %02x %02x", NFCFrame.framebytes[3], (NFCFrame.rolling_crc & 0xff), (NFCFrame.rolling_crc>>8)); + int j; + for(j = 0; j < 25; j++) + Dbprintf("%02x ", NFCFrame.framebytes[j]); + return 0; + } + break ; + } + } + } + return 0; +} + +void HfDumpFelicaLiteS() { + + DbpString("Felica Lite-S READ start"); + + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaSetupSsc(); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + BigBuf_free(); BigBuf_Clear(); + + uint8_t ndef[8]; + uint8_t poll[10] = { 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21}; + uint16_t liteblks[28] = {0x00, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; + + if(!crc_tabccitt_init) + init_crcccitt_tab(); + + if(!manch_tbl_fill) + fillManch(); + + ResetNFCFrame(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER |FPGA_HF_ISO18092_FLAG_NOMOD); + + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + + SpinDelay(500); + + StartCountSspClk(); + + int c; + int cnt = 0; + int cntfails = 0; + uint8_t *dest = (uint8_t *)BigBuf_get_addr(); + + for (;;) { + sendNFCToFPGA(poll,10,GetCountSspClk()+8,1,0); + if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) { + for (c=0; c<8; c++) + ndef[c] = NFCFrame.framebytes[c+4]; + + for (c=0; c<28;) { + BuildFliteRdblk(ndef,1,&liteblks[c]); + sendNFCToFPGA(frameSpace,frameSpace[2]+4,GetCountSspClk()+8,1,0); + if (WaitForFelicaReply(1024) && NFCFrame.framebytes[3] == FELICA_RDBLK_ACK) { + + dest[cnt++] = liteblks[c]; + + uint8_t * fb = NFCFrame.framebytes; + dest[cnt++] = fb[12]; + dest[cnt++] = fb[13]; + + for(int j=0; j<16; j++) + dest[cnt++] = fb[15+j]; + + c++; + cntfails = 0; + } else { + cntfails++; + if (cntfails>12) { + c++; + cntfails = 0; + } + } + } + break; + } + //Resetting Frame mode (First set in fpgaloader.c) + if( BUTTON_PRESS()) + break; + + SpinDelay(500); + if( BUTTON_PRESS()) + break; + } + + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + //setting tracelen - important! it was set by buffer overflow before + set_tracelen(cnt); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + +} +