armsrc: fix mix of spaces & tabs

This commit is contained in:
Philippe Teuwen 2019-03-09 20:34:41 +01:00
commit 8a7c6825b5
47 changed files with 18186 additions and 18184 deletions

View file

@ -20,7 +20,7 @@ Pointer to highest available memory: BigBuf_hi
high BIGBUF_SIZE high BIGBUF_SIZE
reserved = BigBuf_malloc() subtracts amount from BigBuf_hi, reserved = BigBuf_malloc() subtracts amount from BigBuf_hi,
low 0x00 low 0x00
*/ */
// High memory mark // High memory mark
@ -35,92 +35,92 @@ static bool tracing = true; //todo static?
// get the address of BigBuf // get the address of BigBuf
uint8_t *BigBuf_get_addr(void) { uint8_t *BigBuf_get_addr(void) {
return (uint8_t *)BigBuf; return (uint8_t *)BigBuf;
} }
// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
uint8_t *BigBuf_get_EM_addr(void) { uint8_t *BigBuf_get_EM_addr(void) {
// not yet allocated // not yet allocated
if (emulator_memory == NULL) if (emulator_memory == NULL)
emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE); emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
return emulator_memory; return emulator_memory;
} }
// clear ALL of BigBuf // clear ALL of BigBuf
void BigBuf_Clear(void) { void BigBuf_Clear(void) {
BigBuf_Clear_ext(true); BigBuf_Clear_ext(true);
} }
// clear ALL of BigBuf // clear ALL of BigBuf
void BigBuf_Clear_ext(bool verbose) { void BigBuf_Clear_ext(bool verbose) {
memset(BigBuf, 0, BIGBUF_SIZE); memset(BigBuf, 0, BIGBUF_SIZE);
if (verbose) if (verbose)
Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE); Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE);
} }
void BigBuf_Clear_EM(void) { void BigBuf_Clear_EM(void) {
memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE); memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE);
} }
void BigBuf_Clear_keep_EM(void) { void BigBuf_Clear_keep_EM(void) {
memset(BigBuf, 0, BigBuf_hi); memset(BigBuf, 0, BigBuf_hi);
} }
// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
// at the beginning of BigBuf is always for traces/samples // at the beginning of BigBuf is always for traces/samples
uint8_t *BigBuf_malloc(uint16_t chunksize) { uint8_t *BigBuf_malloc(uint16_t chunksize) {
if (BigBuf_hi - chunksize < 0) if (BigBuf_hi - chunksize < 0)
return NULL; // no memory left return NULL; // no memory left
chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4 chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
BigBuf_hi -= chunksize; // aligned to 4 Byte boundary BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
return (uint8_t *)BigBuf + BigBuf_hi; return (uint8_t *)BigBuf + BigBuf_hi;
} }
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again. // free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
void BigBuf_free(void){ void BigBuf_free(void){
BigBuf_hi = BIGBUF_SIZE; BigBuf_hi = BIGBUF_SIZE;
emulator_memory = NULL; emulator_memory = NULL;
// shouldn't this empty BigBuf also? // shouldn't this empty BigBuf also?
} }
// free allocated chunks EXCEPT the emulator memory // free allocated chunks EXCEPT the emulator memory
void BigBuf_free_keep_EM(void) { void BigBuf_free_keep_EM(void) {
if (emulator_memory != NULL) if (emulator_memory != NULL)
BigBuf_hi = emulator_memory - (uint8_t *)BigBuf; BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
else else
BigBuf_hi = BIGBUF_SIZE; BigBuf_hi = BIGBUF_SIZE;
// shouldn't this empty BigBuf also? // shouldn't this empty BigBuf also?
} }
void BigBuf_print_status(void) { void BigBuf_print_status(void) {
Dbprintf("Memory"); Dbprintf("Memory");
Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
Dbprintf(" Available memory........%d", BigBuf_hi); Dbprintf(" Available memory........%d", BigBuf_hi);
Dbprintf("Tracing"); Dbprintf("Tracing");
Dbprintf(" tracing ................%d", tracing); Dbprintf(" tracing ................%d", tracing);
Dbprintf(" traceLen ...............%d", traceLen); Dbprintf(" traceLen ...............%d", traceLen);
} }
// return the maximum trace length (i.e. the unallocated size of BigBuf) // return the maximum trace length (i.e. the unallocated size of BigBuf)
uint16_t BigBuf_max_traceLen(void) { uint16_t BigBuf_max_traceLen(void) {
return BigBuf_hi; return BigBuf_hi;
} }
void clear_trace(void) { void clear_trace(void) {
traceLen = 0; traceLen = 0;
} }
void set_tracelen(uint32_t value) { void set_tracelen(uint32_t value) {
traceLen = value; traceLen = value;
} }
void set_tracing(bool enable) { void set_tracing(bool enable) {
tracing = enable; tracing = enable;
} }
bool get_tracing(void) { bool get_tracing(void) {
return tracing; return tracing;
} }
/** /**
@ -128,7 +128,7 @@ bool get_tracing(void) {
* @return * @return
*/ */
uint32_t BigBuf_get_traceLen(void) { uint32_t BigBuf_get_traceLen(void) {
return traceLen; return traceLen;
} }
/** /**
@ -138,111 +138,111 @@ uint32_t BigBuf_get_traceLen(void) {
annotation of commands/responses. annotation of commands/responses.
**/ **/
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) { bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) {
if (!tracing) return false; if (!tracing) return false;
uint8_t *trace = BigBuf_get_addr(); uint8_t *trace = BigBuf_get_addr();
uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity
uint32_t duration = timestamp_end - timestamp_start; uint32_t duration = timestamp_end - timestamp_start;
// Return when trace is full // Return when trace is full
if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) { if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) {
tracing = false; // don't trace any more tracing = false; // don't trace any more
return false; return false;
} }
// Traceformat: // Traceformat:
// 32 bits timestamp (little endian) // 32 bits timestamp (little endian)
// 16 bits duration (little endian) // 16 bits duration (little endian)
// 16 bits data length (little endian, Highest Bit used as readerToTag flag) // 16 bits data length (little endian, Highest Bit used as readerToTag flag)
// y Bytes data // y Bytes data
// x Bytes parity (one byte per 8 bytes data) // x Bytes parity (one byte per 8 bytes data)
// timestamp (start) // timestamp (start)
trace[traceLen++] = ((timestamp_start >> 0) & 0xff); trace[traceLen++] = ((timestamp_start >> 0) & 0xff);
trace[traceLen++] = ((timestamp_start >> 8) & 0xff); trace[traceLen++] = ((timestamp_start >> 8) & 0xff);
trace[traceLen++] = ((timestamp_start >> 16) & 0xff); trace[traceLen++] = ((timestamp_start >> 16) & 0xff);
trace[traceLen++] = ((timestamp_start >> 24) & 0xff); trace[traceLen++] = ((timestamp_start >> 24) & 0xff);
// duration // duration
trace[traceLen++] = ((duration >> 0) & 0xff); trace[traceLen++] = ((duration >> 0) & 0xff);
trace[traceLen++] = ((duration >> 8) & 0xff); trace[traceLen++] = ((duration >> 8) & 0xff);
// data length // data length
trace[traceLen++] = ((iLen >> 0) & 0xff); trace[traceLen++] = ((iLen >> 0) & 0xff);
trace[traceLen++] = ((iLen >> 8) & 0xff); trace[traceLen++] = ((iLen >> 8) & 0xff);
// readerToTag flag // readerToTag flag
if (!readerToTag) { if (!readerToTag) {
trace[traceLen - 1] |= 0x80; trace[traceLen - 1] |= 0x80;
} }
// data bytes // data bytes
if (btBytes != NULL && iLen != 0) { if (btBytes != NULL && iLen != 0) {
memcpy(trace + traceLen, btBytes, iLen); memcpy(trace + traceLen, btBytes, iLen);
} }
traceLen += iLen; traceLen += iLen;
// parity bytes // parity bytes
if (num_paritybytes != 0) { if (num_paritybytes != 0) {
if (parity != NULL) { if (parity != NULL) {
memcpy(trace + traceLen, parity, num_paritybytes); memcpy(trace + traceLen, parity, num_paritybytes);
} else { } else {
memset(trace + traceLen, 0x00, num_paritybytes); memset(trace + traceLen, 0x00, num_paritybytes);
} }
} }
traceLen += num_paritybytes; traceLen += num_paritybytes;
return true; return true;
} }
int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) { int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) {
/** /**
Todo, rewrite the logger to use the generic functionality instead. It should be noted, however, Todo, rewrite the logger to use the generic functionality instead. It should be noted, however,
that this logger takes number of bits as argument, not number of bytes. that this logger takes number of bits as argument, not number of bytes.
**/ **/
if (!tracing) return false; if (!tracing) return false;
uint8_t *trace = BigBuf_get_addr(); uint8_t *trace = BigBuf_get_addr();
uint32_t iLen = nbytes(iBits); uint32_t iLen = nbytes(iBits);
// Return when trace is full // Return when trace is full
if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false; if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false;
//Hitag traces appear to use this traceformat: //Hitag traces appear to use this traceformat:
// 32 bits timestamp (little endian,Highest Bit used as readerToTag flag) // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag)
// 32 bits parity // 32 bits parity
// 8 bits size (number of bits in the trace entry, not number of bytes) // 8 bits size (number of bits in the trace entry, not number of bytes)
// y Bytes data // y Bytes data
rsamples += iSamples; rsamples += iSamples;
trace[traceLen++] = ((rsamples >> 0) & 0xff); trace[traceLen++] = ((rsamples >> 0) & 0xff);
trace[traceLen++] = ((rsamples >> 8) & 0xff); trace[traceLen++] = ((rsamples >> 8) & 0xff);
trace[traceLen++] = ((rsamples >> 16) & 0xff); trace[traceLen++] = ((rsamples >> 16) & 0xff);
trace[traceLen++] = ((rsamples >> 24) & 0xff); trace[traceLen++] = ((rsamples >> 24) & 0xff);
if (!readerToTag) { if (!readerToTag) {
trace[traceLen - 1] |= 0x80; trace[traceLen - 1] |= 0x80;
} }
trace[traceLen++] = ((dwParity >> 0) & 0xff); trace[traceLen++] = ((dwParity >> 0) & 0xff);
trace[traceLen++] = ((dwParity >> 8) & 0xff); trace[traceLen++] = ((dwParity >> 8) & 0xff);
trace[traceLen++] = ((dwParity >> 16) & 0xff); trace[traceLen++] = ((dwParity >> 16) & 0xff);
trace[traceLen++] = ((dwParity >> 24) & 0xff); trace[traceLen++] = ((dwParity >> 24) & 0xff);
trace[traceLen++] = iBits; trace[traceLen++] = iBits;
memcpy(trace + traceLen, btBytes, iLen); memcpy(trace + traceLen, btBytes, iLen);
traceLen += iLen; traceLen += iLen;
return true; return true;
} }
// Emulator memory // Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){ uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
uint8_t* mem = BigBuf_get_EM_addr(); uint8_t* mem = BigBuf_get_EM_addr();
if (offset + length < CARD_MEMORY_SIZE) { if (offset + length < CARD_MEMORY_SIZE) {
memcpy(mem+offset, data, length); memcpy(mem+offset, data, length);
return 0; return 0;
} }
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE);
return 1; return 1;
} }

View file

@ -17,13 +17,13 @@
#include "string.h" #include "string.h"
#include "ticks.h" #include "ticks.h"
#define BIGBUF_SIZE 40000 #define BIGBUF_SIZE 40000
#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame #define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8) #define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC #define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these #define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
#define CARD_MEMORY_SIZE 4096 #define CARD_MEMORY_SIZE 4096
#define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? #define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!?
extern uint8_t *BigBuf_get_addr(void); extern uint8_t *BigBuf_get_addr(void);
extern uint8_t *BigBuf_get_EM_addr(void); extern uint8_t *BigBuf_get_EM_addr(void);

View file

@ -9,141 +9,141 @@
void LCDSend(unsigned int data) void LCDSend(unsigned int data)
{ {
// 9th bit set for data, clear for command // 9th bit set for data, clear for command
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
// For clarity's sake we pass data with 9th bit clear and commands with 9th // For clarity's sake we pass data with 9th bit clear and commands with 9th
// bit set since they're implemented as defines, se we need to invert bit // bit set since they're implemented as defines, se we need to invert bit
AT91C_BASE_SPI->SPI_TDR = data^0x100; // Send the data/command AT91C_BASE_SPI->SPI_TDR = data^0x100; // Send the data/command
} }
void LCDSetXY(unsigned char x, unsigned char y) void LCDSetXY(unsigned char x, unsigned char y)
{ {
LCDSend(PPASET); // page start/end ram LCDSend(PPASET); // page start/end ram
LCDSend(y); // Start Page to display to LCDSend(y); // Start Page to display to
LCDSend(131); // End Page to display to LCDSend(131); // End Page to display to
LCDSend(PCASET); // column start/end ram LCDSend(PCASET); // column start/end ram
LCDSend(x); // Start Column to display to LCDSend(x); // Start Column to display to
LCDSend(131); // End Column to display to LCDSend(131); // End Column to display to
} }
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color) void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color)
{ {
LCDSetXY(x,y); // Set position LCDSetXY(x,y); // Set position
LCDSend(PRAMWR); // Now write the pixel to the display LCDSend(PRAMWR); // Now write the pixel to the display
LCDSend(color); // Write the data in the specified Color LCDSend(color); // Write the data in the specified Color
} }
void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color) void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color)
{ {
unsigned char i,j; unsigned char i,j;
for (i=0;i < height;i++) // Number of horizontal lines for (i=0;i < height;i++) // Number of horizontal lines
{ {
LCDSetXY(xs,ys+i); // Goto start of fill area (Top Left) LCDSetXY(xs,ys+i); // Goto start of fill area (Top Left)
LCDSend(PRAMWR); // Write to display LCDSend(PRAMWR); // Write to display
for (j=0;j < width;j++) // pixels per line for (j=0;j < width;j++) // pixels per line
LCDSend(color); LCDSend(color);
} }
} }
void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor)
{ {
unsigned int i; unsigned int i;
unsigned char mask=0, px, py, xme, yme, offset; unsigned char mask=0, px, py, xme, yme, offset;
const char *data; const char *data;
data = font_style; // point to the start of the font table data = font_style; // point to the start of the font table
xme = *data; // get font x width xme = *data; // get font x width
data++; data++;
yme = *data; // get font y length yme = *data; // get font y length
data++; data++;
offset = *data; // get data bytes per font offset = *data; // get data bytes per font
do do
{ {
// point to data in table to be loaded // point to data in table to be loaded
data = (font_style + offset) + (offset * (int)(*lcd_string - 32)); data = (font_style + offset) + (offset * (int)(*lcd_string - 32));
for (i=0;i < yme;i++) { for (i=0;i < yme;i++) {
mask |=0x80; mask |=0x80;
for (px=x; px < (x + xme); px++) { for (px=x; px < (x + xme); px++) {
py= y + i; py= y + i;
if (*data & mask) LCDSetPixel (px,py,fcolor); if (*data & mask) LCDSetPixel (px,py,fcolor);
else LCDSetPixel (px,py,bcolor); else LCDSetPixel (px,py,bcolor);
mask>>=1; mask>>=1;
} }
data++; data++;
} }
x+=xme; x+=xme;
lcd_string++; // next character in string lcd_string++; // next character in string
} while(*lcd_string !='\0'); // keep spitting chars out until end of string } while(*lcd_string !='\0'); // keep spitting chars out until end of string
} }
void LCDReset(void) void LCDReset(void)
{ {
LED_A_ON(); LED_A_ON();
SetupSpi(SPI_LCD_MODE); SetupSpi(SPI_LCD_MODE);
LOW(GPIO_LRST); LOW(GPIO_LRST);
SpinDelay(100); SpinDelay(100);
HIGH(GPIO_LRST); HIGH(GPIO_LRST);
SpinDelay(100); SpinDelay(100);
LED_A_OFF(); LED_A_OFF();
} }
void LCDInit(void) void LCDInit(void)
{ {
int i; int i;
LCDReset(); LCDReset();
LCDSend(PSWRESET); // software reset LCDSend(PSWRESET); // software reset
SpinDelay(100); SpinDelay(100);
LCDSend(PSLEEPOUT); // exit sleep mode LCDSend(PSLEEPOUT); // exit sleep mode
LCDSend(PBSTRON); // booster on LCDSend(PBSTRON); // booster on
LCDSend(PDISPON); // display on LCDSend(PDISPON); // display on
LCDSend(PNORON); // normal on LCDSend(PNORON); // normal on
LCDSend(PMADCTL); // rotate display 180 deg LCDSend(PMADCTL); // rotate display 180 deg
LCDSend(0xC0); LCDSend(0xC0);
LCDSend(PCOLMOD); // color mode LCDSend(PCOLMOD); // color mode
LCDSend(0x02); // 8bpp color mode LCDSend(0x02); // 8bpp color mode
LCDSend(PSETCON); // set contrast LCDSend(PSETCON); // set contrast
LCDSend(0xDC); LCDSend(0xDC);
// clear display // clear display
LCDSetXY(0,0); LCDSetXY(0,0);
LCDSend(PRAMWR); // Write to display LCDSend(PRAMWR); // Write to display
i=LCD_XRES*LCD_YRES; i=LCD_XRES*LCD_YRES;
while(i--) LCDSend(WHITE); while(i--) LCDSend(WHITE);
// test text on different colored backgrounds // test text on different colored backgrounds
LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK ); LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK );
LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE ); LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE );
LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED ); LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED );
LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN ); LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN );
LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE ); LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE );
LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW); LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW);
LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN ); LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN );
LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA); LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
// color bands // color bands
LCDFill(0, 1+8* 8, 132, 8, BLACK); LCDFill(0, 1+8* 8, 132, 8, BLACK);
LCDFill(0, 1+8* 9, 132, 8, WHITE); LCDFill(0, 1+8* 9, 132, 8, WHITE);
LCDFill(0, 1+8*10, 132, 8, RED); LCDFill(0, 1+8*10, 132, 8, RED);
LCDFill(0, 1+8*11, 132, 8, GREEN); LCDFill(0, 1+8*11, 132, 8, GREEN);
LCDFill(0, 1+8*12, 132, 8, BLUE); LCDFill(0, 1+8*12, 132, 8, BLUE);
LCDFill(0, 1+8*13, 132, 8, YELLOW); LCDFill(0, 1+8*13, 132, 8, YELLOW);
LCDFill(0, 1+8*14, 132, 8, CYAN); LCDFill(0, 1+8*14, 132, 8, CYAN);
LCDFill(0, 1+8*15, 132, 8, MAGENTA); LCDFill(0, 1+8*15, 132, 8, MAGENTA);
} }

View file

@ -14,110 +14,110 @@
#include "fonts.h" #include "fonts.h"
// The resolution of the LCD // The resolution of the LCD
#define LCD_XRES 132 #define LCD_XRES 132
#define LCD_YRES 132 #define LCD_YRES 132
// 8bpp Color Mode - Some basic colors defined for ease of use // 8bpp Color Mode - Some basic colors defined for ease of use
// remember 8bpp color = 3xRed, 3xGreen & 2xBlue bits // remember 8bpp color = 3xRed, 3xGreen & 2xBlue bits
// organised as RRRGGGBB // organised as RRRGGGBB
#define BLACK 0x00 #define BLACK 0x00
#define BLUE 0x03 #define BLUE 0x03
#define GREEN 0x1C #define GREEN 0x1C
#define CYAN 0x1F #define CYAN 0x1F
#define RED 0xE0 #define RED 0xE0
#define MAGENTA 0xE3 #define MAGENTA 0xE3
#define YELLOW 0xFC #define YELLOW 0xFC
#define WHITE 0xFF #define WHITE 0xFF
// EPSON LCD command set // EPSON LCD command set
#define ECASET 0x115 #define ECASET 0x115
#define EPWRCTR 0x120 #define EPWRCTR 0x120
#define ENOP 0x125 #define ENOP 0x125
#define ERAMWR 0x15C #define ERAMWR 0x15C
#define ERAMRD 0x15D #define ERAMRD 0x15D
#define EPASET 0x175 #define EPASET 0x175
#define EEPSRRD1 0x17C #define EEPSRRD1 0x17C
#define EEPSRRD2 0x17D #define EEPSRRD2 0x17D
#define EVOLCTR 0x181 #define EVOLCTR 0x181
#define ETMPGRD 0x182 #define ETMPGRD 0x182
#define ESLPOUT 0x194 #define ESLPOUT 0x194
#define ESLPIN 0x195 #define ESLPIN 0x195
#define EDISNOR 0x1A6 #define EDISNOR 0x1A6
#define EDISINV 0x1A7 #define EDISINV 0x1A7
#define EPTLIN 0x1A8 #define EPTLIN 0x1A8
#define EPTLOUT 0x1A9 #define EPTLOUT 0x1A9
#define EASCSET 0x1AA #define EASCSET 0x1AA
#define ESCSTART 0x1AB #define ESCSTART 0x1AB
#define EDISOFF 0x1AE #define EDISOFF 0x1AE
#define EDISON 0x1AF #define EDISON 0x1AF
#define ECOMSCN 0x1BB #define ECOMSCN 0x1BB
#define EDATCTL 0x1BC #define EDATCTL 0x1BC
#define EDISCTL 0x1CA #define EDISCTL 0x1CA
#define EEPCOUT 0x1CC #define EEPCOUT 0x1CC
#define EEPCTIN 0x1CD #define EEPCTIN 0x1CD
#define ERGBSET8 0x1CE #define ERGBSET8 0x1CE
#define EOSCON 0x1D1 #define EOSCON 0x1D1
#define EOSCOFF 0x1D2 #define EOSCOFF 0x1D2
#define EVOLUP 0x1D6 #define EVOLUP 0x1D6
#define EVOLDOWN 0x1D7 #define EVOLDOWN 0x1D7
#define ERMWIN 0x1E0 #define ERMWIN 0x1E0
#define ERMWOUT 0x1EE #define ERMWOUT 0x1EE
#define EEPMWR 0x1FC #define EEPMWR 0x1FC
#define EEPMRD 0x1FD #define EEPMRD 0x1FD
// PHILIPS LCD command set // PHILIPS LCD command set
#define PNOP 0x100 #define PNOP 0x100
#define PSWRESET 0x101 #define PSWRESET 0x101
#define PBSTROFF 0x102 #define PBSTROFF 0x102
#define PBSTRON 0x103 #define PBSTRON 0x103
#define PRDDIDIF 0x104 #define PRDDIDIF 0x104
#define PRDDST 0x109 #define PRDDST 0x109
#define PSLEEPIN 0x110 #define PSLEEPIN 0x110
#define PSLEEPOUT 0x111 #define PSLEEPOUT 0x111
#define PPTLON 0x112 #define PPTLON 0x112
#define PNORON 0x113 #define PNORON 0x113
#define PINVOFF 0x120 #define PINVOFF 0x120
#define PINVON 0x121 #define PINVON 0x121
#define PDALO 0x122 #define PDALO 0x122
#define PDAL 0x123 #define PDAL 0x123
#define PSETCON 0x125 #define PSETCON 0x125
#define PDISPOFF 0x128 #define PDISPOFF 0x128
#define PDISPON 0x129 #define PDISPON 0x129
#define PCASET 0x12A #define PCASET 0x12A
#define PPASET 0x12B #define PPASET 0x12B
#define PRAMWR 0x12C #define PRAMWR 0x12C
#define PRGBSET 0x12D #define PRGBSET 0x12D
#define PPTLAR 0x130 #define PPTLAR 0x130
#define PVSCRDEF 0x133 #define PVSCRDEF 0x133
#define PTEOFF 0x134 #define PTEOFF 0x134
#define PTEON 0x135 #define PTEON 0x135
#define PMADCTL 0x136 #define PMADCTL 0x136
#define PSEP 0x137 #define PSEP 0x137
#define PIDMOFF 0x138 #define PIDMOFF 0x138
#define PIDMON 0x139 #define PIDMON 0x139
#define PCOLMOD 0x13A #define PCOLMOD 0x13A
#define PSETVOP 0x1B0 #define PSETVOP 0x1B0
#define PBRS 0x1B4 #define PBRS 0x1B4
#define PTRS 0x1B6 #define PTRS 0x1B6
#define PFINV 0x1B9 #define PFINV 0x1B9
#define PDOR 0x1BA #define PDOR 0x1BA
#define PTCDFE 0x1BD #define PTCDFE 0x1BD
#define PTCVOPE 0x1BF #define PTCVOPE 0x1BF
#define PEC 0x1C0 #define PEC 0x1C0
#define PSETMUL 0x1C2 #define PSETMUL 0x1C2
#define PTCVOPAB 0x1C3 #define PTCVOPAB 0x1C3
#define PTCVOPCD 0x1C4 #define PTCVOPCD 0x1C4
#define PTCDF 0x1C5 #define PTCDF 0x1C5
#define PDF8C 0x1C6 #define PDF8C 0x1C6
#define PSETBS 0x1C7 #define PSETBS 0x1C7
#define PRDTEMP 0x1C8 #define PRDTEMP 0x1C8
#define PNLI 0x1C9 #define PNLI 0x1C9
#define PRDID1 0x1DA #define PRDID1 0x1DA
#define PRDID2 0x1DB #define PRDID2 0x1DB
#define PRDID3 0x1DC #define PRDID3 0x1DC
#define PSFD 0x1EF #define PSFD 0x1EF
#define PECM 0x1F0 #define PECM 0x1F0
void LCDSend(unsigned int data); void LCDSend(unsigned int data);
void LCDInit(void); void LCDInit(void);

File diff suppressed because it is too large Load diff

View file

@ -202,8 +202,8 @@ void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t
// iso15693.h // iso15693.h
void RecordRawAdcSamplesIso15693(void); void RecordRawAdcSamplesIso15693(void);
void AcquireRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void);
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
void Iso15693InitReader(void); void Iso15693InitReader(void);

View file

@ -2,9 +2,9 @@
void Ring_BEE_ONCE(uint16_t music_note) { void Ring_BEE_ONCE(uint16_t music_note) {
BEE_ON(); BEE_ON();
SpinDelayUs(music_note); SpinDelayUs(music_note);
BEE_OFF(); BEE_OFF();
SpinDelayUs(music_note); SpinDelayUs(music_note);
} }
void ring_2_7khz(uint16_t count) { void ring_2_7khz(uint16_t count) {
@ -12,9 +12,9 @@ void ring_2_7khz(uint16_t count) {
} }
void Ring_BEE_TIME(uint16_t music_note,uint16_t count) { void Ring_BEE_TIME(uint16_t music_note,uint16_t count) {
for(uint16_t i=0 ; i < count; i++) for(uint16_t i=0 ; i < count; i++)
Ring_BEE_ONCE(music_note); Ring_BEE_ONCE(music_note);
SpinDelay(9); SpinDelay(9);
} }
void Ring_ALL(uint16_t count) { void Ring_ALL(uint16_t count) {
@ -29,58 +29,58 @@ void Ring_ALL(uint16_t count) {
} }
void Ring_Little_Star(uint16_t count) { void Ring_Little_Star(uint16_t count) {
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1,count);
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1,count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6,count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6,count);
Ring_BEE_TIME(note_5,2*count); Ring_BEE_TIME(note_5,2*count);
LED_A_ON(); LED_A_ON();
/* /*
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_2,count); Ring_BEE_TIME(note_2,count);
Ring_BEE_TIME(note_2,count); Ring_BEE_TIME(note_2,count);
Ring_BEE_TIME(note_1,2*count); Ring_BEE_TIME(note_1,2*count);
LED_A_OFF(); LED_A_OFF();
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_2,2*count); Ring_BEE_TIME(note_2,2*count);
LED_A_ON(); LED_A_ON();
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_2,2*count); Ring_BEE_TIME(note_2,2*count);
LED_A_OFF(); LED_A_OFF();
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1,count);
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1,count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6,count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6,count);
Ring_BEE_TIME(note_5,2*count); Ring_BEE_TIME(note_5,2*count);
LED_A_ON(); LED_A_ON();
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count);
Ring_BEE_TIME(note_2,count); Ring_BEE_TIME(note_2,count);
Ring_BEE_TIME(note_2,count); Ring_BEE_TIME(note_2,count);
Ring_BEE_TIME(note_1,2*count); Ring_BEE_TIME(note_1,2*count);
LED_B_ON(); LED_B_ON();
*/ */
} }

View file

@ -22,7 +22,7 @@
* \email daniel.otte@rub.de * \email daniel.otte@rub.de
* \date 2007-06-16 * \date 2007-06-16
* \brief DES and EDE-DES implementation * \brief DES and EDE-DES implementation
* \license GPLv3 or later * \license GPLv3 or later
* *
*/ */
@ -72,111 +72,111 @@ const uint8_t sbox[256] = {
}; };
const uint8_t e_permtab[] ={ const uint8_t e_permtab[] ={
4, 6, /* 4 bytes in 6 bytes out*/ 4, 6, /* 4 bytes in 6 bytes out*/
32, 1, 2, 3, 4, 5, 32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13, 8, 9, 10, 11, 12, 13,
12, 13, 14, 15, 16, 17, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 16, 17, 18, 19, 20, 21,
20, 21, 22, 23, 24, 25, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 24, 25, 26, 27, 28, 29,
28, 29, 30, 31, 32, 1 28, 29, 30, 31, 32, 1
}; };
const uint8_t p_permtab[] ={ const uint8_t p_permtab[] ={
4, 4, /* 32 bit -> 32 bit */ 4, 4, /* 32 bit -> 32 bit */
16, 7, 20, 21, 16, 7, 20, 21,
29, 12, 28, 17, 29, 12, 28, 17,
1, 15, 23, 26, 1, 15, 23, 26,
5, 18, 31, 10, 5, 18, 31, 10,
2, 8, 24, 14, 2, 8, 24, 14,
32, 27, 3, 9, 32, 27, 3, 9,
19, 13, 30, 6, 19, 13, 30, 6,
22, 11, 4, 25 22, 11, 4, 25
}; };
const uint8_t ip_permtab[] ={ const uint8_t ip_permtab[] ={
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
58, 50, 42, 34, 26, 18, 10, 2, 58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 62, 54, 46, 38, 30, 22, 14, 6,
64, 56, 48, 40, 32, 24, 16, 8, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 57, 49, 41, 33, 25, 17, 9, 1,
59, 51, 43, 35, 27, 19, 11, 3, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 61, 53, 45, 37, 29, 21, 13, 5,
63, 55, 47, 39, 31, 23, 15, 7 63, 55, 47, 39, 31, 23, 15, 7
}; };
const uint8_t inv_ip_permtab[] ={ const uint8_t inv_ip_permtab[] ={
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
40, 8, 48, 16, 56, 24, 64, 32, 40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 38, 6, 46, 14, 54, 22, 62, 30,
37, 5, 45, 13, 53, 21, 61, 29, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 36, 4, 44, 12, 52, 20, 60, 28,
35, 3, 43, 11, 51, 19, 59, 27, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25 33, 1, 41, 9, 49, 17, 57, 25
}; };
const uint8_t pc1_permtab[] ={ const uint8_t pc1_permtab[] ={
8, 7, /* 64 bit -> 56 bit*/ 8, 7, /* 64 bit -> 56 bit*/
57, 49, 41, 33, 25, 17, 9, 57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 10, 2, 59, 51, 43, 35, 27,
19, 11, 3, 60, 52, 44, 36, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 63, 55, 47, 39, 31, 23, 15,
7, 62, 54, 46, 38, 30, 22, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 14, 6, 61, 53, 45, 37, 29,
21, 13, 5, 28, 20, 12, 4 21, 13, 5, 28, 20, 12, 4
}; };
const uint8_t pc2_permtab[] ={ const uint8_t pc2_permtab[] ={
7, 6, /* 56 bit -> 48 bit */ 7, 6, /* 56 bit -> 48 bit */
14, 17, 11, 24, 1, 5, 14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 23, 19, 12, 4, 26, 8,
16, 7, 27, 20, 13, 2, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 41, 52, 31, 37, 47, 55,
30, 40, 51, 45, 33, 48, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 44, 49, 39, 56, 34, 53,
46, 42, 50, 36, 29, 32 46, 42, 50, 36, 29, 32
}; };
const uint8_t splitin6bitword_permtab[] = { const uint8_t splitin6bitword_permtab[] = {
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
64, 64, 1, 6, 2, 3, 4, 5, 64, 64, 1, 6, 2, 3, 4, 5,
64, 64, 7, 12, 8, 9, 10, 11, 64, 64, 7, 12, 8, 9, 10, 11,
64, 64, 13, 18, 14, 15, 16, 17, 64, 64, 13, 18, 14, 15, 16, 17,
64, 64, 19, 24, 20, 21, 22, 23, 64, 64, 19, 24, 20, 21, 22, 23,
64, 64, 25, 30, 26, 27, 28, 29, 64, 64, 25, 30, 26, 27, 28, 29,
64, 64, 31, 36, 32, 33, 34, 35, 64, 64, 31, 36, 32, 33, 34, 35,
64, 64, 37, 42, 38, 39, 40, 41, 64, 64, 37, 42, 38, 39, 40, 41,
64, 64, 43, 48, 44, 45, 46, 47 64, 64, 43, 48, 44, 45, 46, 47
}; };
const uint8_t shiftkey_permtab[] = { const uint8_t shiftkey_permtab[] = {
7, 7, /* 56 bit -> 56 bit */ 7, 7, /* 56 bit -> 56 bit */
2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 10, 11, 12, 13, 14, 15, 16, 17,
18, 19, 20, 21, 22, 23, 24, 25, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 1, 26, 27, 28, 1,
30, 31, 32, 33, 34, 35, 36, 37, 30, 31, 32, 33, 34, 35, 36, 37,
38, 39, 40, 41, 42, 43, 44, 45, 38, 39, 40, 41, 42, 43, 44, 45,
46, 47, 48, 49, 50, 51, 52, 53, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 29 54, 55, 56, 29
}; };
const uint8_t shiftkeyinv_permtab[] = { const uint8_t shiftkeyinv_permtab[] = {
7, 7, 7, 7,
28, 1, 2, 3, 4, 5, 6, 7, 28, 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, 13, 14, 15, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 24, 25, 26, 27,
56, 29, 30, 31, 32, 33, 34, 35, 56, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55 52, 53, 54, 55
}; };
/* /*
@ -203,241 +203,241 @@ const uint8_t shiftkeyinv_permtab[] = {
/******************************************************************************/ /******************************************************************************/
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){ void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
uint8_t ob; /* in-bytes and out-bytes */ uint8_t ob; /* in-bytes and out-bytes */
uint8_t byte, bit; /* counter for bit and byte */ uint8_t byte, bit; /* counter for bit and byte */
ob = ptable[1]; ob = ptable[1];
ptable = &(ptable[2]); ptable = &(ptable[2]);
for(byte=0; byte<ob; ++byte){ for(byte=0; byte<ob; ++byte){
uint8_t x,t=0; uint8_t x,t=0;
for(bit=0; bit<8; ++bit){ for(bit=0; bit<8; ++bit){
x = *ptable++ - 1; x = *ptable++ - 1;
t<<=1; t<<=1;
if((in[x/8]) & (0x80>>(x%8)) ){ if((in[x/8]) & (0x80>>(x%8)) ){
t|=0x01; t|=0x01;
} }
} }
out[byte]=t; out[byte]=t;
} }
} }
/******************************************************************************/ /******************************************************************************/
void changeendian32(uint32_t * a){ void changeendian32(uint32_t * a){
*a = (*a & 0x000000FF) << 24 | *a = (*a & 0x000000FF) << 24 |
(*a & 0x0000FF00) << 8 | (*a & 0x0000FF00) << 8 |
(*a & 0x00FF0000) >> 8 | (*a & 0x00FF0000) >> 8 |
(*a & 0xFF000000) >> 24; (*a & 0xFF000000) >> 24;
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
void shiftkey(uint8_t *key){ void shiftkey(uint8_t *key){
uint8_t k[7]; uint8_t k[7];
memcpy(k, key, 7); memcpy(k, key, 7);
permute((uint8_t*)shiftkey_permtab, k, key); permute((uint8_t*)shiftkey_permtab, k, key);
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
void shiftkey_inv(uint8_t *key){ void shiftkey_inv(uint8_t *key){
uint8_t k[7]; uint8_t k[7];
memcpy(k, key, 7); memcpy(k, key, 7);
permute((uint8_t*)shiftkeyinv_permtab, k, key); permute((uint8_t*)shiftkeyinv_permtab, k, key);
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
uint64_t splitin6bitwords(uint64_t a){ uint64_t splitin6bitwords(uint64_t a){
uint64_t ret=0; uint64_t ret=0;
a &= 0x0000ffffffffffffLL; a &= 0x0000ffffffffffffLL;
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret);
return ret; return ret;
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){ uint8_t substitute(uint8_t a, uint8_t * sbp){
uint8_t x; uint8_t x;
x = sbp[a>>1]; x = sbp[a>>1];
x = (a&1)?x&0x0F:x>>4; x = (a&1)?x&0x0F:x>>4;
return x; return x;
} }
/******************************************************************************/ /******************************************************************************/
uint32_t des_f(uint32_t r, uint8_t* kr){ uint32_t des_f(uint32_t r, uint8_t* kr){
uint8_t i; uint8_t i;
uint32_t t=0,ret; uint32_t t=0,ret;
uint64_t data; uint64_t data;
uint8_t *sbp; /* sboxpointer */ uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data);
for(i=0; i<6; ++i) for(i=0; i<6; ++i)
((uint8_t*)&data)[i] ^= kr[i]; ((uint8_t*)&data)[i] ^= kr[i];
/* Sbox substitution */ /* Sbox substitution */
data = splitin6bitwords(data); data = splitin6bitwords(data);
sbp=(uint8_t*)sbox; sbp=(uint8_t*)sbox;
for(i=0; i<8; ++i){ for(i=0; i<8; ++i){
uint8_t x; uint8_t x;
x = substitute(((uint8_t*)&data)[i], sbp); x = substitute(((uint8_t*)&data)[i], sbp);
t<<=4; t<<=4;
t |= x; t |= x;
sbp += 32; sbp += 32;
} }
changeendian32(&t); changeendian32(&t);
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret);
return ret; return ret;
} }
/******************************************************************************/ /******************************************************************************/
typedef struct { typedef struct {
union { union {
uint8_t v8[8]; uint8_t v8[8];
uint32_t v32[2]; uint32_t v32[2];
} d; } d;
} data_t; } data_t;
#define R (data.d.v32[1]) #define R (data.d.v32[1])
#define L (data.d.v32[0]) #define L (data.d.v32[0])
void des_enc(void* out, const void* in, const void* key){ void des_enc(void* out, const void* in, const void* key){
uint8_t kr[6], k[7]; uint8_t kr[6], k[7];
uint8_t i; uint8_t i;
data_t data; data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=0; i<8; ++i){ for(i=0; i<8; ++i){
shiftkey(k); shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+0))) ) if(ROTTABLE&((1<<((i<<1)+0))) )
shiftkey(k); shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t*)pc2_permtab, k, kr);
L ^= des_f(R, kr); L ^= des_f(R, kr);
shiftkey(k); shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+1))) ) if(ROTTABLE&((1<<((i<<1)+1))) )
shiftkey(k); shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t*)pc2_permtab, k, kr);
R ^= des_f(L, kr); R ^= des_f(L, kr);
} }
/* L <-> R*/ /* L <-> R*/
R ^= L; R ^= L;
L ^= R; L ^= R;
R ^= L; R ^= L;
permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out);
} }
/******************************************************************************/ /******************************************************************************/
void des_dec(void* out, const void* in, const uint8_t* key){ void des_dec(void* out, const void* in, const uint8_t* key){
uint8_t kr[6],k[7]; uint8_t kr[6],k[7];
int8_t i; int8_t i;
data_t data; data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k);
for(i=7; i>=0; --i){ for(i=7; i>=0; --i){
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t*)pc2_permtab, k, kr);
L ^= des_f(R, kr); L ^= des_f(R, kr);
shiftkey_inv(k); shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+1))) ){ if(ROTTABLE&((1<<((i<<1)+1))) ){
shiftkey_inv(k); shiftkey_inv(k);
} }
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t*)pc2_permtab, k, kr);
R ^= des_f(L, kr); R ^= des_f(L, kr);
shiftkey_inv(k); shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+0))) ){ if(ROTTABLE&((1<<((i<<1)+0))) ){
shiftkey_inv(k); shiftkey_inv(k);
} }
} }
/* L <-> R*/ /* L <-> R*/
R ^= L; R ^= L;
L ^= R; L ^= R;
R ^= L; R ^= L;
permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out);
} }
/******************************************************************************/ /******************************************************************************/
void tdes_enc(void* out, void* in, const void* key){ void tdes_enc(void* out, void* in, const void* key){
des_enc(out, in, (uint8_t*)key + 0); des_enc(out, in, (uint8_t*)key + 0);
des_dec(out, out, (uint8_t*)key + 8); des_dec(out, out, (uint8_t*)key + 8);
des_enc(out, out, (uint8_t*)key +16); des_enc(out, out, (uint8_t*)key +16);
} }
/******************************************************************************/ /******************************************************************************/
void tdes_dec(void* out, void* in, const uint8_t* key){ void tdes_dec(void* out, void* in, const uint8_t* key){
des_dec(out, in, (uint8_t*)key +16); des_dec(out, in, (uint8_t*)key +16);
des_enc(out, out, (uint8_t*)key + 8); des_enc(out, out, (uint8_t*)key + 8);
des_dec(out, out, (uint8_t*)key + 0); des_dec(out, out, (uint8_t*)key + 0);
} }
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
if( length % 8 ) return; if( length % 8 ) return;
uint8_t i; uint8_t i;
uint8_t* tin = (uint8_t*) in; uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out; uint8_t* tout = (uint8_t*) out;
while( length > 0 ) while( length > 0 )
{ {
for( i = 0; i < 8; i++ ) for( i = 0; i < 8; i++ )
tout[i] = (unsigned char)( tin[i] ^ iv[i] ); tout[i] = (unsigned char)( tin[i] ^ iv[i] );
des_enc(tout, tin, (uint8_t*)key + 0); des_enc(tout, tin, (uint8_t*)key + 0);
des_dec(tout, tout, (uint8_t*)key + 8); des_dec(tout, tout, (uint8_t*)key + 8);
des_enc(tout, tout, (uint8_t*)key + 0); des_enc(tout, tout, (uint8_t*)key + 0);
memcpy( iv, tout, 8 ); memcpy( iv, tout, 8 );
tin += 8; tin += 8;
tout += 8; tout += 8;
length -= 8; length -= 8;
} }
} }
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){
if( length % 8 ) return; if( length % 8 ) return;
uint8_t i; uint8_t i;
unsigned char temp[8]; unsigned char temp[8];
uint8_t* tin = (uint8_t*) in; uint8_t* tin = (uint8_t*) in;
uint8_t* tout = (uint8_t*) out; uint8_t* tout = (uint8_t*) out;
while( length > 0 ) while( length > 0 )
{ {
memcpy( temp, tin, 8 ); memcpy( temp, tin, 8 );
des_dec(tout, tin, (uint8_t*)key + 0); des_dec(tout, tin, (uint8_t*)key + 0);
des_enc(tout, tout, (uint8_t*)key + 8); des_enc(tout, tout, (uint8_t*)key + 8);
des_dec(tout, tout, (uint8_t*)key + 0); des_dec(tout, tout, (uint8_t*)key + 0);
for( i = 0; i < 8; i++ ) for( i = 0; i < 8; i++ )
tout[i] = (unsigned char)( tout[i] ^ iv[i] ); tout[i] = (unsigned char)( tout[i] ^ iv[i] );
memcpy( iv, temp, 8 ); memcpy( iv, temp, 8 );
tin += 8; tin += 8;
tout += 8; tout += 8;
length -= 8; length -= 8;
} }
} }

View file

@ -17,11 +17,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/** /**
* \file des.h * \file des.h
* \author Daniel Otte * \author Daniel Otte
* \date 2007-06-16 * \date 2007-06-16
* \brief des and tdes declarations * \brief des and tdes declarations
* \license GPLv3 or later * \license GPLv3 or later
* *
*/ */
#ifndef __DES_H_ #ifndef __DES_H_

View file

@ -85,20 +85,20 @@ void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t l
mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
memcpy (cmac, ivect, kbs); memcpy (cmac, ivect, kbs);
free(buffer); free(buffer);
} }
size_t key_block_size (const desfirekey_t key) { size_t key_block_size (const desfirekey_t key) {
size_t block_size = 8; size_t block_size = 8;
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:
case T_3DES: case T_3DES:
case T_3K3DES: case T_3K3DES:
block_size = 8; block_size = 8;
break; break;
case T_AES: case T_AES:
block_size = 16; block_size = 16;
break; break;
} }
return block_size; return block_size;
} }
@ -211,7 +211,7 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
break; break;
// Append MAC // Append MAC
size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset; size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset;
bla++; bla++;
memcpy (res + *nbytes, mac, 4); memcpy (res + *nbytes, mac, 4);
@ -224,7 +224,7 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
if (append_mac) { if (append_mac) {
size_t len = maced_data_length (key, *nbytes); size_t len = maced_data_length (key, *nbytes);
++len; ++len;
memcpy (res, data, *nbytes); memcpy (res, data, *nbytes);
memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH); memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH);
*nbytes += CMAC_LENGTH; *nbytes += CMAC_LENGTH;
@ -448,7 +448,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
case AS_LEGACY: case AS_LEGACY:
AddCrc14A( (uint8_t*)res, end_crc_pos); AddCrc14A( (uint8_t*)res, end_crc_pos);
end_crc_pos = crc_pos + 2; end_crc_pos = crc_pos + 2;
// //
crc = crc16; crc = crc16;
@ -529,11 +529,11 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
switch (operation) { switch (operation) {
case MCO_ENCYPHER: case MCO_ENCYPHER:
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
des_enc(edata, data, key->data); des_enc(edata, data, key->data);
break; break;
case MCO_DECYPHER: case MCO_DECYPHER:
//DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
des_dec(edata, data, key->data); des_dec(edata, data, key->data);
break; break;
} }
break; break;
@ -543,27 +543,27 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
tdes_enc(edata,data, key->data); tdes_enc(edata,data, key->data);
break; break;
case MCO_DECYPHER: case MCO_DECYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
tdes_dec(data, edata, key->data); tdes_dec(data, edata, key->data);
break; break;
} }
break; break;
case T_3K3DES: case T_3K3DES:
switch (operation) { switch (operation) {
case MCO_ENCYPHER: case MCO_ENCYPHER:
tdes_enc(edata,data, key->data); tdes_enc(edata,data, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
break; break;
case MCO_DECYPHER: case MCO_DECYPHER:
tdes_dec(data, edata, key->data); tdes_dec(data, edata, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
break; break;
@ -571,21 +571,21 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
break; break;
case T_AES: case T_AES:
switch (operation) switch (operation)
{ {
case MCO_ENCYPHER: case MCO_ENCYPHER:
{ {
AesCtx ctx; AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesEncrypt(&ctx, data, edata, sizeof(edata) ); AesEncrypt(&ctx, data, edata, sizeof(edata) );
break; break;
} }
case MCO_DECYPHER: case MCO_DECYPHER:
{ {
AesCtx ctx; AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); AesCtxIni(&ctx, ivect, key->data, KEY128,CBC);
AesDecrypt(&ctx, edata, data, sizeof(edata)); AesDecrypt(&ctx, edata, data, sizeof(edata));
break; break;
} }
} }
break; break;
} }
@ -620,11 +620,11 @@ void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *
ivect = DESFIRE (tag)->ivect; ivect = DESFIRE (tag)->ivect;
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE (tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
break; break;
case AS_NEW: case AS_NEW:
break; break;
} }
} }

View file

@ -38,12 +38,12 @@ void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) {
} }
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) { void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) {
if ( key != NULL) { if ( key != NULL) {
key->type = T_DES; key->type = T_DES;
memcpy (key->data, value, 8); memcpy (key->data, value, 8);
memcpy (key->data+8, value, 8); memcpy (key->data+8, value, 8);
update_key_schedules (key); update_key_schedules (key);
} }
} }
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) { void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) {
@ -58,11 +58,11 @@ void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) {
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) { void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) {
if ( key != NULL ){ if ( key != NULL ){
key->type = T_3DES; key->type = T_3DES;
memcpy (key->data, value, 16); memcpy (key->data, value, 16);
memcpy (key->data + 16, value, 8); memcpy (key->data + 16, value, 8);
update_key_schedules (key); update_key_schedules (key);
} }
} }
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) { void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) {
@ -74,11 +74,11 @@ void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) {
} }
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) { void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) {
if ( key != NULL){ if ( key != NULL){
key->type = T_3K3DES; key->type = T_3K3DES;
memcpy (key->data, value, 24); memcpy (key->data, value, 24);
update_key_schedules (key); update_key_schedules (key);
} }
} }
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) { void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) {
@ -87,11 +87,11 @@ void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) { void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) {
if (key != NULL) { if (key != NULL) {
memcpy (key->data, value, 16); memcpy (key->data, value, 16);
key->type = T_AES; key->type = T_AES;
key->aes_version = version; key->aes_version = version;
} }
} }
uint8_t Desfire_key_get_version (desfirekey_t key) { uint8_t Desfire_key_get_version (desfirekey_t key) {

View file

@ -6,15 +6,15 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "desfire.h" #include "desfire.h"
//#include "mifare.h" // iso14a_card_select_t struct //#include "mifare.h" // iso14a_card_select_t struct
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key); void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key); void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key);
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key); void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key); void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key);
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key); void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key);
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key); void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key);
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key); void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key);
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key); void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key);
uint8_t Desfire_key_get_version (desfirekey_t key); uint8_t Desfire_key_get_version (desfirekey_t key);
void Desfire_key_set_version (desfirekey_t key, uint8_t version); void Desfire_key_set_version (desfirekey_t key, uint8_t version);
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
#endif #endif

View file

@ -21,41 +21,41 @@ static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6};
// General Authenticate (request encrypted nonce) WITHOUT the Le at the end // General Authenticate (request encrypted nonce) WITHOUT the Le at the end
static const uint8_t apdu_general_authenticate_pace_get_nonce[] = { static const uint8_t apdu_general_authenticate_pace_get_nonce[] = {
0x10, // CLA 0x10, // CLA
0x86, // INS 0x86, // INS
0x00, // P1 0x00, // P1
0x00, // P2 0x00, // P2
0x02, // Lc 0x02, // Lc
0x7C, // Type: Dynamic Authentication Data 0x7C, // Type: Dynamic Authentication Data
0x00, // Length: 0 bytes 0x00, // Length: 0 bytes
}; };
// MSE: Set AT (only CLA, INS, P1 and P2) // MSE: Set AT (only CLA, INS, P1 and P2)
static const uint8_t apdu_mse_set_at_start[] = { static const uint8_t apdu_mse_set_at_start[] = {
0x00, // CLA 0x00, // CLA
0x22, // INS 0x22, // INS
0xC1, // P1 0xC1, // P1
0xA4, // P2 0xA4, // P2
}; };
// SELECT BINARY with the ID for EF.CardAccess // SELECT BINARY with the ID for EF.CardAccess
static const uint8_t apdu_select_binary_cardaccess[] = { static const uint8_t apdu_select_binary_cardaccess[] = {
0x00, // CLA 0x00, // CLA
0xA4, // INS 0xA4, // INS
0x02, // P1 0x02, // P1
0x0C, // P2 0x0C, // P2
0x02, // Lc 0x02, // Lc
0x01, // ID 0x01, // ID
0x1C // ID 0x1C // ID
}; };
// READ BINARY // READ BINARY
static const uint8_t apdu_read_binary[] = { static const uint8_t apdu_read_binary[] = {
0x00, // CLA 0x00, // CLA
0xB0, // INS 0xB0, // INS
0x00, // P1 0x00, // P1
0x00, // P2 0x00, // P2
0x38 // Le 0x38 // Le
}; };
@ -84,14 +84,14 @@ static uint8_t apdu_replay_general_authenticate_pace_mutual_authenticate[75];
static uint8_t apdu_replay_general_authenticate_pace_perform_key_agreement[18]; static uint8_t apdu_replay_general_authenticate_pace_perform_key_agreement[18];
// pointers to the APDUs (for iterations) // pointers to the APDUs (for iterations)
static struct { static struct {
uint8_t len; uint8_t len;
uint8_t *data; uint8_t *data;
} const apdus_replay[] = { } const apdus_replay[] = {
{sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace}, {sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace},
{sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce}, {sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce},
{sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce}, {sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce},
{sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate}, {sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate},
{sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement} {sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement}
}; };
// lengths of the replay APDUs // lengths of the replay APDUs
@ -105,18 +105,18 @@ static char iso_type = 0;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response)
{ {
switch(iso_type) switch(iso_type)
{ {
case 'a': case 'a':
return iso14_apdu(apdu, (uint16_t) length, false, response, NULL); return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
break; break;
case 'b': case 'b':
return iso14443b_apdu(apdu, length, response); return iso14443b_apdu(apdu, length, response);
break; break;
default: default:
return 0; return 0;
break; break;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -124,9 +124,9 @@ int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_Finish() void EPA_Finish()
{ {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
iso_type = 0; iso_type = 0;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -146,68 +146,68 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
size_t length, size_t length,
pace_version_info_t *pace_info) pace_version_info_t *pace_info)
{ {
size_t index = 0; size_t index = 0;
while (index <= length - 2) { while (index <= length - 2) {
// determine type of element // determine type of element
// SET or SEQUENCE // SET or SEQUENCE
if (data[index] == 0x31 || data[index] == 0x30) { if (data[index] == 0x31 || data[index] == 0x30) {
// enter the set (skip tag + length) // enter the set (skip tag + length)
index += 2; index += 2;
// check for extended length // check for extended length
if ((data[index - 1] & 0x80) != 0) { if ((data[index - 1] & 0x80) != 0) {
index += (data[index-1] & 0x7F); index += (data[index-1] & 0x7F);
} }
} }
// OID // OID
else if (data[index] == 0x06) { else if (data[index] == 0x06) {
// is this a PACE OID? // is this a PACE OID?
if (data[index + 1] == 0x0A // length matches if (data[index + 1] == 0x0A // length matches
&& memcmp(data + index + 2, && memcmp(data + index + 2,
oid_pace_start, oid_pace_start,
sizeof(oid_pace_start)) == 0 // content matches sizeof(oid_pace_start)) == 0 // content matches
&& pace_info != NULL) && pace_info != NULL)
{ {
// first, clear the pace_info struct // first, clear the pace_info struct
memset(pace_info, 0, sizeof(pace_version_info_t)); memset(pace_info, 0, sizeof(pace_version_info_t));
memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid)); memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid));
// a PACE OID is followed by the version // a PACE OID is followed by the version
index += data[index + 1] + 2; index += data[index + 1] + 2;
if (data[index] == 02 && data[index + 1] == 01) { if (data[index] == 02 && data[index + 1] == 01) {
pace_info->version = data[index + 2]; pace_info->version = data[index + 2];
index += 3; index += 3;
} }
else { else {
return index; return index;
} }
// after that there might(!) be the parameter ID // after that there might(!) be the parameter ID
if (data[index] == 02 && data[index + 1] == 01) { if (data[index] == 02 && data[index + 1] == 01) {
pace_info->parameter_id = data[index + 2]; pace_info->parameter_id = data[index + 2];
index += 3; index += 3;
} }
} }
else { else {
// skip this OID // skip this OID
index += 2 + data[index + 1]; index += 2 + data[index + 1];
} }
} }
// if the length is 0, something is wrong // if the length is 0, something is wrong
// TODO: This needs to be extended to support long tags // TODO: This needs to be extended to support long tags
else if (data[index + 1] == 0) { else if (data[index + 1] == 0) {
return index; return index;
} }
else { else {
// skip this part // skip this part
// TODO: This needs to be extended to support long tags // TODO: This needs to be extended to support long tags
// TODO: This needs to be extended to support unknown elements with // TODO: This needs to be extended to support unknown elements with
// a size > 0x7F // a size > 0x7F
index += 2 + data[index + 1]; index += 2 + data[index + 1];
} }
} }
// TODO: We should check whether we reached the end in error, but for that // TODO: We should check whether we reached the end in error, but for that
// we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO) // we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO)
return 0; return 0;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -217,42 +217,42 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
{ {
// the response APDU of the card // the response APDU of the card
// since the card doesn't always care for the expected length we send it, // since the card doesn't always care for the expected length we send it,
// we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
uint8_t response_apdu[262]; uint8_t response_apdu[262];
int rapdu_length = 0; int rapdu_length = 0;
// select the file EF.CardAccess // select the file EF.CardAccess
rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess, rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess,
sizeof(apdu_select_binary_cardaccess), sizeof(apdu_select_binary_cardaccess),
response_apdu); response_apdu);
if (rapdu_length < 6 if (rapdu_length < 6
|| response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00) || response_apdu[rapdu_length - 3] != 0x00)
{ {
DbpString("Failed to select EF.CardAccess!"); DbpString("Failed to select EF.CardAccess!");
return -1; return -1;
} }
// read the file // read the file
rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary, rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary,
sizeof(apdu_read_binary), sizeof(apdu_read_binary),
response_apdu); response_apdu);
if (rapdu_length <= 6 if (rapdu_length <= 6
|| response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00) || response_apdu[rapdu_length - 3] != 0x00)
{ {
Dbprintf("Failed to read EF.CardAccess!"); Dbprintf("Failed to read EF.CardAccess!");
return -1; return -1;
} }
// copy the content into the buffer // copy the content into the buffer
// length of data available: apdu_length - 4 (ISO frame) - 2 (SW) // length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
size_t to_copy = rapdu_length - 6; size_t to_copy = rapdu_length - 6;
to_copy = to_copy < max_length ? to_copy : max_length; to_copy = to_copy < max_length ? to_copy : max_length;
memcpy(buffer, response_apdu+2, to_copy); memcpy(buffer, response_apdu+2, to_copy);
return to_copy; return to_copy;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -261,11 +261,11 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
{ {
// power down the field // power down the field
EPA_Finish(); EPA_Finish();
// send the USB packet // send the USB packet
cmd_send(CMD_ACK,step,func_return,0,0,0); cmd_send(CMD_ACK,step,func_return,0,0,0);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -273,68 +273,68 @@ static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_PACE_Collect_Nonce(UsbCommand *c) void EPA_PACE_Collect_Nonce(UsbCommand *c)
{ {
/* /*
* ack layout: * ack layout:
* arg: * arg:
* 1. element * 1. element
* step where the error occured or 0 if no error occured * step where the error occured or 0 if no error occured
* 2. element * 2. element
* return code of the last executed function * return code of the last executed function
* d: * d:
* Encrypted nonce * Encrypted nonce
*/ */
// return value of a function // return value of a function
int func_return = 0; int func_return = 0;
// set up communication // set up communication
func_return = EPA_Setup(); func_return = EPA_Setup();
if (func_return != 0) { if (func_return != 0) {
EPA_PACE_Collect_Nonce_Abort(1, func_return); EPA_PACE_Collect_Nonce_Abort(1, func_return);
return; return;
} }
// read the CardAccess file // read the CardAccess file
// this array will hold the CardAccess file // this array will hold the CardAccess file
uint8_t card_access[256] = {0}; uint8_t card_access[256] = {0};
int card_access_length = EPA_Read_CardAccess(card_access, 256); int card_access_length = EPA_Read_CardAccess(card_access, 256);
// the response has to be at least this big to hold the OID // the response has to be at least this big to hold the OID
if (card_access_length < 18) { if (card_access_length < 18) {
EPA_PACE_Collect_Nonce_Abort(2, card_access_length); EPA_PACE_Collect_Nonce_Abort(2, card_access_length);
return; return;
} }
// this will hold the PACE info of the card // this will hold the PACE info of the card
pace_version_info_t pace_version_info; pace_version_info_t pace_version_info;
// search for the PACE OID // search for the PACE OID
func_return = EPA_Parse_CardAccess(card_access, func_return = EPA_Parse_CardAccess(card_access,
card_access_length, card_access_length,
&pace_version_info); &pace_version_info);
if (func_return != 0 || pace_version_info.version == 0) { if (func_return != 0 || pace_version_info.version == 0) {
EPA_PACE_Collect_Nonce_Abort(3, func_return); EPA_PACE_Collect_Nonce_Abort(3, func_return);
return; return;
} }
// initiate the PACE protocol // initiate the PACE protocol
// use the CAN for the password since that doesn't change // use the CAN for the password since that doesn't change
func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
// now get the nonce // now get the nonce
uint8_t nonce[256] = {0}; uint8_t nonce[256] = {0};
uint8_t requested_size = (uint8_t)c->arg[0]; uint8_t requested_size = (uint8_t)c->arg[0];
func_return = EPA_PACE_Get_Nonce(requested_size, nonce); func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
// check if the command succeeded // check if the command succeeded
if (func_return < 0) if (func_return < 0)
{ {
EPA_PACE_Collect_Nonce_Abort(4, func_return); EPA_PACE_Collect_Nonce_Abort(4, func_return);
return; return;
} }
// all done, return // all done, return
EPA_Finish(); EPA_Finish();
// save received information // save received information
cmd_send(CMD_ACK,0,func_return,0,nonce,func_return); cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -347,44 +347,44 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
{ {
// build the APDU // build the APDU
uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1]; uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1];
// copy the constant part // copy the constant part
memcpy(apdu, memcpy(apdu,
apdu_general_authenticate_pace_get_nonce, apdu_general_authenticate_pace_get_nonce,
sizeof(apdu_general_authenticate_pace_get_nonce)); sizeof(apdu_general_authenticate_pace_get_nonce));
// append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4; apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
// send it // send it
uint8_t response_apdu[262]; uint8_t response_apdu[262];
int send_return = EPA_APDU(apdu, int send_return = EPA_APDU(apdu,
sizeof(apdu), sizeof(apdu),
response_apdu); response_apdu);
// check if the command succeeded // check if the command succeeded
if (send_return < 6 if (send_return < 6
|| response_apdu[send_return - 4] != 0x90 || response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00) || response_apdu[send_return - 3] != 0x00)
{ {
return -1; return -1;
} }
// if there is no nonce in the RAPDU, return here // if there is no nonce in the RAPDU, return here
if (send_return < 10) if (send_return < 10)
{ {
// no error // no error
return 0; return 0;
} }
// get the actual length of the nonce // get the actual length of the nonce
uint8_t nonce_length = response_apdu[5]; uint8_t nonce_length = response_apdu[5];
if (nonce_length > send_return - 10) if (nonce_length > send_return - 10)
{ {
nonce_length = send_return - 10; nonce_length = send_return - 10;
} }
// copy the nonce // copy the nonce
memcpy(nonce, response_apdu + 6, nonce_length); memcpy(nonce, response_apdu + 6, nonce_length);
return nonce_length; return nonce_length;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -393,53 +393,53 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
{ {
// create the MSE: Set AT APDU // create the MSE: Set AT APDU
uint8_t apdu[23]; uint8_t apdu[23];
// the minimum length (will be increased as more data is added) // the minimum length (will be increased as more data is added)
size_t apdu_length = 20; size_t apdu_length = 20;
// copy the constant part // copy the constant part
memcpy(apdu, memcpy(apdu,
apdu_mse_set_at_start, apdu_mse_set_at_start,
sizeof(apdu_mse_set_at_start)); sizeof(apdu_mse_set_at_start));
// type: OID // type: OID
apdu[5] = 0x80; apdu[5] = 0x80;
// length of the OID // length of the OID
apdu[6] = sizeof(pace_version_info.oid); apdu[6] = sizeof(pace_version_info.oid);
// copy the OID // copy the OID
memcpy(apdu + 7, memcpy(apdu + 7,
pace_version_info.oid, pace_version_info.oid,
sizeof(pace_version_info.oid)); sizeof(pace_version_info.oid));
// type: password // type: password
apdu[17] = 0x83; apdu[17] = 0x83;
// length: 1 // length: 1
apdu[18] = 1; apdu[18] = 1;
// password // password
apdu[19] = password; apdu[19] = password;
// if standardized domain parameters are used, copy the ID // if standardized domain parameters are used, copy the ID
if (pace_version_info.parameter_id != 0) { if (pace_version_info.parameter_id != 0) {
apdu_length += 3; apdu_length += 3;
// type: domain parameter // type: domain parameter
apdu[20] = 0x84; apdu[20] = 0x84;
// length: 1 // length: 1
apdu[21] = 1; apdu[21] = 1;
// copy the parameter ID // copy the parameter ID
apdu[22] = pace_version_info.parameter_id; apdu[22] = pace_version_info.parameter_id;
} }
// now set Lc to the actual length // now set Lc to the actual length
apdu[4] = apdu_length - 5; apdu[4] = apdu_length - 5;
// send it // send it
uint8_t response_apdu[6]; uint8_t response_apdu[6];
int send_return = EPA_APDU(apdu, int send_return = EPA_APDU(apdu,
apdu_length, apdu_length,
response_apdu); response_apdu);
// check if the command succeeded // check if the command succeeded
if (send_return != 6 if (send_return != 6
|| response_apdu[send_return - 4] != 0x90 || response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00) || response_apdu[send_return - 3] != 0x00)
{ {
return 1; return 1;
} }
return 0; return 0;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -447,66 +447,66 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_PACE_Replay(UsbCommand *c) void EPA_PACE_Replay(UsbCommand *c)
{ {
uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0}; uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
// if an APDU has been passed, save it // if an APDU has been passed, save it
if (c->arg[0] != 0) { if (c->arg[0] != 0) {
// make sure it's not too big // make sure it's not too big
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len) if(c->arg[2] > apdus_replay[c->arg[0] - 1].len)
{ {
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0); cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
} }
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1],
c->d.asBytes, c->d.asBytes,
c->arg[2]); c->arg[2]);
// save/update APDU length // save/update APDU length
if (c->arg[1] == 0) { if (c->arg[1] == 0) {
apdu_lengths_replay[c->arg[0] - 1] = c->arg[2]; apdu_lengths_replay[c->arg[0] - 1] = c->arg[2];
} else { } else {
apdu_lengths_replay[c->arg[0] - 1] += c->arg[2]; apdu_lengths_replay[c->arg[0] - 1] += c->arg[2];
} }
cmd_send(CMD_ACK, 0, 0, 0, NULL, 0); cmd_send(CMD_ACK, 0, 0, 0, NULL, 0);
return; return;
} }
// return value of a function // return value of a function
int func_return; int func_return;
// set up communication // set up communication
func_return = EPA_Setup(); func_return = EPA_Setup();
if (func_return != 0) { if (func_return != 0) {
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0); cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0);
return; return;
} }
// increase the timeout (at least some cards really do need this!)///////////// // increase the timeout (at least some cards really do need this!)/////////////
// iso14a_set_timeout(0x0003FFFF); // iso14a_set_timeout(0x0003FFFF);
// response APDU // response APDU
uint8_t response_apdu[300] = {0}; uint8_t response_apdu[300] = {0};
// now replay the data and measure the timings // now replay the data and measure the timings
for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { for (int i = 0; i < sizeof(apdu_lengths_replay); i++) {
StartCountUS(); StartCountUS();
func_return = EPA_APDU(apdus_replay[i].data, func_return = EPA_APDU(apdus_replay[i].data,
apdu_lengths_replay[i], apdu_lengths_replay[i],
response_apdu); response_apdu);
timings[i] = GetCountUS(); timings[i] = GetCountUS();
// every step but the last one should succeed // every step but the last one should succeed
if (i < sizeof(apdu_lengths_replay) - 1 if (i < sizeof(apdu_lengths_replay) - 1
&& (func_return < 6 && (func_return < 6
|| response_apdu[func_return - 4] != 0x90 || response_apdu[func_return - 4] != 0x90
|| response_apdu[func_return - 3] != 0x00)) || response_apdu[func_return - 3] != 0x00))
{ {
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20); cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20);
return; return;
} }
} }
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK,0,0,0,timings,20); cmd_send(CMD_ACK,0,0,0,timings,20);
return; return;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -515,40 +515,40 @@ void EPA_PACE_Replay(UsbCommand *c)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Setup() int EPA_Setup()
{ {
int return_code = 0; int return_code = 0;
uint8_t uid[10]; uint8_t uid[10];
uint8_t pps_response[3]; uint8_t pps_response[3];
uint8_t pps_response_par[1]; uint8_t pps_response_par[1];
iso14a_card_select_t card_a_info; iso14a_card_select_t card_a_info;
iso14b_card_select_t card_b_info; iso14b_card_select_t card_b_info;
// first, look for type A cards // first, look for type A cards
// power up the field // power up the field
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
// select the card // select the card
return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false); return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false);
if (return_code == 1) { if (return_code == 1) {
// send the PPS request // send the PPS request
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
return_code = ReaderReceive(pps_response, pps_response_par); return_code = ReaderReceive(pps_response, pps_response_par);
if (return_code != 3 || pps_response[0] != 0xD0) { if (return_code != 3 || pps_response[0] != 0xD0) {
return return_code == 0 ? 2 : return_code; return return_code == 0 ? 2 : return_code;
} }
Dbprintf("ISO 14443 Type A"); Dbprintf("ISO 14443 Type A");
iso_type = 'a'; iso_type = 'a';
return 0; return 0;
} }
// if we're here, there is no type A card, so we look for type B // if we're here, there is no type A card, so we look for type B
// power up the field // power up the field
iso14443b_setup(); iso14443b_setup();
// select the card // select the card
return_code = iso14443b_select_card( &card_b_info ); return_code = iso14443b_select_card( &card_b_info );
if (return_code == 0) { if (return_code == 0) {
Dbprintf("ISO 14443 Type B"); Dbprintf("ISO 14443 Type B");
iso_type = 'b'; iso_type = 'b';
return 0; return 0;
} }
Dbprintf("No card found."); Dbprintf("No card found.");
return 1; return 1;
} }

View file

@ -18,9 +18,9 @@
// this struct is used by EPA_Parse_CardAccess and contains info about the // this struct is used by EPA_Parse_CardAccess and contains info about the
// PACE protocol supported by the chip // PACE protocol supported by the chip
typedef struct { typedef struct {
uint8_t oid[10]; uint8_t oid[10];
uint8_t version; uint8_t version;
uint8_t parameter_id; uint8_t parameter_id;
} pace_version_info_t; } pace_version_info_t;
// note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h // note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h

File diff suppressed because it is too large Load diff

View file

@ -18,118 +18,118 @@ void FlashmemSetSpiBaudrate(uint32_t baudrate){
Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000); Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000);
} }
// initialize // initialize
bool FlashInit() { bool FlashInit() {
FlashSetup(FLASHMEM_SPIBAUDRATE); FlashSetup(FLASHMEM_SPIBAUDRATE);
StartTicks(); StartTicks();
if (Flash_CheckBusy(BUSY_TIMEOUT)) { if (Flash_CheckBusy(BUSY_TIMEOUT)) {
StopTicks(); StopTicks();
return false; return false;
} }
return true; return true;
} }
void FlashSetup(uint32_t baudrate){ void FlashSetup(uint32_t baudrate){
//WDT_DISABLE //WDT_DISABLE
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
// PA10 -> SPI_NCS2 chip select (FLASHMEM) // PA10 -> SPI_NCS2 chip select (FLASHMEM)
// PA11 -> SPI_NCS0 chip select (FPGA) // PA11 -> SPI_NCS0 chip select (FPGA)
// PA12 -> SPI_MISO Master-In Slave-Out // PA12 -> SPI_MISO Master-In Slave-Out
// PA13 -> SPI_MOSI Master-Out Slave-In // PA13 -> SPI_MOSI Master-Out Slave-In
// PA14 -> SPI_SPCK Serial Clock // PA14 -> SPI_SPCK Serial Clock
// Disable PIO control of the following pins, allows use by the SPI peripheral // Disable PIO control of the following pins, allows use by the SPI peripheral
AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
// Pull-up Enable // Pull-up Enable
AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2);
// Peripheral A // Peripheral A
AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK); AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK);
// Peripheral B // Peripheral B
AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2;
//enable the SPI Peripheral clock //enable the SPI Peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
//reset spi needs double SWRST, see atmel's errata on this case //reset spi needs double SWRST, see atmel's errata on this case
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
// Enable SPI // Enable SPI
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
// NPCS2 Mode 0 // NPCS2 Mode 0
AT91C_BASE_SPI->SPI_MR = AT91C_BASE_SPI->SPI_MR =
(0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
// If DLYBCS is less than or equal to six, six MCK periods // If DLYBCS is less than or equal to six, six MCK periods
// will be inserted by default. // will be inserted by default.
SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode) ( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
( 1 << 4) | // Disable ModeFault Protection ( 1 << 4) | // Disable ModeFault Protection
( 0 << 3) | // makes spi operate at MCK (1 is MCK/2) ( 0 << 3) | // makes spi operate at MCK (1 is MCK/2)
( 0 << 2) | // Chip selects connected directly to peripheral ( 0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode AT91C_SPI_MSTR; // Master Mode
uint8_t csaat = 1; uint8_t csaat = 1;
uint32_t dlybct = 0; uint32_t dlybct = 0;
if (baudrate > FLASH_MINFAST) { if (baudrate > FLASH_MINFAST) {
baudrate = FLASH_FASTBAUD; baudrate = FLASH_FASTBAUD;
//csaat = 0; //csaat = 0;
dlybct = 1500; dlybct = 1500;
} }
AT91C_BASE_SPI->SPI_CSR[2] = AT91C_BASE_SPI->SPI_CSR[2] =
SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods) SPI_DLYBCT(dlybct,MCK)| // Delay between Consecutive Transfers (32 MCK periods)
SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock
SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection SPI_SCBR(baudrate,MCK)| // SPI Baudrate Selection
AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
//AT91C_SPI_CSAAT | // Chip Select inactive after transfer //AT91C_SPI_CSAAT | // Chip Select inactive after transfer
// 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
// If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
// the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
// transferred in the shifter. This can imply for example, that the second data is sent twice. // transferred in the shifter. This can imply for example, that the second data is sent twice.
// COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
( csaat << 3) | ( csaat << 3) |
/* Spi modes: /* Spi modes:
Mode CPOL CPHA NCPHA Mode CPOL CPHA NCPHA
0 0 0 1 clock normally low read on rising edge 0 0 0 1 clock normally low read on rising edge
1 0 1 0 clock normally low read on falling edge 1 0 1 0 clock normally low read on falling edge
2 1 0 1 clock normally high read on falling edge 2 1 0 1 clock normally high read on falling edge
3 1 1 0 clock normally high read on rising edge 3 1 1 0 clock normally high read on rising edge
However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
master mode the ATSAM7S512/256/128/64/321/32 does not sample the data master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
(MISO) on the opposite edge where data clocks out (MOSI) but the same (MISO) on the opposite edge where data clocks out (MOSI) but the same
edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
that the data changes sometime after the rising edge (about 2 ns). To that the data changes sometime after the rising edge (about 2 ns). To
be consistent with normal SPI operation, it is probably safe to say be consistent with normal SPI operation, it is probably safe to say
that the data changes on the falling edge and should be sampled on the that the data changes on the falling edge and should be sampled on the
rising edge. Therefore, it appears that NCPHA should be treated the rising edge. Therefore, it appears that NCPHA should be treated the
same as CPHA. Thus: same as CPHA. Thus:
Mode CPOL CPHA NCPHA Mode CPOL CPHA NCPHA
0 0 0 0 clock normally low read on rising edge 0 0 0 0 clock normally low read on rising edge
1 0 1 1 clock normally low read on falling edge 1 0 1 1 clock normally low read on falling edge
2 1 0 0 clock normally high read on falling edge 2 1 0 0 clock normally high read on falling edge
3 1 1 1 clock normally high read on rising edge 3 1 1 1 clock normally high read on rising edge
*/ */
( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0 ( 0 << 0); // Clock Polarity inactive state is logic 0
// read first, empty buffer // read first, empty buffer
if (AT91C_BASE_SPI->SPI_RDR == 0) {}; if (AT91C_BASE_SPI->SPI_RDR == 0) {};
} }
void FlashStop(void) { void FlashStop(void) {
//Bof //Bof
//* Reset all the Chip Select register //* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0;
AT91C_BASE_SPI->SPI_CSR[2] = 0; AT91C_BASE_SPI->SPI_CSR[2] = 0;
@ -141,164 +141,164 @@ void FlashStop(void) {
// Disable all interrupts // Disable all interrupts
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF; AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
// SPI disable // SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop"); if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop");
StopTicks(); StopTicks();
} }
// send one byte over SPI // send one byte over SPI
uint16_t FlashSendByte(uint32_t data) { uint16_t FlashSendByte(uint32_t data) {
// wait until SPI is ready for transfer // wait until SPI is ready for transfer
//if you are checking for incoming data returned then the TXEMPTY flag is redundant //if you are checking for incoming data returned then the TXEMPTY flag is redundant
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
// send the data // send the data
AT91C_BASE_SPI->SPI_TDR = data; AT91C_BASE_SPI->SPI_TDR = data;
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
// wait recive transfer is complete // wait recive transfer is complete
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){}; while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){};
// reading incoming data // reading incoming data
return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
} }
// send last byte over SPI // send last byte over SPI
uint16_t FlashSendLastByte(uint32_t data) { uint16_t FlashSendLastByte(uint32_t data) {
return FlashSendByte(data | AT91C_SPI_LASTXFER); return FlashSendByte(data | AT91C_SPI_LASTXFER);
} }
// read state register 1 // read state register 1
uint8_t Flash_ReadStat1(void) { uint8_t Flash_ReadStat1(void) {
FlashSendByte(READSTAT1); FlashSendByte(READSTAT1);
return FlashSendLastByte(0xFF); return FlashSendLastByte(0xFF);
} }
bool Flash_CheckBusy(uint32_t timeout) bool Flash_CheckBusy(uint32_t timeout)
{ {
WaitUS(WINBOND_WRITE_DELAY); WaitUS(WINBOND_WRITE_DELAY);
StartCountUS(); StartCountUS();
uint32_t _time = GetCountUS(); uint32_t _time = GetCountUS();
if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in..."); if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in...");
do do
{ {
if (!(Flash_ReadStat1() & BUSY)) if (!(Flash_ReadStat1() & BUSY))
{ {
return false; return false;
} }
} while ((GetCountUS() - _time) < timeout); } while ((GetCountUS() - _time) < timeout);
if (timeout <= (GetCountUS() - _time)) if (timeout <= (GetCountUS() - _time))
{ {
return true; return true;
} }
return false; return false;
} }
// read ID out // read ID out
uint8_t Flash_ReadID(void) { uint8_t Flash_ReadID(void) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
// Manufacture ID / device ID // Manufacture ID / device ID
FlashSendByte(ID); FlashSendByte(ID);
FlashSendByte(0x00); FlashSendByte(0x00);
FlashSendByte(0x00); FlashSendByte(0x00);
FlashSendByte(0x00); FlashSendByte(0x00);
uint8_t man_id = FlashSendByte(0xFF); uint8_t man_id = FlashSendByte(0xFF);
uint8_t dev_id = FlashSendLastByte(0xFF); uint8_t dev_id = FlashSendLastByte(0xFF);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id); if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
if ( (man_id == WINBOND_MANID ) && (dev_id == WINBOND_DEVID) ) if ( (man_id == WINBOND_MANID ) && (dev_id == WINBOND_DEVID) )
return dev_id; return dev_id;
return 0; return 0;
} }
// read unique id for chip. // read unique id for chip.
void Flash_UniqueID(uint8_t *uid) { void Flash_UniqueID(uint8_t *uid) {
if (Flash_CheckBusy(BUSY_TIMEOUT)) return; if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
// reading unique serial number // reading unique serial number
FlashSendByte(UNIQUE_ID); FlashSendByte(UNIQUE_ID);
FlashSendByte(0xFF); FlashSendByte(0xFF);
FlashSendByte(0xFF); FlashSendByte(0xFF);
FlashSendByte(0xFF); FlashSendByte(0xFF);
FlashSendByte(0xFF); FlashSendByte(0xFF);
uid[7] = FlashSendByte(0xFF); uid[7] = FlashSendByte(0xFF);
uid[6] = FlashSendByte(0xFF); uid[6] = FlashSendByte(0xFF);
uid[5] = FlashSendByte(0xFF); uid[5] = FlashSendByte(0xFF);
uid[4] = FlashSendByte(0xFF); uid[4] = FlashSendByte(0xFF);
uid[3] = FlashSendByte(0xFF); uid[3] = FlashSendByte(0xFF);
uid[2] = FlashSendByte(0xFF); uid[2] = FlashSendByte(0xFF);
uid[1] = FlashSendByte(0xFF); uid[1] = FlashSendByte(0xFF);
uid[0] = FlashSendLastByte(0xFF); uid[0] = FlashSendLastByte(0xFF);
} }
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
if (!FlashInit()) return 0; if (!FlashInit()) return 0;
// length should never be zero // length should never be zero
if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd); FlashSendByte(cmd);
Flash_TransferAdresse(address); Flash_TransferAdresse(address);
if (FASTFLASH){ if (FASTFLASH){
FlashSendByte(DUMMYBYTE); FlashSendByte(DUMMYBYTE);
} }
uint16_t i = 0; uint16_t i = 0;
for (; i < (len - 1); i++) for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF); out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF); out[i] = FlashSendLastByte(0xFF);
FlashStop(); FlashStop();
return len; return len;
} }
void Flash_TransferAdresse(uint32_t address){ void Flash_TransferAdresse(uint32_t address){
FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF); FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF); FlashSendByte((address >> 0) & 0xFF);
} }
/* This ensure we can ReadData without having to cycle through initialization everytime */ /* This ensure we can ReadData without having to cycle through initialization everytime */
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero // length should never be zero
if (!len) return 0; if (!len) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd); FlashSendByte(cmd);
Flash_TransferAdresse(address); Flash_TransferAdresse(address);
if (FASTFLASH){ if (FASTFLASH){
FlashSendByte(DUMMYBYTE); FlashSendByte(DUMMYBYTE);
} }
uint16_t i = 0; uint16_t i = 0;
for (; i < (len - 1); i++) for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF); out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF); out[i] = FlashSendLastByte(0xFF);
return len; return len;
} }
@ -307,89 +307,89 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// if len > 256, it might wrap around and overwrite pos 0. // if len > 256, it might wrap around and overwrite pos 0.
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// length should never be zero // length should never be zero
if (!len) if (!len)
return 0; return 0;
// Max 256 bytes write // Max 256 bytes write
if (((address & 0xFF) + len) > 256) { if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len );
return 0; return 0;
} }
// out-of-range // out-of-range
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range"); Dbprintf("Flash_WriteData, block out-of-range");
return 0; return 0;
} }
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
return 0; return 0;
} }
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
FlashSendByte(PAGEPROG); FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF); FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF); FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0; uint16_t i = 0;
for (; i < (len - 1); i++) for (; i < (len - 1); i++)
FlashSendByte(in[i]); FlashSendByte(in[i]);
FlashSendLastByte(in[i]); FlashSendLastByte(in[i]);
FlashStop(); FlashStop();
return len; return len;
} }
// length should never be zero // length should never be zero
// Max 256 bytes write // Max 256 bytes write
// out-of-range // out-of-range
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
if (!len) if (!len)
return 0; return 0;
if (((address & 0xFF) + len) > 256) { if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len );
return 0; return 0;
} }
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range"); Dbprintf("Flash_WriteDataCont, block out-of-range");
return 0; return 0;
} }
FlashSendByte(PAGEPROG); FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF); FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF); FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0; uint16_t i = 0;
for (; i < (len - 1); i++) for (; i < (len - 1); i++)
FlashSendByte(in[i]); FlashSendByte(in[i]);
FlashSendLastByte(in[i]); FlashSendLastByte(in[i]);
return len; return len;
} }
// assumes valid start 256 based 00 address // assumes valid start 256 based 00 address
// //
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) { uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
bool isok; bool isok;
uint16_t res, bytes_sent = 0, bytes_remaining = len; uint16_t res, bytes_sent = 0, bytes_remaining = len;
uint8_t buf[FLASH_MEM_BLOCK_SIZE]; uint8_t buf[FLASH_MEM_BLOCK_SIZE];
while (bytes_remaining > 0) { while (bytes_remaining > 0) {
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
@ -397,85 +397,85 @@ uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet); res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
bytes_remaining -= bytes_in_packet; bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet; bytes_sent += bytes_in_packet;
isok = (res == bytes_in_packet); isok = (res == bytes_in_packet);
if (!isok) if (!isok)
goto out; goto out;
} }
out: out:
FlashStop(); FlashStop();
return len; return len;
} }
bool Flash_WipeMemoryPage(uint8_t page) { bool Flash_WipeMemoryPage(uint8_t page) {
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
return false; return false;
} }
Flash_ReadStat1(); Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms ) // Each block is 64Kb. One block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop(); FlashStop();
return true; return true;
} }
// Wipes flash memory completely, fills with 0xFF // Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory() { bool Flash_WipeMemory() {
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail");
return false; return false;
} }
Flash_ReadStat1(); Flash_ReadStat1();
// Each block is 64Kb. Four blocks // Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms ) // one block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop(); FlashStop();
return true; return true;
} }
// enable the flash write // enable the flash write
void Flash_WriteEnable() { void Flash_WriteEnable() {
FlashSendLastByte(WRITEENABLE); FlashSendLastByte(WRITEENABLE);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled");
} }
// erase 4K at one time // erase 4K at one time
// execution time: 0.8ms / 800us // execution time: 0.8ms / 800us
bool Flash_Erase4k(uint8_t block, uint8_t sector) { bool Flash_Erase4k(uint8_t block, uint8_t sector) {
if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false; if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false;
FlashSendByte(SECTORERASE); FlashSendByte(SECTORERASE);
FlashSendByte(block); FlashSendByte(block);
FlashSendByte(sector << 4); FlashSendByte(sector << 4);
FlashSendLastByte(00); FlashSendLastByte(00);
return true; return true;
} }
/* /*
// erase 32K at one time // erase 32K at one time
// execution time: 0,3s / 300ms // execution time: 0,3s / 300ms
bool Flash_Erase32k(uint32_t address) { bool Flash_Erase32k(uint32_t address) {
if (address & (32*1024 - 1)) { if (address & (32*1024 - 1)) {
if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096"); if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
return false; return false;
} }
FlashSendByte(BLOCK32ERASE); FlashSendByte(BLOCK32ERASE);
FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF); FlashSendByte((address >> 8) & 0xFF);
FlashSendLastByte((address >> 0) & 0xFF); FlashSendLastByte((address >> 0) & 0xFF);
return true; return true;
} }
*/ */
@ -489,52 +489,52 @@ bool Flash_Erase32k(uint32_t address) {
// 0x03 00 00 -- 0x 03 FF FF == block 3 // 0x03 00 00 -- 0x 03 FF FF == block 3
bool Flash_Erase64k(uint8_t block) { bool Flash_Erase64k(uint8_t block) {
if (block > MAX_BLOCKS) return false; if (block > MAX_BLOCKS) return false;
FlashSendByte(BLOCK64ERASE); FlashSendByte(BLOCK64ERASE);
FlashSendByte(block); FlashSendByte(block);
FlashSendByte(0x00); FlashSendByte(0x00);
FlashSendLastByte(0x00); FlashSendLastByte(0x00);
return true; return true;
} }
// Erase chip // Erase chip
void Flash_EraseChip(void) { void Flash_EraseChip(void) {
FlashSendLastByte(CHIPERASE); FlashSendLastByte(CHIPERASE);
} }
void Flashmem_print_status(void) { void Flashmem_print_status(void) {
DbpString("Flash memory"); DbpString("Flash memory");
Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000);
if (!FlashInit()) { if (!FlashInit()) {
DbpString(" Init....................FAIL"); DbpString(" Init....................FAIL");
return; return;
} }
DbpString(" Init....................OK"); DbpString(" Init....................OK");
uint8_t dev_id = Flash_ReadID(); uint8_t dev_id = Flash_ReadID();
switch (dev_id) { switch (dev_id) {
case 0x11 : case 0x11 :
DbpString(" Memory size.............2 mbits / 256kb"); DbpString(" Memory size.............2 mbits / 256kb");
break; break;
case 0x10 : case 0x10 :
DbpString(" Memory size..... .......1 mbits / 128kb"); DbpString(" Memory size..... .......1 mbits / 128kb");
break; break;
case 0x05 : case 0x05 :
DbpString(" Memory size.............512 kbits / 64kb"); DbpString(" Memory size.............512 kbits / 64kb");
break; break;
default : default :
DbpString(" Device ID............... --> Unknown <--"); DbpString(" Device ID............... --> Unknown <--");
break; break;
} }
uint8_t uid[8] = {0,0,0,0,0,0,0,0}; uint8_t uid[8] = {0,0,0,0,0,0,0,0};
Flash_UniqueID(uid); Flash_UniqueID(uid);
Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x",
uid[7], uid[6], uid[5], uid[4], uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0] uid[3], uid[2], uid[1], uid[0]
); );
FlashStop(); FlashStop();
} }

View file

@ -23,7 +23,7 @@
* <http://www.gnu.org/licenses/>. * <http://www.gnu.org/licenses/>.
*/ */
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Common Instructions // // Common Instructions //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#ifndef __FLASHMEM_H #ifndef __FLASHMEM_H
#define __FLASHMEM_H #define __FLASHMEM_H
@ -32,74 +32,74 @@
#include "apps.h" #include "apps.h"
#include "ticks.h" #include "ticks.h"
// Used Command // Used Command
#define ID 0x90 #define ID 0x90
#define MANID 0x90 #define MANID 0x90
#define JEDECID 0x9F #define JEDECID 0x9F
#define READSTAT1 0x05 #define READSTAT1 0x05
#define READSTAT2 0x35 #define READSTAT2 0x35
#define WRITESTAT 0x01 #define WRITESTAT 0x01
#define WRITEDISABLE 0x04 #define WRITEDISABLE 0x04
#define WRITEENABLE 0x06 #define WRITEENABLE 0x06
#define READDATA 0x03 #define READDATA 0x03
#define FASTREAD 0x0B #define FASTREAD 0x0B
#define PAGEPROG 0x02 #define PAGEPROG 0x02
#define SECTORERASE 0x20 #define SECTORERASE 0x20
#define BLOCK32ERASE 0x52 #define BLOCK32ERASE 0x52
#define BLOCK64ERASE 0xD8 #define BLOCK64ERASE 0xD8
#define CHIPERASE 0xC7 #define CHIPERASE 0xC7
#define UNIQUE_ID 0x4B #define UNIQUE_ID 0x4B
// Not used or not support command // Not used or not support command
#define RELEASE 0xAB #define RELEASE 0xAB
#define POWERDOWN 0xB9 #define POWERDOWN 0xB9
#define SUSPEND 0x75 #define SUSPEND 0x75
#define RESUME 0x7A #define RESUME 0x7A
#define BUSY_TIMEOUT 1000000000L #define BUSY_TIMEOUT 1000000000L
#define WINBOND_MANID 0xEF #define WINBOND_MANID 0xEF
#define WINBOND_DEVID 0x11 #define WINBOND_DEVID 0x11
#define PAGESIZE 0x100 #define PAGESIZE 0x100
#define WINBOND_WRITE_DELAY 0x02 #define WINBOND_WRITE_DELAY 0x02
#define SPI_CLK 48000000 #define SPI_CLK 48000000
#define BUSY 0x01 #define BUSY 0x01
#define WRTEN 0x02 #define WRTEN 0x02
#define SUS 0x40 #define SUS 0x40
#define DUMMYBYTE 0xEE #define DUMMYBYTE 0xEE
#define NULLBYTE 0x00 #define NULLBYTE 0x00
#define NULLINT 0x0000 #define NULLINT 0x0000
#define NO_CONTINUE 0x00 #define NO_CONTINUE 0x00
#define PASS 0x01 #define PASS 0x01
#define FAIL 0x00 #define FAIL 0x00
#define maxAddress capacity #define maxAddress capacity
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// List of Error codes // // List of Error codes //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#define SUCCESS 0x00 #define SUCCESS 0x00
#define CALLBEGIN 0x01 #define CALLBEGIN 0x01
#define UNKNOWNCHIP 0x02 #define UNKNOWNCHIP 0x02
#define UNKNOWNCAP 0x03 #define UNKNOWNCAP 0x03
#define CHIPBUSY 0x04 #define CHIPBUSY 0x04
#define OUTOFBOUNDS 0x05 #define OUTOFBOUNDS 0x05
#define CANTENWRITE 0x06 #define CANTENWRITE 0x06
#define PREVWRITTEN 0x07 #define PREVWRITTEN 0x07
#define LOWRAM 0x08 #define LOWRAM 0x08
#define NOSUSPEND 0x09 #define NOSUSPEND 0x09
#define UNKNOWNERROR 0xFF #define UNKNOWNERROR 0xFF
// List of blocks // List of blocks
#define MAX_BLOCKS 4 #define MAX_BLOCKS 4
#define MAX_SECTORS 16 #define MAX_SECTORS 16

View file

@ -7,302 +7,302 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const char FONT6x8[97][8] = { const char FONT6x8[97][8] = {
{0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char {0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
{0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00}, // ! {0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00}, // !
{0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00}, // " {0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00}, // "
{0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00}, // # {0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00}, // #
{0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00}, // $ {0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00}, // $
{0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00}, // % {0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00}, // %
{0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00}, // & {0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00}, // &
{0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00}, // ' {0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00}, // '
{0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00}, // ( {0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00}, // (
{0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00}, // ) {0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00}, // )
{0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00}, // * {0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00}, // *
{0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00}, // + {0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00}, // +
{0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40}, // , {0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40}, // ,
{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, // - {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, // . {0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, // .
{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, // / {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, // /
{0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00}, // 0 {0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00}, // 0
{0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00}, // 1 {0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00}, // 1
{0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00}, // 2 {0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00}, // 2
{0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00}, // 3 {0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00}, // 3
{0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00}, // 4 {0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00}, // 4
{0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00}, // 5 {0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00}, // 5
{0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00}, // 6 {0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00}, // 6
{0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00}, // 7 {0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00}, // 7
{0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00}, // 8 {0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00}, // 8
{0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00}, // 9 {0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00}, // 9
{0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00}, // : {0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00}, // :
{0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00}, // ; {0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00}, // ;
{0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00}, // < {0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00}, // <
{0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00}, // = {0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00}, // =
{0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00}, // > {0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00}, // >
{0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00}, // ? {0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00}, // ?
{0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00}, // @ {0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00}, // @
{0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00}, // A {0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00}, // A
{0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00}, // B {0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00}, // B
{0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00}, // C {0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00}, // C
{0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00}, // D {0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00}, // D
{0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00}, // E {0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00}, // E
{0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00}, // F {0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00}, // F
{0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00}, // G {0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00}, // G
{0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00}, // H {0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00}, // H
{0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // I {0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // I
{0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00}, // J {0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00}, // J
{0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00}, // K {0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00}, // K
{0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00}, // L {0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00}, // L
{0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00}, // M {0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00}, // M
{0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00}, // N {0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00}, // N
{0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // O {0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // O
{0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00}, // P {0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00}, // P
{0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00}, // Q {0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00}, // Q
{0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00}, // R {0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00}, // R
{0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00}, // S {0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00}, // S
{0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00}, // T {0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00}, // T
{0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // U {0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // U
{0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00}, // V {0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00}, // V
{0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00}, // W {0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00}, // W
{0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00}, // X {0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00}, // X
{0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00}, // Y {0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00}, // Y
{0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00}, // Z {0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00}, // Z
{0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00}, // [ {0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00}, // [
{0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00}, // backslash {0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00}, // backslash
{0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00}, // ] {0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00}, // ]
{0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00}, // ^ {0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00}, // ^
{0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00}, // _ {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00}, // _
{0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00}, // ` {0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00}, // `
{0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00}, // a {0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00}, // a
{0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00}, // b {0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00}, // b
{0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00}, // c {0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00}, // c
{0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00}, // d {0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00}, // d
{0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00}, // e {0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00}, // e
{0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00}, // f {0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00}, // f
{0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70}, // g {0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70}, // g
{0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00}, // h {0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00}, // h
{0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00}, // i {0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00}, // i
{0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00}, // j {0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00}, // j
{0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00}, // k {0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00}, // k
{0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // l {0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // l
{0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00}, // m {0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00}, // m
{0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00}, // n {0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00}, // n
{0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00}, // o {0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00}, // o
{0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80}, // p {0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80}, // p
{0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08}, // q {0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08}, // q
{0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00}, // r {0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00}, // r
{0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00}, // s {0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00}, // s
{0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00}, // t {0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00}, // t
{0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00}, // u {0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00}, // u
{0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00}, // v {0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00}, // v
{0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00}, // w {0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00}, // w
{0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00}, // x {0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00}, // x
{0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70}, // y {0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70}, // y
{0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00}, // z {0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00}, // z
{0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00}, // { {0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00}, // {
{0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00}, // | {0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00}, // |
{0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00}, // } {0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00}, // }
{0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00}, // ~ {0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00}, // ~
{0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00} // DEL {0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00} // DEL
}; };
/* /*
const char FONT8x8F[97][8] = { const char FONT8x8F[97][8] = {
{0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
{0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // ! {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // !
{0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // " {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // "
{0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // # {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // #
{0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $ {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $
{0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // % {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // %
{0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // & {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // &
{0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // ' {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // '
{0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // ( {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // (
{0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // ) {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // )
{0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // * {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // *
{0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // + {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // +
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // ,
{0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // - {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // .
{0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // /
{0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0
{0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1 {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1
{0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2 {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2
{0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3 {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3
{0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4 {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4
{0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5 {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5
{0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6 {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6
{0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7 {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7
{0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8 {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8
{0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9 {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9
{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // :
{0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ; {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ;
{0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // < {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // <
{0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // = {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // =
{0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // > {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // >
{0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ? {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ?
{0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @
{0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A
{0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B
{0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C
{0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D
{0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E
{0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F
{0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G
{0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H
{0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I
{0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J
{0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K
{0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L
{0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M
{0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N
{0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O
{0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P
{0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q
{0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R
{0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S
{0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T
{0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U
{0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V
{0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W
{0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X
{0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y
{0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z
{0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [
{0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // backslash {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // backslash
{0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ]
{0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^ {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _
{0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // `
{0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a
{0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b
{0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c
{0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d
{0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e
{0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f
{0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g
{0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h
{0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i
{0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j
{0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k
{0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l
{0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m
{0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n
{0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o
{0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p
{0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q
{0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r
{0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s
{0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t
{0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u
{0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v
{0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w
{0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x
{0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y
{0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z
{0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // { {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // {
{0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // | {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // |
{0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // } {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // }
{0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
{0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00} // DEL {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00} // DEL
}; };
const char FONT8x16[97][16] = { const char FONT8x16[97][16] = {
{0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char {0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
{0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // ! {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // !
{0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // " {0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // "
{0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // # {0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // #
{0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00}, // $ {0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00}, // $
{0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00}, // % {0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00}, // %
{0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // & {0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // &
{0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ' {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // '
{0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00}, // ( {0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00}, // (
{0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00}, // ) {0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00}, // )
{0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00}, // * {0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00}, // *
{0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, // + {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, // +
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // , {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ,
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // . {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // .
{0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00}, // / {0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00}, // /
{0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 0 {0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 0
{0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00}, // 1 {0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00}, // 1
{0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // 2 {0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // 2
{0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // 3 {0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // 3
{0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00}, // 4 {0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00}, // 4
{0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00}, // 5 {0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00}, // 5
{0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 6 {0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 6
{0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, // 7 {0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, // 7
{0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 8 {0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 8
{0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00}, // 9 {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00}, // 9
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // : {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // :
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ; {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ;
{0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, // < {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, // <
{0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, // = {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, // =
{0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, // > {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, // >
{0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00}, // ? {0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00}, // ?
{0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00}, // @ {0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00}, // @
{0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // A {0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // A
{0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00}, // B {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00}, // B
{0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00}, // C {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00}, // C
{0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00}, // D {0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00}, // D
{0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // E {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // E
{0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // F {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // F
{0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00}, // G {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00}, // G
{0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // H {0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // H
{0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // I {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // I
{0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}, // J {0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}, // J
{0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // K {0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // K
{0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // L {0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // L
{0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // M {0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // M
{0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // N {0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // N
{0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00}, // O {0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00}, // O
{0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // P {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // P
{0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00}, // Q {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00}, // Q
{0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // R {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // R
{0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // S {0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // S
{0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // T {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // T
{0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // U {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // U
{0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00}, // V {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00}, // V
{0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // W {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // W
{0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00}, // X {0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00}, // X
{0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // Y {0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // Y
{0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // Z {0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // Z
{0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, // [ {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, // [
{0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, // backslash {0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, // backslash
{0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, // ] {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, // ]
{0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^ {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // _ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // _
{0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ` {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // `
{0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // a {0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // a
{0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00}, // b {0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00}, // b
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // c {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // c
{0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // d {0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // d
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // e {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // e
{0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // f {0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // f
{0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00}, // g {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00}, // g
{0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // h {0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // h
{0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // i {0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // i
{0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00}, // j {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00}, // j
{0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00}, // k {0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00}, // k
{0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // l {0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // l
{0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00}, // m {0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00}, // m
{0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00}, // n {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00}, // n
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // o {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // o
{0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00}, // p {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00}, // p
{0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00}, // q {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00}, // q
{0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // r {0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // r
{0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // s {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // s
{0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00}, // t {0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00}, // t
{0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // u {0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // u
{0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00}, // v {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00}, // v
{0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00}, // w {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00}, // w
{0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // x {0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // x
{0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00}, // y {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00}, // y
{0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00}, // z {0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00}, // z
{0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, // { {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, // {
{0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, // | {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, // |
{0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, // } {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, // }
{0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ {0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
{0x00,0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // DEL {0x00,0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // DEL
}; };
*/ */

View file

@ -21,7 +21,7 @@ extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end;
static uint8_t *fpga_image_ptr = NULL; static uint8_t *fpga_image_ptr = NULL;
static uint32_t uncompressed_bytes_cnt; static uint32_t uncompressed_bytes_cnt;
#define OUTPUT_BUFFER_LEN 80 #define OUTPUT_BUFFER_LEN 80
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Set up the Serial Peripheral Interface as master // Set up the Serial Peripheral Interface as master
@ -29,7 +29,7 @@ static uint32_t uncompressed_bytes_cnt;
// May also be used to write to other SPI attached devices like an LCD // May also be used to write to other SPI attached devices like an LCD
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void DisableSpi(void) { static void DisableSpi(void) {
//* Reset all the Chip Select register //* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0;
AT91C_BASE_SPI->SPI_CSR[2] = 0; AT91C_BASE_SPI->SPI_CSR[2] = 0;
@ -41,77 +41,77 @@ static void DisableSpi(void) {
// Disable all interrupts // Disable all interrupts
AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF; AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF;
// SPI disable // SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
} }
void SetupSpi(int mode) { void SetupSpi(int mode) {
// PA1 -> SPI_NCS3 chip select (MEM) // PA1 -> SPI_NCS3 chip select (MEM)
// PA10 -> SPI_NCS2 chip select (LCD) // PA10 -> SPI_NCS2 chip select (LCD)
// PA11 -> SPI_NCS0 chip select (FPGA) // PA11 -> SPI_NCS0 chip select (FPGA)
// PA12 -> SPI_MISO Master-In Slave-Out // PA12 -> SPI_MISO Master-In Slave-Out
// PA13 -> SPI_MOSI Master-Out Slave-In // PA13 -> SPI_MOSI Master-Out Slave-In
// PA14 -> SPI_SPCK Serial Clock // PA14 -> SPI_SPCK Serial Clock
// Disable PIO control of the following pins, allows use by the SPI peripheral // Disable PIO control of the following pins, allows use by the SPI peripheral
AT91C_BASE_PIOA->PIO_PDR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK; AT91C_BASE_PIOA->PIO_PDR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK;
// Peripheral A // Peripheral A
AT91C_BASE_PIOA->PIO_ASR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK; AT91C_BASE_PIOA->PIO_ASR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK;
// Peripheral B // Peripheral B
//AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; //AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2;
//enable the SPI Peripheral clock //enable the SPI Peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
// Enable SPI // Enable SPI
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
switch (mode) { switch (mode) {
case SPI_FPGA_MODE: case SPI_FPGA_MODE:
AT91C_BASE_SPI->SPI_MR = AT91C_BASE_SPI->SPI_MR =
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
(0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11) (0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
( 0 << 7) | // Local Loopback Disabled ( 0 << 7) | // Local Loopback Disabled
AT91C_SPI_MODFDIS | // Mode Fault Detection disabled AT91C_SPI_MODFDIS | // Mode Fault Detection disabled
( 0 << 2) | // Chip selects connected directly to peripheral ( 0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode AT91C_SPI_MSTR; // Master Mode
AT91C_BASE_SPI->SPI_CSR[0] = AT91C_BASE_SPI->SPI_CSR[0] =
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period) ( 1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits) AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
( 0 << 3) | // Chip Select inactive after transfer ( 0 << 3) | // Chip Select inactive after transfer
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0 ( 0 << 0); // Clock Polarity inactive state is logic 0
break; break;
/* /*
case SPI_LCD_MODE: case SPI_LCD_MODE:
AT91C_BASE_SPI->SPI_MR = AT91C_BASE_SPI->SPI_MR =
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods)
(0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10) (0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)
( 0 << 7) | // Local Loopback Disabled ( 0 << 7) | // Local Loopback Disabled
( 1 << 4) | // Mode Fault Detection disabled ( 1 << 4) | // Mode Fault Detection disabled
( 0 << 2) | // Chip selects connected directly to peripheral ( 0 << 2) | // Chip selects connected directly to peripheral
( 0 << 1) | // Fixed Peripheral Select ( 0 << 1) | // Fixed Peripheral Select
( 1 << 0); // Master Mode ( 1 << 0); // Master Mode
AT91C_BASE_SPI->SPI_CSR[2] = AT91C_BASE_SPI->SPI_CSR[2] =
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period) ( 1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits) AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits)
( 0 << 3) | // Chip Select inactive after transfer ( 0 << 3) | // Chip Select inactive after transfer
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0 ( 0 << 0); // Clock Polarity inactive state is logic 0
break; break;
*/ */
default: default:
DisableSpi(); DisableSpi();
break; break;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -119,35 +119,35 @@ void SetupSpi(int mode) {
// always use when we are talking to the FPGA. Both RX and TX are enabled. // always use when we are talking to the FPGA. Both RX and TX are enabled.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void FpgaSetupSsc(void) { void FpgaSetupSsc(void) {
// First configure the GPIOs, and get ourselves a clock. // First configure the GPIOs, and get ourselves a clock.
AT91C_BASE_PIOA->PIO_ASR = AT91C_BASE_PIOA->PIO_ASR =
GPIO_SSC_FRAME | GPIO_SSC_FRAME |
GPIO_SSC_DIN | GPIO_SSC_DIN |
GPIO_SSC_DOUT | GPIO_SSC_DOUT |
GPIO_SSC_CLK; GPIO_SSC_CLK;
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);
// Now set up the SSC proper, starting from a known state. // Now set up the SSC proper, starting from a known state.
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
// RX clock comes from TX clock, RX starts when TX starts, data changes // RX clock comes from TX clock, RX starts when TX starts, data changes
// on RX clock rising edge, sampled on falling edge // on RX clock rising edge, sampled on falling edge
AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1); AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);
// 8 bits per transfer, no loopback, MSB first, 1 transfer per sync // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync
// pulse, no output sync // pulse, no output sync
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
// clock comes from TK pin, no clock output, outputs change on falling // clock comes from TK pin, no clock output, outputs change on falling
// edge of TK, sample on rising edge of TK, start on positive-going edge of sync // edge of TK, sample on rising edge of TK, start on positive-going edge of sync
AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5); AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5);
// tx framing is the same as the rx framing // tx framing is the same as the rx framing
AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR; AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR;
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -157,15 +157,15 @@ void FpgaSetupSsc(void) {
// is in apps.h, because it should be inlined, for speed. // is in apps.h, because it should be inlined, for speed.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool FpgaSetupSscDma(uint8_t *buf, int len) { bool FpgaSetupSscDma(uint8_t *buf, int len) {
if (buf == NULL) return false; if (buf == NULL) return false;
FpgaDisableSscDma(); FpgaDisableSscDma();
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address
AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address
AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes
FpgaEnableSscDma(); FpgaEnableSscDma();
return true; return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -173,20 +173,20 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) {
// each call. // each call.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data
compressed_fpga_stream->next_out = output_buffer; compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
fpga_image_ptr = output_buffer; fpga_image_ptr = output_buffer;
int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH); int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH);
if (res != Z_OK) if (res != Z_OK)
Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg); Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg);
if (res < 0) if (res < 0)
return res; return res;
} }
uncompressed_bytes_cnt++; uncompressed_bytes_cnt++;
return *fpga_image_ptr++; return *fpga_image_ptr++;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -195,140 +195,140 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8
// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc. // 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) { while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions // skip undesired data belonging to other bitstream_versions
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
} }
return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
} }
static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) {
return BigBuf_malloc(items*size); return BigBuf_malloc(items*size);
} }
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
static void fpga_inflate_free(voidpf opaque, voidpf address) { static void fpga_inflate_free(voidpf opaque, voidpf address) {
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free(); BigBuf_Clear_ext(false);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Initialize decompression of the respective (HF or LF) FPGA stream // Initialize decompression of the respective (HF or LF) FPGA stream
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE];
uncompressed_bytes_cnt = 0; uncompressed_bytes_cnt = 0;
// initialize z_stream structure for inflate: // initialize z_stream structure for inflate:
compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start; compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start;
compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start; compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start;
compressed_fpga_stream->next_out = output_buffer; compressed_fpga_stream->next_out = output_buffer;
compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN;
compressed_fpga_stream->zalloc = &fpga_inflate_malloc; compressed_fpga_stream->zalloc = &fpga_inflate_malloc;
compressed_fpga_stream->zfree = &fpga_inflate_free; compressed_fpga_stream->zfree = &fpga_inflate_free;
inflateInit2(compressed_fpga_stream, 0); inflateInit2(compressed_fpga_stream, 0);
fpga_image_ptr = output_buffer; fpga_image_ptr = output_buffer;
for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++)
header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
// Check for a valid .bit file (starts with bitparse_fixed_header) // Check for a valid .bit file (starts with bitparse_fixed_header)
if (memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) if (memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0)
return true; return true;
return false; return false;
} }
static void DownloadFPGA_byte( uint8_t w) { static void DownloadFPGA_byte( uint8_t w) {
#define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); } #define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); }
SEND_BIT(7); SEND_BIT(7);
SEND_BIT(6); SEND_BIT(6);
SEND_BIT(5); SEND_BIT(5);
SEND_BIT(4); SEND_BIT(4);
SEND_BIT(3); SEND_BIT(3);
SEND_BIT(2); SEND_BIT(2);
SEND_BIT(1); SEND_BIT(1);
SEND_BIT(0); SEND_BIT(0);
} }
// Download the fpga image starting at current stream position with length FpgaImageLen bytes // Download the fpga image starting at current stream position with length FpgaImageLen bytes
static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
int i = 0; int i = 0;
AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON; AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;
AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON; AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON;
HIGH(GPIO_FPGA_ON); // ensure everything is powered on HIGH(GPIO_FPGA_ON); // ensure everything is powered on
SpinDelay(50); SpinDelay(50);
LED_D_ON(); LED_D_ON();
// These pins are inputs // These pins are inputs
AT91C_BASE_PIOA->PIO_ODR = AT91C_BASE_PIOA->PIO_ODR =
GPIO_FPGA_NINIT | GPIO_FPGA_NINIT |
GPIO_FPGA_DONE; GPIO_FPGA_DONE;
// PIO controls the following pins // PIO controls the following pins
AT91C_BASE_PIOA->PIO_PER = AT91C_BASE_PIOA->PIO_PER =
GPIO_FPGA_NINIT | GPIO_FPGA_NINIT |
GPIO_FPGA_DONE; GPIO_FPGA_DONE;
// Enable pull-ups // Enable pull-ups
AT91C_BASE_PIOA->PIO_PPUER = AT91C_BASE_PIOA->PIO_PPUER =
GPIO_FPGA_NINIT | GPIO_FPGA_NINIT |
GPIO_FPGA_DONE; GPIO_FPGA_DONE;
// setup initial logic state // setup initial logic state
HIGH(GPIO_FPGA_NPROGRAM); HIGH(GPIO_FPGA_NPROGRAM);
LOW(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK);
LOW(GPIO_FPGA_DIN); LOW(GPIO_FPGA_DIN);
// These pins are outputs // These pins are outputs
AT91C_BASE_PIOA->PIO_OER = AT91C_BASE_PIOA->PIO_OER =
GPIO_FPGA_NPROGRAM | GPIO_FPGA_NPROGRAM |
GPIO_FPGA_CCLK | GPIO_FPGA_CCLK |
GPIO_FPGA_DIN; GPIO_FPGA_DIN;
// enter FPGA configuration mode // enter FPGA configuration mode
LOW(GPIO_FPGA_NPROGRAM); LOW(GPIO_FPGA_NPROGRAM);
SpinDelay(50); SpinDelay(50);
HIGH(GPIO_FPGA_NPROGRAM); HIGH(GPIO_FPGA_NPROGRAM);
i = 100000; i = 100000;
// wait for FPGA ready to accept data signal // wait for FPGA ready to accept data signal
while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) { while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) {
i--; i--;
} }
// crude error indicator, leave both red LEDs on and return // crude error indicator, leave both red LEDs on and return
if (i==0){ if (i==0){
LED_C_ON(); LED_C_ON();
LED_D_ON(); LED_D_ON();
return; return;
} }
for (i = 0; i < FpgaImageLen; i++) { for (i = 0; i < FpgaImageLen; i++) {
int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
if (b < 0) { if (b < 0) {
Dbprintf("Error %d during FpgaDownload", b); Dbprintf("Error %d during FpgaDownload", b);
break; break;
} }
DownloadFPGA_byte(b); DownloadFPGA_byte(b);
} }
// continue to clock FPGA until ready signal goes high // continue to clock FPGA until ready signal goes high
i = 100000; i = 100000;
while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) {
HIGH(GPIO_FPGA_CCLK); HIGH(GPIO_FPGA_CCLK);
LOW(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK);
} }
// crude error indicator, leave both red LEDs on and return // crude error indicator, leave both red LEDs on and return
if (i==0){ if (i==0){
LED_C_ON(); LED_C_ON();
LED_D_ON(); LED_D_ON();
return; return;
} }
LED_D_OFF(); LED_D_OFF();
} }
/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence /* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence
@ -338,48 +338,48 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
* length. * length.
*/ */
static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
int result = 0; int result = 0;
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
uint16_t numbytes = 0; uint16_t numbytes = 0;
while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++; numbytes++;
uint32_t current_length = 0; uint32_t current_length = 0;
if (current_name < 'a' || current_name > 'e') { if (current_name < 'a' || current_name > 'e') {
/* Strange section name, abort */ /* Strange section name, abort */
break; break;
} }
current_length = 0; current_length = 0;
switch (current_name) { switch (current_name) {
case 'e': case 'e':
/* Four byte length field */ /* Four byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
numbytes += 2; numbytes += 2;
default: /* Fall through, two byte length field */ default: /* Fall through, two byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 2; numbytes += 2;
} }
if (current_name != 'e' && current_length > 255) { if (current_name != 'e' && current_length > 255) {
/* Maybe a parse error */ /* Maybe a parse error */
break; break;
} }
if (current_name == section_name) { if (current_name == section_name) {
/* Found it */ /* Found it */
*section_length = current_length; *section_length = current_length;
result = 1; result = 1;
break; break;
} }
for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) {
get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++; numbytes++;
} }
} }
return result; return result;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -388,34 +388,34 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void FpgaDownloadAndGo(int bitstream_version) { void FpgaDownloadAndGo(int bitstream_version) {
// check whether or not the bitstream is already loaded // check whether or not the bitstream is already loaded
if (downloaded_bitstream == bitstream_version) if (downloaded_bitstream == bitstream_version)
return; return;
z_stream compressed_fpga_stream; z_stream compressed_fpga_stream;
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
bool verbose = (MF_DBGLEVEL > 3); bool verbose = (MF_DBGLEVEL > 3);
// make sure that we have enough memory to decompress // make sure that we have enough memory to decompress
BigBuf_free(); BigBuf_Clear_ext(verbose); BigBuf_free(); BigBuf_Clear_ext(verbose);
if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
return; return;
uint32_t bitstream_length; uint32_t bitstream_length;
if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) {
DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer); DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer);
downloaded_bitstream = bitstream_version; downloaded_bitstream = bitstream_version;
} }
inflateEnd(&compressed_fpga_stream); inflateEnd(&compressed_fpga_stream);
// turn off antenna // turn off antenna
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free(); BigBuf_Clear_ext(false);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -424,10 +424,10 @@ void FpgaDownloadAndGo(int bitstream_version) {
// where C is the 4 bit command and D is the 12 bit data // where C is the 4 bit command and D is the 12 bit data
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void FpgaSendCommand(uint16_t cmd, uint16_t v) { void FpgaSendCommand(uint16_t cmd, uint16_t v) {
SetupSpi(SPI_FPGA_MODE); SetupSpi(SPI_FPGA_MODE);
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data
while (!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF)) {}; // wait till transfer is complete while (!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF)) {}; // wait till transfer is complete
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Write the FPGA setup word (that determines what mode the logic is in, read // Write the FPGA setup word (that determines what mode the logic is in, read
@ -435,7 +435,7 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) {
// avoid changing this function's occurence everywhere in the source code. // avoid changing this function's occurence everywhere in the source code.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void FpgaWriteConfWord(uint8_t v) { void FpgaWriteConfWord(uint8_t v) {
FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -444,35 +444,35 @@ void FpgaWriteConfWord(uint8_t v) {
// the samples from the ADC always flow through the FPGA. // the samples from the ADC always flow through the FPGA.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SetAdcMuxFor(uint32_t whichGpio) { void SetAdcMuxFor(uint32_t whichGpio) {
AT91C_BASE_PIOA->PIO_OER = AT91C_BASE_PIOA->PIO_OER =
GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD | GPIO_MUXSEL_LOPKD |
GPIO_MUXSEL_LORAW | GPIO_MUXSEL_LORAW |
GPIO_MUXSEL_HIRAW; GPIO_MUXSEL_HIRAW;
AT91C_BASE_PIOA->PIO_PER = AT91C_BASE_PIOA->PIO_PER =
GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD | GPIO_MUXSEL_LOPKD |
GPIO_MUXSEL_LORAW | GPIO_MUXSEL_LORAW |
GPIO_MUXSEL_HIRAW; GPIO_MUXSEL_HIRAW;
LOW(GPIO_MUXSEL_HIPKD); LOW(GPIO_MUXSEL_HIPKD);
LOW(GPIO_MUXSEL_LOPKD); LOW(GPIO_MUXSEL_LOPKD);
#ifndef WITH_FPC #ifndef WITH_FPC
LOW(GPIO_MUXSEL_HIRAW); LOW(GPIO_MUXSEL_HIRAW);
LOW(GPIO_MUXSEL_LORAW); LOW(GPIO_MUXSEL_LORAW);
#endif #endif
HIGH(whichGpio); HIGH(whichGpio);
} }
void Fpga_print_status(void) { void Fpga_print_status(void) {
Dbprintf("Currently loaded FPGA image"); Dbprintf("Currently loaded FPGA image");
Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream-1]); Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream-1]);
} }
int FpgaGetCurrent(void) { int FpgaGetCurrent(void) {
return downloaded_bitstream; return downloaded_bitstream;
} }
// Turns off the antenna, // Turns off the antenna,
@ -480,10 +480,10 @@ int FpgaGetCurrent(void) {
// if HF, Disable SSC DMA // if HF, Disable SSC DMA
// turn off trace and leds off. // turn off trace and leds off.
void switch_off(void) { void switch_off(void) {
if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); if (MF_DBGLEVEL > 3) Dbprintf("switch_off");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (downloaded_bitstream == FPGA_BITSTREAM_HF ) if (downloaded_bitstream == FPGA_BITSTREAM_HF )
FpgaDisableSscDma(); FpgaDisableSscDma();
set_tracing(false); set_tracing(false);
LEDsoff(); LEDsoff();
} }

View file

@ -16,11 +16,11 @@
#include <stdbool.h> #include <stdbool.h>
#include "apps.h" #include "apps.h"
#include "fpga.h" #include "fpga.h"
#include "common.h" // standard definitions #include "common.h" // standard definitions
#include "proxmark3.h" // common area #include "proxmark3.h" // common area
#include "string.h" #include "string.h"
#include "BigBuf.h" // bigbuf mem #include "BigBuf.h" // bigbuf mem
#include "zlib.h" // uncompress #include "zlib.h" // uncompress
void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaSendCommand(uint16_t cmd, uint16_t v);
@ -32,7 +32,7 @@ void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, int len); bool FpgaSetupSscDma(uint8_t *buf, int len);
void Fpga_print_status(void); void Fpga_print_status(void);
int FpgaGetCurrent(void); int FpgaGetCurrent(void);
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; #define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
void SetAdcMuxFor(uint32_t whichGpio); void SetAdcMuxFor(uint32_t whichGpio);
@ -45,56 +45,56 @@ extern void switch_off(void);
//#define FPGA_BITSTREAM_FELICA 3 //#define FPGA_BITSTREAM_FELICA 3
// Definitions for the FPGA commands. // Definitions for the FPGA commands.
#define FPGA_CMD_SET_CONFREG (1<<12) #define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12) #define FPGA_CMD_SET_DIVISOR (2<<12)
#define FPGA_CMD_SET_USER_BYTE1 (3<<12) #define FPGA_CMD_SET_USER_BYTE1 (3<<12)
// Definitions for the FPGA configuration word. // Definitions for the FPGA configuration word.
// LF // LF
#define FPGA_MAJOR_MODE_LF_ADC (0<<5) #define FPGA_MAJOR_MODE_LF_ADC (0<<5)
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) #define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) #define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
// HF // HF
#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) #define FPGA_MAJOR_MODE_HF_READER_TX (0<<5)
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) #define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) #define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) #define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) #define FPGA_MAJOR_MODE_HF_SNOOP (4<<5)
#define FPGA_MAJOR_MODE_HF_FELICA (5<<5) #define FPGA_MAJOR_MODE_HF_FELICA (5<<5)
// BOTH // BOTH
#define FPGA_MAJOR_MODE_OFF_LF (6<<5) #define FPGA_MAJOR_MODE_OFF_LF (6<<5)
#define FPGA_MAJOR_MODE_OFF (7<<5) #define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_ADC // Options for LF_ADC
#define FPGA_LF_ADC_READER_FIELD (1<<0) #define FPGA_LF_ADC_READER_FIELD (1<<0)
// Options for LF_EDGE_DETECT // Options for LF_EDGE_DETECT
#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 #define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) #define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)
#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) #define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1)
// Options for the HF reader, tx to tag // Options for the HF reader, tx to tag
#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) #define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0)
// Options for the HF reader, correlating against rx from tag // Options for the HF reader, correlating against rx from tag
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) #define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) #define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) #define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2)
// Options for the HF simulated tag, how to modulate // Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 #define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000
#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001 #define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001
#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010 #define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010
#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100 #define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 #define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101
// no 848K // no 848K
// Options for ISO14443A // Options for ISO14443A
#define FPGA_HF_ISO14443A_SNIFFER (0<<0) #define FPGA_HF_ISO14443A_SNIFFER (0<<0)
#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) #define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0)
#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) #define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0)
#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) #define FPGA_HF_ISO14443A_READER_LISTEN (3<<0)
#define FPGA_HF_ISO14443A_READER_MOD (4<<0) #define FPGA_HF_ISO14443A_READER_MOD (4<<0)
//options for Felica. //options for Felica.
#define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000 #define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000
#define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module #define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module
#define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect #define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect
#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag #define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag
#endif #endif

View file

@ -2,79 +2,79 @@
#include "apps.h" #include "apps.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "util.h" #include "util.h"
#include "usb_cdc.h" // for usb_poll_validate_length #include "usb_cdc.h" // for usb_poll_validate_length
static void RAMFUNC optimizedSnoop(void); static void RAMFUNC optimizedSnoop(void);
static void RAMFUNC optimizedSnoop(void) static void RAMFUNC optimizedSnoop(void)
{ {
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
uint16_t *dest = (uint16_t *)BigBuf_get_addr(); uint16_t *dest = (uint16_t *)BigBuf_get_addr();
uint16_t *destend = dest + n-1; uint16_t *destend = dest + n-1;
// Reading data loop // Reading data loop
while(dest <= destend) { while(dest <= destend) {
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
*dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
dest++; dest++;
} }
} }
//setting tracelen - important! it was set by buffer overflow before //setting tracelen - important! it was set by buffer overflow before
set_tracelen( BigBuf_max_traceLen()); set_tracelen( BigBuf_max_traceLen());
} }
void HfSnoop(int samplesToSkip, int triggersToSkip) void HfSnoop(int samplesToSkip, int triggersToSkip)
{ {
BigBuf_free(); BigBuf_Clear(); BigBuf_free(); BigBuf_Clear();
Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
int trigger_cnt = 0; int trigger_cnt = 0;
LED_D_ON(); LED_D_ON();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Set up the synchronous serial port // Set up the synchronous serial port
FpgaSetupSsc(); FpgaSetupSsc();
// Setting Frame Mode For better performance on high speed data transfer. // Setting Frame Mode For better performance on high speed data transfer.
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP);
SpinDelay(100); SpinDelay(100);
uint16_t r = 0; uint16_t r = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
r = (uint16_t)AT91C_BASE_SSC->SSC_RHR; r = (uint16_t)AT91C_BASE_SSC->SSC_RHR;
r = MAX(r & 0xff, r >> 8); r = MAX(r & 0xff, r >> 8);
if (r >= 180) { // 0xB4 ?? if (r >= 180) { // 0xB4 ??
if (++trigger_cnt > triggersToSkip) if (++trigger_cnt > triggersToSkip)
break; break;
} }
} }
} }
if (!BUTTON_PRESS()) { if (!BUTTON_PRESS()) {
int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0 int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0
while(waitcount != 0) { while(waitcount != 0) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
waitcount--; waitcount--;
} }
optimizedSnoop(); optimizedSnoop();
Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
} }
//Resetting Frame mode (First set in fpgaloader.c) //Resetting Frame mode (First set in fpgaloader.c)
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
DbpString("HF Snoop end"); DbpString("HF Snoop end");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF(); LED_D_OFF();
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -31,66 +31,66 @@ extern "C" {
#include "mifare.h" // structs #include "mifare.h" // structs
typedef struct { typedef struct {
enum { enum {
DEMOD_UNSYNCD, DEMOD_UNSYNCD,
// DEMOD_HALF_SYNCD, // DEMOD_HALF_SYNCD,
// DEMOD_MOD_FIRST_HALF, // DEMOD_MOD_FIRST_HALF,
// DEMOD_NOMOD_FIRST_HALF, // DEMOD_NOMOD_FIRST_HALF,
DEMOD_MANCHESTER_DATA DEMOD_MANCHESTER_DATA
} state; } state;
uint16_t twoBits; uint16_t twoBits;
uint16_t highCnt; uint16_t highCnt;
uint16_t bitCount; uint16_t bitCount;
uint16_t collisionPos; uint16_t collisionPos;
uint16_t syncBit; uint16_t syncBit;
uint8_t parityBits; uint8_t parityBits;
uint8_t parityLen; uint8_t parityLen;
uint16_t shiftReg; uint16_t shiftReg;
uint16_t samples; uint16_t samples;
uint16_t len; uint16_t len;
uint32_t startTime, endTime; uint32_t startTime, endTime;
uint8_t *output; uint8_t *output;
uint8_t *parity; uint8_t *parity;
} tDemod; } tDemod;
/* /*
typedef enum { typedef enum {
MOD_NOMOD = 0, MOD_NOMOD = 0,
MOD_SECOND_HALF, MOD_SECOND_HALF,
MOD_FIRST_HALF, MOD_FIRST_HALF,
MOD_BOTH_HALVES MOD_BOTH_HALVES
} Modulation_t; } Modulation_t;
*/ */
typedef struct { typedef struct {
enum { enum {
STATE_UNSYNCD, STATE_UNSYNCD,
STATE_START_OF_COMMUNICATION, STATE_START_OF_COMMUNICATION,
STATE_MILLER_X, STATE_MILLER_X,
STATE_MILLER_Y, STATE_MILLER_Y,
STATE_MILLER_Z, STATE_MILLER_Z,
// DROP_NONE, // DROP_NONE,
// DROP_FIRST_HALF, // DROP_FIRST_HALF,
} state; } state;
uint16_t shiftReg; uint16_t shiftReg;
int16_t bitCount; int16_t bitCount;
uint16_t len; uint16_t len;
//uint16_t byteCntMax; //uint16_t byteCntMax;
uint16_t posCnt; uint16_t posCnt;
uint16_t syncBit; uint16_t syncBit;
uint8_t parityBits; uint8_t parityBits;
uint8_t parityLen; uint8_t parityLen;
uint32_t fourBits; uint32_t fourBits;
uint32_t startTime, endTime; uint32_t startTime, endTime;
uint8_t *output; uint8_t *output;
uint8_t *parity; uint8_t *parity;
} tUart; } tUart;
#ifndef AddCrc14A #ifndef AddCrc14A
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) # define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
#endif #endif
#ifndef AddCrc14B #ifndef AddCrc14B
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) # define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
#endif #endif
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
@ -129,7 +129,7 @@ extern int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool co
extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); extern int EmSendPrecompiledCmd(tag_response_info_t *response_info);
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
//extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size); //extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size);

File diff suppressed because it is too large Load diff

View file

@ -18,7 +18,7 @@ extern "C" {
#endif #endif
#include "proxmark3.h" #include "proxmark3.h"
#include "common.h" // access to global variable: MF_DBGLEVEL #include "common.h" // access to global variable: MF_DBGLEVEL
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
@ -27,11 +27,11 @@ extern "C" {
#include "protocols.h" #include "protocols.h"
#ifndef AddCrc14A #ifndef AddCrc14A
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) # define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
#endif #endif
#ifndef AddCrc14B #ifndef AddCrc14B
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) # define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
#endif #endif
extern void SendRawCommand14443B_Ex(UsbCommand *c); extern void SendRawCommand14443B_Ex(UsbCommand *c);
@ -45,13 +45,13 @@ extern void WaitForFpgaDelayQueueIsEmpty( uint16_t delay );
extern void ClearFpgaShiftingRegisters(void); extern void ClearFpgaShiftingRegisters(void);
// States for 14B SIM command // States for 14B SIM command
#define SIM_NOFIELD 0 #define SIM_NOFIELD 0
#define SIM_IDLE 1 #define SIM_IDLE 1
#define SIM_HALTED 2 #define SIM_HALTED 2
#define SIM_SELECTING 3 #define SIM_SELECTING 3
#define SIM_HALTING 4 #define SIM_HALTING 4
#define SIM_ACKNOWLEDGE 5 #define SIM_ACKNOWLEDGE 5
#define SIM_WORK 6 #define SIM_WORK 6
#ifdef __cplusplus #ifdef __cplusplus
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,21 +10,21 @@
/* /*
Default LF config is set to: Default LF config is set to:
decimation = 1 (we keep 1 out of 1 samples) decimation = 1 (we keep 1 out of 1 samples)
bits_per_sample = 8 bits_per_sample = 8
averaging = YES averaging = YES
divisor = 95 (125khz) divisor = 95 (125khz)
trigger_threshold = 0 trigger_threshold = 0
*/ */
sample_config config = { 1, 8, 1, 95, 0 } ; sample_config config = { 1, 8, 1, 95, 0 } ;
void printConfig() { void printConfig() {
Dbprintf("LF Sampling config"); Dbprintf("LF Sampling config");
Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor+1)); Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor+1));
Dbprintf(" [b] bps.................%d", config.bits_per_sample); Dbprintf(" [b] bps.................%d", config.bits_per_sample);
Dbprintf(" [d] decimation..........%d", config.decimation); Dbprintf(" [d] decimation..........%d", config.decimation);
Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No"); Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No");
Dbprintf(" [t] trigger threshold...%d", config.trigger_threshold); Dbprintf(" [t] trigger threshold...%d", config.trigger_threshold);
} }
/** /**
@ -39,25 +39,25 @@ void printConfig() {
* @param sc * @param sc
*/ */
void setSamplingConfig(sample_config *sc) { void setSamplingConfig(sample_config *sc) {
if(sc->divisor != 0) config.divisor = sc->divisor; if(sc->divisor != 0) config.divisor = sc->divisor;
if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample; if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample;
if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold; if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold;
config.decimation = (sc->decimation != 0) ? sc->decimation : 1; config.decimation = (sc->decimation != 0) ? sc->decimation : 1;
config.averaging = sc->averaging; config.averaging = sc->averaging;
if(config.bits_per_sample > 8) config.bits_per_sample = 8; if(config.bits_per_sample > 8) config.bits_per_sample = 8;
printConfig(); printConfig();
} }
sample_config* getSamplingConfig() { sample_config* getSamplingConfig() {
return &config; return &config;
} }
struct BitstreamOut { struct BitstreamOut {
uint8_t * buffer; uint8_t * buffer;
uint32_t numbits; uint32_t numbits;
uint32_t position; uint32_t position;
}; };
/** /**
@ -66,39 +66,39 @@ struct BitstreamOut {
* @param bit * @param bit
*/ */
void pushBit( BitstreamOut* stream, uint8_t bit) { void pushBit( BitstreamOut* stream, uint8_t bit) {
int bytepos = stream->position >> 3; // divide by 8 int bytepos = stream->position >> 3; // divide by 8
int bitpos = stream->position & 7; int bitpos = stream->position & 7;
*(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); *(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos);
stream->position++; stream->position++;
stream->numbits++; stream->numbits++;
} }
/** /**
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
* if not already loaded, sets divisor and starts up the antenna. * if not already loaded, sets divisor and starts up the antenna.
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz * @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
* 0 or 95 ==> 125 KHz * 0 or 95 ==> 125 KHz
* *
**/ **/
void LFSetupFPGAForADC(int divisor, bool lf_field) { void LFSetupFPGAForADC(int divisor, bool lf_field) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
else if (divisor == 0) else if (divisor == 0)
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
else else
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0));
// Connect the A/D to the peak-detected low-frequency path. // Connect the A/D to the peak-detected low-frequency path.
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
// 50ms for the resonant antenna to settle. // 50ms for the resonant antenna to settle.
SpinDelay(50); SpinDelay(50);
// Now set up the SSC to get the ADC samples that are now streaming at us. // Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc(); FpgaSetupSsc();
// start a 1.5ticks is 1us // start a 1.5ticks is 1us
StartTicks(); StartTicks();
} }
/** /**
@ -118,97 +118,97 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) {
*/ */
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) { uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) {
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen(); bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen();
if (bits_per_sample < 1) bits_per_sample = 1; if (bits_per_sample < 1) bits_per_sample = 1;
if (bits_per_sample > 8) bits_per_sample = 8; if (bits_per_sample > 8) bits_per_sample = 8;
if (decimation < 1) decimation = 1; if (decimation < 1) decimation = 1;
// use a bit stream to handle the output // use a bit stream to handle the output
BitstreamOut data = { dest , 0, 0}; BitstreamOut data = { dest , 0, 0};
int sample_counter = 0; int sample_counter = 0;
uint8_t sample = 0; uint8_t sample = 0;
// if we want to do averaging // if we want to do averaging
uint32_t sample_sum =0 ; uint32_t sample_sum =0 ;
uint32_t sample_total_numbers = 0; uint32_t sample_total_numbers = 0;
uint32_t sample_total_saved = 0; uint32_t sample_total_saved = 0;
uint32_t cancel_counter = 0; uint32_t cancel_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { while (!BUTTON_PRESS() && !usb_poll_validate_length() ) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
// Testpoint 8 (TP8) can be used to trigger oscilliscope // Testpoint 8 (TP8) can be used to trigger oscilliscope
LED_D_OFF(); LED_D_OFF();
// threshold either high or low values 128 = center 0. if trigger = 178 // threshold either high or low values 128 = center 0. if trigger = 178
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
if (cancel_after > 0) { if (cancel_after > 0) {
cancel_counter++; cancel_counter++;
if (cancel_after == cancel_counter) if (cancel_after == cancel_counter)
break; break;
} }
continue; continue;
} }
trigger_threshold = 0; trigger_threshold = 0;
sample_total_numbers++; sample_total_numbers++;
if (averaging) if (averaging)
sample_sum += sample; sample_sum += sample;
// check decimation // check decimation
if (decimation > 1) { if (decimation > 1) {
sample_counter++; sample_counter++;
if (sample_counter < decimation) continue; if (sample_counter < decimation) continue;
sample_counter = 0; sample_counter = 0;
} }
// averaging // averaging
if (averaging && decimation > 1) { if (averaging && decimation > 1) {
sample = sample_sum / decimation; sample = sample_sum / decimation;
sample_sum =0; sample_sum =0;
} }
// store the sample // store the sample
sample_total_saved ++; sample_total_saved ++;
if (bits_per_sample == 8) { if (bits_per_sample == 8) {
dest[sample_total_saved-1] = sample; dest[sample_total_saved-1] = sample;
// Get the return value correct // Get the return value correct
data.numbits = sample_total_saved << 3; data.numbits = sample_total_saved << 3;
if (sample_total_saved >= bufsize) break; if (sample_total_saved >= bufsize) break;
} else { } else {
pushBit(&data, sample & 0x80); pushBit(&data, sample & 0x80);
if (bits_per_sample > 1) pushBit(&data, sample & 0x40); if (bits_per_sample > 1) pushBit(&data, sample & 0x40);
if (bits_per_sample > 2) pushBit(&data, sample & 0x20); if (bits_per_sample > 2) pushBit(&data, sample & 0x20);
if (bits_per_sample > 3) pushBit(&data, sample & 0x10); if (bits_per_sample > 3) pushBit(&data, sample & 0x10);
if (bits_per_sample > 4) pushBit(&data, sample & 0x08); if (bits_per_sample > 4) pushBit(&data, sample & 0x08);
if (bits_per_sample > 5) pushBit(&data, sample & 0x04); if (bits_per_sample > 5) pushBit(&data, sample & 0x04);
if (bits_per_sample > 6) pushBit(&data, sample & 0x02); if (bits_per_sample > 6) pushBit(&data, sample & 0x02);
if ((data.numbits >> 3) + 1 >= bufsize) break; if ((data.numbits >> 3) + 1 >= bufsize) break;
} }
} }
} }
if (!silent) { if (!silent) {
Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample); Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample);
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
} }
// Ensure that DC offset removal and noise check is performed for any device-side processing // Ensure that DC offset removal and noise check is performed for any device-side processing
removeSignalOffset(dest, bufsize); removeSignalOffset(dest, bufsize);
computeSignalProperties(dest, bufsize); computeSignalProperties(dest, bufsize);
return data.numbits; return data.numbits;
} }
/** /**
* @brief Does sample acquisition, ignoring the config values set in the sample_config. * @brief Does sample acquisition, ignoring the config values set in the sample_config.
@ -219,27 +219,27 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
* @return number of bits sampled * @return number of bits sampled
*/ */
uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { uint32_t DoAcquisition_default(int trigger_threshold, bool silent) {
return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0, 0); return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0, 0);
} }
uint32_t DoAcquisition_config( bool silent, int sample_size) { uint32_t DoAcquisition_config( bool silent, int sample_size) {
return DoAcquisition(config.decimation return DoAcquisition(config.decimation
,config.bits_per_sample ,config.bits_per_sample
,config.averaging ,config.averaging
,config.trigger_threshold ,config.trigger_threshold
,silent ,silent
,sample_size ,sample_size
,0); ,0);
} }
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after) { uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after) {
return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size, cancel_after); return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size, cancel_after);
} }
uint32_t ReadLF(bool activeField, bool silent, int sample_size) { uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
if (!silent) if (!silent)
printConfig(); printConfig();
LFSetupFPGAForADC(config.divisor, activeField); LFSetupFPGAForADC(config.divisor, activeField);
return DoAcquisition_config(silent, sample_size); return DoAcquisition_config(silent, sample_size);
} }
/** /**
@ -247,20 +247,20 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SampleLF(bool printCfg, int sample_size) { uint32_t SampleLF(bool printCfg, int sample_size) {
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
uint32_t ret = ReadLF(true, printCfg, sample_size); uint32_t ret = ReadLF(true, printCfg, sample_size);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret; return ret;
} }
/** /**
* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * Initializes the FPGA for snoop-mode (field off), and acquires the samples.
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SnoopLF() { uint32_t SnoopLF() {
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
uint32_t ret = ReadLF(false, true, 0); uint32_t ret = ReadLF(false, true, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret; return ret;
} }
/** /**
@ -269,61 +269,61 @@ uint32_t SnoopLF() {
**/ **/
void doT55x7Acquisition(size_t sample_size) { void doT55x7Acquisition(size_t sample_size) {
#define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
#define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
#define T55xx_READ_TOL 5 #define T55xx_READ_TOL 5
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen(); uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size ) if ( bufsize > sample_size )
bufsize = sample_size; bufsize = sample_size;
uint8_t curSample = 0, lastSample = 0; uint8_t curSample = 0, lastSample = 0;
uint16_t i = 0, skipCnt = 0; uint16_t i = 0, skipCnt = 0;
bool startFound = false; bool startFound = false;
bool highFound = false; bool highFound = false;
bool lowFound = false; bool lowFound = false;
while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF(); LED_D_OFF();
// skip until the first high sample above threshold // skip until the first high sample above threshold
if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) { if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) {
//if (curSample > lastSample) //if (curSample > lastSample)
// lastSample = curSample; // lastSample = curSample;
highFound = true; highFound = true;
} else if (!highFound) { } else if (!highFound) {
skipCnt++; skipCnt++;
continue; continue;
} }
// skip until the first low sample below threshold // skip until the first low sample below threshold
if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) { if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) {
//if (curSample > lastSample) //if (curSample > lastSample)
lastSample = curSample; lastSample = curSample;
lowFound = true; lowFound = true;
} else if (!lowFound) { } else if (!lowFound) {
skipCnt++; skipCnt++;
continue; continue;
} }
// skip until first high samples begin to change // skip until first high samples begin to change
if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL){ if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL){
// if just found start - recover last sample // if just found start - recover last sample
if (!startFound) { if (!startFound) {
dest[i++] = lastSample; dest[i++] = lastSample;
startFound = true; startFound = true;
} }
// collect samples // collect samples
dest[i++] = curSample; dest[i++] = curSample;
} }
} }
} }
} }
/** /**
* acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384 * acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384
@ -339,117 +339,117 @@ void doT55x7Acquisition(size_t sample_size) {
#endif #endif
void doCotagAcquisition(size_t sample_size) { void doCotagAcquisition(size_t sample_size) {
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen(); uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size ) if ( bufsize > sample_size )
bufsize = sample_size; bufsize = sample_size;
dest[0] = 0; dest[0] = 0;
uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint8_t sample = 0, firsthigh = 0, firstlow = 0;
uint16_t i = 0; uint16_t i = 0;
uint16_t noise_counter = 0; uint16_t noise_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF(); LED_D_OFF();
// find first peak // find first peak
if ( !firsthigh ) { if ( !firsthigh ) {
if (sample < COTAG_ONE_THRESHOLD) { if (sample < COTAG_ONE_THRESHOLD) {
noise_counter++; noise_counter++;
continue; continue;
} }
noise_counter = 0; noise_counter = 0;
firsthigh = 1; firsthigh = 1;
} }
if ( !firstlow ){ if ( !firstlow ){
if (sample > COTAG_ZERO_THRESHOLD ) { if (sample > COTAG_ZERO_THRESHOLD ) {
noise_counter++; noise_counter++;
continue; continue;
} }
noise_counter = 0; noise_counter = 0;
firstlow = 1; firstlow = 1;
} }
++i; ++i;
if ( sample > COTAG_ONE_THRESHOLD) if ( sample > COTAG_ONE_THRESHOLD)
dest[i] = 255; dest[i] = 255;
else if ( sample < COTAG_ZERO_THRESHOLD) else if ( sample < COTAG_ZERO_THRESHOLD)
dest[i] = 0; dest[i] = 0;
else else
dest[i] = dest[i-1]; dest[i] = dest[i-1];
} }
} }
} }
uint32_t doCotagAcquisitionManchester() { uint32_t doCotagAcquisitionManchester() {
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen(); uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > COTAG_BITS ) if ( bufsize > COTAG_BITS )
bufsize = COTAG_BITS; bufsize = COTAG_BITS;
dest[0] = 0; dest[0] = 0;
uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint8_t sample = 0, firsthigh = 0, firstlow = 0;
uint16_t sample_counter = 0, period = 0; uint16_t sample_counter = 0, period = 0;
uint8_t curr = 0, prev = 0; uint8_t curr = 0, prev = 0;
uint16_t noise_counter = 0; uint16_t noise_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF(); LED_D_OFF();
// find first peak // find first peak
if ( !firsthigh ) { if ( !firsthigh ) {
if (sample < COTAG_ONE_THRESHOLD) { if (sample < COTAG_ONE_THRESHOLD) {
noise_counter++; noise_counter++;
continue; continue;
} }
noise_counter = 0; noise_counter = 0;
firsthigh = 1; firsthigh = 1;
} }
if ( !firstlow ){ if ( !firstlow ){
if (sample > COTAG_ZERO_THRESHOLD ) { if (sample > COTAG_ZERO_THRESHOLD ) {
noise_counter++; noise_counter++;
continue; continue;
} }
noise_counter = 0; noise_counter = 0;
firstlow = 1; firstlow = 1;
} }
// set sample 255, 0, or previous // set sample 255, 0, or previous
if ( sample > COTAG_ONE_THRESHOLD){ if ( sample > COTAG_ONE_THRESHOLD){
prev = curr; prev = curr;
curr = 1; curr = 1;
} }
else if ( sample < COTAG_ZERO_THRESHOLD) { else if ( sample < COTAG_ZERO_THRESHOLD) {
prev = curr; prev = curr;
curr = 0; curr = 0;
} }
else { else {
curr = prev; curr = prev;
} }
// full T1 periods, // full T1 periods,
if ( period > 0 ) { if ( period > 0 ) {
--period; --period;
continue; continue;
} }
dest[sample_counter] = curr; dest[sample_counter] = curr;
++sample_counter; ++sample_counter;
period = COTAG_T1; period = COTAG_T1;
} }
} }
return sample_counter; return sample_counter;
} }

View file

@ -5,8 +5,8 @@
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "usb_cdc.h" // for usb_poll_validate_length #include "usb_cdc.h" // for usb_poll_validate_length
#include "ticks.h" // for StartTicks #include "ticks.h" // for StartTicks
typedef struct BitstreamOut BitstreamOut; typedef struct BitstreamOut BitstreamOut;
@ -60,7 +60,7 @@ uint32_t DoAcquisition_config(bool silent, int sample_size);
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
* if not already loaded, sets divisor and starts up the antenna. * if not already loaded, sets divisor and starts up the antenna.
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz * @param divisor : 1, 88> 255 or negative ==> 134.8 KHz
* 0 or 95 ==> 125 KHz * 0 or 95 ==> 125 KHz
* *
**/ **/
void LFSetupFPGAForADC(int divisor, bool lf_field); void LFSetupFPGAForADC(int divisor, bool lf_field);

File diff suppressed because it is too large Load diff

View file

@ -18,189 +18,189 @@ static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
bool InitDesfireCard(){ bool InitDesfireCard(){
iso14a_card_select_t card; iso14a_card_select_t card;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card");
OnError(1); OnError(1);
return false; return false;
} }
return true; return true;
} }
// ARG0 flag enums // ARG0 flag enums
enum { enum {
NONE = 0x00, NONE = 0x00,
INIT = 0x01, INIT = 0x01,
DISCONNECT = 0x02, DISCONNECT = 0x02,
CLEARTRACE = 0x04, CLEARTRACE = 0x04,
BAR = 0x08, BAR = 0x08,
} CmdOptions ; } CmdOptions ;
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
/* ARG0 contains flags. /* ARG0 contains flags.
0x01 = init card. 0x01 = init card.
0x02 = Disconnect 0x02 = Disconnect
0x03 0x03
*/ */
uint8_t flags = arg0; uint8_t flags = arg0;
size_t datalen = arg1; size_t datalen = arg1;
uint8_t resp[RECEIVE_SIZE]; uint8_t resp[RECEIVE_SIZE];
memset(resp,0,sizeof(resp)); memset(resp,0,sizeof(resp));
if (MF_DBGLEVEL >= 4) { if (MF_DBGLEVEL >= 4) {
Dbprintf(" flags : %02X", flags); Dbprintf(" flags : %02X", flags);
Dbprintf(" len : %02X", datalen); Dbprintf(" len : %02X", datalen);
print_result(" RX : ", datain, datalen); print_result(" RX : ", datain, datalen);
} }
if ( flags & CLEARTRACE ) if ( flags & CLEARTRACE )
clear_trace(); clear_trace();
if ( flags & INIT ){ if ( flags & INIT ){
if ( !InitDesfireCard() ) if ( !InitDesfireCard() )
return; return;
} }
int len = DesfireAPDU(datain, datalen, resp); int len = DesfireAPDU(datain, datalen, resp);
if (MF_DBGLEVEL >= 4) if (MF_DBGLEVEL >= 4)
print_result("ERR <--: ", resp, len); print_result("ERR <--: ", resp, len);
if ( !len ) { if ( !len ) {
OnError(2); OnError(2);
return; return;
} }
// reset the pcb_blocknum, // reset the pcb_blocknum,
pcb_blocknum = 0; pcb_blocknum = 0;
if ( flags & DISCONNECT ) if ( flags & DISCONNECT )
OnSuccess(); OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len); cmd_send(CMD_ACK,1,len,0,resp,len);
} }
void MifareDesfireGetInformation(){ void MifareDesfireGetInformation(){
int len = 0; int len = 0;
iso14a_card_select_t card; iso14a_card_select_t card;
uint8_t resp[USB_CMD_DATA_SIZE] = {0x00}; uint8_t resp[USB_CMD_DATA_SIZE] = {0x00};
uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00}; uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00};
/* /*
1 = PCB 1 1 = PCB 1
2 = cid 2 2 = cid 2
3 = desfire command 3 3 = desfire command 3
4-5 = crc 4 key 4-5 = crc 4 key
5-6 crc 5-6 crc
PCB == 0x0A because sending CID byte. PCB == 0x0A because sending CID byte.
CID == 0x00 first card? CID == 0x00 first card?
*/ */
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// card select - information // card select - information
if ( !iso14443a_select_card(NULL, &card, NULL, true, 0, false) ) { if ( !iso14443a_select_card(NULL, &card, NULL, true, 0, false) ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card");
OnError(1); OnError(1);
return; return;
} }
if ( card.uidlen != 7 ) { if ( card.uidlen != 7 ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen);
OnError(2); OnError(2);
return; return;
} }
memcpy(dataout, card.uid, 7); memcpy(dataout, card.uid, 7);
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
uint8_t cmd[] = {GET_VERSION}; uint8_t cmd[] = {GET_VERSION};
size_t cmd_len = sizeof(cmd); size_t cmd_len = sizeof(cmd);
len = DesfireAPDU(cmd, cmd_len, resp); len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) { if ( !len ) {
print_result("ERROR <--: ", resp, len); print_result("ERROR <--: ", resp, len);
OnError(3); OnError(3);
return; return;
} }
LED_A_OFF(); LED_A_OFF();
LED_B_ON(); LED_B_ON();
memcpy(dataout+7,resp+3,7); memcpy(dataout+7,resp+3,7);
// ADDITION_FRAME 1 // ADDITION_FRAME 1
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
len = DesfireAPDU(cmd, cmd_len, resp); len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) { if ( !len ) {
print_result("ERROR <--: ", resp, len); print_result("ERROR <--: ", resp, len);
OnError(3); OnError(3);
return; return;
} }
LED_B_OFF(); LED_B_OFF();
LED_C_ON(); LED_C_ON();
memcpy(dataout+7+7,resp+3,7); memcpy(dataout+7+7,resp+3,7);
// ADDITION_FRAME 2 // ADDITION_FRAME 2
len = DesfireAPDU(cmd, cmd_len, resp); len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) { if ( !len ) {
print_result("ERROR <--: ", resp, len); print_result("ERROR <--: ", resp, len);
OnError(3); OnError(3);
return; return;
} }
memcpy(dataout+7+7+7,resp+3,14); memcpy(dataout+7+7+7,resp+3,14);
cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
// reset the pcb_blocknum, // reset the pcb_blocknum,
pcb_blocknum = 0; pcb_blocknum = 0;
OnSuccess(); OnSuccess();
} }
void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){
int len = 0; int len = 0;
//uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f }; uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
uint8_t null_key_data8[8] = {0x00}; uint8_t null_key_data8[8] = {0x00};
//uint8_t null_key_data16[16] = {0x00}; //uint8_t null_key_data16[16] = {0x00};
//uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
//uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
uint8_t resp[256] = {0x00}; uint8_t resp[256] = {0x00};
uint8_t IV[16] = {0x00}; uint8_t IV[16] = {0x00};
size_t datalen = datain[0]; size_t datalen = datain[0];
uint8_t cmd[40] = {0x00}; uint8_t cmd[40] = {0x00};
uint8_t encRndB[16] = {0x00}; uint8_t encRndB[16] = {0x00};
uint8_t decRndB[16] = {0x00}; uint8_t decRndB[16] = {0x00};
uint8_t nonce[16] = {0x00}; uint8_t nonce[16] = {0x00};
uint8_t both[32] = {0x00}; uint8_t both[32] = {0x00};
uint8_t encBoth[32] = {0x00}; uint8_t encBoth[32] = {0x00};
InitDesfireCard(); InitDesfireCard();
LED_A_ON(); LED_A_ON();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
// 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
// 4 olika crypto algo DES, 3DES, 3K3DES, AES // 4 olika crypto algo DES, 3DES, 3K3DES, AES
// 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO
// des, nyckel 0, // des, nyckel 0,
switch (mode){ switch (mode){
case 1:{ case 1:{
uint8_t keybytes[16]; uint8_t keybytes[16];
uint8_t RndA[8] = {0x00}; uint8_t RndA[8] = {0x00};
@ -416,83 +416,83 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
return; return;
} }
} }
break; break;
case 2: case 2:
//SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
break; break;
case 3:{ case 3:{
//defaultkey //defaultkey
uint8_t keybytes[16] = {0x00}; uint8_t keybytes[16] = {0x00};
if (datain[1] == 0xff){ if (datain[1] == 0xff){
memcpy(keybytes,PICC_MASTER_KEY16,16); memcpy(keybytes,PICC_MASTER_KEY16,16);
} else{ } else{
memcpy(keybytes, datain+1, datalen); memcpy(keybytes, datain+1, datalen);
} }
struct desfire_key defaultkey = {0x00}; struct desfire_key defaultkey = {0x00};
desfirekey_t key = &defaultkey; desfirekey_t key = &defaultkey;
Desfire_aes_key_new( keybytes, key); Desfire_aes_key_new( keybytes, key);
AesCtx ctx; AesCtx ctx;
if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){ if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
if( MF_DBGLEVEL >= 4) { if( MF_DBGLEVEL >= 4) {
DbpString("AES context failed to init"); DbpString("AES context failed to init");
} }
OnError(7); OnError(7);
return; return;
} }
cmd[0] = AUTHENTICATE_AES; cmd[0] = AUTHENTICATE_AES;
cmd[1] = 0x00; //keynumber cmd[1] = 0x00; //keynumber
len = DesfireAPDU(cmd, 2, resp); len = DesfireAPDU(cmd, 2, resp);
if ( !len ) { if ( !len ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) { if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
} }
OnError(3);
return;
}
memcpy( encRndB, resp+3, 16);
// dekryptera tagnonce.
AesDecrypt(&ctx, encRndB, decRndB, 16);
rol(decRndB,16);
memcpy(both, nonce,16);
memcpy(both+16, decRndB ,16 );
AesEncrypt(&ctx, both, encBoth, 32 );
cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, encBoth, 32 );
len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
if ( !len ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout.");
}
OnError(3); OnError(3);
return; return;
} }
if ( resp[2] == 0x00 ){ memcpy( encRndB, resp+3, 16);
// Create AES Session key
struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey;
Desfire_session_key_new( nonce, decRndB , key, skey );
print_result("SESSION : ", skey->data, 16);
} else {
DbpString("Authentication failed.");
OnError(7);
return;
}
break; // dekryptera tagnonce.
} AesDecrypt(&ctx, encRndB, decRndB, 16);
} rol(decRndB,16);
memcpy(both, nonce,16);
memcpy(both+16, decRndB ,16 );
AesEncrypt(&ctx, both, encBoth, 32 );
OnSuccess(); cmd[0] = ADDITIONAL_FRAME;
cmd_send(CMD_ACK,1,len,0,resp,len); memcpy(cmd+1, encBoth, 32 );
len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
if ( !len ) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) {
DbpString("Authentication failed. Card timeout.");
}
OnError(3);
return;
}
if ( resp[2] == 0x00 ){
// Create AES Session key
struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey;
Desfire_session_key_new( nonce, decRndB , key, skey );
print_result("SESSION : ", skey->data, 16);
} else {
DbpString("Authentication failed.");
OnError(7);
return;
}
break;
}
}
OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len);
} }
// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) // 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
@ -501,71 +501,71 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
// dataout = pointer to response data array // dataout = pointer to response data array
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
size_t len = 0; size_t len = 0;
size_t wrappedLen = 0; size_t wrappedLen = 0;
uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00}; uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00};
uint8_t resp[MAX_FRAME_SIZE]; uint8_t resp[MAX_FRAME_SIZE];
uint8_t par[MAX_PARITY_SIZE]; uint8_t par[MAX_PARITY_SIZE];
wrappedLen = CreateAPDU( cmd, cmd_len, wCmd); wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
if (MF_DBGLEVEL >= 4) if (MF_DBGLEVEL >= 4)
print_result("WCMD <--: ", wCmd, wrappedLen); print_result("WCMD <--: ", wCmd, wrappedLen);
ReaderTransmit( wCmd, wrappedLen, NULL); ReaderTransmit( wCmd, wrappedLen, NULL);
len = ReaderReceive(resp, par); len = ReaderReceive(resp, par);
if ( !len ) { if ( !len ) {
if (MF_DBGLEVEL >= 4) Dbprintf("fukked"); if (MF_DBGLEVEL >= 4) Dbprintf("fukked");
return false; //DATA LINK ERROR return false; //DATA LINK ERROR
} }
// if we received an I- or R(ACK)-Block with a block number equal to the // if we received an I- or R(ACK)-Block with a block number equal to the
// current block number, toggle the current block number // current block number, toggle the current block number
else if (len >= 4 // PCB+CID+CRC = 4 bytes else if (len >= 4 // PCB+CID+CRC = 4 bytes
&& ((resp[0] & 0xC0) == 0 // I-Block && ((resp[0] & 0xC0) == 0 // I-Block
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
&& (resp[0] & 0x01) == pcb_blocknum) // equal block numbers && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
{ {
pcb_blocknum ^= 1; //toggle next block pcb_blocknum ^= 1; //toggle next block
} }
memcpy(dataout, resp, len); memcpy(dataout, resp, len);
return len; return len;
} }
// CreateAPDU // CreateAPDU
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){ size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
uint8_t cmd[cmdlen]; uint8_t cmd[cmdlen];
memset(cmd, 0, cmdlen); memset(cmd, 0, cmdlen);
cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar // cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar //
cmd[0] |= pcb_blocknum; // OR the block number into the PCB cmd[0] |= pcb_blocknum; // OR the block number into the PCB
cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
memcpy(cmd+2, datain, len); memcpy(cmd+2, datain, len);
AddCrc14A(cmd, len+2); AddCrc14A(cmd, len+2);
memcpy(dataout, cmd, cmdlen); memcpy(dataout, cmd, cmdlen);
return cmdlen; return cmdlen;
} }
// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
// crc_update(&desfire_crc32, addr, addr_sz); // crc_update(&desfire_crc32, addr, addr_sz);
// crc_update(&desfire_crc32, byte, 8); // crc_update(&desfire_crc32, byte, 8);
// uint32_t crc = crc_finish(&desfire_crc32); // uint32_t crc = crc_finish(&desfire_crc32);
void OnSuccess(){ void OnSuccess(){
pcb_blocknum = 0; pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL); ReaderTransmit(deselect_cmd, 3 , NULL);
mifare_ultra_halt(); mifare_ultra_halt();
switch_off(); switch_off();
} }
void OnError(uint8_t reason){ void OnError(uint8_t reason){
cmd_send(CMD_ACK,0,reason,0,0,0); cmd_send(CMD_ACK,0,reason,0,0,0);
OnSuccess(); OnSuccess();
} }

View file

@ -25,300 +25,300 @@ static uint32_t timerData = 0;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// "hf mf sniff" // "hf mf sniff"
void RAMFUNC SniffMifare(uint8_t param) { void RAMFUNC SniffMifare(uint8_t param) {
// param: // param:
// bit 0 - trigger from first card answer // bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request // bit 1 - trigger from first reader 7-bit request
// C(red) A(yellow) B(green) // C(red) A(yellow) B(green)
LEDsoff(); LEDsoff();
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Allocate memory from BigBuf for some buffers // Allocate memory from BigBuf for some buffers
// free all previous allocations first // free all previous allocations first
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free(); BigBuf_Clear_ext(false);
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
// The command (reader -> tag) that we're receiving. // The command (reader -> tag) that we're receiving.
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// The response (tag -> reader) that we're receiving. // The response (tag -> reader) that we're receiving.
uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// allocate the DMA buffer, used to stream samples from the FPGA // allocate the DMA buffer, used to stream samples from the FPGA
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
uint8_t *data = dmaBuf; uint8_t *data = dmaBuf;
uint8_t previous_data = 0; uint8_t previous_data = 0;
int maxDataLen = 0; int maxDataLen = 0;
int dataLen = 0; int dataLen = 0;
bool ReaderIsActive = false; bool ReaderIsActive = false;
bool TagIsActive = false; bool TagIsActive = false;
// We won't start recording the frames that we acquire until we trigger; // We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a // a good trigger condition to get started is probably when we see a
// response from the tag. // response from the tag.
// triggered == false -- to wait first for card // triggered == false -- to wait first for card
//bool triggered = !(param & 0x03); //bool triggered = !(param & 0x03);
// Set up the demodulator for tag -> reader responses. // Set up the demodulator for tag -> reader responses.
DemodInit(receivedResp, receivedRespPar); DemodInit(receivedResp, receivedRespPar);
// Set up the demodulator for the reader -> tag commands // Set up the demodulator for the reader -> tag commands
UartInit(receivedCmd, receivedCmdPar); UartInit(receivedCmd, receivedCmdPar);
// Setup and start DMA. // Setup and start DMA.
// set transfer address and number of bytes. Start transfer. // set transfer address and number of bytes. Start transfer.
if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){ if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){
if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
return; return;
} }
tUart* uart = GetUart(); tUart* uart = GetUart();
tDemod* demod = GetDemod(); tDemod* demod = GetDemod();
MfSniffInit(); MfSniffInit();
uint32_t sniffCounter = 0; uint32_t sniffCounter = 0;
// loop and listen // loop and listen
while (!BUTTON_PRESS()) { while (!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
LED_A_ON(); LED_A_ON();
/* /*
if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time
// check if a transaction is completed (timeout after 2000ms). // check if a transaction is completed (timeout after 2000ms).
// if yes, stop the DMA transfer and send what we have so far to the client // if yes, stop the DMA transfer and send what we have so far to the client
if (BigBuf_get_traceLen()) { if (BigBuf_get_traceLen()) {
MfSniffSend(); MfSniffSend();
// Reset everything - we missed some sniffed data anyway while the DMA was stopped // Reset everything - we missed some sniffed data anyway while the DMA was stopped
sniffCounter = 0; sniffCounter = 0;
dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
data = dmaBuf; data = dmaBuf;
maxDataLen = 0; maxDataLen = 0;
ReaderIsActive = false; ReaderIsActive = false;
TagIsActive = false; TagIsActive = false;
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer.
} }
} }
*/ */
// number of bytes we have processed so far // number of bytes we have processed so far
int register readBufDataP = data - dmaBuf; int register readBufDataP = data - dmaBuf;
// number of bytes already transferred // number of bytes already transferred
int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred
dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed
else else
dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed
// test for length of buffer // test for length of buffer
if (dataLen > maxDataLen) { // we are more behind than ever... if (dataLen > maxDataLen) { // we are more behind than ever...
maxDataLen = dataLen; maxDataLen = dataLen;
if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
break; break;
} }
} }
if (dataLen < 1) continue; if (dataLen < 1) continue;
// primary buffer was stopped ( <-- we lost data! // primary buffer was stopped ( <-- we lost data!
if (!AT91C_BASE_PDC_SSC->PDC_RCR) { if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf; AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
} }
// secondary buffer sets as primary, secondary buffer was stopped // secondary buffer sets as primary, secondary buffer was stopped
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
} }
LED_A_OFF(); LED_A_OFF();
// Need two samples to feed Miller and Manchester-Decoder // Need two samples to feed Miller and Manchester-Decoder
if (sniffCounter & 0x01) { if (sniffCounter & 0x01) {
// no need to try decoding tag data if the reader is sending // no need to try decoding tag data if the reader is sending
if (!TagIsActive) { if (!TagIsActive) {
uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) {
LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
DemodReset(); DemodReset();
UartReset(); UartReset();
} }
ReaderIsActive = (uart->state != STATE_UNSYNCD); ReaderIsActive = (uart->state != STATE_UNSYNCD);
} }
// no need to try decoding tag data if the reader is sending // no need to try decoding tag data if the reader is sending
if (!ReaderIsActive) { if (!ReaderIsActive) {
uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F);
if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) {
LogTrace(receivedResp, demod->len, 0, 0, NULL, false); LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
DemodReset(); DemodReset();
UartReset(); UartReset();
} }
TagIsActive = (demod->state != DEMOD_UNSYNCD); TagIsActive = (demod->state != DEMOD_UNSYNCD);
} }
} }
previous_data = *data; previous_data = *data;
sniffCounter++; sniffCounter++;
data++; data++;
if (data == dmaBuf + DMA_BUFFER_SIZE) if (data == dmaBuf + DMA_BUFFER_SIZE)
data = dmaBuf; data = dmaBuf;
} // main cycle } // main cycle
MfSniffEnd(); MfSniffEnd();
switch_off(); switch_off();
} }
void MfSniffInit(void){ void MfSniffInit(void){
memset(sniffUID, 0x00, sizeof(sniffUID)); memset(sniffUID, 0x00, sizeof(sniffUID));
memset(sniffATQA, 0x00, sizeof(sniffATQA)); memset(sniffATQA, 0x00, sizeof(sniffATQA));
memset(sniffBuf, 0x00, sizeof(sniffBuf)); memset(sniffBuf, 0x00, sizeof(sniffBuf));
sniffSAK = 0; sniffSAK = 0;
sniffUIDType = SNF_UID_4; sniffUIDType = SNF_UID_4;
timerData = 0; timerData = 0;
} }
void MfSniffEnd(void){ void MfSniffEnd(void){
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK,0,0,0,0,0); cmd_send(CMD_ACK,0,0,0,0,0);
LED_B_OFF(); LED_B_OFF();
} }
/* /*
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) {
// reset on 7-Bit commands from reader // reset on 7-Bit commands from reader
if (reader && (len == 1) && (bitCnt == 7)) { if (reader && (len == 1) && (bitCnt == 7)) {
sniffState = SNF_INIT; sniffState = SNF_INIT;
} }
switch (sniffState) { switch (sniffState) {
case SNF_INIT:{ case SNF_INIT:{
// REQA,WUPA or MAGICWUP from reader // REQA,WUPA or MAGICWUP from reader
if ((len == 1) && (reader) && (bitCnt == 7) ) { if ((len == 1) && (reader) && (bitCnt == 7) ) {
MfSniffInit(); MfSniffInit();
sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA; sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA;
} }
break; break;
} }
case SNF_MAGIC_WUPC2: { case SNF_MAGIC_WUPC2: {
if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) {
sniffState = SNF_CARD_IDLE; sniffState = SNF_CARD_IDLE;
} }
break; break;
} }
case SNF_ATQA:{ case SNF_ATQA:{
// ATQA from tag // ATQA from tag
if ((!reader) && (len == 2)) { if ((!reader) && (len == 2)) {
sniffATQA[0] = data[0]; sniffATQA[0] = data[0];
sniffATQA[1] = data[1]; sniffATQA[1] = data[1];
sniffState = SNF_UID; sniffState = SNF_UID;
} }
break; break;
} }
case SNF_UID: { case SNF_UID: {
if ( !reader ) break; if ( !reader ) break;
if ( len != 9 ) break; if ( len != 9 ) break;
if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; if ( !CheckCrc14443(CRC_14443_A, data, 9)) break;
if ( data[1] != 0x70 ) break; if ( data[1] != 0x70 ) break;
Dbprintf("[!] UID | %x", data[0]); Dbprintf("[!] UID | %x", data[0]);
if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) { if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) {
// UID_4 - select 4 Byte UID from reader // UID_4 - select 4 Byte UID from reader
memcpy(sniffUID, data+2, 4); memcpy(sniffUID, data+2, 4);
sniffUIDType = SNF_UID_4; sniffUIDType = SNF_UID_4;
sniffState = SNF_SAK; sniffState = SNF_SAK;
} else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) { } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) {
// UID_7 - Select 2nd part of 7 Byte UID // UID_7 - Select 2nd part of 7 Byte UID
// get rid of 0x88 // get rid of 0x88
sniffUID[0] = sniffUID[1]; sniffUID[0] = sniffUID[1];
sniffUID[1] = sniffUID[2]; sniffUID[1] = sniffUID[2];
sniffUID[2] = sniffUID[3]; sniffUID[2] = sniffUID[3];
//new uid bytes //new uid bytes
memcpy(sniffUID+3, data+2, 4); memcpy(sniffUID+3, data+2, 4);
sniffUIDType = SNF_UID_7; sniffUIDType = SNF_UID_7;
sniffState = SNF_SAK; sniffState = SNF_SAK;
} else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) { } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) {
// UID_10 - Select 3nd part of 10 Byte UID // UID_10 - Select 3nd part of 10 Byte UID
// 3+3+4 = 10. // 3+3+4 = 10.
// get ride of previous 0x88 // get ride of previous 0x88
sniffUID[3] = sniffUID[4]; sniffUID[3] = sniffUID[4];
sniffUID[4] = sniffUID[5]; sniffUID[4] = sniffUID[5];
sniffUID[5] = sniffUID[6]; sniffUID[5] = sniffUID[6];
// new uid bytes // new uid bytes
memcpy(sniffUID+6, data+2, 4); memcpy(sniffUID+6, data+2, 4);
sniffUIDType = SNF_UID_10; sniffUIDType = SNF_UID_10;
sniffState = SNF_SAK; sniffState = SNF_SAK;
} }
break; break;
} }
case SNF_SAK:{ case SNF_SAK:{
// SAK from card? // SAK from card?
if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) {
sniffSAK = data[0]; sniffSAK = data[0];
// CL2 UID part to be expected // CL2 UID part to be expected
if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) { if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) {
sniffState = SNF_UID; sniffState = SNF_UID;
// CL3 UID part to be expected // CL3 UID part to be expected
} else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) { } else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) {
sniffState = SNF_UID; sniffState = SNF_UID;
} else { } else {
// select completed // select completed
sniffState = SNF_CARD_IDLE; sniffState = SNF_CARD_IDLE;
} }
} }
break; break;
} }
case SNF_CARD_IDLE:{ // trace the card select sequence case SNF_CARD_IDLE:{ // trace the card select sequence
sniffBuf[0] = 0xFF; sniffBuf[0] = 0xFF;
sniffBuf[1] = 0xFF; sniffBuf[1] = 0xFF;
memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID)); memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID));
memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA)); memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA));
sniffBuf[14] = sniffSAK; sniffBuf[14] = sniffSAK;
sniffBuf[15] = 0xFF; sniffBuf[15] = 0xFF;
sniffBuf[16] = 0xFF; sniffBuf[16] = 0xFF;
LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true); LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true);
sniffState = SNF_CARD_CMD; sniffState = SNF_CARD_CMD;
} // intentionally no break; } // intentionally no break;
case SNF_CARD_CMD:{ case SNF_CARD_CMD:{
LogTrace(data, len, 0, 0, NULL, reader); LogTrace(data, len, 0, 0, NULL, reader);
timerData = GetTickCount(); timerData = GetTickCount();
break; break;
} }
default: default:
sniffState = SNF_INIT; sniffState = SNF_INIT;
break; break;
} }
return false; return false;
} }
*/ */
void RAMFUNC MfSniffSend() { void RAMFUNC MfSniffSend() {
uint16_t tracelen = BigBuf_get_traceLen(); uint16_t tracelen = BigBuf_get_traceLen();
uint16_t chunksize = 0; uint16_t chunksize = 0;
int packlen = tracelen; // total number of bytes to send int packlen = tracelen; // total number of bytes to send
uint8_t *data = BigBuf_get_addr(); uint8_t *data = BigBuf_get_addr();
while (packlen > 0) { while (packlen > 0) {
LED_B_ON(); LED_B_ON();
chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512
cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize);
packlen -= chunksize; packlen -= chunksize;
LED_B_OFF(); LED_B_OFF();
} }
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished.
LED_B_OFF(); LED_B_OFF();
} }

View file

@ -21,18 +21,18 @@
#include "mifareutil.h" #include "mifareutil.h"
#include "common.h" #include "common.h"
#define SNF_INIT 0 #define SNF_INIT 0
#define SNF_NO_FIELD 1 #define SNF_NO_FIELD 1
#define SNF_ATQA 2 #define SNF_ATQA 2
#define SNF_UID 3 #define SNF_UID 3
#define SNF_SAK 4 #define SNF_SAK 4
#define SNF_CARD_IDLE 5 #define SNF_CARD_IDLE 5
#define SNF_CARD_CMD 6 #define SNF_CARD_CMD 6
#define SNF_MAGIC_WUPC2 7 #define SNF_MAGIC_WUPC2 7
#define SNF_UID_4 0 #define SNF_UID_4 0
#define SNF_UID_7 0 #define SNF_UID_7 0
#define SNF_UID_10 0 #define SNF_UID_10 0
void MfSniffInit(void); void MfSniffInit(void);
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader); bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader);

File diff suppressed because it is too large Load diff

View file

@ -21,7 +21,7 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "des.h" #include "des.h"
#include "random.h" // fast_prand, prand #include "random.h" // fast_prand, prand
// mifare authentication // mifare authentication
#define CRYPT_NONE 0 #define CRYPT_NONE 0
@ -30,8 +30,8 @@
#define AUTH_FIRST 0 #define AUTH_FIRST 0
#define AUTH_NESTED 2 #define AUTH_NESTED 2
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication #define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// mifare 4bit card answers // mifare 4bit card answers
#define CARD_ACK 0x0A // 1010 - ACK #define CARD_ACK 0x0A // 1010 - ACK
@ -48,7 +48,7 @@
#define MFEMUL_SELECT3 4 #define MFEMUL_SELECT3 4
#define MFEMUL_AUTH1 5 #define MFEMUL_AUTH1 5
#define MFEMUL_AUTH2 6 #define MFEMUL_AUTH2 6
#define MFEMUL_WORK 7 #define MFEMUL_WORK 7
#define MFEMUL_WRITEBL2 8 #define MFEMUL_WRITEBL2 8
#define MFEMUL_INTREG_INC 9 #define MFEMUL_INTREG_INC 9
#define MFEMUL_INTREG_DEC 10 #define MFEMUL_INTREG_DEC 10

View file

@ -41,8 +41,8 @@
This file contains an optimized version of the MAC-calculation algorithm. Some measurements on This file contains an optimized version of the MAC-calculation algorithm. Some measurements on
a std laptop showed it runs in about 1/3 of the time: a std laptop showed it runs in about 1/3 of the time:
Std: 0.428962 Std: 0.428962
Opt: 0.151609 Opt: 0.151609
Additionally, it is self-reliant, not requiring e.g. bitstreams from the cipherutils, thus can Additionally, it is self-reliant, not requiring e.g. bitstreams from the cipherutils, thus can
be easily dropped into a code base. be easily dropped into a code base.
@ -67,162 +67,162 @@
#define opt_B(s) (((s->b >> 6) ^ (s->b >> 5) ^ (s->b >> 4) ^ (s->b)) & 0x1) #define opt_B(s) (((s->b >> 6) ^ (s->b >> 5) ^ (s->b >> 4) ^ (s->b)) & 0x1)
#define opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\ #define opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\
|(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\ |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\
|(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) |(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x))
/* /*
* Some background on the expression above can be found here... * Some background on the expression above can be found here...
uint8_t xopt__select(bool x, bool y, uint8_t r) uint8_t xopt__select(bool x, bool y, uint8_t r)
{ {
uint8_t r_ls2 = r << 2; uint8_t r_ls2 = r << 2;
uint8_t r_and_ls2 = r & r_ls2; uint8_t r_and_ls2 = r & r_ls2;
uint8_t r_or_ls2 = r | r_ls2; uint8_t r_or_ls2 = r | r_ls2;
//r: r0 r1 r2 r3 r4 r5 r6 r7 //r: r0 r1 r2 r3 r4 r5 r6 r7
//r_ls2: r2 r3 r4 r5 r6 r7 0 0 //r_ls2: r2 r3 r4 r5 r6 r7 0 0
// z0 // z0
// z1 // z1
// uint8_t z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4); // <-- original // uint8_t z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4); // <-- original
uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3);
// uint8_t z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y; // <-- original // uint8_t z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y; // <-- original
uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1); uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1);
// uint8_t z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x; // <-- original // uint8_t z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x; // <-- original
uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r ^ x; uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r ^ x;
return (z0 & 4) | (z1 & 2) | (z2 & 1); return (z0 & 4) | (z1 & 2) | (z2 & 1);
} }
*/ */
void opt_successor(const uint8_t* k, State *s, bool y, State* successor) { void opt_successor(const uint8_t* k, State *s, bool y, State* successor) {
uint8_t Tt = 1 & opt_T(s); uint8_t Tt = 1 & opt_T(s);
successor->t = (s->t >> 1); successor->t = (s->t >> 1);
successor->t |= (Tt ^ (s->r >> 7 & 0x1) ^ (s->r >> 3 & 0x1)) << 15; successor->t |= (Tt ^ (s->r >> 7 & 0x1) ^ (s->r >> 3 & 0x1)) << 15;
successor->b = s->b >> 1; successor->b = s->b >> 1;
successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7; successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7;
successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ; successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ;
successor->l = successor->r+s->r; successor->l = successor->r+s->r;
} }
void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Zeroes) { void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Zeroes) {
State x2; State x2;
int i; int i;
uint8_t head = 0; uint8_t head = 0;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
head = 1 & (in[i] >> 7); head = 1 & (in[i] >> 7);
opt_successor(k, s, head, &x2); opt_successor(k, s, head, &x2);
head = 1 & (in[i] >> 6); head = 1 & (in[i] >> 6);
opt_successor(k, &x2, head, s); opt_successor(k, &x2, head, s);
head = 1 & (in[i] >> 5); head = 1 & (in[i] >> 5);
opt_successor(k, s, head, &x2); opt_successor(k, s, head, &x2);
head = 1 & (in[i] >> 4); head = 1 & (in[i] >> 4);
opt_successor(k, &x2, head, s); opt_successor(k, &x2, head, s);
head = 1 & (in[i] >> 3); head = 1 & (in[i] >> 3);
opt_successor(k, s, head, &x2); opt_successor(k, s, head, &x2);
head = 1 & (in[i] >> 2); head = 1 & (in[i] >> 2);
opt_successor(k, &x2, head, s); opt_successor(k, &x2, head, s);
head = 1 & (in[i] >> 1); head = 1 & (in[i] >> 1);
opt_successor(k, s, head, &x2); opt_successor(k, s, head, &x2);
head = 1 & in[i]; head = 1 & in[i];
opt_successor(k, &x2, head, s); opt_successor(k, &x2, head, s);
} }
//For tag MAC, an additional 32 zeroes //For tag MAC, an additional 32 zeroes
if (add32Zeroes) { if (add32Zeroes) {
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
opt_successor(k, s, 0, &x2); opt_successor(k, s, 0, &x2);
opt_successor(k, &x2, 0, s); opt_successor(k, &x2, 0, s);
} }
} }
} }
void opt_output(const uint8_t* k,State* s, uint8_t *buffer) { void opt_output(const uint8_t* k,State* s, uint8_t *buffer) {
uint8_t times = 0; uint8_t times = 0;
uint8_t bout = 0; uint8_t bout = 0;
State temp = {0,0,0,0}; State temp = {0,0,0,0};
for ( ; times < 4; times++) { for ( ; times < 4; times++) {
bout =0; bout =0;
bout |= (s->r & 0x4) << 5; bout |= (s->r & 0x4) << 5;
opt_successor(k, s, 0, &temp); opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) << 4; bout |= (temp.r & 0x4) << 4;
opt_successor(k, &temp, 0, s); opt_successor(k, &temp, 0, s);
bout |= (s->r & 0x4) << 3; bout |= (s->r & 0x4) << 3;
opt_successor(k, s, 0, &temp); opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) << 2; bout |= (temp.r & 0x4) << 2;
opt_successor(k, &temp, 0, s); opt_successor(k, &temp, 0, s);
bout |= (s->r & 0x4) << 1; bout |= (s->r & 0x4) << 1;
opt_successor(k, s, 0, &temp); opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) ; bout |= (temp.r & 0x4) ;
opt_successor(k, &temp, 0, s); opt_successor(k, &temp, 0, s);
bout |= (s->r & 0x4) >> 1; bout |= (s->r & 0x4) >> 1;
opt_successor(k, s, 0, &temp); opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) >> 2; bout |= (temp.r & 0x4) >> 2;
opt_successor(k, &temp, 0, s); opt_successor(k, &temp, 0, s);
buffer[times] = bout; buffer[times] = bout;
} }
} }
void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) { void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) {
State _init = { State _init = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(k,&_init,input,12, false); opt_suc(k,&_init,input,12, false);
opt_output(k,&_init, out); opt_output(k,&_init, out);
} }
uint8_t rev_byte(uint8_t b) { uint8_t rev_byte(uint8_t b) {
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
b = (b & 0xAA) >> 1 | (b & 0x55) << 1; b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
return b; return b;
} }
void opt_reverse_arraybytecpy(uint8_t* dest, uint8_t *src, size_t len) { void opt_reverse_arraybytecpy(uint8_t* dest, uint8_t *src, size_t len) {
uint8_t i; uint8_t i;
for ( i =0; i< len ; i++) for ( i =0; i< len ; i++)
dest[i] = rev_byte(src[i]); dest[i] = rev_byte(src[i]);
} }
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
static uint8_t cc_nr[12]; static uint8_t cc_nr[12];
opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12); opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12);
uint8_t dest [] = {0,0,0,0,0,0,0,0}; uint8_t dest [] = {0,0,0,0,0,0,0,0};
opt_MAC(div_key_p, cc_nr, dest); opt_MAC(div_key_p, cc_nr, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest, 4); opt_reverse_arraybytecpy(mac, dest, 4);
return; return;
} }
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
static uint8_t cc_nr[8+4+4]; static uint8_t cc_nr[8+4+4];
opt_reverse_arraybytecpy(cc_nr, cc_p, 12); opt_reverse_arraybytecpy(cc_nr, cc_p, 12);
State _init = { State _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_nr, 12, true); opt_suc(div_key_p, &_init, cc_nr, 12, true);
uint8_t dest [] = {0,0,0,0}; uint8_t dest [] = {0,0,0,0};
opt_output(div_key_p, &_init, dest); opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4); opt_reverse_arraybytecpy(mac, dest,4);
return; return;
} }
/** /**
@ -234,16 +234,16 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
* @return the cipher state * @return the cipher state
*/ */
State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
static uint8_t cc_nr[8]; static uint8_t cc_nr[8];
opt_reverse_arraybytecpy(cc_nr, cc_p, 8); opt_reverse_arraybytecpy(cc_nr, cc_p, 8);
State _init = { State _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r
0x4c, // b 0x4c, // b
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_nr, 8, false); opt_suc(div_key_p, &_init, cc_nr, 8, false);
return _init; return _init;
} }
/** /**
* The second part of the tag MAC calculation, since the CC is already calculated into the state, * The second part of the tag MAC calculation, since the CC is already calculated into the state,
@ -255,13 +255,13 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
* @param div_key_p - the key to use * @param div_key_p - the key to use
*/ */
void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p) { void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p) {
static uint8_t _nr[4]; static uint8_t _nr[4];
opt_reverse_arraybytecpy(_nr, nr, 4); opt_reverse_arraybytecpy(_nr, nr, 4);
opt_suc(div_key_p, &_init,_nr, 4, true); opt_suc(div_key_p, &_init,_nr, 4, true);
uint8_t dest [] = {0,0,0,0}; uint8_t dest [] = {0,0,0,0};
opt_output(div_key_p, &_init, dest); opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4); opt_reverse_arraybytecpy(mac, dest,4);
return; return;
} }

View file

@ -8,16 +8,16 @@
/** /**
* Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2 * Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2
* consisting of the following four components: * consisting of the following four components:
* 1. the left register l = (l 0 . . . l 7 ) F 8/2 ; * 1. the left register l = (l 0 . . . l 7 ) F 8/2 ;
* 2. the right register r = (r 0 . . . r 7 ) F 8/2 ; * 2. the right register r = (r 0 . . . r 7 ) F 8/2 ;
* 3. the top register t = (t 0 . . . t 15 ) F 16/2 . * 3. the top register t = (t 0 . . . t 15 ) F 16/2 .
* 4. the bottom register b = (b 0 . . . b 7 ) F 8/2 . * 4. the bottom register b = (b 0 . . . b 7 ) F 8/2 .
**/ **/
typedef struct { typedef struct {
uint8_t l; uint8_t l;
uint8_t r; uint8_t r;
uint8_t b; uint8_t b;
uint16_t t; uint16_t t;
} State; } State;
/** The reader MAC is MAC(key, CC * NR ) /** The reader MAC is MAC(key, CC * NR )

View file

@ -5,384 +5,384 @@
size_t DemodPCF7931(uint8_t **outBlocks) { size_t DemodPCF7931(uint8_t **outBlocks) {
uint8_t bits[256] = {0x00}; uint8_t bits[256] = {0x00};
uint8_t blocks[8][16]; uint8_t blocks[8][16];
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
int GraphTraceLen = BigBuf_max_traceLen(); int GraphTraceLen = BigBuf_max_traceLen();
if ( GraphTraceLen > 18000 ) if ( GraphTraceLen > 18000 )
GraphTraceLen = 18000; GraphTraceLen = 18000;
int i, j, lastval, bitidx, half_switch; int i, j, lastval, bitidx, half_switch;
int clock = 64; int clock = 64;
int tolerance = clock / 8; int tolerance = clock / 8;
int pmc, block_done; int pmc, block_done;
int lc, warnings = 0; int lc, warnings = 0;
size_t num_blocks = 0; size_t num_blocks = 0;
int lmin=128, lmax=128; int lmin=128, lmax=128;
uint8_t dir; uint8_t dir;
//clear read buffer //clear read buffer
BigBuf_Clear_keep_EM(); BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
DoAcquisition_default(0, true); DoAcquisition_default(0, true);
lmin = 64; lmin = 64;
lmax = 192; lmax = 192;
i = 2; i = 2;
/* Find first local max/min */ /* Find first local max/min */
if(dest[1] > dest[0]) { if(dest[1] > dest[0]) {
while(i < GraphTraceLen) { while(i < GraphTraceLen) {
if( !(dest[i] > dest[i-1]) && dest[i] > lmax) if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
break; break;
i++; i++;
} }
dir = 0; dir = 0;
} else { } else {
while(i < GraphTraceLen) { while(i < GraphTraceLen) {
if( !(dest[i] < dest[i-1]) && dest[i] < lmin) if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
break; break;
i++; i++;
} }
dir = 1; dir = 1;
} }
lastval = i++; lastval = i++;
half_switch = 0; half_switch = 0;
pmc = 0; pmc = 0;
block_done = 0; block_done = 0;
for (bitidx = 0; i < GraphTraceLen; i++) { for (bitidx = 0; i < GraphTraceLen; i++) {
if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) { if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) {
lc = i - lastval; lc = i - lastval;
lastval = i; lastval = i;
// Switch depending on lc length: // Switch depending on lc length:
// Tolerance is 1/8 of clock rate (arbitrary) // Tolerance is 1/8 of clock rate (arbitrary)
if (ABS(lc-clock/4) < tolerance) { if (ABS(lc-clock/4) < tolerance) {
// 16T0 // 16T0
if((i - pmc) == lc) { /* 16T0 was previous one */ if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */ /* It's a PMC ! */
i += (128+127+16+32+33+16)-1; i += (128+127+16+32+33+16)-1;
lastval = i; lastval = i;
pmc = 0; pmc = 0;
block_done = 1; block_done = 1;
} else { } else {
pmc = i; pmc = i;
} }
} else if (ABS(lc-clock/2) < tolerance) { } else if (ABS(lc-clock/2) < tolerance) {
// 32TO // 32TO
if((i - pmc) == lc) { /* 16T0 was previous one */ if((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */ /* It's a PMC ! */
i += (128+127+16+32+33)-1; i += (128+127+16+32+33)-1;
lastval = i; lastval = i;
pmc = 0; pmc = 0;
block_done = 1; block_done = 1;
} else if(half_switch == 1) { } else if(half_switch == 1) {
bits[bitidx++] = 0; bits[bitidx++] = 0;
half_switch = 0; half_switch = 0;
} }
else else
half_switch++; half_switch++;
} else if (ABS(lc-clock) < tolerance) { } else if (ABS(lc-clock) < tolerance) {
// 64TO // 64TO
bits[bitidx++] = 1; bits[bitidx++] = 1;
} else { } else {
// Error // Error
if (++warnings > 10) { if (++warnings > 10) {
Dbprintf("Error: too many detection errors, aborting."); Dbprintf("Error: too many detection errors, aborting.");
return 0; return 0;
} }
} }
if(block_done == 1) { if(block_done == 1) {
if(bitidx == 128) { if(bitidx == 128) {
for(j = 0; j < 16; ++j) { for(j = 0; j < 16; ++j) {
blocks[num_blocks][j] = blocks[num_blocks][j] =
128 * bits[j*8 + 7]+ 128 * bits[j*8 + 7]+
64*bits[j*8+6]+ 64*bits[j*8+6]+
32*bits[j*8+5]+ 32*bits[j*8+5]+
16*bits[j*8+4]+ 16*bits[j*8+4]+
8*bits[j*8+3]+ 8*bits[j*8+3]+
4*bits[j*8+2]+ 4*bits[j*8+2]+
2*bits[j*8+1]+ 2*bits[j*8+1]+
bits[j*8] bits[j*8]
; ;
} }
num_blocks++; num_blocks++;
} }
bitidx = 0; bitidx = 0;
block_done = 0; block_done = 0;
half_switch = 0; half_switch = 0;
} }
if(i < GraphTraceLen) if(i < GraphTraceLen)
dir =(dest[i-1] > dest[i]) ? 0 : 1; dir =(dest[i-1] > dest[i]) ? 0 : 1;
} }
if(bitidx==255) if(bitidx==255)
bitidx=0; bitidx=0;
warnings = 0; warnings = 0;
if(num_blocks == 4) break; if(num_blocks == 4) break;
} }
memcpy(outBlocks, blocks, 16*num_blocks); memcpy(outBlocks, blocks, 16*num_blocks);
return num_blocks; return num_blocks;
} }
bool IsBlock0PCF7931(uint8_t *block) { bool IsBlock0PCF7931(uint8_t *block) {
// assuming all RFU bits are set to 0 // assuming all RFU bits are set to 0
// if PAC is enabled password is set to 0 // if PAC is enabled password is set to 0
if (block[7] == 0x01) if (block[7] == 0x01)
{ {
if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
return true; return true;
} }
else if (block[7] == 0x00) else if (block[7] == 0x00)
{ {
if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7))
return true; return true;
} }
return false; return false;
} }
bool IsBlock1PCF7931(uint8_t *block) { bool IsBlock1PCF7931(uint8_t *block) {
// assuming all RFU bits are set to 0 // assuming all RFU bits are set to 0
if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0) if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0)
if((block[14] & 0x7f) <= 9 && block[15] <= 9) if((block[14] & 0x7f) <= 9 && block[15] <= 9)
return true; return true;
return false; return false;
} }
void ReadPCF7931() { void ReadPCF7931() {
int found_blocks = 0; // successfully read blocks int found_blocks = 0; // successfully read blocks
int max_blocks = 8; // readable blocks int max_blocks = 8; // readable blocks
uint8_t memory_blocks[8][17]; // PCF content uint8_t memory_blocks[8][17]; // PCF content
uint8_t single_blocks[8][17]; // PFC blocks with unknown position uint8_t single_blocks[8][17]; // PFC blocks with unknown position
int single_blocks_cnt = 0; int single_blocks_cnt = 0;
size_t n = 0; // transmitted blocks size_t n = 0; // transmitted blocks
uint8_t tmp_blocks[4][16]; // temporary read buffer uint8_t tmp_blocks[4][16]; // temporary read buffer
uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
int errors = 0; // error counter int errors = 0; // error counter
int tries = 0; // tries counter int tries = 0; // tries counter
memset(memory_blocks, 0, 8*17*sizeof(uint8_t)); memset(memory_blocks, 0, 8*17*sizeof(uint8_t));
memset(single_blocks, 0, 8*17*sizeof(uint8_t)); memset(single_blocks, 0, 8*17*sizeof(uint8_t));
int i = 0, j = 0; int i = 0, j = 0;
do { do {
i = 0; i = 0;
memset(tmp_blocks, 0, 4*16*sizeof(uint8_t)); memset(tmp_blocks, 0, 4*16*sizeof(uint8_t));
n = DemodPCF7931((uint8_t**)tmp_blocks); n = DemodPCF7931((uint8_t**)tmp_blocks);
if(!n) if(!n)
++errors; ++errors;
// exit if no block is received // exit if no block is received
if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) {
Dbprintf("Error, no tag or bad tag"); Dbprintf("Error, no tag or bad tag");
return; return;
} }
// exit if too many errors during reading // exit if too many errors during reading
if (tries > 50 && (2*errors > tries)) { if (tries > 50 && (2*errors > tries)) {
Dbprintf("Error reading the tag"); Dbprintf("Error reading the tag");
Dbprintf("Here is the partial content"); Dbprintf("Here is the partial content");
goto end; goto end;
} }
// our logic breaks if we don't get at least two blocks // our logic breaks if we don't get at least two blocks
if (n < 2) { if (n < 2) {
if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
continue; continue;
if (single_blocks_cnt < max_blocks) { if (single_blocks_cnt < max_blocks) {
for (i = 0; i < single_blocks_cnt; ++i) { for (i = 0; i < single_blocks_cnt; ++i) {
if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) { if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
j = 1; j = 1;
break; break;
} }
} }
if (j != 1) { if (j != 1) {
memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16); memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
single_blocks_cnt++; single_blocks_cnt++;
} }
j = 0; j = 0;
} }
++tries; ++tries;
continue; continue;
} }
Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
i = 0; i = 0;
if(!found_0_1) { if(!found_0_1) {
while (i < n - 1) { while (i < n - 1) {
if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) { if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) {
found_0_1 = 1; found_0_1 = 1;
memcpy(memory_blocks[0], tmp_blocks[i], 16); memcpy(memory_blocks[0], tmp_blocks[i], 16);
memcpy(memory_blocks[1], tmp_blocks[i+1], 16); memcpy(memory_blocks[1], tmp_blocks[i+1], 16);
memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1; memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
// block 1 tells how many blocks are going to be sent // block 1 tells how many blocks are going to be sent
max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1; max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
found_blocks = 2; found_blocks = 2;
Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks); Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks);
// handle the following blocks // handle the following blocks
for (j = i + 2; j < n; ++j) { for (j = i + 2; j < n; ++j) {
memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16); memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16);
memory_blocks[found_blocks][ALLOC] = 1; memory_blocks[found_blocks][ALLOC] = 1;
++found_blocks; ++found_blocks;
} }
break; break;
} }
++i; ++i;
} }
} else { } else {
// Trying to re-order blocks // Trying to re-order blocks
// Look for identical block in memory blocks // Look for identical block in memory blocks
while (i < n-1) { while (i < n-1) {
// skip all zeroes blocks // skip all zeroes blocks
if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 1; j < max_blocks - 1; ++j) { for (j = 1; j < max_blocks - 1; ++j) {
if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) { if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) {
memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16); memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16);
memory_blocks[j+1][ALLOC] = 1; memory_blocks[j+1][ALLOC] = 1;
if (++found_blocks >= max_blocks) goto end; if (++found_blocks >= max_blocks) goto end;
} }
} }
} }
if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 0; j < max_blocks; ++j) { for (j = 0; j < max_blocks; ++j) {
if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) { if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) {
if (j == 0) { if (j == 0) {
memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16); memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16);
memory_blocks[max_blocks - 1][ALLOC] = 1; memory_blocks[max_blocks - 1][ALLOC] = 1;
} else { } else {
memcpy(memory_blocks[j-1], tmp_blocks[i], 16); memcpy(memory_blocks[j-1], tmp_blocks[i], 16);
memory_blocks[j-1][ALLOC] = 1; memory_blocks[j-1][ALLOC] = 1;
} }
if (++found_blocks >= max_blocks) goto end; if (++found_blocks >= max_blocks) goto end;
} }
} }
} }
++i; ++i;
} }
} }
++tries; ++tries;
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {
Dbprintf("Button pressed, stopping."); Dbprintf("Button pressed, stopping.");
goto end; goto end;
} }
} }
while (found_blocks != max_blocks); while (found_blocks != max_blocks);
end: end:
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
Dbprintf("Memory content:"); Dbprintf("Memory content:");
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
for (i = 0; i < max_blocks; ++i) { for (i = 0; i < max_blocks; ++i) {
if (memory_blocks[i][ALLOC]) if (memory_blocks[i][ALLOC])
print_result("Block", memory_blocks[i], 16); print_result("Block", memory_blocks[i], 16);
else else
Dbprintf("<missing block %d>", i); Dbprintf("<missing block %d>", i);
} }
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
if (found_blocks < max_blocks) { if (found_blocks < max_blocks) {
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
Dbprintf("Blocks with unknown position:"); Dbprintf("Blocks with unknown position:");
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
for (i = 0; i < single_blocks_cnt; ++i) for (i = 0; i < single_blocks_cnt; ++i)
print_result("Block", single_blocks[i], 16); print_result("Block", single_blocks[i], 16);
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
} }
cmd_send(CMD_ACK,0,0,0,0,0); cmd_send(CMD_ACK,0,0,0,0,0);
} }
static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
uint32_t tab[1024] = {0}; // data times frame uint32_t tab[1024] = {0}; // data times frame
uint32_t u = 0; uint32_t u = 0;
uint8_t parity = 0; uint8_t parity = 0;
bool comp = 0; bool comp = 0;
//BUILD OF THE DATA FRAME //BUILD OF THE DATA FRAME
//alimentation of the tag (time for initializing) //alimentation of the tag (time for initializing)
AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab);
AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab);
//password indication bit //password indication bit
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
//password (on 56 bits) //password (on 56 bits)
AddBytePCF7931(pass[0], tab, l, p); AddBytePCF7931(pass[0], tab, l, p);
AddBytePCF7931(pass[1], tab, l, p); AddBytePCF7931(pass[1], tab, l, p);
AddBytePCF7931(pass[2], tab, l, p); AddBytePCF7931(pass[2], tab, l, p);
AddBytePCF7931(pass[3], tab, l, p); AddBytePCF7931(pass[3], tab, l, p);
AddBytePCF7931(pass[4], tab, l, p); AddBytePCF7931(pass[4], tab, l, p);
AddBytePCF7931(pass[5], tab, l, p); AddBytePCF7931(pass[5], tab, l, p);
AddBytePCF7931(pass[6], tab, l, p); AddBytePCF7931(pass[6], tab, l, p);
//programming mode (0 or 1) //programming mode (0 or 1)
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
//block adress on 6 bits //block adress on 6 bits
for (u = 0; u < 6; ++u) { for (u = 0; u < 6; ++u) {
if (address&(1<<u)) { // bit 1 if (address&(1<<u)) { // bit 1
++parity; ++parity;
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
} else{ // bit 0 } else{ // bit 0
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
} }
} }
//byte address on 4 bits //byte address on 4 bits
for (u = 0; u < 4; ++u) for (u = 0; u < 4; ++u)
{ {
if (byte&(1<<u)) { // bit 1 if (byte&(1<<u)) { // bit 1
parity++; parity++;
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
} }
else // bit 0 else // bit 0
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
} }
//data on 8 bits //data on 8 bits
for (u=0; u<8; u++) for (u=0; u<8; u++)
{ {
if (data&(1<<u)) { // bit 1 if (data&(1<<u)) { // bit 1
parity++; parity++;
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
} }
else //bit 0 else //bit 0
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
} }
//parity bit //parity bit
if ((parity % 2) == 0) if ((parity % 2) == 0)
AddBitPCF7931(0, tab, l, p); //even parity AddBitPCF7931(0, tab, l, p); //even parity
else else
AddBitPCF7931(1, tab, l, p);//odd parity AddBitPCF7931(1, tab, l, p);//odd parity
//time access memory //time access memory
AddPatternPCF7931(5120+2680, 0, 0, tab); AddPatternPCF7931(5120+2680, 0, 0, tab);
//conversion of the scale time //conversion of the scale time
for (u = 0; u < 500; ++u) for (u = 0; u < 500; ++u)
tab[u]=(tab[u] * 3)/2; tab[u]=(tab[u] * 3)/2;
//compensation of the counter reload //compensation of the counter reload
while (!comp){ while (!comp){
comp = 1; comp = 1;
for (u = 0; tab[u] != 0; ++u) for (u = 0; tab[u] != 0; ++u)
if(tab[u] > 0xFFFF){ if(tab[u] > 0xFFFF){
tab[u] -= 0xFFFF; tab[u] -= 0xFFFF;
comp = 0; comp = 0;
} }
} }
SendCmdPCF7931(tab); SendCmdPCF7931(tab);
} }
/* Write on a byte of a PCF7931 tag /* Write on a byte of a PCF7931 tag
@ -391,16 +391,16 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3
@param data : data to write @param data : data to write
*/ */
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
Dbprintf("Initialization delay : %d us", init_delay); Dbprintf("Initialization delay : %d us", init_delay);
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7); Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7);
Dbprintf("Block address : %02x", address); Dbprintf("Block address : %02x", address);
Dbprintf("Byte address : %02x", byte); Dbprintf("Byte address : %02x", byte);
Dbprintf("Data : %02x", data); Dbprintf("Data : %02x", data);
uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7}; uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7};
RealWritePCF7931 (password, init_delay, l, p, address, byte, data); RealWritePCF7931 (password, init_delay, l, p, address, byte, data);
} }
@ -409,52 +409,52 @@ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, ui
*/ */
void SendCmdPCF7931(uint32_t * tab){ void SendCmdPCF7931(uint32_t * tab){
uint16_t u=0, tempo=0; uint16_t u=0, tempo=0;
Dbprintf("Sending data frame..."); Dbprintf("Sending data frame...");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU );
LED_A_ON(); LED_A_ON();
// steal this pin from the SSP and use it to control the modulation // steal this pin from the SSP and use it to control the modulation
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
//initialization of the timer //initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (0x1 << AT91C_ID_TC0); AT91C_BASE_PMC->PMC_PCER |= (0x1 << AT91C_ID_TC0);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable 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 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
AT91C_BASE_TCB->TCB_BCR = 1; AT91C_BASE_TCB->TCB_BCR = 1;
tempo = AT91C_BASE_TC0->TC_CV; tempo = AT91C_BASE_TC0->TC_CV;
for( u = 0; tab[u] != 0; u += 3){ for( u = 0; tab[u] != 0; u += 3){
// modulate antenna // modulate antenna
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
while (tempo != tab[u]) while (tempo != tab[u])
tempo = AT91C_BASE_TC0->TC_CV; tempo = AT91C_BASE_TC0->TC_CV;
// stop modulating antenna // stop modulating antenna
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
while (tempo != tab[u+1]) while (tempo != tab[u+1])
tempo = AT91C_BASE_TC0->TC_CV; tempo = AT91C_BASE_TC0->TC_CV;
// modulate antenna // modulate antenna
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
while (tempo != tab[u+2]) while (tempo != tab[u+2])
tempo = AT91C_BASE_TC0->TC_CV; tempo = AT91C_BASE_TC0->TC_CV;
} }
LED_A_OFF(); LED_A_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(200); SpinDelay(200);
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable
LED(0xFFFF, 1000); LED(0xFFFF, 1000);
} }
@ -465,16 +465,16 @@ void SendCmdPCF7931(uint32_t * tab){
* @param p : offset on low pulse positioning * @param p : offset on low pulse positioning
*/ */
bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
uint32_t u; uint32_t u;
for (u = 0; u < 8; ++u) { for (u = 0; u < 8; ++u) {
if (byte & (1 << u)) { //bit is 1 if (byte & (1 << u)) { //bit is 1
if( AddBitPCF7931(1, tab, l, p)==1) return 1; if( AddBitPCF7931(1, tab, l, p)==1) return 1;
} else { //bit is 0 } else { //bit is 0
if (AddBitPCF7931(0, tab, l, p)==1) return 1; if (AddBitPCF7931(0, tab, l, p)==1) return 1;
} }
} }
return 0; return 0;
} }
/* Add a bits for building the data frame of PCF7931 tags /* Add a bits for building the data frame of PCF7931 tags
@ -484,32 +484,32 @@ bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
* @param p : offset on low pulse positioning * @param p : offset on low pulse positioning
*/ */
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){ bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
uint8_t u = 0; uint8_t u = 0;
//we put the cursor at the last value of the array //we put the cursor at the last value of the array
for ( u = 0; tab[u] != 0; u += 3 ) { } for ( u = 0; tab[u] != 0; u += 3 ) { }
if ( b == 1 ) { //add a bit 1 if ( b == 1 ) { //add a bit 1
if ( u == 0 ) if ( u == 0 )
tab[u] = 34 * T0_PCF + p; tab[u] = 34 * T0_PCF + p;
else else
tab[u] = 34 * T0_PCF + tab[u-1] + p; tab[u] = 34 * T0_PCF + tab[u-1] + p;
tab[u+1] = 6 * T0_PCF + tab[u] + l; tab[u+1] = 6 * T0_PCF + tab[u] + l;
tab[u+2] = 88 * T0_PCF + tab[u+1] - l - p; tab[u+2] = 88 * T0_PCF + tab[u+1] - l - p;
return 0; return 0;
} else { //add a bit 0 } else { //add a bit 0
if ( u == 0 ) if ( u == 0 )
tab[u] = 98 * T0_PCF + p; tab[u] = 98 * T0_PCF + p;
else else
tab[u] = 98 * T0_PCF + tab[u-1] + p; tab[u] = 98 * T0_PCF + tab[u-1] + p;
tab[u+1] = 6 * T0_PCF + tab[u] + l; tab[u+1] = 6 * T0_PCF + tab[u] + l;
tab[u+2] = 24 * T0_PCF + tab[u+1] - l - p; tab[u+2] = 24 * T0_PCF + tab[u+1] - l - p;
return 0; return 0;
} }
return 1; return 1;
} }
/* Add a custom pattern in the data frame /* Add a custom pattern in the data frame
@ -519,12 +519,12 @@ bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
* @param tab : array of the data frame * @param tab : array of the data frame
*/ */
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){
uint32_t u = 0; uint32_t u = 0;
for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array
tab[u] = (u == 0) ? a : a + tab[u-1]; tab[u] = (u == 0) ? a : a + tab[u-1];
tab[u+1] = b + tab[u]; tab[u+1] = b + tab[u];
tab[u+2] = c + tab[u+1]; tab[u+2] = c + tab[u+1];
return 0; return 0;
} }

View file

@ -1,6 +1,6 @@
/*- /*-
* Copyright (c) 1986, 1988, 1991, 1993 * Copyright (c) 1986, 1988, 1991, 1993
* The Regents of the University of California. All rights reserved. * The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc. * (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed * All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph * to the University of California by American Telephone and Telegraph
@ -31,7 +31,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
*/ */
#include "printf.h" #include "printf.h"
@ -50,7 +50,7 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) #define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z')))
/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */
#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) #define MAXNBUF (sizeof(intmax_t) * NBBY + 1)
/* /*
* Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
@ -61,17 +61,17 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static char * static char *
ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
{ {
char *p, c; char *p, c;
p = nbuf; p = nbuf;
*p = '\0'; *p = '\0';
do { do {
c = hex2ascii(num % base); c = hex2ascii(num % base);
*++p = upper ? toupper(c) : c; *++p = upper ? toupper(c) : c;
} while (num /= base); } while (num /= base);
if (lenp) if (lenp)
*lenp = p - nbuf; *lenp = p - nbuf;
return (p); return (p);
} }
/* /*
@ -82,7 +82,7 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
* The format %b is supported to decode error registers. * The format %b is supported to decode error registers.
* Its usage is: * Its usage is:
* *
* printf("reg=%b\n", regval, "*"); * printf("reg=%b\n", regval, "*");
* *
* where is the output base expressed as a control character, e.g. * where is the output base expressed as a control character, e.g.
* \10 gives octal; \20 gives hex. Each arg is a sequence of characters, * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
@ -90,340 +90,340 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
* the next characters (up to a control character, i.e. a character <= 32), * the next characters (up to a control character, i.e. a character <= 32),
* give the name of the register. Thus: * give the name of the register. Thus:
* *
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
* *
* would produce output: * would produce output:
* *
* reg=3 * reg=3
* *
* XXX: %D -- Hexdump, takes pointer and separator string: * XXX: %D -- Hexdump, takes pointer and separator string:
* ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX
* ("%*D", len, ptr, " " -> XX XX XX XX ... * ("%*D", len, ptr, " " -> XX XX XX XX ...
*/ */
int int
kvsprintf(char const *fmt, void *arg, int radix, va_list ap) kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
{ {
#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; } #define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
char nbuf[MAXNBUF]; char nbuf[MAXNBUF];
char *d; char *d;
const char *p, *percent, *q; const char *p, *percent, *q;
u_char *up; u_char *up;
int ch, n; int ch, n;
uintmax_t num; uintmax_t num;
int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot;
int cflag, hflag, jflag, tflag, zflag; int cflag, hflag, jflag, tflag, zflag;
int dwidth, upper; int dwidth, upper;
char padc; char padc;
int stop = 0, retval = 0; int stop = 0, retval = 0;
num = 0; num = 0;
d = (char *) arg; d = (char *) arg;
if (fmt == NULL) if (fmt == NULL)
fmt = "(fmt null)\n"; fmt = "(fmt null)\n";
if (radix < 2 || radix > 36) if (radix < 2 || radix > 36)
radix = 10; radix = 10;
for (;;) { for (;;) {
padc = ' '; padc = ' ';
width = 0; width = 0;
while ((ch = (u_char)*fmt++) != '%' || stop) { while ((ch = (u_char)*fmt++) != '%' || stop) {
PCHAR(ch); PCHAR(ch);
if (ch == '\0') if (ch == '\0')
return (retval); return (retval);
} }
percent = fmt - 1; percent = fmt - 1;
qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0; sign = 0; dot = 0; dwidth = 0; upper = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0;
reswitch: switch (ch = (u_char)*fmt++) { reswitch: switch (ch = (u_char)*fmt++) {
case '.': case '.':
dot = 1; dot = 1;
goto reswitch; goto reswitch;
case '#': case '#':
sharpflag = 1; sharpflag = 1;
goto reswitch; goto reswitch;
case '+': case '+':
sign = 1; sign = 1;
goto reswitch; goto reswitch;
case '-': case '-':
ladjust = 1; ladjust = 1;
goto reswitch; goto reswitch;
case '%': case '%':
PCHAR(ch); PCHAR(ch);
break; break;
case '*': case '*':
if (!dot) { if (!dot) {
width = va_arg(ap, int); width = va_arg(ap, int);
if (width < 0) { if (width < 0) {
ladjust = !ladjust; ladjust = !ladjust;
width = -width; width = -width;
} }
} else { } else {
dwidth = va_arg(ap, int); dwidth = va_arg(ap, int);
} }
goto reswitch; goto reswitch;
case '0': case '0':
if (!dot) { if (!dot) {
padc = '0'; padc = '0';
goto reswitch; goto reswitch;
} }
case '1': case '2': case '3': case '4': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9': case '5': case '6': case '7': case '8': case '9':
for (n = 0;; ++fmt) { for (n = 0;; ++fmt) {
n = n * 10 + ch - '0'; n = n * 10 + ch - '0';
ch = *fmt; ch = *fmt;
if (ch < '0' || ch > '9') if (ch < '0' || ch > '9')
break; break;
} }
if (dot) if (dot)
dwidth = n; dwidth = n;
else else
width = n; width = n;
goto reswitch; goto reswitch;
case 'b': case 'b':
num = (u_int)va_arg(ap, int); num = (u_int)va_arg(ap, int);
p = va_arg(ap, char *); p = va_arg(ap, char *);
for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;)
PCHAR(*q--); PCHAR(*q--);
if (num == 0) if (num == 0)
break; break;
for (tmp = 0; *p;) { for (tmp = 0; *p;) {
n = *p++; n = *p++;
if (num & (1 << (n - 1))) { if (num & (1 << (n - 1))) {
PCHAR(tmp ? ',' : '<'); PCHAR(tmp ? ',' : '<');
for (; (n = *p) > ' '; ++p) for (; (n = *p) > ' '; ++p)
PCHAR(n); PCHAR(n);
tmp = 1; tmp = 1;
} else } else
for (; *p > ' '; ++p) for (; *p > ' '; ++p)
continue; continue;
} }
if (tmp) if (tmp)
PCHAR('>'); PCHAR('>');
break; break;
case 'c': case 'c':
PCHAR(va_arg(ap, int)); PCHAR(va_arg(ap, int));
break; break;
case 'D': case 'D':
up = va_arg(ap, u_char *); up = va_arg(ap, u_char *);
p = va_arg(ap, char *); p = va_arg(ap, char *);
if (!width) if (!width)
width = 16; width = 16;
while(width--) { while(width--) {
PCHAR(hex2ascii(*up >> 4)); PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f)); PCHAR(hex2ascii(*up & 0x0f));
up++; up++;
if (width) if (width)
for (q=p;*q;q++) for (q=p;*q;q++)
PCHAR(*q); PCHAR(*q);
} }
break; break;
case 'd': case 'd':
case 'i': case 'i':
base = 10; base = 10;
sign = 1; sign = 1;
goto handle_sign; goto handle_sign;
case 'h': case 'h':
if (hflag) { if (hflag) {
hflag = 0; hflag = 0;
cflag = 1; cflag = 1;
} else } else
hflag = 1; hflag = 1;
goto reswitch; goto reswitch;
case 'j': case 'j':
jflag = 1; jflag = 1;
goto reswitch; goto reswitch;
case 'l': case 'l':
if (lflag) { if (lflag) {
lflag = 0; lflag = 0;
qflag = 1; qflag = 1;
} else } else
lflag = 1; lflag = 1;
goto reswitch; goto reswitch;
case 'n': case 'n':
if (jflag) if (jflag)
*(va_arg(ap, intmax_t *)) = retval; *(va_arg(ap, intmax_t *)) = retval;
else if (qflag) else if (qflag)
*(va_arg(ap, quad_t *)) = retval; *(va_arg(ap, quad_t *)) = retval;
else if (lflag) else if (lflag)
*(va_arg(ap, long *)) = retval; *(va_arg(ap, long *)) = retval;
else if (zflag) else if (zflag)
*(va_arg(ap, size_t *)) = retval; *(va_arg(ap, size_t *)) = retval;
else if (hflag) else if (hflag)
*(va_arg(ap, short *)) = retval; *(va_arg(ap, short *)) = retval;
else if (cflag) else if (cflag)
*(va_arg(ap, char *)) = retval; *(va_arg(ap, char *)) = retval;
else else
*(va_arg(ap, int *)) = retval; *(va_arg(ap, int *)) = retval;
break; break;
case 'o': case 'o':
base = 8; base = 8;
goto handle_nosign; goto handle_nosign;
case 'p': case 'p':
base = 16; base = 16;
sharpflag = (width == 0); sharpflag = (width == 0);
sign = 0; sign = 0;
num = (uintptr_t)va_arg(ap, void *); num = (uintptr_t)va_arg(ap, void *);
goto number; goto number;
case 'q': case 'q':
qflag = 1; qflag = 1;
goto reswitch; goto reswitch;
case 'r': case 'r':
base = radix; base = radix;
if (sign) if (sign)
goto handle_sign; goto handle_sign;
goto handle_nosign; goto handle_nosign;
case 's': case 's':
p = va_arg(ap, char *); p = va_arg(ap, char *);
if (p == NULL) if (p == NULL)
p = "(null)"; p = "(null)";
if (!dot) if (!dot)
n = strlen (p); n = strlen (p);
else else
for (n = 0; n < dwidth && p[n]; n++) for (n = 0; n < dwidth && p[n]; n++)
continue; continue;
width -= n; width -= n;
if (!ladjust && width > 0) if (!ladjust && width > 0)
while (width--) while (width--)
PCHAR(padc); PCHAR(padc);
while (n--) while (n--)
PCHAR(*p++); PCHAR(*p++);
if (ladjust && width > 0) if (ladjust && width > 0)
while (width--) while (width--)
PCHAR(padc); PCHAR(padc);
break; break;
case 't': case 't':
tflag = 1; tflag = 1;
goto reswitch; goto reswitch;
case 'u': case 'u':
base = 10; base = 10;
goto handle_nosign; goto handle_nosign;
case 'X': case 'X':
upper = 1; upper = 1;
case 'x': case 'x':
base = 16; base = 16;
goto handle_nosign; goto handle_nosign;
case 'y': case 'y':
base = 16; base = 16;
sign = 1; sign = 1;
goto handle_sign; goto handle_sign;
case 'z': case 'z':
zflag = 1; zflag = 1;
goto reswitch; goto reswitch;
handle_nosign: handle_nosign:
sign = 0; sign = 0;
if (jflag) if (jflag)
num = va_arg(ap, uintmax_t); num = va_arg(ap, uintmax_t);
else if (qflag) else if (qflag)
num = va_arg(ap, u_quad_t); num = va_arg(ap, u_quad_t);
else if (tflag) else if (tflag)
num = va_arg(ap, ptrdiff_t); num = va_arg(ap, ptrdiff_t);
else if (lflag) else if (lflag)
num = va_arg(ap, u_long); num = va_arg(ap, u_long);
else if (zflag) else if (zflag)
num = va_arg(ap, size_t); num = va_arg(ap, size_t);
else if (hflag) else if (hflag)
num = (u_short)va_arg(ap, int); num = (u_short)va_arg(ap, int);
else if (cflag) else if (cflag)
num = (u_char)va_arg(ap, int); num = (u_char)va_arg(ap, int);
else else
num = va_arg(ap, u_int); num = va_arg(ap, u_int);
goto number; goto number;
handle_sign: handle_sign:
if (jflag) if (jflag)
num = va_arg(ap, intmax_t); num = va_arg(ap, intmax_t);
else if (qflag) else if (qflag)
num = va_arg(ap, quad_t); num = va_arg(ap, quad_t);
else if (tflag) else if (tflag)
num = va_arg(ap, ptrdiff_t); num = va_arg(ap, ptrdiff_t);
else if (lflag) else if (lflag)
num = va_arg(ap, long); num = va_arg(ap, long);
else if (zflag) else if (zflag)
num = va_arg(ap, ssize_t); num = va_arg(ap, ssize_t);
else if (hflag) else if (hflag)
num = (short)va_arg(ap, int); num = (short)va_arg(ap, int);
else if (cflag) else if (cflag)
num = (char)va_arg(ap, int); num = (char)va_arg(ap, int);
else else
num = va_arg(ap, int); num = va_arg(ap, int);
number: number:
if (sign && (intmax_t)num < 0) { if (sign && (intmax_t)num < 0) {
neg = 1; neg = 1;
num = -(intmax_t)num; num = -(intmax_t)num;
} }
p = ksprintn(nbuf, num, base, &tmp, upper); p = ksprintn(nbuf, num, base, &tmp, upper);
if (sharpflag && num != 0) { if (sharpflag && num != 0) {
if (base == 8) if (base == 8)
tmp++; tmp++;
else if (base == 16) else if (base == 16)
tmp += 2; tmp += 2;
} }
if (neg) if (neg)
tmp++; tmp++;
if (!ladjust && padc != '0' && width if (!ladjust && padc != '0' && width
&& (width -= tmp) > 0) && (width -= tmp) > 0)
while (width--) while (width--)
PCHAR(padc); PCHAR(padc);
if (neg) if (neg)
PCHAR('-'); PCHAR('-');
if (sharpflag && num != 0) { if (sharpflag && num != 0) {
if (base == 8) { if (base == 8) {
PCHAR('0'); PCHAR('0');
} else if (base == 16) { } else if (base == 16) {
PCHAR('0'); PCHAR('0');
PCHAR('x'); PCHAR('x');
} }
} }
if (!ladjust && width && (width -= tmp) > 0) if (!ladjust && width && (width -= tmp) > 0)
while (width--) while (width--)
PCHAR(padc); PCHAR(padc);
while (*p) while (*p)
PCHAR(*p--); PCHAR(*p--);
if (ladjust && width && (width -= tmp) > 0) if (ladjust && width && (width -= tmp) > 0)
while (width--) while (width--)
PCHAR(padc); PCHAR(padc);
break; break;
default: default:
while (percent < fmt) while (percent < fmt)
PCHAR(*percent++); PCHAR(*percent++);
/* /*
* Since we ignore an formatting argument it is no * Since we ignore an formatting argument it is no
* longer safe to obey the remaining formatting * longer safe to obey the remaining formatting
* arguments as the arguments will no longer match * arguments as the arguments will no longer match
* the format specs. * the format specs.
*/ */
stop = 1; stop = 1;
break; break;
} }
} }
PCHAR(0); PCHAR(0);
return retval; return retval;
#undef PCHAR #undef PCHAR
} }
int vsprintf(char *dest, const char *fmt, va_list ap) int vsprintf(char *dest, const char *fmt, va_list ap)
{ {
return kvsprintf(fmt, dest, 10, ap); return kvsprintf(fmt, dest, 10, ap);
} }
int int
sprintf(char *dest, const char *fmt, ...) sprintf(char *dest, const char *fmt, ...)
{ {
/* http://www.pagetable.com/?p=298 */ /* http://www.pagetable.com/?p=298 */
int retval; int retval;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
retval = kvsprintf(fmt, dest, 10, ap); retval = kvsprintf(fmt, dest, 10, ap);
va_end(ap); va_end(ap);
return retval; return retval;
} }

View file

@ -23,62 +23,62 @@ extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __b
static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size)
{ {
uint8_t *allocated_memory; uint8_t *allocated_memory;
allocated_memory = next_free_memory; allocated_memory = next_free_memory;
next_free_memory += items*size; next_free_memory += items*size;
return allocated_memory; return allocated_memory;
} }
static void inflate_free(voidpf opaque, voidpf address) static void inflate_free(voidpf opaque, voidpf address)
{ {
// nothing to do // nothing to do
} }
static void uncompress_data_section(void) static void uncompress_data_section(void)
{ {
z_stream data_section; z_stream data_section;
next_free_memory = BigBuf_get_addr(); next_free_memory = BigBuf_get_addr();
// initialize zstream structure // initialize zstream structure
data_section.next_in = (uint8_t *) &__data_src_start__; data_section.next_in = (uint8_t *) &__data_src_start__;
data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter. data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter.
data_section.next_out = (uint8_t *) &__data_start__; data_section.next_out = (uint8_t *) &__data_start__;
data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct. data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct.
data_section.zalloc = &inflate_malloc; data_section.zalloc = &inflate_malloc;
data_section.zfree = &inflate_free; data_section.zfree = &inflate_free;
data_section.opaque = NULL; data_section.opaque = NULL;
// initialize zlib for inflate // initialize zlib for inflate
inflateInit2(&data_section, 15); inflateInit2(&data_section, 15);
// uncompress data segment to RAM // uncompress data segment to RAM
inflate(&data_section, Z_FINISH); inflate(&data_section, Z_FINISH);
// save the size of the compressed data section // save the size of the compressed data section
common_area.arg1 = data_section.total_in; common_area.arg1 = data_section.total_in;
} }
void __attribute__((section(".startos"))) Vector(void) void __attribute__((section(".startos"))) Vector(void)
{ {
/* Stack should have been set up by the bootloader */ /* Stack should have been set up by the bootloader */
// char *src; // char *src;
char *dst, *end; char *dst, *end;
uncompress_data_section(); uncompress_data_section();
/* Set up (that is: clear) BSS. */ /* Set up (that is: clear) BSS. */
dst = &__bss_start__; dst = &__bss_start__;
end = &__bss_end__; end = &__bss_end__;
while(dst < end) *dst++ = 0; while(dst < end) *dst++ = 0;
// Set up data segment: Copy from flash to ram // Set up data segment: Copy from flash to ram
// src = &__data_src_start__; // src = &__data_src_start__;
// dst = &__data_start__; // dst = &__data_start__;
// end = &__data_end__; // end = &__data_end__;
// while(dst < end) *dst++ = *src++; // while(dst < end) *dst++ = *src++;
AppMain(); AppMain();
} }
#endif #endif

View file

@ -11,39 +11,39 @@
void *memcpy(void *dest, const void *src, int len) void *memcpy(void *dest, const void *src, int len)
{ {
uint8_t *d = dest; uint8_t *d = dest;
const uint8_t *s = src; const uint8_t *s = src;
while((len--) > 0) { while((len--) > 0) {
*d = *s; *d = *s;
d++; d++;
s++; s++;
} }
return dest; return dest;
} }
void *memset(void *dest, int c, int len) void *memset(void *dest, int c, int len)
{ {
uint8_t *d = dest; uint8_t *d = dest;
while((len--) > 0) { while((len--) > 0) {
*d = c; *d = c;
d++; d++;
} }
return dest; return dest;
} }
int memcmp(const void *av, const void *bv, int len) int memcmp(const void *av, const void *bv, int len)
{ {
const uint8_t *a = av; const uint8_t *a = av;
const uint8_t *b = bv; const uint8_t *b = bv;
while((len--) > 0) { while((len--) > 0) {
if(*a != *b) { if(*a != *b) {
return *a - *b; return *a - *b;
} }
a++; a++;
b++; b++;
} }
return 0; return 0;
} }
void memxor(uint8_t * dest, uint8_t * src, size_t len) { void memxor(uint8_t * dest, uint8_t * src, size_t len) {
@ -53,36 +53,36 @@ void memxor(uint8_t * dest, uint8_t * src, size_t len) {
int strlen(const char *str) int strlen(const char *str)
{ {
int l = 0; int l = 0;
while(*str) { while(*str) {
l++; l++;
str++; str++;
} }
return l; return l;
} }
char* strncat(char *dest, const char *src, unsigned int n) char* strncat(char *dest, const char *src, unsigned int n)
{ {
unsigned int dest_len = strlen(dest); unsigned int dest_len = strlen(dest);
unsigned int i; unsigned int i;
for (i = 0 ; i < n && src[i] != '\0' ; i++) for (i = 0 ; i < n && src[i] != '\0' ; i++)
dest[dest_len + i] = src[i]; dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0'; dest[dest_len + i] = '\0';
return dest; return dest;
} }
char* strcat(char *dest, const char *src) char* strcat(char *dest, const char *src)
{ {
unsigned int dest_len = strlen(dest); unsigned int dest_len = strlen(dest);
unsigned int i; unsigned int i;
for (i = 0 ; src[i] != '\0' ; i++) for (i = 0 ; src[i] != '\0' ; i++)
dest[dest_len + i] = src[i]; dest[dest_len + i] = src[i];
dest[dest_len + i] = '\0'; dest[dest_len + i] = '\0';
return dest; return dest;
} }
////////////////////////////////////////// code to do 'itoa' ////////////////////////////////////////// code to do 'itoa'

View file

@ -12,160 +12,160 @@
// attempt at high resolution microsecond timer // attempt at high resolution microsecond timer
// beware: timer counts in 21.3uS increments (1024/48Mhz) // beware: timer counts in 21.3uS increments (1024/48Mhz)
void SpinDelayUs(int us) { void SpinDelayUs(int us) {
int ticks = (48 * us) >> 10; int ticks = (48 * us) >> 10;
// Borrow a PWM unit for my real-time clock // Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 1024 gives 46.875 kHz // 48 MHz / 1024 gives 46.875 kHz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;) { for(;;) {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
if (now == (uint16_t)(start + ticks)) if (now == (uint16_t)(start + ticks))
return; return;
WDT_HIT(); WDT_HIT();
} }
} }
void SpinDelay(int ms) { void SpinDelay(int ms) {
// convert to uS and call microsecond delay function // convert to uS and call microsecond delay function
SpinDelayUs(ms*1000); SpinDelayUs(ms*1000);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// timer lib // timer lib
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// test procedure: // test procedure:
// //
// ti = GetTickCount(); // ti = GetTickCount();
// SpinDelay(1000); // SpinDelay(1000);
// ti = GetTickCount() - ti; // ti = GetTickCount() - ti;
// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount()); // Dbprintf("timer(1s): %d t=%d", ti, GetTickCount());
void StartTickCount(void) { void StartTickCount(void) {
// This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz. // 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. // 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 uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency
// set RealTimeCounter divider to count at 1kHz: // set RealTimeCounter divider to count at 1kHz:
AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf); AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf);
// note: worst case precision is approx 2.5% // note: worst case precision is approx 2.5%
} }
/* /*
* Get the current count. * Get the current count.
*/ */
uint32_t RAMFUNC GetTickCount(void){ uint32_t RAMFUNC GetTickCount(void){
return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2; return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// microseconds timer // microseconds timer
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void StartCountUS(void) { void StartCountUS(void) {
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
// fast clock // fast clock
// tick=1.5mks // tick=1.5mks
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable 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_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_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR |
AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET; AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET;
AT91C_BASE_TC0->TC_RA = 1; AT91C_BASE_TC0->TC_RA = 1;
AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000 AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0 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_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->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; AT91C_BASE_TCB->TCB_BCR = 1;
while (AT91C_BASE_TC1->TC_CV > 0); while (AT91C_BASE_TC1->TC_CV > 0);
} }
uint32_t RAMFUNC GetCountUS(void){ uint32_t RAMFUNC GetCountUS(void){
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10); //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 // By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3; return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// Timer for iso14443 commands. Uses ssp_clk from FPGA // Timer for iso14443 commands. Uses ssp_clk from FPGA
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void StartCountSspClk(void) { void StartCountSspClk(void) {
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers 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_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1
| AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none | AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none
| AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0 | 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: // 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_CCR = AT91C_TC_CLKDIS; // disable TC1
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz 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_CPCSTOP // Stop clock on RC compare
| AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event | 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_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16)
| AT91C_TC_ENETRG // Enable external trigger event | AT91C_TC_ENETRG // Enable external trigger event
| AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare | AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare
| AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVE // Waveform Mode
| AT91C_TC_AEEVT_SET // Set TIOA1 on external event | AT91C_TC_AEEVT_SET // Set TIOA1 on external event
| AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare | AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare
AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04 AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04
// use TC0 to count TIOA1 pulses // use TC0 to count TIOA1 pulses
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0 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_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1
| AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVE // Waveform Mode
| AT91C_TC_WAVESEL_UP // just count | AT91C_TC_WAVESEL_UP // just count
| AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare | AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare
| AT91C_TC_ACPC_SET; // Set TIOA0 on RC 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_RA = 1; // RA Compare value = 1; pulse width to TC2
AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow 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) // 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_CCR = AT91C_TC_CLKDIS; // disable TC2
AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0 AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0
| AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVE // Waveform Mode
| AT91C_TC_WAVESEL_UP; // just count | AT91C_TC_WAVESEL_UP; // just count
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0 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_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 AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC2
// synchronize the counter with the ssp_frame signal. // synchronize the counter with the ssp_frame signal.
// Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present // 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 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_FRAME); // wait for ssp_frame to be low
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high 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 // 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 // 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) 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 (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, // 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. // 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). // (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. // 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. // Therefore need to wait quite some time before we can use the counter.
while (AT91C_BASE_TC2->TC_CV > 0); while (AT91C_BASE_TC2->TC_CV > 0);
} }
void ResetSspClk(void) { void ResetSspClk(void) {
//enable clock of timer and software trigger //enable clock of timer and software trigger
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
AT91C_BASE_TC1->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; AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (AT91C_BASE_TC2->TC_CV > 0); while (AT91C_BASE_TC2->TC_CV > 0);
} }
uint32_t RAMFUNC GetCountSspClk(void) { uint32_t RAMFUNC GetCountSspClk(void) {
uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV; 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 if ((tmp_count & 0x0000ffff) == 0) //small chance that we may have missed an increment in TC2
return (AT91C_BASE_TC2->TC_CV << 16); return (AT91C_BASE_TC2->TC_CV << 16);
return tmp_count; return tmp_count;
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -173,68 +173,68 @@ uint32_t RAMFUNC GetCountSspClk(void) {
// 1us = 1.5ticks // 1us = 1.5ticks
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void StartTicks(void){ void StartTicks(void){
// initialization of the timer // initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
// disable TC0 and TC1 for re-configuration // disable TC0 and TC1 for re-configuration
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// first configure TC1 (higher, 0xFFFF0000) 16 bit counter // first configure TC1 (higher, 0xFFFF0000) 16 bit counter
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0 AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0 AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0
// second configure TC0 (lower, 0x0000FFFF) 16 bit counter // second configure TC0 (lower, 0x0000FFFF) 16 bit counter
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32
AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO |
AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit) AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit)
AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit) AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit)
AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit) AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit)
AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero
AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer
// synchronized startup procedure // synchronized startup procedure
while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero
while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared) while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared)
// return to zero // return to zero
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
while (AT91C_BASE_TC0->TC_CV > 0); while (AT91C_BASE_TC0->TC_CV > 0);
} }
uint32_t GetTicks(void) { uint32_t GetTicks(void) {
uint32_t hi, lo; uint32_t hi, lo;
do { do {
hi = AT91C_BASE_TC1->TC_CV; hi = AT91C_BASE_TC1->TC_CV;
lo = AT91C_BASE_TC0->TC_CV; lo = AT91C_BASE_TC0->TC_CV;
} while(hi != AT91C_BASE_TC1->TC_CV); } while(hi != AT91C_BASE_TC1->TC_CV);
return (hi << 16) | lo; return (hi << 16) | lo;
} }
// Wait - Spindelay in ticks. // Wait - Spindelay in ticks.
// if called with a high number, this will trigger the WDT... // if called with a high number, this will trigger the WDT...
void WaitTicks(uint32_t ticks){ void WaitTicks(uint32_t ticks){
if ( ticks == 0 ) return; if ( ticks == 0 ) return;
ticks += GetTicks(); ticks += GetTicks();
while (GetTicks() < ticks); while (GetTicks() < ticks);
} }
// Wait / Spindelay in us (microseconds) // Wait / Spindelay in us (microseconds)
// 1us = 1.5ticks. // 1us = 1.5ticks.
void WaitUS(uint16_t us){ void WaitUS(uint16_t us){
WaitTicks( (uint32_t)us * 3/2 ); WaitTicks( (uint32_t)us * 3/2 );
} }
void WaitMS(uint16_t ms){ void WaitMS(uint16_t ms){
WaitTicks( (uint32_t)ms * 1500 ); WaitTicks( (uint32_t)ms * 1500 );
} }
// stop clock // stop clock
void StopTicks(void){ void StopTicks(void){
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
} }

View file

@ -10,7 +10,7 @@
#include "util.h" #include "util.h"
size_t nbytes(size_t nbits) { size_t nbytes(size_t nbits) {
return (nbits >> 3)+((nbits % 8) > 0); return (nbits >> 3)+((nbits % 8) > 0);
} }
/* /*
@ -19,19 +19,19 @@ size_t nbytes(size_t nbits) {
Example: reflect(0x3e23L,3) == 0x3e26 Example: reflect(0x3e23L,3) == 0x3e26
*/ */
uint32_t reflect(uint32_t v, int b) { uint32_t reflect(uint32_t v, int b) {
uint32_t t = v; uint32_t t = v;
for ( int i = 0; i < b; ++i) { for ( int i = 0; i < b; ++i) {
if (t & 1) if (t & 1)
v |= BITMASK((b-1)-i); v |= BITMASK((b-1)-i);
else else
v &= ~BITMASK((b-1)-i); v &= ~BITMASK((b-1)-i);
t>>=1; t>>=1;
} }
return v; return v;
} }
uint8_t reflect8(uint8_t b) { uint8_t reflect8(uint8_t b) {
return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
} }
uint16_t reflect16(uint16_t b) { uint16_t reflect16(uint16_t b) {
uint16_t v = 0; uint16_t v = 0;
@ -56,19 +56,19 @@ uint16_t reflect16(uint16_t b) {
} }
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) {
while (len--) { while (len--) {
dest[len] = (uint8_t) n; dest[len] = (uint8_t) n;
n >>= 8; n >>= 8;
} }
} }
uint64_t bytes_to_num(uint8_t* src, size_t len) { uint64_t bytes_to_num(uint8_t* src, size_t len) {
uint64_t num = 0; uint64_t num = 0;
while (len--) { while (len--) {
num = (num << 8) | (*src); num = (num << 8) | (*src);
src++; src++;
} }
return num; return num;
} }
// RotateLeft - Ultralight, Desfire // RotateLeft - Ultralight, Desfire
@ -107,11 +107,11 @@ uint8_t hex2int(char hexchar){
case 'a': case 'a':
case 'A': return 10; break; case 'A': return 10; break;
case 'b': case 'b':
case 'B': return 11; break; case 'B': return 11; break;
case 'c': case 'c':
case 'C': return 12; break; case 'C': return 12; break;
case 'd': case 'd':
case 'D': return 13; break; case 'D': return 13; break;
case 'e': case 'e':
case 'E': return 14; break; case 'E': return 14; break;
case 'f': case 'f':
@ -122,36 +122,36 @@ uint8_t hex2int(char hexchar){
} }
void LEDsoff() { void LEDsoff() {
LED_A_OFF(); LED_A_OFF();
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
LED_D_OFF(); LED_D_OFF();
} }
// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8] // LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]
void LED(int led, int ms) { void LED(int led, int ms) {
if (led & LED_RED) if (led & LED_RED)
LED_C_ON(); LED_C_ON();
if (led & LED_ORANGE) if (led & LED_ORANGE)
LED_A_ON(); LED_A_ON();
if (led & LED_GREEN) if (led & LED_GREEN)
LED_B_ON(); LED_B_ON();
if (led & LED_RED2) if (led & LED_RED2)
LED_D_ON(); LED_D_ON();
if (!ms) if (!ms)
return; return;
SpinDelay(ms); SpinDelay(ms);
if (led & LED_RED) if (led & LED_RED)
LED_C_OFF(); LED_C_OFF();
if (led & LED_ORANGE) if (led & LED_ORANGE)
LED_A_OFF(); LED_A_OFF();
if (led & LED_GREEN) if (led & LED_GREEN)
LED_B_OFF(); LED_B_OFF();
if (led & LED_RED2) if (led & LED_RED2)
LED_D_OFF(); LED_D_OFF();
} }
void SpinOff(uint32_t pause) { void SpinOff(uint32_t pause) {
@ -166,7 +166,7 @@ void SpinOff(uint32_t pause) {
void SpinErr(uint8_t led, uint32_t speed, uint8_t times) { void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
SpinOff(speed); SpinOff(speed);
NTIME(times) NTIME(times)
{ {
switch (led) { switch (led) {
case 0: case 0:
LED_A_INV(); LED_A_INV();
@ -223,102 +223,102 @@ void SpinUp(uint32_t speed) {
// In general, don't use this function unless you expect a // In general, don't use this function unless you expect a
// double click, otherwise it will waste 500ms -- use BUTTON_HELD instead // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead
int BUTTON_CLICKED(int ms) { int BUTTON_CLICKED(int ms) {
// Up to 500ms in between clicks to mean a double click // Up to 500ms in between clicks to mean a double click
int ticks = (48000 * (ms ? ms : 1000)) >> 10; int ticks = (48000 * (ms ? ms : 1000)) >> 10;
// If we're not even pressed, forget about it! // If we're not even pressed, forget about it!
if (!BUTTON_PRESS()) if (!BUTTON_PRESS())
return BUTTON_NO_CLICK; return BUTTON_NO_CLICK;
// Borrow a PWM unit for my real-time clock // Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 1024 gives 46.875 kHz // 48 MHz / 1024 gives 46.875 kHz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
int letoff = 0; int letoff = 0;
for(;;) for(;;)
{ {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// We haven't let off the button yet // We haven't let off the button yet
if (!letoff) if (!letoff)
{ {
// We just let it off! // We just let it off!
if (!BUTTON_PRESS()) if (!BUTTON_PRESS())
{ {
letoff = 1; letoff = 1;
// reset our timer for 500ms // reset our timer for 500ms
start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
ticks = (48000 * (500)) >> 10; ticks = (48000 * (500)) >> 10;
} }
// Still haven't let it off // Still haven't let it off
else else
// Have we held down a full second? // Have we held down a full second?
if (now == (uint16_t)(start + ticks)) if (now == (uint16_t)(start + ticks))
return BUTTON_HOLD; return BUTTON_HOLD;
} }
// We already let off, did we click again? // We already let off, did we click again?
else else
// Sweet, double click! // Sweet, double click!
if (BUTTON_PRESS()) if (BUTTON_PRESS())
return BUTTON_DOUBLE_CLICK; return BUTTON_DOUBLE_CLICK;
// Have we ran out of time to double click? // Have we ran out of time to double click?
else else
if (now == (uint16_t)(start + ticks)) if (now == (uint16_t)(start + ticks))
// At least we did a single click // At least we did a single click
return BUTTON_SINGLE_CLICK; return BUTTON_SINGLE_CLICK;
WDT_HIT(); WDT_HIT();
} }
// We should never get here // We should never get here
return BUTTON_ERROR; return BUTTON_ERROR;
} }
// Determine if a button is held down // Determine if a button is held down
int BUTTON_HELD(int ms) { int BUTTON_HELD(int ms) {
// If button is held for one second // If button is held for one second
int ticks = (48000 * (ms ? ms : 1000)) >> 10; int ticks = (48000 * (ms ? ms : 1000)) >> 10;
// If we're not even pressed, forget about it! // If we're not even pressed, forget about it!
if (!BUTTON_PRESS()) if (!BUTTON_PRESS())
return BUTTON_NO_CLICK; return BUTTON_NO_CLICK;
// Borrow a PWM unit for my real-time clock // Borrow a PWM unit for my real-time clock
AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0);
// 48 MHz / 1024 gives 46.875 kHz // 48 MHz / 1024 gives 46.875 kHz
AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10);
AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0;
AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff;
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;) for(;;)
{ {
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// As soon as our button let go, we didn't hold long enough // As soon as our button let go, we didn't hold long enough
if (!BUTTON_PRESS()) if (!BUTTON_PRESS())
return BUTTON_SINGLE_CLICK; return BUTTON_SINGLE_CLICK;
// Have we waited the full second? // Have we waited the full second?
else else
if (now == (uint16_t)(start + ticks)) if (now == (uint16_t)(start + ticks))
return BUTTON_HOLD; return BUTTON_HOLD;
WDT_HIT(); WDT_HIT();
} }
// We should never get here // We should never get here
return BUTTON_ERROR; return BUTTON_ERROR;
} }
/* Similar to FpgaGatherVersion this formats stored version information /* Similar to FpgaGatherVersion this formats stored version information
@ -327,30 +327,30 @@ int BUTTON_HELD(int ms) {
* prefix in dst. * prefix in dst.
*/ */
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) { void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) {
struct version_information *v = (struct version_information*)version_information; struct version_information *v = (struct version_information*)version_information;
dst[0] = 0; dst[0] = 0;
strncat(dst, prefix, len-1); strncat(dst, prefix, len-1);
if (v->magic != VERSION_INFORMATION_MAGIC) { if (v->magic != VERSION_INFORMATION_MAGIC) {
strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1); strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1);
return; return;
} }
if (v->versionversion != 1) { if (v->versionversion != 1) {
strncat(dst, "Version information not understood\n", len - strlen(dst) - 1); strncat(dst, "Version information not understood\n", len - strlen(dst) - 1);
return; return;
} }
if (!v->present) { if (!v->present) {
strncat(dst, "Version information not available\n", len - strlen(dst) - 1); strncat(dst, "Version information not available\n", len - strlen(dst) - 1);
return; return;
} }
strncat(dst, v->gitversion, len - strlen(dst) - 1); strncat(dst, v->gitversion, len - strlen(dst) - 1);
if (v->clean == 0) { if (v->clean == 0) {
strncat(dst, "-unclean", len - strlen(dst) - 1); strncat(dst, "-unclean", len - strlen(dst) - 1);
} else if (v->clean == 2) { } else if (v->clean == 2) {
strncat(dst, "-suspect", len - strlen(dst) - 1); strncat(dst, "-suspect", len - strlen(dst) - 1);
} }
strncat(dst, " ", len - strlen(dst) - 1); strncat(dst, " ", len - strlen(dst) - 1);
strncat(dst, v->buildtime, len - strlen(dst) - 1); strncat(dst, v->buildtime, len - strlen(dst) - 1);
strncat(dst, "\n", len - strlen(dst) - 1); strncat(dst, "\n", len - strlen(dst) - 1);
} }

View file

@ -46,8 +46,8 @@
size_t nbytes(size_t nbits); size_t nbytes(size_t nbits);
extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... extern uint32_t reflect(uint32_t v, int b); // used in crc.c ...
extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal
extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len); uint64_t bytes_to_num(uint8_t* src, size_t len);