Clean up line endings, switch everything to LF instead of CRLF
authormarcansoft <marcansoft@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Sat, 20 Feb 2010 21:24:25 +0000 (21:24 +0000)
committermarcansoft <marcansoft@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Sat, 20 Feb 2010 21:24:25 +0000 (21:24 +0000)
Doing this for bootrom and armsrc for now. If you're using Windows,
please configure your editor for LF line endings.

18 files changed:
armsrc/LCD.c
armsrc/LCD.h
armsrc/Makefile
armsrc/appmain.c
armsrc/apps.h
armsrc/fonts.c
armsrc/fonts.h
armsrc/fpgaloader.c
armsrc/iso14443.c
armsrc/iso14443a.c
armsrc/iso15693.c
armsrc/ldscript
armsrc/lfops.c
bootrom/Makefile
bootrom/bootrom.c
bootrom/flash-reset.s
bootrom/fromflash.c
bootrom/ldscript-flash

index 8e44f7de41d0b34924322bcdb8b6d8c3f06d7a4a..d8d6308dec9a125e60aed4fdb0ef6940f3fb23a0 100644 (file)
-#include <proxmark3.h>\r
-#include "apps.h"\r
-#include "LCD.h"\r
-\r
-void LCDSend(unsigned int data)\r
-{\r
-       // 9th bit set for data, clear for command\r
-       while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);      // wait for the transfer to complete\r
-       // For clarity's sake we pass data with 9th bit clear and commands with 9th\r
-       // bit set since they're implemented as defines, se we need to invert bit\r
-       AT91C_BASE_SPI->SPI_TDR = data^0x100;                                                   // Send the data/command\r
-}\r
-\r
-void LCDSetXY(unsigned char x, unsigned char y)\r
-{\r
-       LCDSend(PPASET);                        // page start/end ram\r
-       LCDSend(y);                                     // Start Page to display to\r
-       LCDSend(131);                           // End Page to display to\r
-\r
-       LCDSend(PCASET);                        // column start/end ram\r
-       LCDSend(x);                                     // Start Column to display to\r
-       LCDSend(131);                           // End Column to display to\r
-}\r
-\r
-void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color)\r
-{\r
-       LCDSetXY(x,y);                          // Set position\r
-       LCDSend(PRAMWR);                        // Now write the pixel to the display\r
-       LCDSend(color);                         // Write the data in the specified Color\r
-}\r
-\r
-void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color)\r
-{\r
-    unsigned char i,j;\r
-\r
-    for (i=0;i < height;i++)   // Number of horizontal lines\r
-    {\r
-               LCDSetXY(xs,ys+i);              // Goto start of fill area (Top Left)\r
-               LCDSend(PRAMWR);                // Write to display\r
-\r
-               for (j=0;j < width;j++) // pixels per line\r
-                       LCDSend(color);\r
-    }\r
-}\r
-\r
-void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor)\r
-{\r
-       unsigned int  i;\r
-       unsigned char mask=0, px, py, xme, yme, offset;\r
-       const char *data;\r
-\r
-       data = font_style;                      // point to the start of the font table\r
-\r
-       xme = *data;                            // get font x width\r
-       data++;\r
-       yme = *data;                            // get font y length\r
-       data++;\r
-       offset = *data;                         // get data bytes per font\r
-\r
-       do\r
-       {\r
-               // point to data in table to be loaded\r
-               data =  (font_style + offset) + (offset * (int)(*lcd_string - 32));\r
-\r
-               for (i=0;i < yme;i++) {\r
-                       mask |=0x80;\r
-\r
-                       for (px=x; px < (x + xme); px++) {\r
-                               py= y + i;\r
-\r
-                               if (*data & mask)       LCDSetPixel (px,py,fcolor);\r
-                               else                            LCDSetPixel (px,py,bcolor);\r
-\r
-                               mask>>=1;\r
-                       }\r
-                       data++;\r
-               }\r
-               x+=xme;\r
-\r
-               lcd_string++;                                           // next character in string\r
-\r
-       } while(*lcd_string !='\0');                    // keep spitting chars out until end of string\r
-}\r
-\r
-void LCDReset(void)\r
-{\r
-       LED_A_ON();\r
-       SetupSpi(SPI_LCD_MODE);\r
-       LOW(GPIO_LRST);\r
-       SpinDelay(100);\r
-\r
-       HIGH(GPIO_LRST);\r
-       SpinDelay(100);\r
-       LED_A_OFF();\r
-}\r
-\r
-void LCDInit(void)\r
-{\r
-       int i;\r
-\r
-       LCDReset();\r
-\r
-       LCDSend(PSWRESET);                      // software reset\r
-       SpinDelay(100);\r
-       LCDSend(PSLEEPOUT);                     // exit sleep mode\r
-       LCDSend(PBSTRON);                       // booster on\r
-       LCDSend(PDISPON);                       // display on\r
-       LCDSend(PNORON);                        // normal on\r
-       LCDSend(PMADCTL);                       // rotate display 180 deg\r
-       LCDSend(0xC0);\r
-\r
-       LCDSend(PCOLMOD);                       // color mode\r
-       LCDSend(0x02);                          // 8bpp color mode\r
-\r
-    LCDSend(PSETCON);                  // set contrast\r
-    LCDSend(0xDC);\r
-    \r
-       // clear display\r
-    LCDSetXY(0,0);\r
-       LCDSend(PRAMWR);                        // Write to display\r
-       i=LCD_XRES*LCD_YRES;\r
-       while(i--) LCDSend(WHITE);\r
-}\r
+#include <proxmark3.h>
+#include "apps.h"
+#include "LCD.h"
+
+void LCDSend(unsigned int data)
+{
+       // 9th bit set for data, clear for command
+       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
+       // 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
+}
+
+void LCDSetXY(unsigned char x, unsigned char y)
+{
+       LCDSend(PPASET);                        // page start/end ram
+       LCDSend(y);                                     // Start Page to display to
+       LCDSend(131);                           // End Page to display to
+
+       LCDSend(PCASET);                        // column start/end ram
+       LCDSend(x);                                     // Start Column to display to
+       LCDSend(131);                           // End Column to display to
+}
+
+void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color)
+{
+       LCDSetXY(x,y);                          // Set position
+       LCDSend(PRAMWR);                        // Now write the pixel to the display
+       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)
+{
+    unsigned char i,j;
+
+    for (i=0;i < height;i++)   // Number of horizontal lines
+    {
+               LCDSetXY(xs,ys+i);              // Goto start of fill area (Top Left)
+               LCDSend(PRAMWR);                // Write to display
+
+               for (j=0;j < width;j++) // pixels per line
+                       LCDSend(color);
+    }
+}
+
+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 char mask=0, px, py, xme, yme, offset;
+       const char *data;
+
+       data = font_style;                      // point to the start of the font table
+
+       xme = *data;                            // get font x width
+       data++;
+       yme = *data;                            // get font y length
+       data++;
+       offset = *data;                         // get data bytes per font
+
+       do
+       {
+               // point to data in table to be loaded
+               data =  (font_style + offset) + (offset * (int)(*lcd_string - 32));
+
+               for (i=0;i < yme;i++) {
+                       mask |=0x80;
+
+                       for (px=x; px < (x + xme); px++) {
+                               py= y + i;
+
+                               if (*data & mask)       LCDSetPixel (px,py,fcolor);
+                               else                            LCDSetPixel (px,py,bcolor);
+
+                               mask>>=1;
+                       }
+                       data++;
+               }
+               x+=xme;
+
+               lcd_string++;                                           // next character in string
+
+       } while(*lcd_string !='\0');                    // keep spitting chars out until end of string
+}
+
+void LCDReset(void)
+{
+       LED_A_ON();
+       SetupSpi(SPI_LCD_MODE);
+       LOW(GPIO_LRST);
+       SpinDelay(100);
+
+       HIGH(GPIO_LRST);
+       SpinDelay(100);
+       LED_A_OFF();
+}
+
+void LCDInit(void)
+{
+       int i;
+
+       LCDReset();
+
+       LCDSend(PSWRESET);                      // software reset
+       SpinDelay(100);
+       LCDSend(PSLEEPOUT);                     // exit sleep mode
+       LCDSend(PBSTRON);                       // booster on
+       LCDSend(PDISPON);                       // display on
+       LCDSend(PNORON);                        // normal on
+       LCDSend(PMADCTL);                       // rotate display 180 deg
+       LCDSend(0xC0);
+
+       LCDSend(PCOLMOD);                       // color mode
+       LCDSend(0x02);                          // 8bpp color mode
+
+    LCDSend(PSETCON);                  // set contrast
+    LCDSend(0xDC);
+    
+       // clear display
+    LCDSetXY(0,0);
+       LCDSend(PRAMWR);                        // Write to display
+       i=LCD_XRES*LCD_YRES;
+       while(i--) LCDSend(WHITE);
+}
index 17b334d190270fbfab602addd8711948a802fde8..ccc94317837d9857194c25fca4759f1d7c6e7fa1 100644 (file)
-#ifndef __LCD\r
-#define __LCD\r
-\r
-// The resolution of the LCD\r
-#define LCD_XRES       132\r
-#define LCD_YRES       132\r
-\r
-// 8bpp Color Mode - Some basic colors defined for ease of use\r
-// remember 8bpp color = 3xRed, 3xGreen & 2xBlue bits\r
-// organised as RRRGGGBB\r
-\r
-#define BLACK          0x00\r
-#define BLUE           0x03\r
-#define GREEN          0x1C\r
-#define CYAN           0x1F\r
-#define RED                    0xE0\r
-#define MAGENTA                0xE3\r
-#define YELLOW         0xFC\r
-#define WHITE          0xFF\r
-\r
-// EPSON LCD command set\r
-#define ECASET         0x115\r
-#define EPWRCTR                0x120\r
-#define ENOP           0x125\r
-#define ERAMWR         0x15C\r
-#define ERAMRD         0x15D\r
-#define EPASET         0x175\r
-#define EEPSRRD1       0x17C\r
-#define EEPSRRD2       0x17D\r
-#define EVOLCTR                0x181\r
-#define ETMPGRD                0x182\r
-#define ESLPOUT                0x194\r
-#define ESLPIN         0x195\r
-#define EDISNOR                0x1A6\r
-#define EDISINV                0x1A7\r
-#define EPTLIN         0x1A8\r
-#define EPTLOUT                0x1A9\r
-#define EASCSET                0x1AA\r
-#define ESCSTART       0x1AB\r
-#define EDISOFF                0x1AE\r
-#define EDISON         0x1AF\r
-#define ECOMSCN                0x1BB\r
-#define EDATCTL                0x1BC\r
-#define EDISCTL                0x1CA\r
-#define EEPCOUT                0x1CC\r
-#define EEPCTIN                0x1CD\r
-#define ERGBSET8       0x1CE\r
-#define EOSCON         0x1D1\r
-#define EOSCOFF                0x1D2\r
-#define EVOLUP         0x1D6\r
-#define EVOLDOWN       0x1D7\r
-#define ERMWIN         0x1E0\r
-#define ERMWOUT                0x1EE\r
-#define EEPMWR         0x1FC\r
-#define EEPMRD         0x1FD\r
-\r
-// PHILIPS LCD command set\r
-#define PNOP           0x100\r
-#define PSWRESET       0x101\r
-#define PBSTROFF       0x102\r
-#define PBSTRON                0x103\r
-#define PRDDIDIF       0x104\r
-#define PRDDST         0x109\r
-#define PSLEEPIN       0x110\r
-#define PSLEEPOUT      0x111\r
-#define PPTLON         0x112\r
-#define PNORON         0x113\r
-#define PINVOFF                0x120\r
-#define PINVON         0x121\r
-#define PDALO          0x122\r
-#define PDAL           0x123\r
-#define PSETCON                0x125\r
-#define PDISPOFF       0x128\r
-#define PDISPON                0x129\r
-#define PCASET         0x12A\r
-#define PPASET         0x12B\r
-#define PRAMWR         0x12C\r
-#define PRGBSET                0x12D\r
-#define PPTLAR         0x130\r
-#define PVSCRDEF       0x133\r
-#define PTEOFF         0x134\r
-#define PTEON          0x135\r
-#define PMADCTL                0x136\r
-#define PSEP           0x137\r
-#define PIDMOFF                0x138\r
-#define PIDMON         0x139\r
-#define PCOLMOD                0x13A\r
-#define PSETVOP                0x1B0\r
-#define PBRS           0x1B4\r
-#define PTRS           0x1B6\r
-#define PFINV          0x1B9\r
-#define PDOR           0x1BA\r
-#define PTCDFE         0x1BD\r
-#define PTCVOPE                0x1BF\r
-#define PEC                    0x1C0\r
-#define PSETMUL                0x1C2\r
-#define PTCVOPAB       0x1C3\r
-#define PTCVOPCD       0x1C4\r
-#define PTCDF          0x1C5\r
-#define PDF8C          0x1C6\r
-#define PSETBS         0x1C7\r
-#define PRDTEMP                0x1C8\r
-#define PNLI           0x1C9\r
-#define PRDID1         0x1DA\r
-#define PRDID2         0x1DB\r
-#define PRDID3         0x1DC\r
-#define PSFD           0x1EF\r
-#define PECM           0x1F0\r
-\r
-void LCDSend(unsigned int data);\r
-void LCDInit(void);\r
-void LCDReset(void);\r
-void LCDSetXY(unsigned char x, unsigned char y);\r
-void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color);\r
-void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor);\r
-void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color);\r
-#endif\r
+#ifndef __LCD
+#define __LCD
+
+// The resolution of the LCD
+#define LCD_XRES       132
+#define LCD_YRES       132
+
+// 8bpp Color Mode - Some basic colors defined for ease of use
+// remember 8bpp color = 3xRed, 3xGreen & 2xBlue bits
+// organised as RRRGGGBB
+
+#define BLACK          0x00
+#define BLUE           0x03
+#define GREEN          0x1C
+#define CYAN           0x1F
+#define RED                    0xE0
+#define MAGENTA                0xE3
+#define YELLOW         0xFC
+#define WHITE          0xFF
+
+// EPSON LCD command set
+#define ECASET         0x115
+#define EPWRCTR                0x120
+#define ENOP           0x125
+#define ERAMWR         0x15C
+#define ERAMRD         0x15D
+#define EPASET         0x175
+#define EEPSRRD1       0x17C
+#define EEPSRRD2       0x17D
+#define EVOLCTR                0x181
+#define ETMPGRD                0x182
+#define ESLPOUT                0x194
+#define ESLPIN         0x195
+#define EDISNOR                0x1A6
+#define EDISINV                0x1A7
+#define EPTLIN         0x1A8
+#define EPTLOUT                0x1A9
+#define EASCSET                0x1AA
+#define ESCSTART       0x1AB
+#define EDISOFF                0x1AE
+#define EDISON         0x1AF
+#define ECOMSCN                0x1BB
+#define EDATCTL                0x1BC
+#define EDISCTL                0x1CA
+#define EEPCOUT                0x1CC
+#define EEPCTIN                0x1CD
+#define ERGBSET8       0x1CE
+#define EOSCON         0x1D1
+#define EOSCOFF                0x1D2
+#define EVOLUP         0x1D6
+#define EVOLDOWN       0x1D7
+#define ERMWIN         0x1E0
+#define ERMWOUT                0x1EE
+#define EEPMWR         0x1FC
+#define EEPMRD         0x1FD
+
+// PHILIPS LCD command set
+#define PNOP           0x100
+#define PSWRESET       0x101
+#define PBSTROFF       0x102
+#define PBSTRON                0x103
+#define PRDDIDIF       0x104
+#define PRDDST         0x109
+#define PSLEEPIN       0x110
+#define PSLEEPOUT      0x111
+#define PPTLON         0x112
+#define PNORON         0x113
+#define PINVOFF                0x120
+#define PINVON         0x121
+#define PDALO          0x122
+#define PDAL           0x123
+#define PSETCON                0x125
+#define PDISPOFF       0x128
+#define PDISPON                0x129
+#define PCASET         0x12A
+#define PPASET         0x12B
+#define PRAMWR         0x12C
+#define PRGBSET                0x12D
+#define PPTLAR         0x130
+#define PVSCRDEF       0x133
+#define PTEOFF         0x134
+#define PTEON          0x135
+#define PMADCTL                0x136
+#define PSEP           0x137
+#define PIDMOFF                0x138
+#define PIDMON         0x139
+#define PCOLMOD                0x13A
+#define PSETVOP                0x1B0
+#define PBRS           0x1B4
+#define PTRS           0x1B6
+#define PFINV          0x1B9
+#define PDOR           0x1BA
+#define PTCDFE         0x1BD
+#define PTCVOPE                0x1BF
+#define PEC                    0x1C0
+#define PSETMUL                0x1C2
+#define PTCVOPAB       0x1C3
+#define PTCVOPCD       0x1C4
+#define PTCDF          0x1C5
+#define PDF8C          0x1C6
+#define PSETBS         0x1C7
+#define PRDTEMP                0x1C8
+#define PNLI           0x1C9
+#define PRDID1         0x1DA
+#define PRDID2         0x1DB
+#define PRDID3         0x1DC
+#define PSFD           0x1EF
+#define PECM           0x1F0
+
+void LCDSend(unsigned int data);
+void LCDInit(void);
+void LCDReset(void);
+void LCDSetXY(unsigned char x, unsigned char y);
+void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color);
+void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor);
+void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color);
+#endif
index 2614b9e9735898d3c7901463c7d2c8edefc0c65d..0aa4ea6b7295255eb5ceda041290bf822378b2d1 100644 (file)
@@ -1,70 +1,70 @@
-# Makefile for armsrc, see ../common/Makefile.common for common settings\r
-\r
-APP_INCLUDES = apps.h\r
-\r
-#remove one of the following defines and comment out the relevant line\r
-#in the next section to remove that particular feature from compilation  \r
-APP_CFLAGS     = -O6 -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b\r
-#-DWITH_LCD \r
-\r
-#SRC_LCD = fonts.c LCD.c\r
-SRC_LF = lfops.c hitag2.c\r
-SRC_ISO15693 = iso15693.c\r
-SRC_ISO14443a = iso14443a.c\r
-SRC_ISO14443b = iso14443.c\r
-\r
-THUMBSRC = start.c \\r
-       $(SRC_LCD) \\r
-       $(SRC_ISO15693) \\r
-       $(SRC_LF) \\r
-       appmain.c printf.c \\r
-       util.c \\r
-       usb.c\r
-\r
-# These are to be compiled in ARM mode\r
-ARMSRC = fpgaloader.c \\r
-       legicrf.c \\r
-       iso14443crc.c \\r
-       crc16.c \\r
-       $(SRC_ISO14443a) \\r
-       $(SRC_ISO14443b) \\r
-        legic_prng.c \\r
-       crc.c\r
-\r
-# stdint.h provided locally until GCC 4.5 becomes C99 compliant\r
-APP_CFLAGS += -I.\r
-\r
-# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC\r
-include ../common/Makefile.common\r
-\r
-all: $(OBJDIR)/osimage.s19 $(OBJDIR)/fpgaimage.s19\r
-\r
-$(OBJDIR)/fpga.o: fpga.bit\r
-       $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_bit_start=_binary_fpga_bit_start --redefine-sym _binary____fpga_fpga_bit_end=_binary_fpga_bit_end --prefix-sections=fpga_bit  $^ $@\r
-\r
-$(OBJDIR)/fullimage.elf: $(VERSIONOBJ) $(OBJDIR)/fpga.o $(THUMBOBJ) $(ARMOBJ) $(LIBGCC)\r
-       $(LD) -g -Tldscript -Map=$(patsubst %.elf,%.map,$@) -o $@ $^\r
-\r
-$(OBJDIR)/fpgaimage.elf: $(OBJDIR)/fullimage.elf\r
-       $(OBJCOPY) -F elf32-littlearm --only-section .fpgaimage $^ $@  \r
-\r
-$(OBJDIR)/osimage.elf: $(OBJDIR)/fullimage.elf\r
-       $(OBJCOPY) -F elf32-littlearm --remove-section .fpgaimage $^ $@\r
-\r
-clean:\r
-       $(DELETE) $(OBJDIR)$(PATHSEP)*.o\r
-       $(DELETE) $(OBJDIR)$(PATHSEP)*.elf\r
-       $(DELETE) $(OBJDIR)$(PATHSEP)*.s19\r
-       $(DELETE) $(OBJDIR)$(PATHSEP)*.map\r
-       $(DELETE) $(OBJDIR)$(PATHSEP)*.d\r
-       $(DELETE) version.c\r
-\r
-.PHONY: all clean help\r
-help:\r
-       @echo Multi-OS Makefile, you are running on $(DETECTED_OS)\r
-       @echo Possible targets:\r
-       @echo + all               - Make both:\r
-       @echo + $(OBJDIR)/osimage.s19   - The OS image\r
-       @echo + $(OBJDIR)/fpgaimage.s19 - The FPGA image\r
-       @echo + clean             - Clean $(OBJDIR)\r
-\r
+# Makefile for armsrc, see ../common/Makefile.common for common settings
+
+APP_INCLUDES = apps.h
+
+#remove one of the following defines and comment out the relevant line
+#in the next section to remove that particular feature from compilation  
+APP_CFLAGS     = -O6 -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b
+#-DWITH_LCD 
+
+#SRC_LCD = fonts.c LCD.c
+SRC_LF = lfops.c hitag2.c
+SRC_ISO15693 = iso15693.c
+SRC_ISO14443a = iso14443a.c
+SRC_ISO14443b = iso14443.c
+
+THUMBSRC = start.c \
+       $(SRC_LCD) \
+       $(SRC_ISO15693) \
+       $(SRC_LF) \
+       appmain.c printf.c \
+       util.c \
+       usb.c
+
+# These are to be compiled in ARM mode
+ARMSRC = fpgaloader.c \
+       legicrf.c \
+       iso14443crc.c \
+       crc16.c \
+       $(SRC_ISO14443a) \
+       $(SRC_ISO14443b) \
+        legic_prng.c \
+       crc.c
+
+# stdint.h provided locally until GCC 4.5 becomes C99 compliant
+APP_CFLAGS += -I.
+
+# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
+include ../common/Makefile.common
+
+all: $(OBJDIR)/osimage.s19 $(OBJDIR)/fpgaimage.s19
+
+$(OBJDIR)/fpga.o: fpga.bit
+       $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_bit_start=_binary_fpga_bit_start --redefine-sym _binary____fpga_fpga_bit_end=_binary_fpga_bit_end --prefix-sections=fpga_bit  $^ $@
+
+$(OBJDIR)/fullimage.elf: $(VERSIONOBJ) $(OBJDIR)/fpga.o $(THUMBOBJ) $(ARMOBJ) $(LIBGCC)
+       $(LD) -g -Tldscript -Map=$(patsubst %.elf,%.map,$@) -o $@ $^
+
+$(OBJDIR)/fpgaimage.elf: $(OBJDIR)/fullimage.elf
+       $(OBJCOPY) -F elf32-littlearm --only-section .fpgaimage $^ $@  
+
+$(OBJDIR)/osimage.elf: $(OBJDIR)/fullimage.elf
+       $(OBJCOPY) -F elf32-littlearm --remove-section .fpgaimage $^ $@
+
+clean:
+       $(DELETE) $(OBJDIR)$(PATHSEP)*.o
+       $(DELETE) $(OBJDIR)$(PATHSEP)*.elf
+       $(DELETE) $(OBJDIR)$(PATHSEP)*.s19
+       $(DELETE) $(OBJDIR)$(PATHSEP)*.map
+       $(DELETE) $(OBJDIR)$(PATHSEP)*.d
+       $(DELETE) version.c
+
+.PHONY: all clean help
+help:
+       @echo Multi-OS Makefile, you are running on $(DETECTED_OS)
+       @echo Possible targets:
+       @echo + all               - Make both:
+       @echo + $(OBJDIR)/osimage.s19   - The OS image
+       @echo + $(OBJDIR)/fpgaimage.s19 - The FPGA image
+       @echo + clean             - Clean $(OBJDIR)
+
index b517fa6cd36c5fe401d02371bf4018cf2ff03fe1..e5415010e3005817363ecfb5c1642da6d0392b02 100644 (file)
-//-----------------------------------------------------------------------------\r
-// The main application code. This is the first thing called after start.c\r
-// executes.\r
-// Jonathan Westhues, Mar 2006\r
-// Edits by Gerhard de Koning Gans, Sep 2007 (##)\r
-//-----------------------------------------------------------------------------\r
-\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-#include "legicrf.h"\r
-#ifdef WITH_LCD\r
-#include "fonts.h"\r
-#include "LCD.h"\r
-#endif\r
-\r
-#define va_list __builtin_va_list\r
-#define va_start __builtin_va_start\r
-#define va_arg __builtin_va_arg\r
-#define va_end __builtin_va_end\r
-int kvsprintf(char const *fmt, void *arg, int radix, va_list ap);\r
-       \r
-\r
-#define abs(x) ( ((x)<0) ? -(x) : (x) )\r
-\r
-//=============================================================================\r
-// A buffer where we can queue things up to be sent through the FPGA, for\r
-// any purpose (fake tag, as reader, whatever). We go MSB first, since that\r
-// is the order in which they go out on the wire.\r
-//=============================================================================\r
-\r
-BYTE ToSend[512];\r
-int ToSendMax;\r
-static int ToSendBit;\r
-struct common_area common_area __attribute__((section(".commonarea")));\r
-\r
-void BufferClear(void)\r
-{\r
-       memset(BigBuf,0,sizeof(BigBuf));\r
-       Dbprintf("Buffer cleared (%i bytes)",sizeof(BigBuf));\r
-}\r
-\r
-void ToSendReset(void)\r
-{\r
-       ToSendMax = -1;\r
-       ToSendBit = 8;\r
-}\r
-\r
-void ToSendStuffBit(int b)\r
-{\r
-       if(ToSendBit >= 8) {\r
-               ToSendMax++;\r
-               ToSend[ToSendMax] = 0;\r
-               ToSendBit = 0;\r
-       }\r
-\r
-       if(b) {\r
-               ToSend[ToSendMax] |= (1 << (7 - ToSendBit));\r
-       }\r
-\r
-       ToSendBit++;\r
-\r
-       if(ToSendBit >= sizeof(ToSend)) {\r
-               ToSendBit = 0;\r
-               DbpString("ToSendStuffBit overflowed!");\r
-       }\r
-}\r
-\r
-//=============================================================================\r
-// Debug print functions, to go out over USB, to the usual PC-side client.\r
-//=============================================================================\r
-\r
-void DbpString(char *str)\r
-{\r
-       /* this holds up stuff unless we're connected to usb */\r
-       if (!UsbConnected())\r
-               return;\r
-\r
-       UsbCommand c;\r
-       c.cmd = CMD_DEBUG_PRINT_STRING;\r
-       c.arg[0] = strlen(str);\r
-       if(c.arg[0] > sizeof(c.d.asBytes)) {\r
-               c.arg[0] = sizeof(c.d.asBytes);\r
-       }\r
-       memcpy(c.d.asBytes, str, c.arg[0]);\r
-\r
-       UsbSendPacket((BYTE *)&c, sizeof(c));\r
-       // TODO fix USB so stupid things like this aren't req'd\r
-       SpinDelay(50);\r
-}\r
-\r
-#if 0\r
-void DbpIntegers(int x1, int x2, int x3)\r
-{\r
-       /* this holds up stuff unless we're connected to usb */\r
-       if (!UsbConnected())\r
-               return;\r
-\r
-       UsbCommand c;\r
-       c.cmd = CMD_DEBUG_PRINT_INTEGERS;\r
-       c.arg[0] = x1;\r
-       c.arg[1] = x2;\r
-       c.arg[2] = x3;\r
-\r
-       UsbSendPacket((BYTE *)&c, sizeof(c));\r
-       // XXX\r
-       SpinDelay(50);\r
-}\r
-#endif\r
-\r
-void Dbprintf(const char *fmt, ...) {\r
-// should probably limit size here; oh well, let's just use a big buffer\r
-       char output_string[128];\r
-       va_list ap;\r
-\r
-       va_start(ap, fmt);\r
-       kvsprintf(fmt, output_string, 10, ap);\r
-       va_end(ap);\r
\r
-       DbpString(output_string);\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Read an ADC channel and block till it completes, then return the result\r
-// in ADC units (0 to 1023). Also a routine to average 32 samples and\r
-// return that.\r
-//-----------------------------------------------------------------------------\r
-static int ReadAdc(int ch)\r
-{\r
-       DWORD d;\r
-\r
-       AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;\r
-       AT91C_BASE_ADC->ADC_MR =\r
-               ADC_MODE_PRESCALE(32) |\r
-               ADC_MODE_STARTUP_TIME(16) |\r
-               ADC_MODE_SAMPLE_HOLD_TIME(8);\r
-       AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch);\r
-\r
-       AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;\r
-       while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch)))\r
-               ;\r
-       d = AT91C_BASE_ADC->ADC_CDR[ch];\r
-\r
-       return d;\r
-}\r
-\r
-static int AvgAdc(int ch)\r
-{\r
-       int i;\r
-       int a = 0;\r
-\r
-       for(i = 0; i < 32; i++) {\r
-               a += ReadAdc(ch);\r
-       }\r
-\r
-       return (a + 15) >> 5;\r
-}\r
-\r
-void MeasureAntennaTuning(void)\r
-{\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int i, ptr = 0, adcval = 0, peak = 0, peakv = 0, peakf = 0;;\r
-       int vLf125 = 0, vLf134 = 0, vHf = 0;    // in mV\r
-\r
-       UsbCommand c;\r
-\r
-       DbpString("Measuring antenna characteristics, please wait.");\r
-       memset(BigBuf,0,sizeof(BigBuf));\r
-\r
-/*\r
- * Sweeps the useful LF range of the proxmark from\r
- * 46.8kHz (divisor=255) to 600kHz (divisor=19) and\r
- * read the voltage in the antenna, the result left\r
- * in the buffer is a graph which should clearly show\r
- * the resonating frequency of your LF antenna\r
- * ( hopefully around 95 if it is tuned to 125kHz!)\r
- */\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
-       for (i=255; i>19; i--) {\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);\r
-               SpinDelay(20);\r
-               // Vref = 3.3V, and a 10000:240 voltage divider on the input\r
-               // can measure voltages up to 137500 mV\r
-               adcval = ((137500 * AvgAdc(ADC_CHAN_LF)) >> 10);\r
-               if (i==95)      vLf125 = adcval; // voltage at 125Khz\r
-               if (i==89)      vLf134 = adcval; // voltage at 134Khz\r
-\r
-               dest[i] = adcval>>8; // scale int to fit in byte for graphing purposes\r
-               if(dest[i] > peak) {\r
-                       peakv = adcval;\r
-                       peak = dest[i];\r
-                       peakf = i;\r
-                       ptr = i;\r
-               }\r
-       }\r
-\r
-       // Let the FPGA drive the high-frequency antenna around 13.56 MHz.\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-       SpinDelay(20);\r
-       // Vref = 3300mV, and an 10:1 voltage divider on the input\r
-       // can measure voltages up to 33000 mV\r
-       vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;\r
-\r
-       c.cmd = CMD_MEASURED_ANTENNA_TUNING;\r
-       c.arg[0] = (vLf125 << 0) | (vLf134 << 16);\r
-       c.arg[1] = vHf;\r
-       c.arg[2] = peakf | (peakv << 16);\r
-       UsbSendPacket((BYTE *)&c, sizeof(c));\r
-}\r
-\r
-void MeasureAntennaTuningHf(void)\r
-{\r
-       int vHf = 0;    // in mV\r
-\r
-       DbpString("Measuring HF antenna, press button to exit");\r
-\r
-       for (;;) {\r
-               // Let the FPGA drive the high-frequency antenna around 13.56 MHz.\r
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-               SpinDelay(20);\r
-               // Vref = 3300mV, and an 10:1 voltage divider on the input\r
-               // can measure voltages up to 33000 mV\r
-               vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;\r
-       \r
-               Dbprintf("%d mV",vHf);\r
-               if (BUTTON_PRESS()) break;\r
-       }\r
-       DbpString("cancelled");\r
-}\r
-\r
-\r
-void SimulateTagHfListen(void)\r
-{\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int n = sizeof(BigBuf);\r
-       BYTE v = 0;\r
-       int i;\r
-       int p = 0;\r
-\r
-       // We're using this mode just so that I can test it out; the simulated\r
-       // tag mode would work just as well and be simpler.\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);\r
-\r
-       // We need to listen to the high-frequency, peak-detected path.\r
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-\r
-       FpgaSetupSsc();\r
-\r
-       i = 0;\r
-       for(;;) {\r
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-                       AT91C_BASE_SSC->SSC_THR = 0xff;\r
-               }\r
-               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-                       BYTE r = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
-\r
-                       v <<= 1;\r
-                       if(r & 1) {\r
-                               v |= 1;\r
-                       }\r
-                       p++;\r
-\r
-                       if(p >= 8) {\r
-                               dest[i] = v;\r
-                               v = 0;\r
-                               p = 0;\r
-                               i++;\r
-\r
-                               if(i >= n) {\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-       DbpString("simulate tag (now type bitsamples)");\r
-}\r
-\r
-void ReadMem(int addr)\r
-{\r
-       const BYTE *data = ((BYTE *)addr);\r
-\r
-       Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x",\r
-               addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);\r
-}\r
-\r
-/* osimage version information is linked in */\r
-extern struct version_information version_information;\r
-/* bootrom version information is pointed to from _bootphase1_version_pointer */\r
-extern char *_bootphase1_version_pointer, _flash_start, _flash_end;\r
-void SendVersion(void)\r
-{\r
-       char temp[48]; /* Limited data payload in USB packets */\r
-       DbpString("Prox/RFID mark3 RFID instrument");\r
-       \r
-       /* Try to find the bootrom version information. Expect to find a pointer at \r
-        * symbol _bootphase1_version_pointer, perform slight sanity checks on the\r
-        * pointer, then use it.\r
-        */\r
-       char *bootrom_version = *(char**)&_bootphase1_version_pointer;\r
-       if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {\r
-               DbpString("bootrom version information appears invalid");\r
-       } else {\r
-               FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);\r
-               DbpString(temp);\r
-       }\r
-       \r
-       FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);\r
-       DbpString(temp);\r
-       \r
-       FpgaGatherVersion(temp, sizeof(temp));\r
-       DbpString(temp);\r
-}\r
-\r
-#ifdef WITH_LF\r
-// samy's sniff and repeat routine\r
-void SamyRun()\r
-{\r
-       DbpString("Stand-alone mode! No PC necessary.");\r
-\r
-       // 3 possible options? no just 2 for now\r
-#define OPTS 2\r
-\r
-       int high[OPTS], low[OPTS];\r
-\r
-       // Oooh pretty -- notify user we're in elite samy mode now\r
-       LED(LED_RED,    200);\r
-       LED(LED_ORANGE, 200);\r
-       LED(LED_GREEN,  200);\r
-       LED(LED_ORANGE, 200);\r
-       LED(LED_RED,    200);\r
-       LED(LED_ORANGE, 200);\r
-       LED(LED_GREEN,  200);\r
-       LED(LED_ORANGE, 200);\r
-       LED(LED_RED,    200);\r
-\r
-       int selected = 0;\r
-       int playing = 0;\r
-\r
-       // Turn on selected LED\r
-       LED(selected + 1, 0);\r
-\r
-       for (;;)\r
-       {\r
-               UsbPoll(FALSE);\r
-               WDT_HIT();\r
-\r
-               // Was our button held down or pressed?\r
-               int button_pressed = BUTTON_HELD(1000);\r
-               SpinDelay(300);\r
-\r
-               // Button was held for a second, begin recording\r
-               if (button_pressed > 0)\r
-               {\r
-                       LEDsoff();\r
-                       LED(selected + 1, 0);\r
-                       LED(LED_RED2, 0);\r
-\r
-                       // record\r
-                       DbpString("Starting recording");\r
-\r
-                       // wait for button to be released\r
-                       while(BUTTON_PRESS())\r
-                               WDT_HIT();\r
-\r
-                       /* need this delay to prevent catching some weird data */\r
-                       SpinDelay(500);\r
-\r
-                       CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);\r
-                       Dbprintf("Recorded %x %x %x", selected, high[selected], low[selected]);\r
-\r
-                       LEDsoff();\r
-                       LED(selected + 1, 0);\r
-                       // Finished recording\r
-\r
-                       // If we were previously playing, set playing off\r
-                       // so next button push begins playing what we recorded\r
-                       playing = 0;\r
-               }\r
-\r
-               // Change where to record (or begin playing)\r
-               else if (button_pressed)\r
-               {\r
-                       // Next option if we were previously playing\r
-                       if (playing)\r
-                               selected = (selected + 1) % OPTS;\r
-                       playing = !playing;\r
-\r
-                       LEDsoff();\r
-                       LED(selected + 1, 0);\r
-\r
-                       // Begin transmitting\r
-                       if (playing)\r
-                       {\r
-                               LED(LED_GREEN, 0);\r
-                               DbpString("Playing");\r
-                               // wait for button to be released\r
-                               while(BUTTON_PRESS())\r
-                                       WDT_HIT();\r
-                               Dbprintf("%x %x %x", selected, high[selected], low[selected]);\r
-                               CmdHIDsimTAG(high[selected], low[selected], 0);\r
-                               DbpString("Done playing");\r
-                               if (BUTTON_HELD(1000) > 0)\r
-                                       {\r
-                                       DbpString("Exiting");\r
-                                       LEDsoff();\r
-                                       return;\r
-                                       }\r
-\r
-                               /* We pressed a button so ignore it here with a delay */\r
-                               SpinDelay(300);\r
-\r
-                               // when done, we're done playing, move to next option\r
-                               selected = (selected + 1) % OPTS;\r
-                               playing = !playing;\r
-                               LEDsoff();\r
-                               LED(selected + 1, 0);\r
-                       }\r
-                       else\r
-                               while(BUTTON_PRESS())\r
-                                       WDT_HIT();\r
-               }\r
-       }\r
-}\r
-#endif\r
-\r
-/*\r
-OBJECTIVE\r
-Listen and detect an external reader. Determine the best location\r
-for the antenna.\r
-\r
-INSTRUCTIONS:\r
-Inside the ListenReaderField() function, there is two mode.\r
-By default, when you call the function, you will enter mode 1.\r
-If you press the PM3 button one time, you will enter mode 2.\r
-If you press the PM3 button a second time, you will exit the function.\r
-\r
-DESCRIPTION OF MODE 1:\r
-This mode just listens for an external reader field and lights up green\r
-for HF and/or red for LF. This is the original mode of the detectreader\r
-function.\r
-\r
-DESCRIPTION OF MODE 2:\r
-This mode will visually represent, using the LEDs, the actual strength of the\r
-current compared to the maximum current detected. Basically, once you know\r
-what kind of external reader is present, it will help you spot the best location to place\r
-your antenna. You will probably not get some good results if there is a LF and a HF reader\r
-at the same place! :-)\r
-\r
-LIGHT SCHEME USED:\r
-*/\r
-static const char LIGHT_SCHEME[] = {\r
-               0x0, /* ----     | No field detected */\r
-               0x1, /* X---     | 14% of maximum current detected */\r
-               0x2, /* -X--     | 29% of maximum current detected */\r
-               0x4, /* --X-     | 43% of maximum current detected */\r
-               0x8, /* ---X     | 57% of maximum current detected */\r
-               0xC, /* --XX     | 71% of maximum current detected */\r
-               0xE, /* -XXX     | 86% of maximum current detected */\r
-               0xF, /* XXXX     | 100% of maximum current detected */\r
-};\r
-static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);\r
-\r
-void ListenReaderField(int limit)\r
-{\r
-       int lf_av, lf_av_new, lf_baseline= 0, lf_count= 0, lf_max;\r
-       int hf_av, hf_av_new,  hf_baseline= 0, hf_count= 0, hf_max;\r
-       int mode=1, display_val, display_max, i;\r
-\r
-#define LF_ONLY                1\r
-#define HF_ONLY                2\r
-\r
-       LEDsoff();\r
-\r
-       lf_av=lf_max=ReadAdc(ADC_CHAN_LF);\r
-\r
-       if(limit != HF_ONLY) {\r
-               Dbprintf("LF 125/134 Baseline: %d", lf_av);\r
-               lf_baseline = lf_av;\r
-       }\r
-\r
-       hf_av=hf_max=ReadAdc(ADC_CHAN_HF);\r
-\r
-       if (limit != LF_ONLY) {\r
-               Dbprintf("HF 13.56 Baseline: %d", hf_av);\r
-               hf_baseline = hf_av;\r
-       }\r
-\r
-       for(;;) {\r
-               if (BUTTON_PRESS()) {\r
-                       SpinDelay(500);\r
-                       switch (mode) {\r
-                               case 1:\r
-                                       mode=2;\r
-                                       DbpString("Signal Strength Mode");\r
-                                       break;\r
-                               case 2:\r
-                               default:\r
-                                       DbpString("Stopped");\r
-                                       LEDsoff();\r
-                                       return;\r
-                                       break;\r
-                       }\r
-               }\r
-               WDT_HIT();\r
-\r
-               if (limit != HF_ONLY) {\r
-                       if(mode==1) {\r
-                               if (abs(lf_av - lf_baseline) > 10) LED_D_ON();\r
-                               else                               LED_D_OFF();\r
-                       }\r
-                       \r
-                       ++lf_count;\r
-                       lf_av_new= ReadAdc(ADC_CHAN_LF);\r
-                       // see if there's a significant change\r
-                       if(abs(lf_av - lf_av_new) > 10) {\r
-                               Dbprintf("LF 125/134 Field Change: %x %x %x", lf_av, lf_av_new, lf_count);\r
-                               lf_av = lf_av_new;\r
-                               if (lf_av > lf_max)\r
-                                       lf_max = lf_av;\r
-                               lf_count= 0;\r
-                       }\r
-               }\r
-\r
-               if (limit != LF_ONLY) {\r
-                       if (mode == 1){\r
-                               if (abs(hf_av - hf_baseline) > 10) LED_B_ON();\r
-                               else                               LED_B_OFF();\r
-                       }\r
-                       \r
-                       ++hf_count;\r
-                       hf_av_new= ReadAdc(ADC_CHAN_HF);\r
-                       // see if there's a significant change\r
-                       if(abs(hf_av - hf_av_new) > 10) {\r
-                               Dbprintf("HF 13.56 Field Change: %x %x %x", hf_av, hf_av_new, hf_count);\r
-                               hf_av = hf_av_new;\r
-                               if (hf_av > hf_max)\r
-                                       hf_max = hf_av;\r
-                               hf_count= 0;\r
-                       }\r
-               }\r
-               \r
-               if(mode == 2) {\r
-                       if (limit == LF_ONLY) {\r
-                               display_val = lf_av;\r
-                               display_max = lf_max;\r
-                       } else if (limit == HF_ONLY) {\r
-                               display_val = hf_av;\r
-                               display_max = hf_max;\r
-                       } else { /* Pick one at random */\r
-                               if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) {\r
-                                       display_val = hf_av;\r
-                                       display_max = hf_max;\r
-                               } else {\r
-                                       display_val = lf_av;\r
-                                       display_max = lf_max;\r
-                               }\r
-                       }\r
-                       for (i=0; i<LIGHT_LEN; i++) {\r
-                               if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) {\r
-                                       if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF();\r
-                                       if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF();\r
-                                       if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF();\r
-                                       if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF();\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-void UsbPacketReceived(BYTE *packet, int len)\r
-{\r
-       UsbCommand *c = (UsbCommand *)packet;\r
-       UsbCommand ack;\r
-       ack.cmd = CMD_ACK;\r
-\r
-       switch(c->cmd) {\r
-#ifdef WITH_LF\r
-               case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
-                       AcquireRawAdcSamples125k(c->arg[0]);\r
-                       UsbSendPacket((BYTE*)&ack, sizeof(ack));\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_LF\r
-               case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:\r
-                       ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_ISO15693\r
-               case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:\r
-                       AcquireRawAdcSamplesIso15693();\r
-                       break;\r
-#endif\r
-\r
-               case CMD_BUFF_CLEAR:\r
-                       BufferClear();\r
-                       break;\r
-\r
-#ifdef WITH_ISO15693\r
-               case CMD_READER_ISO_15693:\r
-                       ReaderIso15693(c->arg[0]);\r
-                       break;\r
-#endif\r
-\r
-               case CMD_READER_LEGIC_RF:\r
-                       LegicRfReader(c->arg[0], c->arg[1]);\r
-                       break;
-\r
-#ifdef WITH_ISO15693\r
-               case CMD_SIMTAG_ISO_15693:\r
-                       SimTagIso15693(c->arg[0]);\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_ISO14443b\r
-               case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:\r
-                       AcquireRawAdcSamplesIso14443(c->arg[0]);\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_ISO14443b\r
-               case CMD_READ_SRI512_TAG:\r
-                       ReadSRI512Iso14443(c->arg[0]);\r
-                       break;\r
-               case CMD_READ_SRIX4K_TAG:\r
-                       ReadSRIX4KIso14443(c->arg[0]);\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_ISO14443a\r
-               case CMD_READER_ISO_14443a:\r
-                       ReaderIso14443a(c->arg[0]);\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_ISO14443a\r
-               case CMD_READER_MIFARE:\r
-                       ReaderMifare(c->arg[0]);\r
-                       break;\r
-#endif\r
-      \r
-#ifdef WITH_ISO14443b\r
-               case CMD_SNOOP_ISO_14443:\r
-                       SnoopIso14443();\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_ISO14443a\r
-               case CMD_SNOOP_ISO_14443a:\r
-                       SnoopIso14443a();\r
-                       break;\r
-#endif\r
-\r
-               case CMD_SIMULATE_TAG_HF_LISTEN:\r
-                       SimulateTagHfListen();\r
-                       break;\r
-\r
-#ifdef WITH_ISO14443b\r
-               case CMD_SIMULATE_TAG_ISO_14443:\r
-                       SimulateIso14443Tag();\r
-                       break;\r
-#endif\r
-               \r
-#ifdef WITH_ISO14443a\r
-               case CMD_SIMULATE_TAG_ISO_14443a:\r
-                       SimulateIso14443aTag(c->arg[0], c->arg[1]);  // ## Simulate iso14443a tag - pass tag type & UID\r
-                       break;\r
-#endif\r
-\r
-               case CMD_MEASURE_ANTENNA_TUNING:\r
-                       MeasureAntennaTuning();\r
-                       break;\r
-\r
-               case CMD_MEASURE_ANTENNA_TUNING_HF:\r
-                       MeasureAntennaTuningHf();\r
-                       break;\r
-\r
-               case CMD_LISTEN_READER_FIELD:\r
-                       ListenReaderField(c->arg[0]);\r
-                       break;\r
-\r
-#ifdef WITH_LF\r
-               case CMD_HID_DEMOD_FSK:\r
-                       CmdHIDdemodFSK(0, 0, 0, 1);                             // Demodulate HID tag\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_LF\r
-               case CMD_HID_SIM_TAG:\r
-                       CmdHIDsimTAG(c->arg[0], c->arg[1], 1);                                  // Simulate HID tag by ID\r
-                       break;\r
-#endif\r
-\r
-               case CMD_FPGA_MAJOR_MODE_OFF:           // ## FPGA Control\r
-                       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-                       SpinDelay(200);\r
-                       LED_D_OFF(); // LED D indicates field ON or OFF\r
-                       break;\r
-\r
-#ifdef WITH_LF\r
-               case CMD_READ_TI_TYPE:\r
-                       ReadTItag();\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_LF\r
-               case CMD_WRITE_TI_TYPE:\r
-                       WriteTItag(c->arg[0],c->arg[1],c->arg[2]);\r
-                       break;\r
-#endif\r
-\r
-               case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: {\r
-                       UsbCommand n;\r
-                       if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {\r
-                               n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;\r
-                       } else {\r
-                               n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;\r
-                       }\r
-                       n.arg[0] = c->arg[0];\r
-                       memcpy(n.d.asDwords, BigBuf+c->arg[0], 12*sizeof(DWORD));\r
-                       UsbSendPacket((BYTE *)&n, sizeof(n));\r
-                       break;\r
-               }\r
-\r
-               case CMD_DOWNLOADED_SIM_SAMPLES_125K: {\r
-                       BYTE *b = (BYTE *)BigBuf;\r
-                       memcpy(b+c->arg[0], c->d.asBytes, 48);\r
-                       //Dbprintf("copied 48 bytes to %i",b+c->arg[0]);\r
-                       UsbSendPacket((BYTE*)&ack, sizeof(ack));\r
-                       break;\r
-               }\r
-\r
-#ifdef WITH_LF\r
-               case CMD_SIMULATE_TAG_125K:\r
-                       LED_A_ON();\r
-                       SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);\r
-                       LED_A_OFF();\r
-                       break;\r
-#endif\r
-\r
-               case CMD_READ_MEM:\r
-                       ReadMem(c->arg[0]);\r
-                       break;\r
-\r
-               case CMD_SET_LF_DIVISOR:\r
-                       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);\r
-                       break;\r
-\r
-               case CMD_SET_ADC_MUX:\r
-                       switch(c->arg[0]) {\r
-                               case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;\r
-                               case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;\r
-                               case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;\r
-                               case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;\r
-                       }\r
-                       break;\r
-\r
-               case CMD_VERSION:\r
-                       SendVersion();\r
-                       break;\r
-\r
-#ifdef WITH_LF\r
-               case CMD_LF_SIMULATE_BIDIR:\r
-                       SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);\r
-                       break;\r
-#endif\r
-\r
-#ifdef WITH_LCD\r
-               case CMD_LCD_RESET:\r
-                       LCDReset();\r
-                       break;\r
-               case CMD_LCD:\r
-                       LCDSend(c->arg[0]);\r
-                       break;\r
-#endif\r
-               case CMD_SETUP_WRITE:\r
-               case CMD_FINISH_WRITE:\r
-               case CMD_HARDWARE_RESET:\r
-                       USB_D_PLUS_PULLUP_OFF();\r
-                       SpinDelay(1000);\r
-                       SpinDelay(1000);\r
-                       AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
-                       for(;;) {\r
-                               // We're going to reset, and the bootrom will take control.\r
-                       }\r
-                       break;\r
-\r
-               case CMD_START_FLASH:\r
-                       if(common_area.flags.bootrom_present) {\r
-                               common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;\r
-                       }\r
-                       USB_D_PLUS_PULLUP_OFF();\r
-                       AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
-                       for(;;);\r
-                       break;\r
-                       \r
-               case CMD_DEVICE_INFO: {\r
-                       UsbCommand c;\r
-                       c.cmd = CMD_DEVICE_INFO;\r
-                       c.arg[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;\r
-                       if(common_area.flags.bootrom_present) c.arg[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;\r
-                       UsbSendPacket((BYTE*)&c, sizeof(c));\r
-               }\r
-                       break;\r
-               default:\r
-                       Dbprintf("%s: 0x%04x","unknown command:",c->cmd);\r
-                       break;\r
-       }\r
-}\r
-\r
-void  __attribute__((noreturn)) AppMain(void)\r
-{\r
-       SpinDelay(100);\r
-       \r
-       if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {\r
-               /* Initialize common area */\r
-               memset(&common_area, 0, sizeof(common_area));\r
-               common_area.magic = COMMON_AREA_MAGIC;\r
-               common_area.version = 1;\r
-       }\r
-       common_area.flags.osimage_present = 1;\r
-\r
-       LED_D_OFF();\r
-       LED_C_OFF();\r
-       LED_B_OFF();\r
-       LED_A_OFF();\r
-\r
-       UsbStart();\r
-\r
-       // The FPGA gets its clock from us from PCK0 output, so set that up.\r
-       AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;\r
-       AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;\r
-       AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;\r
-       // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz\r
-       AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |\r
-               AT91C_PMC_PRES_CLK_4;\r
-       AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;\r
-\r
-       // Reset SPI\r
-       AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;\r
-       // Reset SSC\r
-       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
-\r
-       // Load the FPGA image, which we have stored in our flash.\r
-       FpgaDownloadAndGo();\r
-\r
-#ifdef WITH_LCD\r
-\r
-       LCDInit();\r
-\r
-       // test text on different colored backgrounds\r
-       LCDString(" The quick brown fox  ",     (char *)&FONT6x8,1,1+8*0,WHITE  ,BLACK );\r
-       LCDString("  jumped over the     ",     (char *)&FONT6x8,1,1+8*1,BLACK  ,WHITE );\r
-       LCDString("     lazy dog.        ",     (char *)&FONT6x8,1,1+8*2,YELLOW ,RED   );\r
-       LCDString(" AaBbCcDdEeFfGgHhIiJj ",     (char *)&FONT6x8,1,1+8*3,RED    ,GREEN );\r
-       LCDString(" KkLlMmNnOoPpQqRrSsTt ",     (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE  );\r
-       LCDString("UuVvWwXxYyZz0123456789",     (char *)&FONT6x8,1,1+8*5,BLUE   ,YELLOW);\r
-       LCDString("`-=[]_;',./~!@#$%^&*()",     (char *)&FONT6x8,1,1+8*6,BLACK  ,CYAN  );\r
-       LCDString("     _+{}|:\\\"<>?     ",(char *)&FONT6x8,1,1+8*7,BLUE  ,MAGENTA);\r
-\r
-       // color bands\r
-       LCDFill(0, 1+8* 8, 132, 8, BLACK);\r
-       LCDFill(0, 1+8* 9, 132, 8, WHITE);\r
-       LCDFill(0, 1+8*10, 132, 8, RED);\r
-       LCDFill(0, 1+8*11, 132, 8, GREEN);\r
-       LCDFill(0, 1+8*12, 132, 8, BLUE);\r
-       LCDFill(0, 1+8*13, 132, 8, YELLOW);\r
-       LCDFill(0, 1+8*14, 132, 8, CYAN);\r
-       LCDFill(0, 1+8*15, 132, 8, MAGENTA);\r
-\r
-#endif\r
-\r
-       for(;;) {\r
-               UsbPoll(FALSE);\r
-               WDT_HIT();\r
-\r
-#ifdef WITH_LF\r
-               if (BUTTON_HELD(1000) > 0)\r
-                       SamyRun();\r
-#endif\r
-       }\r
-}\r
+//-----------------------------------------------------------------------------
+// The main application code. This is the first thing called after start.c
+// executes.
+// Jonathan Westhues, Mar 2006
+// Edits by Gerhard de Koning Gans, Sep 2007 (##)
+//-----------------------------------------------------------------------------
+
+#include <proxmark3.h>
+#include "apps.h"
+#include "legicrf.h"
+#ifdef WITH_LCD
+#include "fonts.h"
+#include "LCD.h"
+#endif
+
+#define va_list __builtin_va_list
+#define va_start __builtin_va_start
+#define va_arg __builtin_va_arg
+#define va_end __builtin_va_end
+int kvsprintf(char const *fmt, void *arg, int radix, va_list ap);
+       
+
+#define abs(x) ( ((x)<0) ? -(x) : (x) )
+
+//=============================================================================
+// A buffer where we can queue things up to be sent through the FPGA, for
+// any purpose (fake tag, as reader, whatever). We go MSB first, since that
+// is the order in which they go out on the wire.
+//=============================================================================
+
+BYTE ToSend[512];
+int ToSendMax;
+static int ToSendBit;
+struct common_area common_area __attribute__((section(".commonarea")));
+
+void BufferClear(void)
+{
+       memset(BigBuf,0,sizeof(BigBuf));
+       Dbprintf("Buffer cleared (%i bytes)",sizeof(BigBuf));
+}
+
+void ToSendReset(void)
+{
+       ToSendMax = -1;
+       ToSendBit = 8;
+}
+
+void ToSendStuffBit(int b)
+{
+       if(ToSendBit >= 8) {
+               ToSendMax++;
+               ToSend[ToSendMax] = 0;
+               ToSendBit = 0;
+       }
+
+       if(b) {
+               ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
+       }
+
+       ToSendBit++;
+
+       if(ToSendBit >= sizeof(ToSend)) {
+               ToSendBit = 0;
+               DbpString("ToSendStuffBit overflowed!");
+       }
+}
+
+//=============================================================================
+// Debug print functions, to go out over USB, to the usual PC-side client.
+//=============================================================================
+
+void DbpString(char *str)
+{
+       /* this holds up stuff unless we're connected to usb */
+       if (!UsbConnected())
+               return;
+
+       UsbCommand c;
+       c.cmd = CMD_DEBUG_PRINT_STRING;
+       c.arg[0] = strlen(str);
+       if(c.arg[0] > sizeof(c.d.asBytes)) {
+               c.arg[0] = sizeof(c.d.asBytes);
+       }
+       memcpy(c.d.asBytes, str, c.arg[0]);
+
+       UsbSendPacket((BYTE *)&c, sizeof(c));
+       // TODO fix USB so stupid things like this aren't req'd
+       SpinDelay(50);
+}
+
+#if 0
+void DbpIntegers(int x1, int x2, int x3)
+{
+       /* this holds up stuff unless we're connected to usb */
+       if (!UsbConnected())
+               return;
+
+       UsbCommand c;
+       c.cmd = CMD_DEBUG_PRINT_INTEGERS;
+       c.arg[0] = x1;
+       c.arg[1] = x2;
+       c.arg[2] = x3;
+
+       UsbSendPacket((BYTE *)&c, sizeof(c));
+       // XXX
+       SpinDelay(50);
+}
+#endif
+
+void Dbprintf(const char *fmt, ...) {
+// should probably limit size here; oh well, let's just use a big buffer
+       char output_string[128];
+       va_list ap;
+
+       va_start(ap, fmt);
+       kvsprintf(fmt, output_string, 10, ap);
+       va_end(ap);
+       DbpString(output_string);
+}
+
+//-----------------------------------------------------------------------------
+// Read an ADC channel and block till it completes, then return the result
+// in ADC units (0 to 1023). Also a routine to average 32 samples and
+// return that.
+//-----------------------------------------------------------------------------
+static int ReadAdc(int ch)
+{
+       DWORD d;
+
+       AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
+       AT91C_BASE_ADC->ADC_MR =
+               ADC_MODE_PRESCALE(32) |
+               ADC_MODE_STARTUP_TIME(16) |
+               ADC_MODE_SAMPLE_HOLD_TIME(8);
+       AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch);
+
+       AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
+       while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch)))
+               ;
+       d = AT91C_BASE_ADC->ADC_CDR[ch];
+
+       return d;
+}
+
+static int AvgAdc(int ch)
+{
+       int i;
+       int a = 0;
+
+       for(i = 0; i < 32; i++) {
+               a += ReadAdc(ch);
+       }
+
+       return (a + 15) >> 5;
+}
+
+void MeasureAntennaTuning(void)
+{
+       BYTE *dest = (BYTE *)BigBuf;
+       int i, ptr = 0, adcval = 0, peak = 0, peakv = 0, peakf = 0;;
+       int vLf125 = 0, vLf134 = 0, vHf = 0;    // in mV
+
+       UsbCommand c;
+
+       DbpString("Measuring antenna characteristics, please wait.");
+       memset(BigBuf,0,sizeof(BigBuf));
+
+/*
+ * Sweeps the useful LF range of the proxmark from
+ * 46.8kHz (divisor=255) to 600kHz (divisor=19) and
+ * read the voltage in the antenna, the result left
+ * in the buffer is a graph which should clearly show
+ * the resonating frequency of your LF antenna
+ * ( hopefully around 95 if it is tuned to 125kHz!)
+ */
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+       for (i=255; i>19; i--) {
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
+               SpinDelay(20);
+               // Vref = 3.3V, and a 10000:240 voltage divider on the input
+               // can measure voltages up to 137500 mV
+               adcval = ((137500 * AvgAdc(ADC_CHAN_LF)) >> 10);
+               if (i==95)      vLf125 = adcval; // voltage at 125Khz
+               if (i==89)      vLf134 = adcval; // voltage at 134Khz
+
+               dest[i] = adcval>>8; // scale int to fit in byte for graphing purposes
+               if(dest[i] > peak) {
+                       peakv = adcval;
+                       peak = dest[i];
+                       peakf = i;
+                       ptr = i;
+               }
+       }
+
+       // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+       SpinDelay(20);
+       // Vref = 3300mV, and an 10:1 voltage divider on the input
+       // can measure voltages up to 33000 mV
+       vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
+
+       c.cmd = CMD_MEASURED_ANTENNA_TUNING;
+       c.arg[0] = (vLf125 << 0) | (vLf134 << 16);
+       c.arg[1] = vHf;
+       c.arg[2] = peakf | (peakv << 16);
+       UsbSendPacket((BYTE *)&c, sizeof(c));
+}
+
+void MeasureAntennaTuningHf(void)
+{
+       int vHf = 0;    // in mV
+
+       DbpString("Measuring HF antenna, press button to exit");
+
+       for (;;) {
+               // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+               SpinDelay(20);
+               // Vref = 3300mV, and an 10:1 voltage divider on the input
+               // can measure voltages up to 33000 mV
+               vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
+       
+               Dbprintf("%d mV",vHf);
+               if (BUTTON_PRESS()) break;
+       }
+       DbpString("cancelled");
+}
+
+
+void SimulateTagHfListen(void)
+{
+       BYTE *dest = (BYTE *)BigBuf;
+       int n = sizeof(BigBuf);
+       BYTE v = 0;
+       int i;
+       int p = 0;
+
+       // We're using this mode just so that I can test it out; the simulated
+       // tag mode would work just as well and be simpler.
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
+
+       // We need to listen to the high-frequency, peak-detected path.
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+       FpgaSetupSsc();
+
+       i = 0;
+       for(;;) {
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                       AT91C_BASE_SSC->SSC_THR = 0xff;
+               }
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       BYTE r = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+
+                       v <<= 1;
+                       if(r & 1) {
+                               v |= 1;
+                       }
+                       p++;
+
+                       if(p >= 8) {
+                               dest[i] = v;
+                               v = 0;
+                               p = 0;
+                               i++;
+
+                               if(i >= n) {
+                                       break;
+                               }
+                       }
+               }
+       }
+       DbpString("simulate tag (now type bitsamples)");
+}
+
+void ReadMem(int addr)
+{
+       const BYTE *data = ((BYTE *)addr);
+
+       Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x",
+               addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+}
+
+/* osimage version information is linked in */
+extern struct version_information version_information;
+/* bootrom version information is pointed to from _bootphase1_version_pointer */
+extern char *_bootphase1_version_pointer, _flash_start, _flash_end;
+void SendVersion(void)
+{
+       char temp[48]; /* Limited data payload in USB packets */
+       DbpString("Prox/RFID mark3 RFID instrument");
+       
+       /* Try to find the bootrom version information. Expect to find a pointer at 
+        * symbol _bootphase1_version_pointer, perform slight sanity checks on the
+        * pointer, then use it.
+        */
+       char *bootrom_version = *(char**)&_bootphase1_version_pointer;
+       if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {
+               DbpString("bootrom version information appears invalid");
+       } else {
+               FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);
+               DbpString(temp);
+       }
+       
+       FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
+       DbpString(temp);
+       
+       FpgaGatherVersion(temp, sizeof(temp));
+       DbpString(temp);
+}
+
+#ifdef WITH_LF
+// samy's sniff and repeat routine
+void SamyRun()
+{
+       DbpString("Stand-alone mode! No PC necessary.");
+
+       // 3 possible options? no just 2 for now
+#define OPTS 2
+
+       int high[OPTS], low[OPTS];
+
+       // Oooh pretty -- notify user we're in elite samy mode now
+       LED(LED_RED,    200);
+       LED(LED_ORANGE, 200);
+       LED(LED_GREEN,  200);
+       LED(LED_ORANGE, 200);
+       LED(LED_RED,    200);
+       LED(LED_ORANGE, 200);
+       LED(LED_GREEN,  200);
+       LED(LED_ORANGE, 200);
+       LED(LED_RED,    200);
+
+       int selected = 0;
+       int playing = 0;
+
+       // Turn on selected LED
+       LED(selected + 1, 0);
+
+       for (;;)
+       {
+               UsbPoll(FALSE);
+               WDT_HIT();
+
+               // Was our button held down or pressed?
+               int button_pressed = BUTTON_HELD(1000);
+               SpinDelay(300);
+
+               // Button was held for a second, begin recording
+               if (button_pressed > 0)
+               {
+                       LEDsoff();
+                       LED(selected + 1, 0);
+                       LED(LED_RED2, 0);
+
+                       // record
+                       DbpString("Starting recording");
+
+                       // wait for button to be released
+                       while(BUTTON_PRESS())
+                               WDT_HIT();
+
+                       /* need this delay to prevent catching some weird data */
+                       SpinDelay(500);
+
+                       CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
+                       Dbprintf("Recorded %x %x %x", selected, high[selected], low[selected]);
+
+                       LEDsoff();
+                       LED(selected + 1, 0);
+                       // Finished recording
+
+                       // If we were previously playing, set playing off
+                       // so next button push begins playing what we recorded
+                       playing = 0;
+               }
+
+               // Change where to record (or begin playing)
+               else if (button_pressed)
+               {
+                       // Next option if we were previously playing
+                       if (playing)
+                               selected = (selected + 1) % OPTS;
+                       playing = !playing;
+
+                       LEDsoff();
+                       LED(selected + 1, 0);
+
+                       // Begin transmitting
+                       if (playing)
+                       {
+                               LED(LED_GREEN, 0);
+                               DbpString("Playing");
+                               // wait for button to be released
+                               while(BUTTON_PRESS())
+                                       WDT_HIT();
+                               Dbprintf("%x %x %x", selected, high[selected], low[selected]);
+                               CmdHIDsimTAG(high[selected], low[selected], 0);
+                               DbpString("Done playing");
+                               if (BUTTON_HELD(1000) > 0)
+                                       {
+                                       DbpString("Exiting");
+                                       LEDsoff();
+                                       return;
+                                       }
+
+                               /* We pressed a button so ignore it here with a delay */
+                               SpinDelay(300);
+
+                               // when done, we're done playing, move to next option
+                               selected = (selected + 1) % OPTS;
+                               playing = !playing;
+                               LEDsoff();
+                               LED(selected + 1, 0);
+                       }
+                       else
+                               while(BUTTON_PRESS())
+                                       WDT_HIT();
+               }
+       }
+}
+#endif
+
+/*
+OBJECTIVE
+Listen and detect an external reader. Determine the best location
+for the antenna.
+
+INSTRUCTIONS:
+Inside the ListenReaderField() function, there is two mode.
+By default, when you call the function, you will enter mode 1.
+If you press the PM3 button one time, you will enter mode 2.
+If you press the PM3 button a second time, you will exit the function.
+
+DESCRIPTION OF MODE 1:
+This mode just listens for an external reader field and lights up green
+for HF and/or red for LF. This is the original mode of the detectreader
+function.
+
+DESCRIPTION OF MODE 2:
+This mode will visually represent, using the LEDs, the actual strength of the
+current compared to the maximum current detected. Basically, once you know
+what kind of external reader is present, it will help you spot the best location to place
+your antenna. You will probably not get some good results if there is a LF and a HF reader
+at the same place! :-)
+
+LIGHT SCHEME USED:
+*/
+static const char LIGHT_SCHEME[] = {
+               0x0, /* ----     | No field detected */
+               0x1, /* X---     | 14% of maximum current detected */
+               0x2, /* -X--     | 29% of maximum current detected */
+               0x4, /* --X-     | 43% of maximum current detected */
+               0x8, /* ---X     | 57% of maximum current detected */
+               0xC, /* --XX     | 71% of maximum current detected */
+               0xE, /* -XXX     | 86% of maximum current detected */
+               0xF, /* XXXX     | 100% of maximum current detected */
+};
+static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);
+
+void ListenReaderField(int limit)
+{
+       int lf_av, lf_av_new, lf_baseline= 0, lf_count= 0, lf_max;
+       int hf_av, hf_av_new,  hf_baseline= 0, hf_count= 0, hf_max;
+       int mode=1, display_val, display_max, i;
+
+#define LF_ONLY                1
+#define HF_ONLY                2
+
+       LEDsoff();
+
+       lf_av=lf_max=ReadAdc(ADC_CHAN_LF);
+
+       if(limit != HF_ONLY) {
+               Dbprintf("LF 125/134 Baseline: %d", lf_av);
+               lf_baseline = lf_av;
+       }
+
+       hf_av=hf_max=ReadAdc(ADC_CHAN_HF);
+
+       if (limit != LF_ONLY) {
+               Dbprintf("HF 13.56 Baseline: %d", hf_av);
+               hf_baseline = hf_av;
+       }
+
+       for(;;) {
+               if (BUTTON_PRESS()) {
+                       SpinDelay(500);
+                       switch (mode) {
+                               case 1:
+                                       mode=2;
+                                       DbpString("Signal Strength Mode");
+                                       break;
+                               case 2:
+                               default:
+                                       DbpString("Stopped");
+                                       LEDsoff();
+                                       return;
+                                       break;
+                       }
+               }
+               WDT_HIT();
+
+               if (limit != HF_ONLY) {
+                       if(mode==1) {
+                               if (abs(lf_av - lf_baseline) > 10) LED_D_ON();
+                               else                               LED_D_OFF();
+                       }
+                       
+                       ++lf_count;
+                       lf_av_new= ReadAdc(ADC_CHAN_LF);
+                       // see if there's a significant change
+                       if(abs(lf_av - lf_av_new) > 10) {
+                               Dbprintf("LF 125/134 Field Change: %x %x %x", lf_av, lf_av_new, lf_count);
+                               lf_av = lf_av_new;
+                               if (lf_av > lf_max)
+                                       lf_max = lf_av;
+                               lf_count= 0;
+                       }
+               }
+
+               if (limit != LF_ONLY) {
+                       if (mode == 1){
+                               if (abs(hf_av - hf_baseline) > 10) LED_B_ON();
+                               else                               LED_B_OFF();
+                       }
+                       
+                       ++hf_count;
+                       hf_av_new= ReadAdc(ADC_CHAN_HF);
+                       // see if there's a significant change
+                       if(abs(hf_av - hf_av_new) > 10) {
+                               Dbprintf("HF 13.56 Field Change: %x %x %x", hf_av, hf_av_new, hf_count);
+                               hf_av = hf_av_new;
+                               if (hf_av > hf_max)
+                                       hf_max = hf_av;
+                               hf_count= 0;
+                       }
+               }
+               
+               if(mode == 2) {
+                       if (limit == LF_ONLY) {
+                               display_val = lf_av;
+                               display_max = lf_max;
+                       } else if (limit == HF_ONLY) {
+                               display_val = hf_av;
+                               display_max = hf_max;
+                       } else { /* Pick one at random */
+                               if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) {
+                                       display_val = hf_av;
+                                       display_max = hf_max;
+                               } else {
+                                       display_val = lf_av;
+                                       display_max = lf_max;
+                               }
+                       }
+                       for (i=0; i<LIGHT_LEN; i++) {
+                               if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) {
+                                       if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF();
+                                       if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF();
+                                       if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF();
+                                       if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF();
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
+void UsbPacketReceived(BYTE *packet, int len)
+{
+       UsbCommand *c = (UsbCommand *)packet;
+       UsbCommand ack;
+       ack.cmd = CMD_ACK;
+
+       switch(c->cmd) {
+#ifdef WITH_LF
+               case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
+                       AcquireRawAdcSamples125k(c->arg[0]);
+                       UsbSendPacket((BYTE*)&ack, sizeof(ack));
+                       break;
+#endif
+
+#ifdef WITH_LF
+               case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
+                       ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
+                       break;
+#endif
+
+#ifdef WITH_ISO15693
+               case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
+                       AcquireRawAdcSamplesIso15693();
+                       break;
+#endif
+
+               case CMD_BUFF_CLEAR:
+                       BufferClear();
+                       break;
+
+#ifdef WITH_ISO15693
+               case CMD_READER_ISO_15693:
+                       ReaderIso15693(c->arg[0]);
+                       break;
+#endif
+
+               case CMD_READER_LEGIC_RF:
+                       LegicRfReader(c->arg[0], c->arg[1]);
+                       break;
+
+#ifdef WITH_ISO15693
+               case CMD_SIMTAG_ISO_15693:
+                       SimTagIso15693(c->arg[0]);
+                       break;
+#endif
+
+#ifdef WITH_ISO14443b
+               case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
+                       AcquireRawAdcSamplesIso14443(c->arg[0]);
+                       break;
+#endif
+
+#ifdef WITH_ISO14443b
+               case CMD_READ_SRI512_TAG:
+                       ReadSRI512Iso14443(c->arg[0]);
+                       break;
+               case CMD_READ_SRIX4K_TAG:
+                       ReadSRIX4KIso14443(c->arg[0]);
+                       break;
+#endif
+
+#ifdef WITH_ISO14443a
+               case CMD_READER_ISO_14443a:
+                       ReaderIso14443a(c->arg[0]);
+                       break;
+#endif
+
+#ifdef WITH_ISO14443a
+               case CMD_READER_MIFARE:
+                       ReaderMifare(c->arg[0]);
+                       break;
+#endif
+      
+#ifdef WITH_ISO14443b
+               case CMD_SNOOP_ISO_14443:
+                       SnoopIso14443();
+                       break;
+#endif
+
+#ifdef WITH_ISO14443a
+               case CMD_SNOOP_ISO_14443a:
+                       SnoopIso14443a();
+                       break;
+#endif
+
+               case CMD_SIMULATE_TAG_HF_LISTEN:
+                       SimulateTagHfListen();
+                       break;
+
+#ifdef WITH_ISO14443b
+               case CMD_SIMULATE_TAG_ISO_14443:
+                       SimulateIso14443Tag();
+                       break;
+#endif
+               
+#ifdef WITH_ISO14443a
+               case CMD_SIMULATE_TAG_ISO_14443a:
+                       SimulateIso14443aTag(c->arg[0], c->arg[1]);  // ## Simulate iso14443a tag - pass tag type & UID
+                       break;
+#endif
+
+               case CMD_MEASURE_ANTENNA_TUNING:
+                       MeasureAntennaTuning();
+                       break;
+
+               case CMD_MEASURE_ANTENNA_TUNING_HF:
+                       MeasureAntennaTuningHf();
+                       break;
+
+               case CMD_LISTEN_READER_FIELD:
+                       ListenReaderField(c->arg[0]);
+                       break;
+
+#ifdef WITH_LF
+               case CMD_HID_DEMOD_FSK:
+                       CmdHIDdemodFSK(0, 0, 0, 1);                             // Demodulate HID tag
+                       break;
+#endif
+
+#ifdef WITH_LF
+               case CMD_HID_SIM_TAG:
+                       CmdHIDsimTAG(c->arg[0], c->arg[1], 1);                                  // Simulate HID tag by ID
+                       break;
+#endif
+
+               case CMD_FPGA_MAJOR_MODE_OFF:           // ## FPGA Control
+                       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+                       SpinDelay(200);
+                       LED_D_OFF(); // LED D indicates field ON or OFF
+                       break;
+
+#ifdef WITH_LF
+               case CMD_READ_TI_TYPE:
+                       ReadTItag();
+                       break;
+#endif
+
+#ifdef WITH_LF
+               case CMD_WRITE_TI_TYPE:
+                       WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
+                       break;
+#endif
+
+               case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: {
+                       UsbCommand n;
+                       if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
+                               n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
+                       } else {
+                               n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
+                       }
+                       n.arg[0] = c->arg[0];
+                       memcpy(n.d.asDwords, BigBuf+c->arg[0], 12*sizeof(DWORD));
+                       UsbSendPacket((BYTE *)&n, sizeof(n));
+                       break;
+               }
+
+               case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
+                       BYTE *b = (BYTE *)BigBuf;
+                       memcpy(b+c->arg[0], c->d.asBytes, 48);
+                       //Dbprintf("copied 48 bytes to %i",b+c->arg[0]);
+                       UsbSendPacket((BYTE*)&ack, sizeof(ack));
+                       break;
+               }
+
+#ifdef WITH_LF
+               case CMD_SIMULATE_TAG_125K:
+                       LED_A_ON();
+                       SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
+                       LED_A_OFF();
+                       break;
+#endif
+
+               case CMD_READ_MEM:
+                       ReadMem(c->arg[0]);
+                       break;
+
+               case CMD_SET_LF_DIVISOR:
+                       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);
+                       break;
+
+               case CMD_SET_ADC_MUX:
+                       switch(c->arg[0]) {
+                               case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break;
+                               case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break;
+                               case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break;
+                               case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break;
+                       }
+                       break;
+
+               case CMD_VERSION:
+                       SendVersion();
+                       break;
+
+#ifdef WITH_LF
+               case CMD_LF_SIMULATE_BIDIR:
+                       SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
+                       break;
+#endif
+
+#ifdef WITH_LCD
+               case CMD_LCD_RESET:
+                       LCDReset();
+                       break;
+               case CMD_LCD:
+                       LCDSend(c->arg[0]);
+                       break;
+#endif
+               case CMD_SETUP_WRITE:
+               case CMD_FINISH_WRITE:
+               case CMD_HARDWARE_RESET:
+                       USB_D_PLUS_PULLUP_OFF();
+                       SpinDelay(1000);
+                       SpinDelay(1000);
+                       AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
+                       for(;;) {
+                               // We're going to reset, and the bootrom will take control.
+                       }
+                       break;
+
+               case CMD_START_FLASH:
+                       if(common_area.flags.bootrom_present) {
+                               common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
+                       }
+                       USB_D_PLUS_PULLUP_OFF();
+                       AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
+                       for(;;);
+                       break;
+                       
+               case CMD_DEVICE_INFO: {
+                       UsbCommand c;
+                       c.cmd = CMD_DEVICE_INFO;
+                       c.arg[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
+                       if(common_area.flags.bootrom_present) c.arg[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
+                       UsbSendPacket((BYTE*)&c, sizeof(c));
+               }
+                       break;
+               default:
+                       Dbprintf("%s: 0x%04x","unknown command:",c->cmd);
+                       break;
+       }
+}
+
+void  __attribute__((noreturn)) AppMain(void)
+{
+       SpinDelay(100);
+       
+       if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) {
+               /* Initialize common area */
+               memset(&common_area, 0, sizeof(common_area));
+               common_area.magic = COMMON_AREA_MAGIC;
+               common_area.version = 1;
+       }
+       common_area.flags.osimage_present = 1;
+
+       LED_D_OFF();
+       LED_C_OFF();
+       LED_B_OFF();
+       LED_A_OFF();
+
+       UsbStart();
+
+       // The FPGA gets its clock from us from PCK0 output, so set that up.
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
+       AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0;
+       AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK0;
+       // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
+       AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK |
+               AT91C_PMC_PRES_CLK_4;
+       AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0;
+
+       // Reset SPI
+       AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
+       // Reset SSC
+       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
+
+       // Load the FPGA image, which we have stored in our flash.
+       FpgaDownloadAndGo();
+
+#ifdef WITH_LCD
+
+       LCDInit();
+
+       // test text on different colored backgrounds
+       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("     lazy dog.        ",     (char *)&FONT6x8,1,1+8*2,YELLOW ,RED   );
+       LCDString(" AaBbCcDdEeFfGgHhIiJj ",     (char *)&FONT6x8,1,1+8*3,RED    ,GREEN );
+       LCDString(" KkLlMmNnOoPpQqRrSsTt ",     (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE  );
+       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*7,BLUE  ,MAGENTA);
+
+       // color bands
+       LCDFill(0, 1+8* 8, 132, 8, BLACK);
+       LCDFill(0, 1+8* 9, 132, 8, WHITE);
+       LCDFill(0, 1+8*10, 132, 8, RED);
+       LCDFill(0, 1+8*11, 132, 8, GREEN);
+       LCDFill(0, 1+8*12, 132, 8, BLUE);
+       LCDFill(0, 1+8*13, 132, 8, YELLOW);
+       LCDFill(0, 1+8*14, 132, 8, CYAN);
+       LCDFill(0, 1+8*15, 132, 8, MAGENTA);
+
+#endif
+
+       for(;;) {
+               UsbPoll(FALSE);
+               WDT_HIT();
+
+#ifdef WITH_LF
+               if (BUTTON_HELD(1000) > 0)
+                       SamyRun();
+#endif
+       }
+}
index 71c25d1a5d8af2839155649e5ecae19e5d99c036..938028e73e84e97a40c42ac21aa4a5b67ff5ed6d 100644 (file)
-//-----------------------------------------------------------------------------\r
-// Definitions internal to the app source.\r
-// Jonathan Westhues, Aug 2005\r
-// Added ISO14443-A support by Gerhard de Koning Gans, April 2008\r
-//-----------------------------------------------------------------------------\r
-\r
-#ifndef __APPS_H\r
-#define __APPS_H\r
-\r
-#include "stdint.h"\r
-#include "stddef.h"\r
-typedef unsigned char byte_t;\r
-\r
-// The large multi-purpose buffer, typically used to hold A/D samples,\r
-// maybe processed in some way.\r
-DWORD BigBuf[8000];\r
-\r
-/// appmain.h\r
-void ReadMem(int addr);\r
-void __attribute__((noreturn)) AppMain(void);\r
-void SamyRun(void);\r
-//void DbpIntegers(int a, int b, int c);\r
-void DbpString(char *str);\r
-void Dbprintf(const char *fmt, ...);\r
-\r
-void ToSendStuffBit(int b);\r
-void ToSendReset(void);\r
-void ListenReaderField(int limit);\r
-void AcquireRawAdcSamples125k(BOOL at134khz);\r
-void DoAcquisition125k(void);\r
-extern int ToSendMax;\r
-extern BYTE ToSend[];\r
-extern DWORD BigBuf[];\r
-\r
-/// fpga.h\r
-void FpgaSendCommand(WORD cmd, WORD v);\r
-void FpgaWriteConfWord(BYTE v);\r
-void FpgaDownloadAndGo(void);\r
-void FpgaGatherVersion(char *dst, int len);\r
-void FpgaSetupSsc(void);\r
-void SetupSpi(int mode);\r
-void FpgaSetupSscDma(BYTE *buf, int len);\r
-void SetAdcMuxFor(DWORD whichGpio);\r
-\r
-// Definitions for the FPGA commands.\r
-#define FPGA_CMD_SET_CONFREG                                           (1<<12)\r
-#define FPGA_CMD_SET_DIVISOR                                           (2<<12)\r
-// Definitions for the FPGA configuration word.\r
-#define FPGA_MAJOR_MODE_LF_READER                                      (0<<5)\r
-#define FPGA_MAJOR_MODE_LF_SIMULATOR                           (1<<5)\r
-#define FPGA_MAJOR_MODE_HF_READER_TX                           (2<<5)\r
-#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR                     (3<<5)\r
-#define FPGA_MAJOR_MODE_HF_SIMULATOR                           (4<<5)\r
-#define FPGA_MAJOR_MODE_HF_ISO14443A                           (5<<5)\r
-#define FPGA_MAJOR_MODE_LF_PASSTHRU                                    (6<<5)\r
-#define FPGA_MAJOR_MODE_OFF                                                    (7<<5)\r
-// Options for the HF reader, tx to tag\r
-#define FPGA_HF_READER_TX_SHALLOW_MOD                          (1<<0)\r
-// Options for the HF reader, correlating against rx from tag\r
-#define FPGA_HF_READER_RX_XCORR_848_KHZ                                (1<<0)\r
-#define FPGA_HF_READER_RX_XCORR_SNOOP                          (1<<1)\r
-#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ                   (1<<2)\r
-// Options for the HF simulated tag, how to modulate\r
-#define FPGA_HF_SIMULATOR_NO_MODULATION                                (0<<0)\r
-#define FPGA_HF_SIMULATOR_MODULATE_BPSK                                (1<<0)\r
-#define FPGA_HF_SIMULATOR_MODULATE_212K                                (2<<0)\r
-// Options for ISO14443A\r
-#define FPGA_HF_ISO14443A_SNIFFER                                      (0<<0)\r
-#define FPGA_HF_ISO14443A_TAGSIM_LISTEN                                (1<<0)\r
-#define FPGA_HF_ISO14443A_TAGSIM_MOD                           (2<<0)\r
-#define FPGA_HF_ISO14443A_READER_LISTEN                                (3<<0)\r
-#define FPGA_HF_ISO14443A_READER_MOD                           (4<<0)\r
-\r
-/// lfops.h\r
-void AcquireRawAdcSamples125k(BOOL at134khz);\r
-void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command);\r
-void ReadTItag(void);\r
-void WriteTItag(DWORD idhi, DWORD idlo, WORD crc);\r
-void AcquireTiType(void);\r
-void AcquireRawBitsTI(void);\r
-void SimulateTagLowFrequency(int period, int gap, int ledcontrol);\r
-void CmdHIDsimTAG(int hi, int lo, int ledcontrol);\r
-void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);\r
-void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);\r
-\r
-/// iso14443.h\r
-void SimulateIso14443Tag(void);\r
-void AcquireRawAdcSamplesIso14443(DWORD parameter);\r
-void ReadSRI512Iso14443(DWORD parameter);\r
-void ReadSRIX4KIso14443(DWORD parameter);\r
-void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast);\r
-void SnoopIso14443(void);\r
-\r
-/// iso14443a.h\r
-void SnoopIso14443a(void);\r
-void SimulateIso14443aTag(int tagType, int TagUid);    // ## simulate iso14443a tag\r
-void ReaderIso14443a(DWORD parameter);\r
-void ReaderMifare(DWORD parameter);\r
-\r
-/// iso15693.h\r
-void AcquireRawAdcSamplesIso15693(void);\r
-void ReaderIso15693(DWORD parameter);  // Simulate an ISO15693 reader - greg\r
-void SimTagIso15693(DWORD parameter);  // simulate an ISO15693 tag - greg\r
-\r
-/// util.h\r
-#define LED_RED 1\r
-#define LED_ORANGE 2\r
-#define LED_GREEN 4\r
-#define LED_RED2 8\r
-#define BUTTON_HOLD 1\r
-#define BUTTON_NO_CLICK 0\r
-#define BUTTON_SINGLE_CLICK -1\r
-#define BUTTON_DOUBLE_CLICK -2\r
-#define BUTTON_ERROR -99\r
-int strlen(char *str);\r
-void *memcpy(void *dest, const void *src, int len);\r
-void *memset(void *dest, int c, int len);\r
-int memcmp(const void *av, const void *bv, int len);\r
-char *strncat(char *dest, const char *src, unsigned int n);\r
-void num_to_bytes(uint64_t n, size_t len, byte_t* dest);\r
-uint64_t bytes_to_num(byte_t* src, size_t len);\r
-\r
-void SpinDelay(int ms);\r
-void SpinDelayUs(int us);\r
-void LED(int led, int ms);\r
-void LEDsoff();\r
-int BUTTON_CLICKED(int ms);\r
-int BUTTON_HELD(int ms);\r
-void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);\r
-\r
-#endif\r
+//-----------------------------------------------------------------------------
+// Definitions internal to the app source.
+// Jonathan Westhues, Aug 2005
+// Added ISO14443-A support by Gerhard de Koning Gans, April 2008
+//-----------------------------------------------------------------------------
+
+#ifndef __APPS_H
+#define __APPS_H
+
+#include "stdint.h"
+#include "stddef.h"
+typedef unsigned char byte_t;
+
+// The large multi-purpose buffer, typically used to hold A/D samples,
+// maybe processed in some way.
+DWORD BigBuf[8000];
+
+/// appmain.h
+void ReadMem(int addr);
+void __attribute__((noreturn)) AppMain(void);
+void SamyRun(void);
+//void DbpIntegers(int a, int b, int c);
+void DbpString(char *str);
+void Dbprintf(const char *fmt, ...);
+
+void ToSendStuffBit(int b);
+void ToSendReset(void);
+void ListenReaderField(int limit);
+void AcquireRawAdcSamples125k(BOOL at134khz);
+void DoAcquisition125k(void);
+extern int ToSendMax;
+extern BYTE ToSend[];
+extern DWORD BigBuf[];
+
+/// fpga.h
+void FpgaSendCommand(WORD cmd, WORD v);
+void FpgaWriteConfWord(BYTE v);
+void FpgaDownloadAndGo(void);
+void FpgaGatherVersion(char *dst, int len);
+void FpgaSetupSsc(void);
+void SetupSpi(int mode);
+void FpgaSetupSscDma(BYTE *buf, int len);
+void SetAdcMuxFor(DWORD whichGpio);
+
+// Definitions for the FPGA commands.
+#define FPGA_CMD_SET_CONFREG                                           (1<<12)
+#define FPGA_CMD_SET_DIVISOR                                           (2<<12)
+// Definitions for the FPGA configuration word.
+#define FPGA_MAJOR_MODE_LF_READER                                      (0<<5)
+#define FPGA_MAJOR_MODE_LF_SIMULATOR                           (1<<5)
+#define FPGA_MAJOR_MODE_HF_READER_TX                           (2<<5)
+#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR                     (3<<5)
+#define FPGA_MAJOR_MODE_HF_SIMULATOR                           (4<<5)
+#define FPGA_MAJOR_MODE_HF_ISO14443A                           (5<<5)
+#define FPGA_MAJOR_MODE_LF_PASSTHRU                                    (6<<5)
+#define FPGA_MAJOR_MODE_OFF                                                    (7<<5)
+// Options for the HF reader, tx to tag
+#define FPGA_HF_READER_TX_SHALLOW_MOD                          (1<<0)
+// 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_SNOOP                          (1<<1)
+#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ                   (1<<2)
+// Options for the HF simulated tag, how to modulate
+#define FPGA_HF_SIMULATOR_NO_MODULATION                                (0<<0)
+#define FPGA_HF_SIMULATOR_MODULATE_BPSK                                (1<<0)
+#define FPGA_HF_SIMULATOR_MODULATE_212K                                (2<<0)
+// Options for ISO14443A
+#define FPGA_HF_ISO14443A_SNIFFER                                      (0<<0)
+#define FPGA_HF_ISO14443A_TAGSIM_LISTEN                                (1<<0)
+#define FPGA_HF_ISO14443A_TAGSIM_MOD                           (2<<0)
+#define FPGA_HF_ISO14443A_READER_LISTEN                                (3<<0)
+#define FPGA_HF_ISO14443A_READER_MOD                           (4<<0)
+
+/// lfops.h
+void AcquireRawAdcSamples125k(BOOL at134khz);
+void ModThenAcquireRawAdcSamples125k(int delay_off,int period_0,int period_1,BYTE *command);
+void ReadTItag(void);
+void WriteTItag(DWORD idhi, DWORD idlo, WORD crc);
+void AcquireTiType(void);
+void AcquireRawBitsTI(void);
+void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
+void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
+void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
+
+/// iso14443.h
+void SimulateIso14443Tag(void);
+void AcquireRawAdcSamplesIso14443(DWORD parameter);
+void ReadSRI512Iso14443(DWORD parameter);
+void ReadSRIX4KIso14443(DWORD parameter);
+void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast);
+void SnoopIso14443(void);
+
+/// iso14443a.h
+void SnoopIso14443a(void);
+void SimulateIso14443aTag(int tagType, int TagUid);    // ## simulate iso14443a tag
+void ReaderIso14443a(DWORD parameter);
+void ReaderMifare(DWORD parameter);
+
+/// iso15693.h
+void AcquireRawAdcSamplesIso15693(void);
+void ReaderIso15693(DWORD parameter);  // Simulate an ISO15693 reader - greg
+void SimTagIso15693(DWORD parameter);  // simulate an ISO15693 tag - greg
+
+/// util.h
+#define LED_RED 1
+#define LED_ORANGE 2
+#define LED_GREEN 4
+#define LED_RED2 8
+#define BUTTON_HOLD 1
+#define BUTTON_NO_CLICK 0
+#define BUTTON_SINGLE_CLICK -1
+#define BUTTON_DOUBLE_CLICK -2
+#define BUTTON_ERROR -99
+int strlen(char *str);
+void *memcpy(void *dest, const void *src, int len);
+void *memset(void *dest, int c, int len);
+int memcmp(const void *av, const void *bv, int len);
+char *strncat(char *dest, const char *src, unsigned int n);
+void num_to_bytes(uint64_t n, size_t len, byte_t* dest);
+uint64_t bytes_to_num(byte_t* src, size_t len);
+
+void SpinDelay(int ms);
+void SpinDelayUs(int us);
+void LED(int led, int ms);
+void LEDsoff();
+int BUTTON_CLICKED(int ms);
+int BUTTON_HELD(int ms);
+void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
+
+#endif
index 81e99ce5ba53309ed8a6ecd0c5be00846ea4e6ec..78c2654dab33b13401b9f20d2a47ab9e50ee24dd 100644 (file)
-const char FONT6x8[97][8] = {\r
-       {0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00},      // columns, rows, bytes per char\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // space\r
-       {0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00},      // !\r
-       {0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00},      // "\r
-       {0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00},      // #\r
-       {0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00},      // $\r
-       {0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00},      // %\r
-       {0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00},      // &\r
-       {0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00},      // '\r
-       {0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00},      // (\r
-       {0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00},      // )\r
-       {0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00},      // *\r
-       {0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00},      // +\r
-       {0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40},      // ,\r
-       {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00},      // -\r
-       {0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00},      // .\r
-       {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00},      // /\r
-       {0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00},      // 0\r
-       {0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00},      // 1\r
-       {0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00},      // 2\r
-       {0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00},      // 3\r
-       {0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00},      // 4\r
-       {0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00},      // 5\r
-       {0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00},      // 6\r
-       {0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00},      // 7\r
-       {0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00},      // 8\r
-       {0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00},      // 9\r
-       {0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00},      // :\r
-       {0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00},      // ;\r
-       {0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00},      // <\r
-       {0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00},      // =\r
-       {0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00},      // >\r
-       {0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00},      // ?\r
-       {0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00},      // @\r
-       {0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00},      // A\r
-       {0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00},      // B\r
-       {0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00},      // C\r
-       {0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00},      // D\r
-       {0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00},      // E\r
-       {0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00},      // F\r
-       {0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00},      // G\r
-       {0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00},      // H\r
-       {0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00},      // I\r
-       {0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00},      // J\r
-       {0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00},      // K\r
-       {0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00},      // L\r
-       {0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00},      // M\r
-       {0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00},      // N\r
-       {0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00},      // O\r
-       {0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00},      // P\r
-       {0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00},      // Q\r
-       {0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00},      // R\r
-       {0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00},      // S\r
-       {0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00},      // T\r
-       {0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00},      // U\r
-       {0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00},      // V\r
-       {0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00},      // W\r
-       {0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00},      // X\r
-       {0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00},      // Y\r
-       {0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00},      // Z\r
-       {0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00},      // [\r
-       {0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00},      // backslash\r
-       {0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00},      // ]\r
-       {0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00},      // ^\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00},      // _\r
-       {0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00},      // `\r
-       {0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00},      // a\r
-       {0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00},      // b\r
-       {0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00},      // c\r
-       {0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00},      // d\r
-       {0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00},      // e\r
-       {0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00},      // f\r
-       {0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70},      // g\r
-       {0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00},      // h\r
-       {0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00},      // i\r
-       {0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00},      // j\r
-       {0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00},      // k\r
-       {0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00},      // l\r
-       {0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00},      // m\r
-       {0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00},      // n\r
-       {0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00},      // o\r
-       {0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80},      // p\r
-       {0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08},      // q\r
-       {0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00},      // r\r
-       {0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00},      // s\r
-       {0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00},      // t\r
-       {0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00},      // u\r
-       {0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00},      // v\r
-       {0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00},      // w\r
-       {0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00},      // x\r
-       {0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70},      // y\r
-       {0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00},      // z\r
-       {0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00},      // {\r
-       {0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00},      // |\r
-       {0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00},      // }\r
-       {0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00},      // ~\r
-       {0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00}       // DEL\r
-};\r
-/*\r
-const char FONT8x8F[97][8] = {\r
-       {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00},      // columns, rows, bytes per char\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // space\r
-       {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00},      // !\r
-       {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00},      // "\r
-       {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00},      // #\r
-       {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00},      // $\r
-       {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00},      // %\r
-       {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00},      // &\r
-       {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00},      // '\r
-       {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00},      // (\r
-       {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00},      // )\r
-       {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00},      // *\r
-       {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00},      // +\r
-       {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30},      // ,\r
-       {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00},      // -\r
-       {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00},      // .\r
-       {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00},      // /\r
-       {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00},      // 0\r
-       {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00},      // 1\r
-       {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00},      // 2\r
-       {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00},      // 3\r
-       {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00},      // 4\r
-       {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00},      // 5\r
-       {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00},      // 6\r
-       {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00},      // 7\r
-       {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00},      // 8\r
-       {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00},      // 9\r
-       {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00},      // :\r
-       {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30},      // ;\r
-       {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00},      // <\r
-       {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00},      // =\r
-       {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00},      // >\r
-       {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00},      // ?\r
-       {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00},      // @\r
-       {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00},      // A\r
-       {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00},      // B\r
-       {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00},      // C\r
-       {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00},      // D\r
-       {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00},      // E\r
-       {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00},      // F\r
-       {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00},      // G\r
-       {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00},      // H\r
-       {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00},      // I\r
-       {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00},      // J\r
-       {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00},      // K\r
-       {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00},      // L\r
-       {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00},      // M\r
-       {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00},      // N\r
-       {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00},      // O\r
-       {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00},      // P\r
-       {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00},      // Q\r
-       {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00},      // R\r
-       {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00},      // S\r
-       {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00},      // T\r
-       {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00},      // U\r
-       {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00},      // V\r
-       {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00},      // W\r
-       {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00},      // X\r
-       {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00},      // Y\r
-       {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00},      // Z\r
-       {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00},      // [\r
-       {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00},      // backslash\r
-       {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00},      // ]\r
-       {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00},      // ^\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},      // _\r
-       {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00},      // `\r
-       {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00},      // a\r
-       {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00},      // b\r
-       {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00},      // c\r
-       {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00},      // d\r
-       {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00},      // e\r
-       {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00},      // f\r
-       {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C},      // g\r
-       {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00},      // h\r
-       {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00},      // i\r
-       {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C},      // j\r
-       {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00},      // k\r
-       {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00},      // l\r
-       {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00},      // m\r
-       {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00},      // n\r
-       {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00},      // o\r
-       {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78},      // p\r
-       {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F},      // q\r
-       {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00},      // r\r
-       {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00},      // s\r
-       {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00},      // t\r
-       {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00},      // u\r
-       {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00},      // v\r
-       {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00},      // w\r
-       {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00},      // x\r
-       {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C},      // y\r
-       {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00},      // z\r
-       {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00},      // {\r
-       {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00},      // |\r
-       {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00},      // }\r
-       {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00},      // ~\r
-       {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}       // DEL\r
-};\r
-\r
-const char FONT8x16[97][16] = {\r
-       {0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // columns, rows, bytes per char\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // space\r
-       {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00},      // !\r
-       {0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // "\r
-       {0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00},      // #\r
-       {0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00},      // $\r
-       {0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00},      // %\r
-       {0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},      // &\r
-       {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // '\r
-       {0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00},      // (\r
-       {0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00},      // )\r
-       {0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00},      // *\r
-       {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00},      // +\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00},      // ,\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // -\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00},      // .\r
-       {0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00},      // /\r
-       {0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},      // 0\r
-       {0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00},      // 1\r
-       {0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00},      // 2\r
-       {0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00},      // 3\r
-       {0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00},      // 4\r
-       {0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00},      // 5\r
-       {0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},      // 6\r
-       {0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00},      // 7\r
-       {0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},      // 8\r
-       {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00},      // 9\r
-       {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00},      // :\r
-       {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00},      // ;\r
-       {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00},      // <\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00},      // =\r
-       {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00},      // >\r
-       {0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00},      // ?\r
-       {0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00},      // @\r
-       {0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00},      // A\r
-       {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00},      // B\r
-       {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00},      // C\r
-       {0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00},      // D\r
-       {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00},      // E\r
-       {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},      // F\r
-       {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00},      // G\r
-       {0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00},      // H\r
-       {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},      // I\r
-       {0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00},      // J\r
-       {0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00},      // K\r
-       {0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00},      // L\r
-       {0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00},      // M\r
-       {0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00},      // N\r
-       {0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00},      // O\r
-       {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},      // P\r
-       {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00},      // Q\r
-       {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00},      // R\r
-       {0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},      // S\r
-       {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},      // T\r
-       {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},      // U\r
-       {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00},      // V\r
-       {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00},      // W\r
-       {0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00},      // X\r
-       {0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},      // Y\r
-       {0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00},      // Z\r
-       {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00},      // [\r
-       {0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00},      // backslash\r
-       {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00},      // ]\r
-       {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // ^\r
-       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},      // _\r
-       {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // `\r
-       {0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},      // a\r
-       {0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00},      // b\r
-       {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00},      // c\r
-       {0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},      // d\r
-       {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00},      // e\r
-       {0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},      // f\r
-       {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00},      // g\r
-       {0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00},      // h\r
-       {0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00},      // i\r
-       {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00},      // j\r
-       {0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00},      // k\r
-       {0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00},      // l\r
-       {0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00},      // m\r
-       {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00},      // n\r
-       {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00},      // o\r
-       {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00},      // p\r
-       {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00},      // q\r
-       {0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00},      // r\r
-       {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00},      // s\r
-       {0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00},      // t\r
-       {0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00},      // u\r
-       {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00},      // v\r
-       {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00},      // w\r
-       {0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00},      // x\r
-       {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00},      // y\r
-       {0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00},      // z\r
-       {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00},      // {\r
-       {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00},      // |\r
-       {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00},      // }\r
-       {0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // ~\r
-       {0x00,0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}       // DEL\r
-};\r
-*/\r
+const char FONT6x8[97][8] = {
+       {0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00},      // columns, rows, bytes per char
+       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // space
+       {0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00},      // !
+       {0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00},      // "
+       {0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00},      // #
+       {0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00},      // $
+       {0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00},      // %
+       {0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00},      // &
+       {0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00},      // '
+       {0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00},      // (
+       {0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00},      // )
+       {0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00},      // *
+       {0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00},      // +
+       {0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40},      // ,
+       {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00},      // -
+       {0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00},      // .
+       {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00},      // /
+       {0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00},      // 0
+       {0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00},      // 1
+       {0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00},      // 2
+       {0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00},      // 3
+       {0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00},      // 4
+       {0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00},      // 5
+       {0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00},      // 6
+       {0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00},      // 7
+       {0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00},      // 8
+       {0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00},      // 9
+       {0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00},      // :
+       {0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00},      // ;
+       {0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00},      // <
+       {0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00},      // =
+       {0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00},      // >
+       {0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00},      // ?
+       {0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00},      // @
+       {0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00},      // A
+       {0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00},      // B
+       {0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00},      // C
+       {0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00},      // D
+       {0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00},      // E
+       {0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00},      // F
+       {0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00},      // G
+       {0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00},      // H
+       {0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00},      // I
+       {0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00},      // J
+       {0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00},      // K
+       {0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00},      // L
+       {0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00},      // M
+       {0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00},      // N
+       {0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00},      // O
+       {0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00},      // P
+       {0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00},      // Q
+       {0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00},      // R
+       {0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00},      // S
+       {0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00},      // T
+       {0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00},      // U
+       {0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00},      // V
+       {0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00},      // W
+       {0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00},      // X
+       {0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00},      // Y
+       {0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00},      // Z
+       {0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00},      // [
+       {0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00},      // backslash
+       {0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00},      // ]
+       {0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00},      // ^
+       {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00},      // _
+       {0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00},      // `
+       {0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00},      // a
+       {0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00},      // b
+       {0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00},      // c
+       {0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00},      // d
+       {0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00},      // e
+       {0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00},      // f
+       {0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70},      // g
+       {0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00},      // h
+       {0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00},      // i
+       {0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00},      // j
+       {0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00},      // k
+       {0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00},      // l
+       {0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00},      // m
+       {0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00},      // n
+       {0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00},      // o
+       {0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80},      // p
+       {0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08},      // q
+       {0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00},      // r
+       {0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00},      // s
+       {0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00},      // t
+       {0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00},      // u
+       {0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00},      // v
+       {0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00},      // w
+       {0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00},      // x
+       {0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70},      // y
+       {0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00},      // z
+       {0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00},      // {
+       {0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00},      // |
+       {0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00},      // }
+       {0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00},      // ~
+       {0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00}       // DEL
+};
+/*
+const char FONT8x8F[97][8] = {
+       {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00},      // columns, rows, bytes per char
+       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},      // space
+       {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00},      // !
+       {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00},      // "
+       {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00},      // #
+       {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00},      // $
+       {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00},      // %
+       {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00},      // &
+       {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00},      // '
+       {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00},      // (
+       {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00},      // )
+       {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00},      // *
+       {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00},      // +
+       {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30},      // ,
+       {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00},      // -
+       {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00},      // .
+       {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00},      // /
+       {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00},      // 0
+       {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00},      // 1
+       {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00},      // 2
+       {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00},      // 3
+       {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00},      // 4
+       {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00},      // 5
+       {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00},      // 6
+       {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00},      // 7
+       {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00},      // 8
+       {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00},      // 9
+       {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00},      // :
+       {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30},      // ;
+       {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00},      // <
+       {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00},      // =
+       {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00},      // >
+       {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00},      // ?
+       {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00},      // @
+       {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00},      // A
+       {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00},      // B
+       {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00},      // C
+       {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00},      // D
+       {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00},      // E
+       {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00},      // F
+       {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00},      // G
+       {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00},      // H
+       {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00},      // I
+       {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00},      // J
+       {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00},      // K
+       {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00},      // L
+       {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00},      // M
+       {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00},      // N
+       {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00},      // O
+       {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00},      // P
+       {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00},      // Q
+       {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00},      // R
+       {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00},      // S
+       {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00},      // T
+       {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00},      // U
+       {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00},      // V
+       {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00},      // W
+       {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00},      // X
+       {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00},      // Y
+       {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00},      // Z
+       {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00},      // [
+       {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00},      // backslash
+       {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00},      // ]
+       {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00},      // ^
+       {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},      // _
+       {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00},      // `
+       {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00},      // a
+       {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00},      // b
+       {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00},      // c
+       {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00},      // d
+       {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00},      // e
+       {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00},      // f
+       {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C},      // g
+       {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00},      // h
+       {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00},      // i
+       {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C},      // j
+       {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00},      // k
+       {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00},      // l
+       {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00},      // m
+       {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00},      // n
+       {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00},      // o
+       {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78},      // p
+       {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F},      // q
+       {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00},      // r
+       {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00},      // s
+       {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00},      // t
+       {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00},      // u
+       {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00},      // v
+       {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00},      // w
+       {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00},      // x
+       {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C},      // y
+       {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00},      // z
+       {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00},      // {
+       {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00},      // |
+       {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00},      // }
+       {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00},      // ~
+       {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00}       // DEL
+};
+
+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
+       {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,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},      // #
+       {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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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},      // ]
+       {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},      // _
+       {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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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
+};
+*/
index 621a7f56ef01442fd438c41b9b61408facedd20c..5280ca278a1a5fe9b881ca71f762088115be82b9 100644 (file)
@@ -1,6 +1,6 @@
-#ifndef __FONTS_H\r
-#define __FONTS_H\r
-extern const char FONT6x8[97][8];\r
-extern const char FONT8x8F[97][8];\r
-extern const char FONT8x16[97][16];\r
-#endif\r
+#ifndef __FONTS_H
+#define __FONTS_H
+extern const char FONT6x8[97][8];
+extern const char FONT8x8F[97][8];
+extern const char FONT8x16[97][16];
+#endif
index 04db41b3c38ebc97fe948fe524918f8e1ca6b38b..8ce07dd37fe5a05e96f3200cd401b9f12401d9c3 100644 (file)
-//-----------------------------------------------------------------------------\r
-// Routines to load the FPGA image, and then to configure the FPGA's major\r
-// mode once it is configured.\r
-//\r
-// Jonathan Westhues, April 2006\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-\r
-//-----------------------------------------------------------------------------\r
-// Set up the Serial Peripheral Interface as master\r
-// Used to write the FPGA config word\r
-// May also be used to write to other SPI attached devices like an LCD\r
-//-----------------------------------------------------------------------------\r
-void SetupSpi(int mode)\r
-{\r
-       // PA10 -> SPI_NCS2 chip select (LCD)\r
-       // PA11 -> SPI_NCS0 chip select (FPGA)\r
-       // PA12 -> SPI_MISO Master-In Slave-Out\r
-       // PA13 -> SPI_MOSI Master-Out Slave-In\r
-       // PA14 -> SPI_SPCK Serial Clock\r
-\r
-       // Disable PIO control of the following pins, allows use by the SPI peripheral\r
-       AT91C_BASE_PIOA->PIO_PDR =\r
-               GPIO_NCS0       |\r
-               GPIO_NCS2       |\r
-               GPIO_MISO       |\r
-               GPIO_MOSI       |\r
-               GPIO_SPCK;\r
-\r
-       AT91C_BASE_PIOA->PIO_ASR =\r
-               GPIO_NCS0       |\r
-               GPIO_MISO       |\r
-               GPIO_MOSI       |\r
-               GPIO_SPCK;\r
-\r
-       AT91C_BASE_PIOA->PIO_BSR = GPIO_NCS2;\r
-\r
-       //enable the SPI Peripheral clock\r
-       AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_SPI);\r
-       // Enable SPI\r
-       AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;\r
-\r
-       switch (mode) {\r
-               case SPI_FPGA_MODE:\r
-                       AT91C_BASE_SPI->SPI_MR =\r
-                               ( 0 << 24)      |       // Delay between chip selects (take default: 6 MCK periods)\r
-                               (14 << 16)      |       // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)\r
-                               ( 0 << 7)       |       // Local Loopback Disabled\r
-                               ( 1 << 4)       |       // Mode Fault Detection disabled\r
-                               ( 0 << 2)       |       // Chip selects connected directly to peripheral\r
-                               ( 0 << 1)       |       // Fixed Peripheral Select\r
-                               ( 1 << 0);              // Master Mode\r
-                       AT91C_BASE_SPI->SPI_CSR[0] =\r
-                               ( 1 << 24)      |       // Delay between Consecutive Transfers (32 MCK periods)\r
-                               ( 1 << 16)      |       // Delay Before SPCK (1 MCK period)\r
-                               ( 6 << 8)       |       // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud\r
-                               ( 8 << 4)       |       // Bits per Transfer (16 bits)\r
-                               ( 0 << 3)       |       // Chip Select inactive after transfer\r
-                               ( 1 << 1)       |       // Clock Phase data captured on leading edge, changes on following edge\r
-                               ( 0 << 0);              // Clock Polarity inactive state is logic 0\r
-                       break;\r
-               case SPI_LCD_MODE:\r
-                       AT91C_BASE_SPI->SPI_MR =\r
-                               ( 0 << 24)      |       // Delay between chip selects (take default: 6 MCK periods)\r
-                               (11 << 16)      |       // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)\r
-                               ( 0 << 7)       |       // Local Loopback Disabled\r
-                               ( 1 << 4)       |       // Mode Fault Detection disabled\r
-                               ( 0 << 2)       |       // Chip selects connected directly to peripheral\r
-                               ( 0 << 1)       |       // Fixed Peripheral Select\r
-                               ( 1 << 0);              // Master Mode\r
-                       AT91C_BASE_SPI->SPI_CSR[2] =\r
-                               ( 1 << 24)      |       // Delay between Consecutive Transfers (32 MCK periods)\r
-                               ( 1 << 16)      |       // Delay Before SPCK (1 MCK period)\r
-                               ( 6 << 8)       |       // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud\r
-                               ( 1 << 4)       |       // Bits per Transfer (9 bits)\r
-                               ( 0 << 3)       |       // Chip Select inactive after transfer\r
-                               ( 1 << 1)       |       // Clock Phase data captured on leading edge, changes on following edge\r
-                               ( 0 << 0);              // Clock Polarity inactive state is logic 0\r
-                       break;\r
-               default:                                // Disable SPI\r
-                       AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;\r
-                       break;\r
-       }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Set up the synchronous serial port, with the one set of options that we\r
-// always use when we are talking to the FPGA. Both RX and TX are enabled.\r
-//-----------------------------------------------------------------------------\r
-void FpgaSetupSsc(void)\r
-{\r
-       // First configure the GPIOs, and get ourselves a clock.\r
-       AT91C_BASE_PIOA->PIO_ASR =\r
-               GPIO_SSC_FRAME  |\r
-               GPIO_SSC_DIN    |\r
-               GPIO_SSC_DOUT   |\r
-               GPIO_SSC_CLK;\r
-       AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;\r
-\r
-       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);\r
-\r
-       // Now set up the SSC proper, starting from a known state.\r
-       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
-\r
-       // RX clock comes from TX clock, RX starts when TX starts, data changes\r
-       // on RX clock rising edge, sampled on falling edge\r
-       AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1);\r
-\r
-       // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync\r
-       // pulse, no output sync, start on positive-going edge of sync\r
-       AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) |\r
-               AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);\r
-\r
-       // clock comes from TK pin, no clock output, outputs change on falling\r
-       // edge of TK, start on rising edge of TF\r
-       AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) |\r
-               SSC_CLOCK_MODE_START(5);\r
-\r
-       // tx framing is the same as the rx framing\r
-       AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR;\r
-\r
-       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Set up DMA to receive samples from the FPGA. We will use the PDC, with\r
-// a single buffer as a circular buffer (so that we just chain back to\r
-// ourselves, not to another buffer). The stuff to manipulate those buffers\r
-// is in apps.h, because it should be inlined, for speed.\r
-//-----------------------------------------------------------------------------\r
-void FpgaSetupSscDma(BYTE *buf, int len)\r
-{\r
-       AT91C_BASE_PDC_SSC->PDC_RPR = (DWORD)buf;\r
-       AT91C_BASE_PDC_SSC->PDC_RCR = len;\r
-       AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)buf;\r
-       AT91C_BASE_PDC_SSC->PDC_RNCR = len;\r
-       AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;\r
-}\r
-\r
-static void DownloadFPGA_byte(unsigned char w)\r
-{\r
-#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); }\r
-       SEND_BIT(7);\r
-       SEND_BIT(6);\r
-       SEND_BIT(5);\r
-       SEND_BIT(4);\r
-       SEND_BIT(3);\r
-       SEND_BIT(2);\r
-       SEND_BIT(1);\r
-       SEND_BIT(0);\r
-}\r
-\r
-// Download the fpga image starting at FpgaImage and with length FpgaImageLen bytes\r
-// If bytereversal is set: reverse the byte order in each 4-byte word\r
-static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int bytereversal)\r
-{\r
-       int i=0;\r
-\r
-       AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;\r
-       AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON;\r
-       HIGH(GPIO_FPGA_ON);             // ensure everything is powered on\r
-\r
-       SpinDelay(50);\r
-\r
-       LED_D_ON();\r
-\r
-       // These pins are inputs\r
-    AT91C_BASE_PIOA->PIO_ODR =\r
-       GPIO_FPGA_NINIT |\r
-       GPIO_FPGA_DONE;\r
-       // PIO controls the following pins\r
-    AT91C_BASE_PIOA->PIO_PER =\r
-       GPIO_FPGA_NINIT |\r
-       GPIO_FPGA_DONE;\r
-       // Enable pull-ups\r
-       AT91C_BASE_PIOA->PIO_PPUER =\r
-               GPIO_FPGA_NINIT |\r
-               GPIO_FPGA_DONE;\r
-\r
-       // setup initial logic state\r
-       HIGH(GPIO_FPGA_NPROGRAM);\r
-       LOW(GPIO_FPGA_CCLK);\r
-       LOW(GPIO_FPGA_DIN);\r
-       // These pins are outputs\r
-       AT91C_BASE_PIOA->PIO_OER =\r
-               GPIO_FPGA_NPROGRAM      |\r
-               GPIO_FPGA_CCLK          |\r
-               GPIO_FPGA_DIN;\r
-\r
-       // enter FPGA configuration mode\r
-       LOW(GPIO_FPGA_NPROGRAM);\r
-       SpinDelay(50);\r
-       HIGH(GPIO_FPGA_NPROGRAM);\r
-\r
-       i=100000;\r
-       // wait for FPGA ready to accept data signal\r
-       while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) {\r
-               i--;\r
-       }\r
-\r
-       // crude error indicator, leave both red LEDs on and return\r
-       if (i==0){\r
-               LED_C_ON();\r
-               LED_D_ON();\r
-               return;\r
-       }\r
-\r
-       if(bytereversal) {\r
-               /* This is only supported for DWORD aligned images */\r
-               if( ((int)FpgaImage % sizeof(DWORD)) == 0 ) {\r
-                       i=0;\r
-                       while(FpgaImageLen-->0)\r
-                               DownloadFPGA_byte(FpgaImage[(i++)^0x3]);\r
-                       /* Explanation of the magic in the above line: \r
-                        * i^0x3 inverts the lower two bits of the integer i, counting backwards\r
-                        * for each 4 byte increment. The generated sequence of (i++)^3 is\r
-                        * 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12 etc. pp. \r
-                        */\r
-               }\r
-       } else {\r
-               while(FpgaImageLen-->0)\r
-                       DownloadFPGA_byte(*FpgaImage++);\r
-       }\r
-\r
-       // continue to clock FPGA until ready signal goes high\r
-       i=100000;\r
-       while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) {\r
-               HIGH(GPIO_FPGA_CCLK);\r
-               LOW(GPIO_FPGA_CCLK);\r
-       }\r
-       // crude error indicator, leave both red LEDs on and return\r
-       if (i==0){\r
-               LED_C_ON();\r
-               LED_D_ON();\r
-               return;\r
-       }\r
-       LED_D_OFF();\r
-}\r
-\r
-static char *bitparse_headers_start;\r
-static char *bitparse_bitstream_end;\r
-static int bitparse_initialized;\r
-/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence\r
- * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01\r
- * After that the format is 1 byte section type (ASCII character), 2 byte length\r
- * (big endian), <length> bytes content. Except for section 'e' which has 4 bytes\r
- * length.\r
- */\r
-static const char _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};\r
-static int bitparse_init(void * start_address, void *end_address)\r
-{\r
-       bitparse_initialized = 0;\r
-       \r
-       if(memcmp(_bitparse_fixed_header, start_address, sizeof(_bitparse_fixed_header)) != 0) {\r
-               return 0; /* Not matched */\r
-       } else {\r
-               bitparse_headers_start= ((char*)start_address) + sizeof(_bitparse_fixed_header);\r
-               bitparse_bitstream_end= (char*)end_address;\r
-               bitparse_initialized = 1;\r
-               return 1;\r
-       }\r
-}\r
-\r
-int bitparse_find_section(char section_name, char **section_start, unsigned int *section_length)\r
-{\r
-       char *pos = bitparse_headers_start;\r
-       int result = 0;\r
-\r
-       if(!bitparse_initialized) return 0;\r
-\r
-       while(pos < bitparse_bitstream_end) {\r
-               char current_name = *pos++;\r
-               unsigned int current_length = 0;\r
-               if(current_name < 'a' || current_name > 'e') {\r
-                       /* Strange section name, abort */\r
-                       break;\r
-               }\r
-               current_length = 0;\r
-               switch(current_name) {\r
-               case 'e':\r
-                       /* Four byte length field */\r
-                       current_length += (*pos++) << 24;\r
-                       current_length += (*pos++) << 16;\r
-               default: /* Fall through, two byte length field */\r
-                       current_length += (*pos++) << 8;\r
-                       current_length += (*pos++) << 0;\r
-               }\r
-               \r
-               if(current_name != 'e' && current_length > 255) {\r
-                       /* Maybe a parse error */\r
-                       break;\r
-               }\r
-               \r
-               if(current_name == section_name) {\r
-                       /* Found it */\r
-                       *section_start = pos;\r
-                       *section_length = current_length;\r
-                       result = 1;\r
-                       break;\r
-               }\r
-               \r
-               pos += current_length; /* Skip section */\r
-       }\r
-       \r
-       return result;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Find out which FPGA image format is stored in flash, then call DownloadFPGA\r
-// with the right parameters to download the image\r
-//-----------------------------------------------------------------------------\r
-extern char _binary_fpga_bit_start, _binary_fpga_bit_end;\r
-void FpgaDownloadAndGo(void)\r
-{\r
-       /* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start\r
-        */\r
-       if(bitparse_init(&_binary_fpga_bit_start, &_binary_fpga_bit_end)) {\r
-               /* Successfully initialized the .bit parser. Find the 'e' section and\r
-                * send its contents to the FPGA.\r
-                */\r
-               char *bitstream_start;\r
-               unsigned int bitstream_length;\r
-               if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) {\r
-                       DownloadFPGA(bitstream_start, bitstream_length, 0);\r
-                       \r
-                       return; /* All done */\r
-               }\r
-       }\r
-       \r
-       /* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF\r
-        * 0xAA995566 at address 0x102000. This is raw bitstream with a size of 336,768 bits \r
-        * = 10,524 DWORDs, stored as DWORDS e.g. little-endian in memory, but each DWORD\r
-        * is still to be transmitted in MSBit first order. Set the invert flag to indicate\r
-        * that the DownloadFPGA function should invert every 4 byte sequence when doing\r
-        * the bytewise download.\r
-        */\r
-       if( *(DWORD*)0x102000 == 0xFFFFFFFF && *(DWORD*)0x102004 == 0xAA995566 )\r
-               DownloadFPGA((char*)0x102000, 10524*4, 1);\r
-}\r
-\r
-void FpgaGatherVersion(char *dst, int len)\r
-{\r
-       char *fpga_info; \r
-       unsigned int fpga_info_len;\r
-       dst[0] = 0;\r
-       if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) {\r
-               strncat(dst, "FPGA image: legacy image without version information", len-1);\r
-       } else {\r
-               strncat(dst, "FPGA image built", len-1);\r
-               /* USB packets only have 48 bytes data payload, so be terse */\r
-#if 0\r
-               if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
-                       strncat(dst, " from ", len-1);\r
-                       strncat(dst, fpga_info, len-1);\r
-               }\r
-               if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
-                       strncat(dst, " for ", len-1);\r
-                       strncat(dst, fpga_info, len-1);\r
-               }\r
-#endif\r
-               if(bitparse_find_section('c', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
-                       strncat(dst, " on ", len-1);\r
-                       strncat(dst, fpga_info, len-1);\r
-               }\r
-               if(bitparse_find_section('d', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {\r
-                       strncat(dst, " at ", len-1);\r
-                       strncat(dst, fpga_info, len-1);\r
-               }\r
-       }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Send a 16 bit command/data pair to the FPGA.\r
-// The bit format is:  C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0\r
-// where C is the 4 bit command and D is the 12 bit data\r
-//-----------------------------------------------------------------------------\r
-void FpgaSendCommand(WORD cmd, WORD v)\r
-{\r
-       SetupSpi(SPI_FPGA_MODE);\r
-       while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0);              // wait for the transfer to complete\r
-       AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v;         // send the data\r
-}\r
-//-----------------------------------------------------------------------------\r
-// Write the FPGA setup word (that determines what mode the logic is in, read\r
-// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to\r
-// avoid changing this function's occurence everywhere in the source code.\r
-//-----------------------------------------------------------------------------\r
-void FpgaWriteConfWord(BYTE v)\r
-{\r
-       FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Set up the CMOS switches that mux the ADC: four switches, independently\r
-// closable, but should only close one at a time. Not an FPGA thing, but\r
-// the samples from the ADC always flow through the FPGA.\r
-//-----------------------------------------------------------------------------\r
-void SetAdcMuxFor(DWORD whichGpio)\r
-{\r
-       AT91C_BASE_PIOA->PIO_OER =\r
-               GPIO_MUXSEL_HIPKD |\r
-               GPIO_MUXSEL_LOPKD |\r
-               GPIO_MUXSEL_LORAW |\r
-               GPIO_MUXSEL_HIRAW;\r
-\r
-       AT91C_BASE_PIOA->PIO_PER =\r
-               GPIO_MUXSEL_HIPKD |\r
-               GPIO_MUXSEL_LOPKD |\r
-               GPIO_MUXSEL_LORAW |\r
-               GPIO_MUXSEL_HIRAW;\r
-\r
-       LOW(GPIO_MUXSEL_HIPKD);\r
-       LOW(GPIO_MUXSEL_HIRAW);\r
-       LOW(GPIO_MUXSEL_LORAW);\r
-       LOW(GPIO_MUXSEL_LOPKD);\r
-\r
-       HIGH(whichGpio);\r
-}\r
+//-----------------------------------------------------------------------------
+// Routines to load the FPGA image, and then to configure the FPGA's major
+// mode once it is configured.
+//
+// Jonathan Westhues, April 2006
+//-----------------------------------------------------------------------------
+#include <proxmark3.h>
+#include "apps.h"
+
+//-----------------------------------------------------------------------------
+// Set up the Serial Peripheral Interface as master
+// Used to write the FPGA config word
+// May also be used to write to other SPI attached devices like an LCD
+//-----------------------------------------------------------------------------
+void SetupSpi(int mode)
+{
+       // PA10 -> SPI_NCS2 chip select (LCD)
+       // PA11 -> SPI_NCS0 chip select (FPGA)
+       // PA12 -> SPI_MISO Master-In Slave-Out
+       // PA13 -> SPI_MOSI Master-Out Slave-In
+       // PA14 -> SPI_SPCK Serial Clock
+
+       // Disable PIO control of the following pins, allows use by the SPI peripheral
+       AT91C_BASE_PIOA->PIO_PDR =
+               GPIO_NCS0       |
+               GPIO_NCS2       |
+               GPIO_MISO       |
+               GPIO_MOSI       |
+               GPIO_SPCK;
+
+       AT91C_BASE_PIOA->PIO_ASR =
+               GPIO_NCS0       |
+               GPIO_MISO       |
+               GPIO_MOSI       |
+               GPIO_SPCK;
+
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_NCS2;
+
+       //enable the SPI Peripheral clock
+       AT91C_BASE_PMC->PMC_PCER = (1<<AT91C_ID_SPI);
+       // Enable SPI
+       AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
+
+       switch (mode) {
+               case SPI_FPGA_MODE:
+                       AT91C_BASE_SPI->SPI_MR =
+                               ( 0 << 24)      |       // Delay between chip selects (take default: 6 MCK periods)
+                               (14 << 16)      |       // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
+                               ( 0 << 7)       |       // Local Loopback Disabled
+                               ( 1 << 4)       |       // Mode Fault Detection disabled
+                               ( 0 << 2)       |       // Chip selects connected directly to peripheral
+                               ( 0 << 1)       |       // Fixed Peripheral Select
+                               ( 1 << 0);              // Master Mode
+                       AT91C_BASE_SPI->SPI_CSR[0] =
+                               ( 1 << 24)      |       // Delay between Consecutive Transfers (32 MCK periods)
+                               ( 1 << 16)      |       // Delay Before SPCK (1 MCK period)
+                               ( 6 << 8)       |       // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
+                               ( 8 << 4)       |       // Bits per Transfer (16 bits)
+                               ( 0 << 3)       |       // Chip Select inactive after transfer
+                               ( 1 << 1)       |       // Clock Phase data captured on leading edge, changes on following edge
+                               ( 0 << 0);              // Clock Polarity inactive state is logic 0
+                       break;
+               case SPI_LCD_MODE:
+                       AT91C_BASE_SPI->SPI_MR =
+                               ( 0 << 24)      |       // Delay between chip selects (take default: 6 MCK periods)
+                               (11 << 16)      |       // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10)
+                               ( 0 << 7)       |       // Local Loopback Disabled
+                               ( 1 << 4)       |       // Mode Fault Detection disabled
+                               ( 0 << 2)       |       // Chip selects connected directly to peripheral
+                               ( 0 << 1)       |       // Fixed Peripheral Select
+                               ( 1 << 0);              // Master Mode
+                       AT91C_BASE_SPI->SPI_CSR[2] =
+                               ( 1 << 24)      |       // Delay between Consecutive Transfers (32 MCK periods)
+                               ( 1 << 16)      |       // Delay Before SPCK (1 MCK period)
+                               ( 6 << 8)       |       // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
+                               ( 1 << 4)       |       // Bits per Transfer (9 bits)
+                               ( 0 << 3)       |       // Chip Select inactive after transfer
+                               ( 1 << 1)       |       // Clock Phase data captured on leading edge, changes on following edge
+                               ( 0 << 0);              // Clock Polarity inactive state is logic 0
+                       break;
+               default:                                // Disable SPI
+                       AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
+                       break;
+       }
+}
+
+//-----------------------------------------------------------------------------
+// Set up the synchronous serial port, with the one set of options that we
+// always use when we are talking to the FPGA. Both RX and TX are enabled.
+//-----------------------------------------------------------------------------
+void FpgaSetupSsc(void)
+{
+       // First configure the GPIOs, and get ourselves a clock.
+       AT91C_BASE_PIOA->PIO_ASR =
+               GPIO_SSC_FRAME  |
+               GPIO_SSC_DIN    |
+               GPIO_SSC_DOUT   |
+               GPIO_SSC_CLK;
+       AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
+
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);
+
+       // Now set up the SSC proper, starting from a known state.
+       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
+
+       // RX clock comes from TX clock, RX starts when TX starts, data changes
+       // on RX clock rising edge, sampled on falling edge
+       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
+       // pulse, no output sync, start on positive-going edge of sync
+       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
+       // edge of TK, start on rising edge of TF
+       AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) |
+               SSC_CLOCK_MODE_START(5);
+
+       // tx framing is the same as the rx framing
+       AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR;
+
+       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;
+}
+
+//-----------------------------------------------------------------------------
+// Set up DMA to receive samples from the FPGA. We will use the PDC, with
+// a single buffer as a circular buffer (so that we just chain back to
+// ourselves, not to another buffer). The stuff to manipulate those buffers
+// is in apps.h, because it should be inlined, for speed.
+//-----------------------------------------------------------------------------
+void FpgaSetupSscDma(BYTE *buf, int len)
+{
+       AT91C_BASE_PDC_SSC->PDC_RPR = (DWORD)buf;
+       AT91C_BASE_PDC_SSC->PDC_RCR = len;
+       AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)buf;
+       AT91C_BASE_PDC_SSC->PDC_RNCR = len;
+       AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
+}
+
+static void DownloadFPGA_byte(unsigned char 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); }
+       SEND_BIT(7);
+       SEND_BIT(6);
+       SEND_BIT(5);
+       SEND_BIT(4);
+       SEND_BIT(3);
+       SEND_BIT(2);
+       SEND_BIT(1);
+       SEND_BIT(0);
+}
+
+// Download the fpga image starting at FpgaImage and with length FpgaImageLen bytes
+// If bytereversal is set: reverse the byte order in each 4-byte word
+static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int bytereversal)
+{
+       int i=0;
+
+       AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON;
+       HIGH(GPIO_FPGA_ON);             // ensure everything is powered on
+
+       SpinDelay(50);
+
+       LED_D_ON();
+
+       // These pins are inputs
+    AT91C_BASE_PIOA->PIO_ODR =
+       GPIO_FPGA_NINIT |
+       GPIO_FPGA_DONE;
+       // PIO controls the following pins
+    AT91C_BASE_PIOA->PIO_PER =
+       GPIO_FPGA_NINIT |
+       GPIO_FPGA_DONE;
+       // Enable pull-ups
+       AT91C_BASE_PIOA->PIO_PPUER =
+               GPIO_FPGA_NINIT |
+               GPIO_FPGA_DONE;
+
+       // setup initial logic state
+       HIGH(GPIO_FPGA_NPROGRAM);
+       LOW(GPIO_FPGA_CCLK);
+       LOW(GPIO_FPGA_DIN);
+       // These pins are outputs
+       AT91C_BASE_PIOA->PIO_OER =
+               GPIO_FPGA_NPROGRAM      |
+               GPIO_FPGA_CCLK          |
+               GPIO_FPGA_DIN;
+
+       // enter FPGA configuration mode
+       LOW(GPIO_FPGA_NPROGRAM);
+       SpinDelay(50);
+       HIGH(GPIO_FPGA_NPROGRAM);
+
+       i=100000;
+       // wait for FPGA ready to accept data signal
+       while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) {
+               i--;
+       }
+
+       // crude error indicator, leave both red LEDs on and return
+       if (i==0){
+               LED_C_ON();
+               LED_D_ON();
+               return;
+       }
+
+       if(bytereversal) {
+               /* This is only supported for DWORD aligned images */
+               if( ((int)FpgaImage % sizeof(DWORD)) == 0 ) {
+                       i=0;
+                       while(FpgaImageLen-->0)
+                               DownloadFPGA_byte(FpgaImage[(i++)^0x3]);
+                       /* Explanation of the magic in the above line: 
+                        * i^0x3 inverts the lower two bits of the integer i, counting backwards
+                        * for each 4 byte increment. The generated sequence of (i++)^3 is
+                        * 3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12 etc. pp. 
+                        */
+               }
+       } else {
+               while(FpgaImageLen-->0)
+                       DownloadFPGA_byte(*FpgaImage++);
+       }
+
+       // continue to clock FPGA until ready signal goes high
+       i=100000;
+       while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) {
+               HIGH(GPIO_FPGA_CCLK);
+               LOW(GPIO_FPGA_CCLK);
+       }
+       // crude error indicator, leave both red LEDs on and return
+       if (i==0){
+               LED_C_ON();
+               LED_D_ON();
+               return;
+       }
+       LED_D_OFF();
+}
+
+static char *bitparse_headers_start;
+static char *bitparse_bitstream_end;
+static int bitparse_initialized;
+/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence
+ * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01
+ * After that the format is 1 byte section type (ASCII character), 2 byte length
+ * (big endian), <length> bytes content. Except for section 'e' which has 4 bytes
+ * length.
+ */
+static const char _bitparse_fixed_header[] = {0x00, 0x09, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xf0, 0x00, 0x00, 0x01};
+static int bitparse_init(void * start_address, void *end_address)
+{
+       bitparse_initialized = 0;
+       
+       if(memcmp(_bitparse_fixed_header, start_address, sizeof(_bitparse_fixed_header)) != 0) {
+               return 0; /* Not matched */
+       } else {
+               bitparse_headers_start= ((char*)start_address) + sizeof(_bitparse_fixed_header);
+               bitparse_bitstream_end= (char*)end_address;
+               bitparse_initialized = 1;
+               return 1;
+       }
+}
+
+int bitparse_find_section(char section_name, char **section_start, unsigned int *section_length)
+{
+       char *pos = bitparse_headers_start;
+       int result = 0;
+
+       if(!bitparse_initialized) return 0;
+
+       while(pos < bitparse_bitstream_end) {
+               char current_name = *pos++;
+               unsigned int current_length = 0;
+               if(current_name < 'a' || current_name > 'e') {
+                       /* Strange section name, abort */
+                       break;
+               }
+               current_length = 0;
+               switch(current_name) {
+               case 'e':
+                       /* Four byte length field */
+                       current_length += (*pos++) << 24;
+                       current_length += (*pos++) << 16;
+               default: /* Fall through, two byte length field */
+                       current_length += (*pos++) << 8;
+                       current_length += (*pos++) << 0;
+               }
+               
+               if(current_name != 'e' && current_length > 255) {
+                       /* Maybe a parse error */
+                       break;
+               }
+               
+               if(current_name == section_name) {
+                       /* Found it */
+                       *section_start = pos;
+                       *section_length = current_length;
+                       result = 1;
+                       break;
+               }
+               
+               pos += current_length; /* Skip section */
+       }
+       
+       return result;
+}
+
+//-----------------------------------------------------------------------------
+// Find out which FPGA image format is stored in flash, then call DownloadFPGA
+// with the right parameters to download the image
+//-----------------------------------------------------------------------------
+extern char _binary_fpga_bit_start, _binary_fpga_bit_end;
+void FpgaDownloadAndGo(void)
+{
+       /* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start
+        */
+       if(bitparse_init(&_binary_fpga_bit_start, &_binary_fpga_bit_end)) {
+               /* Successfully initialized the .bit parser. Find the 'e' section and
+                * send its contents to the FPGA.
+                */
+               char *bitstream_start;
+               unsigned int bitstream_length;
+               if(bitparse_find_section('e', &bitstream_start, &bitstream_length)) {
+                       DownloadFPGA(bitstream_start, bitstream_length, 0);
+                       
+                       return; /* All done */
+               }
+       }
+       
+       /* Fallback for the old flash image format: Check for the magic marker 0xFFFFFFFF
+        * 0xAA995566 at address 0x102000. This is raw bitstream with a size of 336,768 bits 
+        * = 10,524 DWORDs, stored as DWORDS e.g. little-endian in memory, but each DWORD
+        * is still to be transmitted in MSBit first order. Set the invert flag to indicate
+        * that the DownloadFPGA function should invert every 4 byte sequence when doing
+        * the bytewise download.
+        */
+       if( *(DWORD*)0x102000 == 0xFFFFFFFF && *(DWORD*)0x102004 == 0xAA995566 )
+               DownloadFPGA((char*)0x102000, 10524*4, 1);
+}
+
+void FpgaGatherVersion(char *dst, int len)
+{
+       char *fpga_info; 
+       unsigned int fpga_info_len;
+       dst[0] = 0;
+       if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) {
+               strncat(dst, "FPGA image: legacy image without version information", len-1);
+       } else {
+               strncat(dst, "FPGA image built", len-1);
+               /* USB packets only have 48 bytes data payload, so be terse */
+#if 0
+               if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
+                       strncat(dst, " from ", len-1);
+                       strncat(dst, fpga_info, len-1);
+               }
+               if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
+                       strncat(dst, " for ", len-1);
+                       strncat(dst, fpga_info, len-1);
+               }
+#endif
+               if(bitparse_find_section('c', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
+                       strncat(dst, " on ", len-1);
+                       strncat(dst, fpga_info, len-1);
+               }
+               if(bitparse_find_section('d', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
+                       strncat(dst, " at ", len-1);
+                       strncat(dst, fpga_info, len-1);
+               }
+       }
+}
+
+//-----------------------------------------------------------------------------
+// Send a 16 bit command/data pair to the FPGA.
+// The bit format is:  C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
+// where C is the 4 bit command and D is the 12 bit data
+//-----------------------------------------------------------------------------
+void FpgaSendCommand(WORD cmd, WORD v)
+{
+       SetupSpi(SPI_FPGA_MODE);
+       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
+}
+//-----------------------------------------------------------------------------
+// Write the FPGA setup word (that determines what mode the logic is in, read
+// vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to
+// avoid changing this function's occurence everywhere in the source code.
+//-----------------------------------------------------------------------------
+void FpgaWriteConfWord(BYTE v)
+{
+       FpgaSendCommand(FPGA_CMD_SET_CONFREG, v);
+}
+
+//-----------------------------------------------------------------------------
+// Set up the CMOS switches that mux the ADC: four switches, independently
+// closable, but should only close one at a time. Not an FPGA thing, but
+// the samples from the ADC always flow through the FPGA.
+//-----------------------------------------------------------------------------
+void SetAdcMuxFor(DWORD whichGpio)
+{
+       AT91C_BASE_PIOA->PIO_OER =
+               GPIO_MUXSEL_HIPKD |
+               GPIO_MUXSEL_LOPKD |
+               GPIO_MUXSEL_LORAW |
+               GPIO_MUXSEL_HIRAW;
+
+       AT91C_BASE_PIOA->PIO_PER =
+               GPIO_MUXSEL_HIPKD |
+               GPIO_MUXSEL_LOPKD |
+               GPIO_MUXSEL_LORAW |
+               GPIO_MUXSEL_HIRAW;
+
+       LOW(GPIO_MUXSEL_HIPKD);
+       LOW(GPIO_MUXSEL_HIRAW);
+       LOW(GPIO_MUXSEL_LORAW);
+       LOW(GPIO_MUXSEL_LOPKD);
+
+       HIGH(whichGpio);
+}
index b20d1be934aa8be4e318beadccfec1cf8067ceda..1543efc9bd04d93a120cbf3505f014228ebd6efe 100644 (file)
-//-----------------------------------------------------------------------------\r
-// Routines to support ISO 14443. This includes both the reader software and\r
-// the `fake tag' modes. At the moment only the Type B modulation is\r
-// supported.\r
-// Jonathan Westhues, split Nov 2006\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-#include "iso14443crc.h"\r
-\r
-\r
-//static void GetSamplesFor14443(BOOL weTx, int n);\r
-\r
-#define DEMOD_TRACE_SIZE 4096\r
-#define READER_TAG_BUFFER_SIZE 2048\r
-#define TAG_READER_BUFFER_SIZE 2048\r
-#define DMA_BUFFER_SIZE 1024\r
-\r
-//=============================================================================\r
-// An ISO 14443 Type B tag. We listen for commands from the reader, using\r
-// a UART kind of thing that's implemented in software. When we get a\r
-// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.\r
-// If it's good, then we can do something appropriate with it, and send\r
-// a response.\r
-//=============================================================================\r
-\r
-//-----------------------------------------------------------------------------\r
-// Code up a string of octets at layer 2 (including CRC, we don't generate\r
-// that here) so that they can be transmitted to the reader. Doesn't transmit\r
-// them yet, just leaves them ready to send in ToSend[].\r
-//-----------------------------------------------------------------------------\r
-static void CodeIso14443bAsTag(const BYTE *cmd, int len)\r
-{\r
-    int i;\r
-\r
-    ToSendReset();\r
-\r
-    // Transmit a burst of ones, as the initial thing that lets the\r
-    // reader get phase sync. This (TR1) must be > 80/fs, per spec,\r
-    // but tag that I've tried (a Paypass) exceeds that by a fair bit,\r
-    // so I will too.\r
-    for(i = 0; i < 20; i++) {\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-    }\r
-\r
-    // Send SOF.\r
-    for(i = 0; i < 10; i++) {\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-    }\r
-    for(i = 0; i < 2; i++) {\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-    }\r
-\r
-    for(i = 0; i < len; i++) {\r
-        int j;\r
-        BYTE b = cmd[i];\r
-\r
-        // Start bit\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-\r
-        // Data bits\r
-        for(j = 0; j < 8; j++) {\r
-            if(b & 1) {\r
-                ToSendStuffBit(1);\r
-                ToSendStuffBit(1);\r
-                ToSendStuffBit(1);\r
-                ToSendStuffBit(1);\r
-            } else {\r
-                ToSendStuffBit(0);\r
-                ToSendStuffBit(0);\r
-                ToSendStuffBit(0);\r
-                ToSendStuffBit(0);\r
-            }\r
-            b >>= 1;\r
-        }\r
-\r
-        // Stop bit\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-    }\r
-\r
-    // Send SOF.\r
-    for(i = 0; i < 10; i++) {\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-        ToSendStuffBit(0);\r
-    }\r
-    for(i = 0; i < 10; i++) {\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-    }\r
-\r
-    // Convert from last byte pos to length\r
-    ToSendMax++;\r
-\r
-    // Add a few more for slop\r
-    ToSendMax += 2;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// The software UART that receives commands from the reader, and its state\r
-// variables.\r
-//-----------------------------------------------------------------------------\r
-static struct {\r
-    enum {\r
-        STATE_UNSYNCD,\r
-        STATE_GOT_FALLING_EDGE_OF_SOF,\r
-        STATE_AWAITING_START_BIT,\r
-        STATE_RECEIVING_DATA,\r
-        STATE_ERROR_WAIT\r
-    }       state;\r
-    WORD    shiftReg;\r
-    int     bitCnt;\r
-    int     byteCnt;\r
-    int     byteCntMax;\r
-    int     posCnt;\r
-    BYTE   *output;\r
-} Uart;\r
-\r
-/* Receive & handle a bit coming from the reader.\r
- *\r
- * LED handling:\r
- * LED A -> ON once we have received the SOF and are expecting the rest.\r
- * LED A -> OFF once we have received EOF or are in error state or unsynced\r
- *\r
- * Returns: true if we received a EOF\r
- *          false if we are still waiting for some more\r
- */\r
-static BOOL Handle14443UartBit(int bit)\r
-{\r
-    switch(Uart.state) {\r
-        case STATE_UNSYNCD:\r
-               LED_A_OFF();\r
-            if(!bit) {\r
-                // we went low, so this could be the beginning\r
-                // of an SOF\r
-                Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;\r
-                Uart.posCnt = 0;\r
-                Uart.bitCnt = 0;\r
-            }\r
-            break;\r
-\r
-        case STATE_GOT_FALLING_EDGE_OF_SOF:\r
-            Uart.posCnt++;\r
-            if(Uart.posCnt == 2) {\r
-                if(bit) {\r
-                    if(Uart.bitCnt >= 10) {\r
-                        // we've seen enough consecutive\r
-                        // zeros that it's a valid SOF\r
-                        Uart.posCnt = 0;\r
-                        Uart.byteCnt = 0;\r
-                        Uart.state = STATE_AWAITING_START_BIT;\r
-                        LED_A_ON(); // Indicate we got a valid SOF\r
-                    } else {\r
-                        // didn't stay down long enough\r
-                        // before going high, error\r
-                        Uart.state = STATE_ERROR_WAIT;\r
-                    }\r
-                } else {\r
-                    // do nothing, keep waiting\r
-                }\r
-                Uart.bitCnt++;\r
-            }\r
-            if(Uart.posCnt >= 4) Uart.posCnt = 0;\r
-            if(Uart.bitCnt > 14) {\r
-                // Give up if we see too many zeros without\r
-                // a one, too.\r
-                Uart.state = STATE_ERROR_WAIT;\r
-            }\r
-            break;\r
-\r
-        case STATE_AWAITING_START_BIT:\r
-            Uart.posCnt++;\r
-            if(bit) {\r
-                if(Uart.posCnt > 25) {\r
-                    // stayed high for too long between\r
-                    // characters, error\r
-                    Uart.state = STATE_ERROR_WAIT;\r
-                }\r
-            } else {\r
-                // falling edge, this starts the data byte\r
-                Uart.posCnt = 0;\r
-                Uart.bitCnt = 0;\r
-                Uart.shiftReg = 0;\r
-                Uart.state = STATE_RECEIVING_DATA;\r
-                LED_A_ON(); // Indicate we're receiving\r
-            }\r
-            break;\r
-\r
-        case STATE_RECEIVING_DATA:\r
-            Uart.posCnt++;\r
-            if(Uart.posCnt == 2) {\r
-                // time to sample a bit\r
-                Uart.shiftReg >>= 1;\r
-                if(bit) {\r
-                    Uart.shiftReg |= 0x200;\r
-                }\r
-                Uart.bitCnt++;\r
-            }\r
-            if(Uart.posCnt >= 4) {\r
-                Uart.posCnt = 0;\r
-            }\r
-            if(Uart.bitCnt == 10) {\r
-                if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))\r
-                {\r
-                    // this is a data byte, with correct\r
-                    // start and stop bits\r
-                    Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;\r
-                    Uart.byteCnt++;\r
-\r
-                    if(Uart.byteCnt >= Uart.byteCntMax) {\r
-                        // Buffer overflowed, give up\r
-                        Uart.posCnt = 0;\r
-                        Uart.state = STATE_ERROR_WAIT;\r
-                    } else {\r
-                        // so get the next byte now\r
-                        Uart.posCnt = 0;\r
-                        Uart.state = STATE_AWAITING_START_BIT;\r
-                    }\r
-                } else if(Uart.shiftReg == 0x000) {\r
-                    // this is an EOF byte\r
-                       LED_A_OFF(); // Finished receiving\r
-                    return TRUE;\r
-                } else {\r
-                    // this is an error\r
-                    Uart.posCnt = 0;\r
-                    Uart.state = STATE_ERROR_WAIT;\r
-                }\r
-            }\r
-            break;\r
-\r
-        case STATE_ERROR_WAIT:\r
-            // We're all screwed up, so wait a little while\r
-            // for whatever went wrong to finish, and then\r
-            // start over.\r
-            Uart.posCnt++;\r
-            if(Uart.posCnt > 10) {\r
-                Uart.state = STATE_UNSYNCD;\r
-            }\r
-            break;\r
-\r
-        default:\r
-            Uart.state = STATE_UNSYNCD;\r
-            break;\r
-    }\r
-\r
-    if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error\r
-\r
-    return FALSE;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Receive a command (from the reader to us, where we are the simulated tag),\r
-// and store it in the given buffer, up to the given maximum length. Keeps\r
-// spinning, waiting for a well-framed command, until either we get one\r
-// (returns TRUE) or someone presses the pushbutton on the board (FALSE).\r
-//\r
-// Assume that we're called with the SSC (to the FPGA) and ADC path set\r
-// correctly.\r
-//-----------------------------------------------------------------------------\r
-static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)\r
-{\r
-    BYTE mask;\r
-    int i, bit;\r
-\r
-    // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen\r
-    // only, since we are receiving, not transmitting).\r
-    // Signal field is off with the appropriate LED\r
-    LED_D_OFF();\r
-    FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);\r
-\r
-\r
-    // Now run a `software UART' on the stream of incoming samples.\r
-    Uart.output = received;\r
-    Uart.byteCntMax = maxLen;\r
-    Uart.state = STATE_UNSYNCD;\r
-\r
-    for(;;) {\r
-        WDT_HIT();\r
-\r
-        if(BUTTON_PRESS()) return FALSE;\r
-\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = 0x00;\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-            BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
-\r
-            mask = 0x80;\r
-            for(i = 0; i < 8; i++, mask >>= 1) {\r
-                bit = (b & mask);\r
-                if(Handle14443UartBit(bit)) {\r
-                    *len = Uart.byteCnt;\r
-                    return TRUE;\r
-                }\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Main loop of simulated tag: receive commands from reader, decide what\r
-// response to send, and send it.\r
-//-----------------------------------------------------------------------------\r
-void SimulateIso14443Tag(void)\r
-{\r
-    static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
-    static const BYTE response1[] = {\r
-        0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,\r
-        0x00, 0x21, 0x85, 0x5e, 0xd7\r
-    };\r
-\r
-    BYTE *resp;\r
-    int respLen;\r
-\r
-    BYTE *resp1 = (((BYTE *)BigBuf) + 800);\r
-    int resp1Len;\r
-\r
-    BYTE *receivedCmd = (BYTE *)BigBuf;\r
-    int len;\r
-\r
-    int i;\r
-\r
-    int cmdsRecvd = 0;\r
-\r
-    memset(receivedCmd, 0x44, 400);\r
-\r
-    CodeIso14443bAsTag(response1, sizeof(response1));\r
-    memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;\r
-\r
-    // We need to listen to the high-frequency, peak-detected path.\r
-    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-    FpgaSetupSsc();\r
-\r
-    cmdsRecvd = 0;\r
-\r
-    for(;;) {\r
-        BYTE b1, b2;\r
-\r
-        if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {\r
-               Dbprintf("button pressed, received %d commands", cmdsRecvd);\r
-               break;\r
-        }\r
-\r
-        // Good, look at the command now.\r
-\r
-        if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {\r
-            resp = resp1; respLen = resp1Len;\r
-        } else {\r
-            Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);\r
-            // And print whether the CRC fails, just for good measure\r
-            ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);\r
-            if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {\r
-                // Not so good, try again.\r
-                DbpString("+++CRC fail");\r
-            } else {\r
-                DbpString("CRC passes");\r
-            }\r
-            break;\r
-        }\r
-\r
-        memset(receivedCmd, 0x44, 32);\r
-\r
-        cmdsRecvd++;\r
-\r
-        if(cmdsRecvd > 0x30) {\r
-            DbpString("many commands later...");\r
-            break;\r
-        }\r
-\r
-        if(respLen <= 0) continue;\r
-\r
-        // Modulate BPSK\r
-        // Signal field is off with the appropriate LED\r
-        LED_D_OFF();\r
-        FpgaWriteConfWord(\r
-               FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);\r
-        AT91C_BASE_SSC->SSC_THR = 0xff;\r
-        FpgaSetupSsc();\r
-\r
-        // Transmit the response.\r
-        i = 0;\r
-        for(;;) {\r
-            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-                BYTE b = resp[i];\r
-\r
-                AT91C_BASE_SSC->SSC_THR = b;\r
-\r
-                i++;\r
-                if(i > respLen) {\r
-                    break;\r
-                }\r
-            }\r
-            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-                volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
-                (void)b;\r
-            }\r
-        }\r
-    }\r
-}\r
-\r
-//=============================================================================\r
-// An ISO 14443 Type B reader. We take layer two commands, code them\r
-// appropriately, and then send them to the tag. We then listen for the\r
-// tag's response, which we leave in the buffer to be demodulated on the\r
-// PC side.\r
-//=============================================================================\r
-\r
-static struct {\r
-    enum {\r
-        DEMOD_UNSYNCD,\r
-        DEMOD_PHASE_REF_TRAINING,\r
-        DEMOD_AWAITING_FALLING_EDGE_OF_SOF,\r
-        DEMOD_GOT_FALLING_EDGE_OF_SOF,\r
-        DEMOD_AWAITING_START_BIT,\r
-        DEMOD_RECEIVING_DATA,\r
-        DEMOD_ERROR_WAIT\r
-    }       state;\r
-    int     bitCount;\r
-    int     posCount;\r
-    int     thisBit;\r
-    int     metric;\r
-    int     metricN;\r
-    WORD    shiftReg;\r
-    BYTE   *output;\r
-    int     len;\r
-    int     sumI;\r
-    int     sumQ;\r
-} Demod;\r
-\r
-/*\r
- * Handles reception of a bit from the tag\r
- *\r
- * LED handling:\r
- * LED C -> ON once we have received the SOF and are expecting the rest.\r
- * LED C -> OFF once we have received EOF or are unsynced\r
- *\r
- * Returns: true if we received a EOF\r
- *          false if we are still waiting for some more\r
- *\r
- */\r
-static BOOL Handle14443SamplesDemod(int ci, int cq)\r
-{\r
-    int v;\r
-\r
-    // The soft decision on the bit uses an estimate of just the\r
-    // quadrant of the reference angle, not the exact angle.\r
-#define MAKE_SOFT_DECISION() { \\r
-        if(Demod.sumI > 0) { \\r
-            v = ci; \\r
-        } else { \\r
-            v = -ci; \\r
-        } \\r
-        if(Demod.sumQ > 0) { \\r
-            v += cq; \\r
-        } else { \\r
-            v -= cq; \\r
-        } \\r
-    }\r
-\r
-    switch(Demod.state) {\r
-        case DEMOD_UNSYNCD:\r
-            v = ci;\r
-            if(v < 0) v = -v;\r
-            if(cq > 0) {\r
-                v += cq;\r
-            } else {\r
-                v -= cq;\r
-            }\r
-            if(v > 40) {\r
-                Demod.posCount = 0;\r
-                Demod.state = DEMOD_PHASE_REF_TRAINING;\r
-                Demod.sumI = 0;\r
-                Demod.sumQ = 0;\r
-            }\r
-            break;\r
-\r
-        case DEMOD_PHASE_REF_TRAINING:\r
-            if(Demod.posCount < 8) {\r
-                Demod.sumI += ci;\r
-                Demod.sumQ += cq;\r
-            } else if(Demod.posCount > 100) {\r
-                // error, waited too long\r
-                Demod.state = DEMOD_UNSYNCD;\r
-            } else {\r
-                MAKE_SOFT_DECISION();\r
-                if(v < 0) {\r
-                    Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;\r
-                    Demod.posCount = 0;\r
-                }\r
-            }\r
-            Demod.posCount++;\r
-            break;\r
-\r
-        case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:\r
-            MAKE_SOFT_DECISION();\r
-            if(v < 0) {\r
-                Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;\r
-                Demod.posCount = 0;\r
-            } else {\r
-                if(Demod.posCount > 100) {\r
-                    Demod.state = DEMOD_UNSYNCD;\r
-                }\r
-            }\r
-            Demod.posCount++;\r
-            break;\r
-\r
-        case DEMOD_GOT_FALLING_EDGE_OF_SOF:\r
-            MAKE_SOFT_DECISION();\r
-            if(v > 0) {\r
-                if(Demod.posCount < 12) {\r
-                    Demod.state = DEMOD_UNSYNCD;\r
-                } else {\r
-                       LED_C_ON(); // Got SOF\r
-                    Demod.state = DEMOD_AWAITING_START_BIT;\r
-                    Demod.posCount = 0;\r
-                    Demod.len = 0;\r
-                    Demod.metricN = 0;\r
-                    Demod.metric = 0;\r
-                }\r
-            } else {\r
-                if(Demod.posCount > 100) {\r
-                    Demod.state = DEMOD_UNSYNCD;\r
-                }\r
-            }\r
-            Demod.posCount++;\r
-            break;\r
-\r
-        case DEMOD_AWAITING_START_BIT:\r
-            MAKE_SOFT_DECISION();\r
-            if(v > 0) {\r
-                if(Demod.posCount > 10) {\r
-                    Demod.state = DEMOD_UNSYNCD;\r
-                }\r
-            } else {\r
-                Demod.bitCount = 0;\r
-                Demod.posCount = 1;\r
-                Demod.thisBit = v;\r
-                Demod.shiftReg = 0;\r
-                Demod.state = DEMOD_RECEIVING_DATA;\r
-            }\r
-            break;\r
-\r
-        case DEMOD_RECEIVING_DATA:\r
-            MAKE_SOFT_DECISION();\r
-            if(Demod.posCount == 0) {\r
-                Demod.thisBit = v;\r
-                Demod.posCount = 1;\r
-            } else {\r
-                Demod.thisBit += v;\r
-\r
-                if(Demod.thisBit > 0) {\r
-                    Demod.metric += Demod.thisBit;\r
-                } else {\r
-                    Demod.metric -= Demod.thisBit;\r
-                }\r
-                (Demod.metricN)++;\r
-\r
-                Demod.shiftReg >>= 1;\r
-                if(Demod.thisBit > 0) {\r
-                    Demod.shiftReg |= 0x200;\r
-                }\r
-\r
-                Demod.bitCount++;\r
-                if(Demod.bitCount == 10) {\r
-                    WORD s = Demod.shiftReg;\r
-                    if((s & 0x200) && !(s & 0x001)) {\r
-                        BYTE b = (s >> 1);\r
-                        Demod.output[Demod.len] = b;\r
-                        Demod.len++;\r
-                        Demod.state = DEMOD_AWAITING_START_BIT;\r
-                    } else if(s == 0x000) {\r
-                        // This is EOF\r
-                       LED_C_OFF();\r
-                        return TRUE;\r
-                        Demod.state = DEMOD_UNSYNCD;\r
-                    } else {\r
-                        Demod.state = DEMOD_UNSYNCD;\r
-                    }\r
-                }\r
-                Demod.posCount = 0;\r
-            }\r
-            break;\r
-\r
-        default:\r
-            Demod.state = DEMOD_UNSYNCD;\r
-            break;\r
-    }\r
-\r
-    if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...\r
-    return FALSE;\r
-}\r
-\r
-/*\r
- *  Demodulate the samples we received from the tag\r
- *  weTx: set to 'TRUE' if we behave like a reader\r
- *        set to 'FALSE' if we behave like a snooper\r
- *  quiet: set to 'TRUE' to disable debug output\r
- */\r
-static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet)\r
-{\r
-    int max = 0;\r
-    BOOL gotFrame = FALSE;\r
-\r
-//#   define DMA_BUFFER_SIZE 8\r
-    SBYTE *dmaBuf;\r
-\r
-    int lastRxCounter;\r
-    SBYTE *upTo;\r
-\r
-    int ci, cq;\r
-\r
-    int samples = 0;\r
-\r
-    // Clear out the state of the "UART" that receives from the tag.\r
-    memset(BigBuf, 0x44, 400);\r
-    Demod.output = (BYTE *)BigBuf;\r
-    Demod.len = 0;\r
-    Demod.state = DEMOD_UNSYNCD;\r
-\r
-    // And the UART that receives from the reader\r
-    Uart.output = (((BYTE *)BigBuf) + 1024);\r
-    Uart.byteCntMax = 100;\r
-    Uart.state = STATE_UNSYNCD;\r
-\r
-    // Setup for the DMA.\r
-    dmaBuf = (SBYTE *)(BigBuf + 32);\r
-    upTo = dmaBuf;\r
-    lastRxCounter = DMA_BUFFER_SIZE;\r
-    FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
-\r
-    // Signal field is ON with the appropriate LED:\r
-       if (weTx) LED_D_ON(); else LED_D_OFF();\r
-    // And put the FPGA in the appropriate mode\r
-    FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
-       (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
-\r
-    for(;;) {\r
-        int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;\r
-        if(behindBy > max) max = behindBy;\r
-\r
-        while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1))\r
-                    > 2)\r
-        {\r
-            ci = upTo[0];\r
-            cq = upTo[1];\r
-            upTo += 2;\r
-            if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
-                upTo -= DMA_BUFFER_SIZE;\r
-                AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)upTo;\r
-                AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
-            }\r
-            lastRxCounter -= 2;\r
-            if(lastRxCounter <= 0) {\r
-                lastRxCounter += DMA_BUFFER_SIZE;\r
-            }\r
-\r
-            samples += 2;\r
-\r
-            Handle14443UartBit(1);\r
-            Handle14443UartBit(1);\r
-\r
-            if(Handle14443SamplesDemod(ci, cq)) {\r
-                gotFrame = 1;\r
-            }\r
-        }\r
-\r
-        if(samples > 2000) {\r
-            break;\r
-        }\r
-    }\r
-    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
-    if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len);\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Read the tag's response. We just receive a stream of slightly-processed\r
-// samples from the FPGA, which we will later do some signal processing on,\r
-// to get the bits.\r
-//-----------------------------------------------------------------------------\r
-/*static void GetSamplesFor14443(BOOL weTx, int n)\r
-{\r
-    BYTE *dest = (BYTE *)BigBuf;\r
-    int c;\r
-\r
-    FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
-       (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
-\r
-    c = 0;\r
-    for(;;) {\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = 0x43;\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-            SBYTE b;\r
-            b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;\r
-\r
-            dest[c++] = (BYTE)b;\r
-\r
-            if(c >= n) {\r
-                break;\r
-            }\r
-        }\r
-    }\r
-}*/\r
-\r
-//-----------------------------------------------------------------------------\r
-// Transmit the command (to the tag) that was placed in ToSend[].\r
-//-----------------------------------------------------------------------------\r
-static void TransmitFor14443(void)\r
-{\r
-    int c;\r
-\r
-    FpgaSetupSsc();\r
-\r
-    while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-        AT91C_BASE_SSC->SSC_THR = 0xff;\r
-    }\r
-\r
-    // Signal field is ON with the appropriate Red LED\r
-       LED_D_ON();\r
-       // Signal we are transmitting with the Green LED\r
-       LED_B_ON();\r
-       FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);\r
-\r
-    for(c = 0; c < 10;) {\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = 0xff;\r
-            c++;\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
-            (void)r;\r
-        }\r
-        WDT_HIT();\r
-    }\r
-\r
-    c = 0;\r
-    for(;;) {\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = ToSend[c];\r
-            c++;\r
-            if(c >= ToSendMax) {\r
-                break;\r
-            }\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;\r
-            (void)r;\r
-        }\r
-        WDT_HIT();\r
-    }\r
-    LED_B_OFF(); // Finished sending\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Code a layer 2 command (string of octets, including CRC) into ToSend[],\r
-// so that it is ready to transmit to the tag using TransmitFor14443().\r
-//-----------------------------------------------------------------------------\r
-void CodeIso14443bAsReader(const BYTE *cmd, int len)\r
-{\r
-    int i, j;\r
-    BYTE b;\r
-\r
-    ToSendReset();\r
-\r
-    // Establish initial reference level\r
-    for(i = 0; i < 40; i++) {\r
-        ToSendStuffBit(1);\r
-    }\r
-    // Send SOF\r
-    for(i = 0; i < 10; i++) {\r
-        ToSendStuffBit(0);\r
-    }\r
-\r
-    for(i = 0; i < len; i++) {\r
-        // Stop bits/EGT\r
-        ToSendStuffBit(1);\r
-        ToSendStuffBit(1);\r
-        // Start bit\r
-        ToSendStuffBit(0);\r
-        // Data bits\r
-        b = cmd[i];\r
-        for(j = 0; j < 8; j++) {\r
-            if(b & 1) {\r
-                ToSendStuffBit(1);\r
-            } else {\r
-                ToSendStuffBit(0);\r
-            }\r
-            b >>= 1;\r
-        }\r
-    }\r
-    // Send EOF\r
-    ToSendStuffBit(1);\r
-    for(i = 0; i < 10; i++) {\r
-        ToSendStuffBit(0);\r
-    }\r
-    for(i = 0; i < 8; i++) {\r
-        ToSendStuffBit(1);\r
-    }\r
-\r
-    // And then a little more, to make sure that the last character makes\r
-    // it out before we switch to rx mode.\r
-    for(i = 0; i < 24; i++) {\r
-        ToSendStuffBit(1);\r
-    }\r
-\r
-    // Convert from last character reference to length\r
-    ToSendMax++;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Read an ISO 14443 tag. We send it some set of commands, and record the\r
-// responses.\r
-// The command name is misleading, it actually decodes the reponse in HEX\r
-// into the output buffer (read the result using hexsamples, not hisamples)\r
-//-----------------------------------------------------------------------------\r
-void AcquireRawAdcSamplesIso14443(DWORD parameter)\r
-{\r
-    BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
-\r
-    // Make sure that we start from off, since the tags are stateful;\r
-    // confusing things will happen if we don't reset them between reads.\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-    LED_D_OFF();\r
-    SpinDelay(200);\r
-\r
-    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-    FpgaSetupSsc();\r
-\r
-    // Now give it time to spin up.\r
-    // Signal field is on with the appropriate LED\r
-    LED_D_ON();\r
-    FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
-    SpinDelay(200);\r
-\r
-    CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
-    TransmitFor14443();\r
-//    LED_A_ON();\r
-    GetSamplesFor14443Demod(TRUE, 2000, FALSE);\r
-//    LED_A_OFF();\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Read a SRI512 ISO 14443 tag.\r
-//\r
-// SRI512 tags are just simple memory tags, here we're looking at making a dump\r
-// of the contents of the memory. No anticollision algorithm is done, we assume\r
-// we have a single tag in the field.\r
-//\r
-// I tried to be systematic and check every answer of the tag, every CRC, etc...\r
-//-----------------------------------------------------------------------------\r
-void ReadSRI512Iso14443(DWORD parameter)\r
-{\r
-     ReadSTMemoryIso14443(parameter,0x0F);\r
-}\r
-void ReadSRIX4KIso14443(DWORD parameter)\r
-{\r
-     ReadSTMemoryIso14443(parameter,0x7F);\r
-}\r
-\r
-void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast)\r
-{\r
-    BYTE i = 0x00;\r
-\r
-    // Make sure that we start from off, since the tags are stateful;\r
-    // confusing things will happen if we don't reset them between reads.\r
-    LED_D_OFF();\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-    SpinDelay(200);\r
-\r
-    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-    FpgaSetupSsc();\r
-\r
-    // Now give it time to spin up.\r
-    // Signal field is on with the appropriate LED\r
-    LED_D_ON();\r
-    FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
-    SpinDelay(200);\r
-\r
-    // First command: wake up the tag using the INITIATE command\r
-    BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b};\r
-    CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
-    TransmitFor14443();\r
-//    LED_A_ON();\r
-    GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
-//    LED_A_OFF();\r
-\r
-    if (Demod.len == 0) {\r
-       DbpString("No response from tag");\r
-       return;\r
-    } else {\r
-       Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x",\r
-               Demod.output[0], Demod.output[1],Demod.output[2]);\r
-    }\r
-    // There is a response, SELECT the uid\r
-    DbpString("Now SELECT tag:");\r
-    cmd1[0] = 0x0E; // 0x0E is SELECT\r
-    cmd1[1] = Demod.output[0];\r
-    ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
-    CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
-    TransmitFor14443();\r
-//    LED_A_ON();\r
-    GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
-//    LED_A_OFF();\r
-    if (Demod.len != 3) {\r
-       Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);\r
-       return;\r
-    }\r
-    // Check the CRC of the answer:\r
-    ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);\r
-    if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {\r
-       DbpString("CRC Error reading select response.");\r
-       return;\r
-    }\r
-    // Check response from the tag: should be the same UID as the command we just sent:\r
-    if (cmd1[1] != Demod.output[0]) {\r
-       Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]);\r
-       return;\r
-    }\r
-    // Tag is now selected,\r
-    // First get the tag's UID:\r
-    cmd1[0] = 0x0B;\r
-    ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);\r
-    CodeIso14443bAsReader(cmd1, 3); // Only first three bytes for this one\r
-    TransmitFor14443();\r
-//    LED_A_ON();\r
-    GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
-//    LED_A_OFF();\r
-    if (Demod.len != 10) {\r
-       Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);\r
-       return;\r
-    }\r
-    // The check the CRC of the answer (use cmd1 as temporary variable):\r
-    ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);\r
-           if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {\r
-       Dbprintf("CRC Error reading block! - Below: expected, got %x %x",\r
-               (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);\r
-       // Do not return;, let's go on... (we should retry, maybe ?)\r
-    }\r
-    Dbprintf("Tag UID (64 bits): %08x %08x",\r
-       (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],\r
-       (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);\r
-\r
-    // Now loop to read all 16 blocks, address from 0 to 15\r
-    DbpString("Tag memory dump, block 0 to 15");\r
-    cmd1[0] = 0x08;\r
-    i = 0x00;\r
-    dwLast++;\r
-    for (;;) {\r
-           if (i == dwLast) {\r
-                   DbpString("System area block (0xff):");\r
-                   i = 0xff;\r
-           }\r
-           cmd1[1] = i;\r
-           ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
-           CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
-           TransmitFor14443();\r
-//         LED_A_ON();\r
-           GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
-//         LED_A_OFF();\r
-           if (Demod.len != 6) { // Check if we got an answer from the tag\r
-               DbpString("Expected 6 bytes from tag, got less...");\r
-               return;\r
-           }\r
-           // The check the CRC of the answer (use cmd1 as temporary variable):\r
-           ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);\r
-            if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {\r
-               Dbprintf("CRC Error reading block! - Below: expected, got %x %x",\r
-                       (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);\r
-               // Do not return;, let's go on... (we should retry, maybe ?)\r
-           }\r
-           // Now print out the memory location:\r
-           Dbprintf("Address=%x, Contents=%x, CRC=%x", i,\r
-               (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],\r
-               (Demod.output[4]<<8)+Demod.output[5]);\r
-           if (i == 0xff) {\r
-               break;\r
-           }\r
-           i++;\r
-    }\r
-}\r
-\r
-\r
-//=============================================================================\r
-// Finally, the `sniffer' combines elements from both the reader and\r
-// simulated tag, to show both sides of the conversation.\r
-//=============================================================================\r
-\r
-//-----------------------------------------------------------------------------\r
-// Record the sequence of commands sent by the reader to the tag, with\r
-// triggering so that we start recording at the point that the tag is moved\r
-// near the reader.\r
-//-----------------------------------------------------------------------------\r
-/*\r
- * Memory usage for this function, (within BigBuf)\r
- * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE\r
- * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE\r
- * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE\r
- * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DMA_BUFFER_SIZE\r
- */\r
-void SnoopIso14443(void)\r
-{\r
-    // We won't start recording the frames that we acquire until we trigger;\r
-    // a good trigger condition to get started is probably when we see a\r
-    // response from the tag.\r
-    BOOL triggered = FALSE;\r
-\r
-    // The command (reader -> tag) that we're working on receiving.\r
-    BYTE *receivedCmd = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE;\r
-    // The response (tag -> reader) that we're working on receiving.\r
-    BYTE *receivedResponse = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE;\r
-\r
-    // As we receive stuff, we copy it from receivedCmd or receivedResponse\r
-    // into trace, along with its length and other annotations.\r
-    BYTE *trace = (BYTE *)BigBuf;\r
-    int traceLen = 0;\r
-\r
-    // The DMA buffer, used to stream samples from the FPGA.\r
-    SBYTE *dmaBuf = (SBYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE + TAG_READER_BUFFER_SIZE;\r
-    int lastRxCounter;\r
-    SBYTE *upTo;\r
-    int ci, cq;\r
-    int maxBehindBy = 0;\r
-\r
-    // Count of samples received so far, so that we can include timing\r
-    // information in the trace buffer.\r
-    int samples = 0;\r
-\r
-    // Initialize the trace buffer\r
-    memset(trace, 0x44, DEMOD_TRACE_SIZE);\r
-\r
-    // Set up the demodulator for tag -> reader responses.\r
-    Demod.output = receivedResponse;\r
-    Demod.len = 0;\r
-    Demod.state = DEMOD_UNSYNCD;\r
-\r
-    // And the reader -> tag commands\r
-    memset(&Uart, 0, sizeof(Uart));\r
-    Uart.output = receivedCmd;\r
-    Uart.byteCntMax = 100;\r
-    Uart.state = STATE_UNSYNCD;\r
-\r
-       // Print some debug information about the buffer sizes\r
-       Dbprintf("Snooping buffers initialized:");\r
-       Dbprintf("  Trace: %i bytes", DEMOD_TRACE_SIZE);\r
-       Dbprintf("  Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE);\r
-       Dbprintf("  tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE);\r
-       Dbprintf("  DMA: %i bytes", DMA_BUFFER_SIZE);\r
-       \r
-       // Use a counter for blinking the LED\r
-       long ledCount=0;\r
-       long ledFlashAt=200000;\r
-       \r
-    // And put the FPGA in the appropriate mode\r
-    // Signal field is off with the appropriate LED\r
-    LED_D_OFF();\r
-    FpgaWriteConfWord(\r
-       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
-       FPGA_HF_READER_RX_XCORR_SNOOP);\r
-    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-\r
-    // Setup for the DMA.\r
-    FpgaSetupSsc();\r
-    upTo = dmaBuf;\r
-    lastRxCounter = DMA_BUFFER_SIZE;\r
-    FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
-    // And now we loop, receiving samples.\r
-    for(;;) {\r
-               // Blink the LED while Snooping\r
-               ledCount++;\r
-               if (ledCount == ledFlashAt) {\r
-                       LED_D_ON();\r
-               }\r
-               if (ledCount >= 2*ledFlashAt) {\r
-                       LED_D_OFF();\r
-                       ledCount=0;\r
-               }\r
-               \r
-       int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &\r
-                                (DMA_BUFFER_SIZE-1);\r
-        if(behindBy > maxBehindBy) {\r
-            maxBehindBy = behindBy;\r
-            if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not?\r
-                Dbprintf("blew circular buffer! behindBy=%x", behindBy);\r
-                goto done;\r
-            }\r
-        }\r
-        if(behindBy < 2) continue;\r
-\r
-        ci = upTo[0];\r
-        cq = upTo[1];\r
-        upTo += 2;\r
-        lastRxCounter -= 2;\r
-        if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
-            upTo -= DMA_BUFFER_SIZE;\r
-            lastRxCounter += DMA_BUFFER_SIZE;\r
-            AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD) upTo;\r
-            AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;\r
-        }\r
-\r
-        samples += 2;\r
-\r
-#define HANDLE_BIT_IF_BODY \\r
-            if(triggered) { \\r
-                               ledFlashAt=30000; \\r
-                trace[traceLen++] = ((samples >>  0) & 0xff); \\r
-                trace[traceLen++] = ((samples >>  8) & 0xff); \\r
-                trace[traceLen++] = ((samples >> 16) & 0xff); \\r
-                trace[traceLen++] = ((samples >> 24) & 0xff); \\r
-                trace[traceLen++] = 0; \\r
-                trace[traceLen++] = 0; \\r
-                trace[traceLen++] = 0; \\r
-                trace[traceLen++] = 0; \\r
-                trace[traceLen++] = Uart.byteCnt; \\r
-                memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \\r
-                traceLen += Uart.byteCnt; \\r
-                if(traceLen > 1000) break; \\r
-            } \\r
-            /* And ready to receive another command. */ \\r
-            memset(&Uart, 0, sizeof(Uart)); \\r
-            Uart.output = receivedCmd; \\r
-            Uart.byteCntMax = 100; \\r
-            Uart.state = STATE_UNSYNCD; \\r
-            /* And also reset the demod code, which might have been */ \\r
-            /* false-triggered by the commands from the reader. */ \\r
-            memset(&Demod, 0, sizeof(Demod)); \\r
-            Demod.output = receivedResponse; \\r
-            Demod.state = DEMOD_UNSYNCD; \\r
-\r
-        if(Handle14443UartBit(ci & 1)) {\r
-            HANDLE_BIT_IF_BODY\r
-        }\r
-        if(Handle14443UartBit(cq & 1)) {\r
-            HANDLE_BIT_IF_BODY\r
-        }\r
-\r
-        if(Handle14443SamplesDemod(ci, cq)) {\r
-            // timestamp, as a count of samples\r
-            trace[traceLen++] = ((samples >>  0) & 0xff);\r
-            trace[traceLen++] = ((samples >>  8) & 0xff);\r
-            trace[traceLen++] = ((samples >> 16) & 0xff);\r
-            trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);\r
-            // correlation metric (~signal strength estimate)\r
-            if(Demod.metricN != 0) {\r
-                Demod.metric /= Demod.metricN;\r
-            }\r
-            trace[traceLen++] = ((Demod.metric >>  0) & 0xff);\r
-            trace[traceLen++] = ((Demod.metric >>  8) & 0xff);\r
-            trace[traceLen++] = ((Demod.metric >> 16) & 0xff);\r
-            trace[traceLen++] = ((Demod.metric >> 24) & 0xff);\r
-            // length\r
-            trace[traceLen++] = Demod.len;\r
-            memcpy(trace+traceLen, receivedResponse, Demod.len);\r
-            traceLen += Demod.len;\r
-            if(traceLen > DEMOD_TRACE_SIZE) {          \r
-                               DbpString("Reached trace limit");\r
-                               goto done;\r
-                       }\r
-\r
-            triggered = TRUE;\r
-\r
-            // And ready to receive another response.\r
-            memset(&Demod, 0, sizeof(Demod));\r
-            Demod.output = receivedResponse;\r
-            Demod.state = DEMOD_UNSYNCD;\r
-        }\r
-               WDT_HIT();\r
-\r
-        if(BUTTON_PRESS()) {\r
-            DbpString("cancelled");\r
-            goto done;\r
-        }\r
-    }\r
-\r
-done:\r
-       LED_D_OFF();\r
-    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
-       DbpString("Snoop statistics:");\r
-    Dbprintf("  Max behind by: %i", maxBehindBy);\r
-       Dbprintf("  Uart State: %x", Uart.state);\r
-       Dbprintf("  Uart ByteCnt: %i", Uart.byteCnt);\r
-       Dbprintf("  Uart ByteCntMax: %i", Uart.byteCntMax);\r
-       Dbprintf("  Trace length: %i", traceLen);\r
-}\r
+//-----------------------------------------------------------------------------
+// Routines to support ISO 14443. This includes both the reader software and
+// the `fake tag' modes. At the moment only the Type B modulation is
+// supported.
+// Jonathan Westhues, split Nov 2006
+//-----------------------------------------------------------------------------
+#include <proxmark3.h>
+#include "apps.h"
+#include "iso14443crc.h"
+
+
+//static void GetSamplesFor14443(BOOL weTx, int n);
+
+#define DEMOD_TRACE_SIZE 4096
+#define READER_TAG_BUFFER_SIZE 2048
+#define TAG_READER_BUFFER_SIZE 2048
+#define DMA_BUFFER_SIZE 1024
+
+//=============================================================================
+// An ISO 14443 Type B tag. We listen for commands from the reader, using
+// a UART kind of thing that's implemented in software. When we get a
+// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
+// If it's good, then we can do something appropriate with it, and send
+// a response.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Code up a string of octets at layer 2 (including CRC, we don't generate
+// that here) so that they can be transmitted to the reader. Doesn't transmit
+// them yet, just leaves them ready to send in ToSend[].
+//-----------------------------------------------------------------------------
+static void CodeIso14443bAsTag(const BYTE *cmd, int len)
+{
+    int i;
+
+    ToSendReset();
+
+    // Transmit a burst of ones, as the initial thing that lets the
+    // reader get phase sync. This (TR1) must be > 80/fs, per spec,
+    // but tag that I've tried (a Paypass) exceeds that by a fair bit,
+    // so I will too.
+    for(i = 0; i < 20; i++) {
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+    }
+
+    // Send SOF.
+    for(i = 0; i < 10; i++) {
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+    }
+    for(i = 0; i < 2; i++) {
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+    }
+
+    for(i = 0; i < len; i++) {
+        int j;
+        BYTE b = cmd[i];
+
+        // Start bit
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+
+        // Data bits
+        for(j = 0; j < 8; j++) {
+            if(b & 1) {
+                ToSendStuffBit(1);
+                ToSendStuffBit(1);
+                ToSendStuffBit(1);
+                ToSendStuffBit(1);
+            } else {
+                ToSendStuffBit(0);
+                ToSendStuffBit(0);
+                ToSendStuffBit(0);
+                ToSendStuffBit(0);
+            }
+            b >>= 1;
+        }
+
+        // Stop bit
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+    }
+
+    // Send SOF.
+    for(i = 0; i < 10; i++) {
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+        ToSendStuffBit(0);
+    }
+    for(i = 0; i < 10; i++) {
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+    }
+
+    // Convert from last byte pos to length
+    ToSendMax++;
+
+    // Add a few more for slop
+    ToSendMax += 2;
+}
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+    enum {
+        STATE_UNSYNCD,
+        STATE_GOT_FALLING_EDGE_OF_SOF,
+        STATE_AWAITING_START_BIT,
+        STATE_RECEIVING_DATA,
+        STATE_ERROR_WAIT
+    }       state;
+    WORD    shiftReg;
+    int     bitCnt;
+    int     byteCnt;
+    int     byteCntMax;
+    int     posCnt;
+    BYTE   *output;
+} Uart;
+
+/* Receive & handle a bit coming from the reader.
+ *
+ * LED handling:
+ * LED A -> ON once we have received the SOF and are expecting the rest.
+ * LED A -> OFF once we have received EOF or are in error state or unsynced
+ *
+ * Returns: true if we received a EOF
+ *          false if we are still waiting for some more
+ */
+static BOOL Handle14443UartBit(int bit)
+{
+    switch(Uart.state) {
+        case STATE_UNSYNCD:
+               LED_A_OFF();
+            if(!bit) {
+                // we went low, so this could be the beginning
+                // of an SOF
+                Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
+                Uart.posCnt = 0;
+                Uart.bitCnt = 0;
+            }
+            break;
+
+        case STATE_GOT_FALLING_EDGE_OF_SOF:
+            Uart.posCnt++;
+            if(Uart.posCnt == 2) {
+                if(bit) {
+                    if(Uart.bitCnt >= 10) {
+                        // we've seen enough consecutive
+                        // zeros that it's a valid SOF
+                        Uart.posCnt = 0;
+                        Uart.byteCnt = 0;
+                        Uart.state = STATE_AWAITING_START_BIT;
+                        LED_A_ON(); // Indicate we got a valid SOF
+                    } else {
+                        // didn't stay down long enough
+                        // before going high, error
+                        Uart.state = STATE_ERROR_WAIT;
+                    }
+                } else {
+                    // do nothing, keep waiting
+                }
+                Uart.bitCnt++;
+            }
+            if(Uart.posCnt >= 4) Uart.posCnt = 0;
+            if(Uart.bitCnt > 14) {
+                // Give up if we see too many zeros without
+                // a one, too.
+                Uart.state = STATE_ERROR_WAIT;
+            }
+            break;
+
+        case STATE_AWAITING_START_BIT:
+            Uart.posCnt++;
+            if(bit) {
+                if(Uart.posCnt > 25) {
+                    // stayed high for too long between
+                    // characters, error
+                    Uart.state = STATE_ERROR_WAIT;
+                }
+            } else {
+                // falling edge, this starts the data byte
+                Uart.posCnt = 0;
+                Uart.bitCnt = 0;
+                Uart.shiftReg = 0;
+                Uart.state = STATE_RECEIVING_DATA;
+                LED_A_ON(); // Indicate we're receiving
+            }
+            break;
+
+        case STATE_RECEIVING_DATA:
+            Uart.posCnt++;
+            if(Uart.posCnt == 2) {
+                // time to sample a bit
+                Uart.shiftReg >>= 1;
+                if(bit) {
+                    Uart.shiftReg |= 0x200;
+                }
+                Uart.bitCnt++;
+            }
+            if(Uart.posCnt >= 4) {
+                Uart.posCnt = 0;
+            }
+            if(Uart.bitCnt == 10) {
+                if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
+                {
+                    // this is a data byte, with correct
+                    // start and stop bits
+                    Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
+                    Uart.byteCnt++;
+
+                    if(Uart.byteCnt >= Uart.byteCntMax) {
+                        // Buffer overflowed, give up
+                        Uart.posCnt = 0;
+                        Uart.state = STATE_ERROR_WAIT;
+                    } else {
+                        // so get the next byte now
+                        Uart.posCnt = 0;
+                        Uart.state = STATE_AWAITING_START_BIT;
+                    }
+                } else if(Uart.shiftReg == 0x000) {
+                    // this is an EOF byte
+                       LED_A_OFF(); // Finished receiving
+                    return TRUE;
+                } else {
+                    // this is an error
+                    Uart.posCnt = 0;
+                    Uart.state = STATE_ERROR_WAIT;
+                }
+            }
+            break;
+
+        case STATE_ERROR_WAIT:
+            // We're all screwed up, so wait a little while
+            // for whatever went wrong to finish, and then
+            // start over.
+            Uart.posCnt++;
+            if(Uart.posCnt > 10) {
+                Uart.state = STATE_UNSYNCD;
+            }
+            break;
+
+        default:
+            Uart.state = STATE_UNSYNCD;
+            break;
+    }
+
+    if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error
+
+    return FALSE;
+}
+
+//-----------------------------------------------------------------------------
+// Receive a command (from the reader to us, where we are the simulated tag),
+// and store it in the given buffer, up to the given maximum length. Keeps
+// spinning, waiting for a well-framed command, until either we get one
+// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
+//
+// Assume that we're called with the SSC (to the FPGA) and ADC path set
+// correctly.
+//-----------------------------------------------------------------------------
+static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)
+{
+    BYTE mask;
+    int i, bit;
+
+    // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
+    // only, since we are receiving, not transmitting).
+    // Signal field is off with the appropriate LED
+    LED_D_OFF();
+    FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
+
+
+    // Now run a `software UART' on the stream of incoming samples.
+    Uart.output = received;
+    Uart.byteCntMax = maxLen;
+    Uart.state = STATE_UNSYNCD;
+
+    for(;;) {
+        WDT_HIT();
+
+        if(BUTTON_PRESS()) return FALSE;
+
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+            AT91C_BASE_SSC->SSC_THR = 0x00;
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+            BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+
+            mask = 0x80;
+            for(i = 0; i < 8; i++, mask >>= 1) {
+                bit = (b & mask);
+                if(Handle14443UartBit(bit)) {
+                    *len = Uart.byteCnt;
+                    return TRUE;
+                }
+            }
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Main loop of simulated tag: receive commands from reader, decide what
+// response to send, and send it.
+//-----------------------------------------------------------------------------
+void SimulateIso14443Tag(void)
+{
+    static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
+    static const BYTE response1[] = {
+        0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,
+        0x00, 0x21, 0x85, 0x5e, 0xd7
+    };
+
+    BYTE *resp;
+    int respLen;
+
+    BYTE *resp1 = (((BYTE *)BigBuf) + 800);
+    int resp1Len;
+
+    BYTE *receivedCmd = (BYTE *)BigBuf;
+    int len;
+
+    int i;
+
+    int cmdsRecvd = 0;
+
+    memset(receivedCmd, 0x44, 400);
+
+    CodeIso14443bAsTag(response1, sizeof(response1));
+    memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
+
+    // We need to listen to the high-frequency, peak-detected path.
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+    FpgaSetupSsc();
+
+    cmdsRecvd = 0;
+
+    for(;;) {
+        BYTE b1, b2;
+
+        if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {
+               Dbprintf("button pressed, received %d commands", cmdsRecvd);
+               break;
+        }
+
+        // Good, look at the command now.
+
+        if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {
+            resp = resp1; respLen = resp1Len;
+        } else {
+            Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd);
+            // And print whether the CRC fails, just for good measure
+            ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);
+            if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {
+                // Not so good, try again.
+                DbpString("+++CRC fail");
+            } else {
+                DbpString("CRC passes");
+            }
+            break;
+        }
+
+        memset(receivedCmd, 0x44, 32);
+
+        cmdsRecvd++;
+
+        if(cmdsRecvd > 0x30) {
+            DbpString("many commands later...");
+            break;
+        }
+
+        if(respLen <= 0) continue;
+
+        // Modulate BPSK
+        // Signal field is off with the appropriate LED
+        LED_D_OFF();
+        FpgaWriteConfWord(
+               FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
+        AT91C_BASE_SSC->SSC_THR = 0xff;
+        FpgaSetupSsc();
+
+        // Transmit the response.
+        i = 0;
+        for(;;) {
+            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                BYTE b = resp[i];
+
+                AT91C_BASE_SSC->SSC_THR = b;
+
+                i++;
+                if(i > respLen) {
+                    break;
+                }
+            }
+            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+                (void)b;
+            }
+        }
+    }
+}
+
+//=============================================================================
+// An ISO 14443 Type B reader. We take layer two commands, code them
+// appropriately, and then send them to the tag. We then listen for the
+// tag's response, which we leave in the buffer to be demodulated on the
+// PC side.
+//=============================================================================
+
+static struct {
+    enum {
+        DEMOD_UNSYNCD,
+        DEMOD_PHASE_REF_TRAINING,
+        DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
+        DEMOD_GOT_FALLING_EDGE_OF_SOF,
+        DEMOD_AWAITING_START_BIT,
+        DEMOD_RECEIVING_DATA,
+        DEMOD_ERROR_WAIT
+    }       state;
+    int     bitCount;
+    int     posCount;
+    int     thisBit;
+    int     metric;
+    int     metricN;
+    WORD    shiftReg;
+    BYTE   *output;
+    int     len;
+    int     sumI;
+    int     sumQ;
+} Demod;
+
+/*
+ * Handles reception of a bit from the tag
+ *
+ * LED handling:
+ * LED C -> ON once we have received the SOF and are expecting the rest.
+ * LED C -> OFF once we have received EOF or are unsynced
+ *
+ * Returns: true if we received a EOF
+ *          false if we are still waiting for some more
+ *
+ */
+static BOOL Handle14443SamplesDemod(int ci, int cq)
+{
+    int v;
+
+    // The soft decision on the bit uses an estimate of just the
+    // quadrant of the reference angle, not the exact angle.
+#define MAKE_SOFT_DECISION() { \
+        if(Demod.sumI > 0) { \
+            v = ci; \
+        } else { \
+            v = -ci; \
+        } \
+        if(Demod.sumQ > 0) { \
+            v += cq; \
+        } else { \
+            v -= cq; \
+        } \
+    }
+
+    switch(Demod.state) {
+        case DEMOD_UNSYNCD:
+            v = ci;
+            if(v < 0) v = -v;
+            if(cq > 0) {
+                v += cq;
+            } else {
+                v -= cq;
+            }
+            if(v > 40) {
+                Demod.posCount = 0;
+                Demod.state = DEMOD_PHASE_REF_TRAINING;
+                Demod.sumI = 0;
+                Demod.sumQ = 0;
+            }
+            break;
+
+        case DEMOD_PHASE_REF_TRAINING:
+            if(Demod.posCount < 8) {
+                Demod.sumI += ci;
+                Demod.sumQ += cq;
+            } else if(Demod.posCount > 100) {
+                // error, waited too long
+                Demod.state = DEMOD_UNSYNCD;
+            } else {
+                MAKE_SOFT_DECISION();
+                if(v < 0) {
+                    Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
+                    Demod.posCount = 0;
+                }
+            }
+            Demod.posCount++;
+            break;
+
+        case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
+            MAKE_SOFT_DECISION();
+            if(v < 0) {
+                Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
+                Demod.posCount = 0;
+            } else {
+                if(Demod.posCount > 100) {
+                    Demod.state = DEMOD_UNSYNCD;
+                }
+            }
+            Demod.posCount++;
+            break;
+
+        case DEMOD_GOT_FALLING_EDGE_OF_SOF:
+            MAKE_SOFT_DECISION();
+            if(v > 0) {
+                if(Demod.posCount < 12) {
+                    Demod.state = DEMOD_UNSYNCD;
+                } else {
+                       LED_C_ON(); // Got SOF
+                    Demod.state = DEMOD_AWAITING_START_BIT;
+                    Demod.posCount = 0;
+                    Demod.len = 0;
+                    Demod.metricN = 0;
+                    Demod.metric = 0;
+                }
+            } else {
+                if(Demod.posCount > 100) {
+                    Demod.state = DEMOD_UNSYNCD;
+                }
+            }
+            Demod.posCount++;
+            break;
+
+        case DEMOD_AWAITING_START_BIT:
+            MAKE_SOFT_DECISION();
+            if(v > 0) {
+                if(Demod.posCount > 10) {
+                    Demod.state = DEMOD_UNSYNCD;
+                }
+            } else {
+                Demod.bitCount = 0;
+                Demod.posCount = 1;
+                Demod.thisBit = v;
+                Demod.shiftReg = 0;
+                Demod.state = DEMOD_RECEIVING_DATA;
+            }
+            break;
+
+        case DEMOD_RECEIVING_DATA:
+            MAKE_SOFT_DECISION();
+            if(Demod.posCount == 0) {
+                Demod.thisBit = v;
+                Demod.posCount = 1;
+            } else {
+                Demod.thisBit += v;
+
+                if(Demod.thisBit > 0) {
+                    Demod.metric += Demod.thisBit;
+                } else {
+                    Demod.metric -= Demod.thisBit;
+                }
+                (Demod.metricN)++;
+
+                Demod.shiftReg >>= 1;
+                if(Demod.thisBit > 0) {
+                    Demod.shiftReg |= 0x200;
+                }
+
+                Demod.bitCount++;
+                if(Demod.bitCount == 10) {
+                    WORD s = Demod.shiftReg;
+                    if((s & 0x200) && !(s & 0x001)) {
+                        BYTE b = (s >> 1);
+                        Demod.output[Demod.len] = b;
+                        Demod.len++;
+                        Demod.state = DEMOD_AWAITING_START_BIT;
+                    } else if(s == 0x000) {
+                        // This is EOF
+                       LED_C_OFF();
+                        return TRUE;
+                        Demod.state = DEMOD_UNSYNCD;
+                    } else {
+                        Demod.state = DEMOD_UNSYNCD;
+                    }
+                }
+                Demod.posCount = 0;
+            }
+            break;
+
+        default:
+            Demod.state = DEMOD_UNSYNCD;
+            break;
+    }
+
+    if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized...
+    return FALSE;
+}
+
+/*
+ *  Demodulate the samples we received from the tag
+ *  weTx: set to 'TRUE' if we behave like a reader
+ *        set to 'FALSE' if we behave like a snooper
+ *  quiet: set to 'TRUE' to disable debug output
+ */
+static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet)
+{
+    int max = 0;
+    BOOL gotFrame = FALSE;
+
+//#   define DMA_BUFFER_SIZE 8
+    SBYTE *dmaBuf;
+
+    int lastRxCounter;
+    SBYTE *upTo;
+
+    int ci, cq;
+
+    int samples = 0;
+
+    // Clear out the state of the "UART" that receives from the tag.
+    memset(BigBuf, 0x44, 400);
+    Demod.output = (BYTE *)BigBuf;
+    Demod.len = 0;
+    Demod.state = DEMOD_UNSYNCD;
+
+    // And the UART that receives from the reader
+    Uart.output = (((BYTE *)BigBuf) + 1024);
+    Uart.byteCntMax = 100;
+    Uart.state = STATE_UNSYNCD;
+
+    // Setup for the DMA.
+    dmaBuf = (SBYTE *)(BigBuf + 32);
+    upTo = dmaBuf;
+    lastRxCounter = DMA_BUFFER_SIZE;
+    FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);
+
+    // Signal field is ON with the appropriate LED:
+       if (weTx) LED_D_ON(); else LED_D_OFF();
+    // And put the FPGA in the appropriate mode
+    FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
+       (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
+
+    for(;;) {
+        int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
+        if(behindBy > max) max = behindBy;
+
+        while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1))
+                    > 2)
+        {
+            ci = upTo[0];
+            cq = upTo[1];
+            upTo += 2;
+            if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
+                upTo -= DMA_BUFFER_SIZE;
+                AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD)upTo;
+                AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+            }
+            lastRxCounter -= 2;
+            if(lastRxCounter <= 0) {
+                lastRxCounter += DMA_BUFFER_SIZE;
+            }
+
+            samples += 2;
+
+            Handle14443UartBit(1);
+            Handle14443UartBit(1);
+
+            if(Handle14443SamplesDemod(ci, cq)) {
+                gotFrame = 1;
+            }
+        }
+
+        if(samples > 2000) {
+            break;
+        }
+    }
+    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+    if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len);
+}
+
+//-----------------------------------------------------------------------------
+// Read the tag's response. We just receive a stream of slightly-processed
+// samples from the FPGA, which we will later do some signal processing on,
+// to get the bits.
+//-----------------------------------------------------------------------------
+/*static void GetSamplesFor14443(BOOL weTx, int n)
+{
+    BYTE *dest = (BYTE *)BigBuf;
+    int c;
+
+    FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
+       (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
+
+    c = 0;
+    for(;;) {
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+            AT91C_BASE_SSC->SSC_THR = 0x43;
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+            SBYTE b;
+            b = (SBYTE)AT91C_BASE_SSC->SSC_RHR;
+
+            dest[c++] = (BYTE)b;
+
+            if(c >= n) {
+                break;
+            }
+        }
+    }
+}*/
+
+//-----------------------------------------------------------------------------
+// Transmit the command (to the tag) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitFor14443(void)
+{
+    int c;
+
+    FpgaSetupSsc();
+
+    while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+        AT91C_BASE_SSC->SSC_THR = 0xff;
+    }
+
+    // Signal field is ON with the appropriate Red LED
+       LED_D_ON();
+       // Signal we are transmitting with the Green LED
+       LED_B_ON();
+       FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
+
+    for(c = 0; c < 10;) {
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+            AT91C_BASE_SSC->SSC_THR = 0xff;
+            c++;
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
+            (void)r;
+        }
+        WDT_HIT();
+    }
+
+    c = 0;
+    for(;;) {
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+            AT91C_BASE_SSC->SSC_THR = ToSend[c];
+            c++;
+            if(c >= ToSendMax) {
+                break;
+            }
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
+            (void)r;
+        }
+        WDT_HIT();
+    }
+    LED_B_OFF(); // Finished sending
+}
+
+//-----------------------------------------------------------------------------
+// Code a layer 2 command (string of octets, including CRC) into ToSend[],
+// so that it is ready to transmit to the tag using TransmitFor14443().
+//-----------------------------------------------------------------------------
+void CodeIso14443bAsReader(const BYTE *cmd, int len)
+{
+    int i, j;
+    BYTE b;
+
+    ToSendReset();
+
+    // Establish initial reference level
+    for(i = 0; i < 40; i++) {
+        ToSendStuffBit(1);
+    }
+    // Send SOF
+    for(i = 0; i < 10; i++) {
+        ToSendStuffBit(0);
+    }
+
+    for(i = 0; i < len; i++) {
+        // Stop bits/EGT
+        ToSendStuffBit(1);
+        ToSendStuffBit(1);
+        // Start bit
+        ToSendStuffBit(0);
+        // Data bits
+        b = cmd[i];
+        for(j = 0; j < 8; j++) {
+            if(b & 1) {
+                ToSendStuffBit(1);
+            } else {
+                ToSendStuffBit(0);
+            }
+            b >>= 1;
+        }
+    }
+    // Send EOF
+    ToSendStuffBit(1);
+    for(i = 0; i < 10; i++) {
+        ToSendStuffBit(0);
+    }
+    for(i = 0; i < 8; i++) {
+        ToSendStuffBit(1);
+    }
+
+    // And then a little more, to make sure that the last character makes
+    // it out before we switch to rx mode.
+    for(i = 0; i < 24; i++) {
+        ToSendStuffBit(1);
+    }
+
+    // Convert from last character reference to length
+    ToSendMax++;
+}
+
+//-----------------------------------------------------------------------------
+// Read an ISO 14443 tag. We send it some set of commands, and record the
+// responses.
+// The command name is misleading, it actually decodes the reponse in HEX
+// into the output buffer (read the result using hexsamples, not hisamples)
+//-----------------------------------------------------------------------------
+void AcquireRawAdcSamplesIso14443(DWORD parameter)
+{
+    BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
+
+    // Make sure that we start from off, since the tags are stateful;
+    // confusing things will happen if we don't reset them between reads.
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+    LED_D_OFF();
+    SpinDelay(200);
+
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+    FpgaSetupSsc();
+
+    // Now give it time to spin up.
+    // Signal field is on with the appropriate LED
+    LED_D_ON();
+    FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
+    SpinDelay(200);
+
+    CodeIso14443bAsReader(cmd1, sizeof(cmd1));
+    TransmitFor14443();
+//    LED_A_ON();
+    GetSamplesFor14443Demod(TRUE, 2000, FALSE);
+//    LED_A_OFF();
+}
+
+//-----------------------------------------------------------------------------
+// Read a SRI512 ISO 14443 tag.
+//
+// SRI512 tags are just simple memory tags, here we're looking at making a dump
+// of the contents of the memory. No anticollision algorithm is done, we assume
+// we have a single tag in the field.
+//
+// I tried to be systematic and check every answer of the tag, every CRC, etc...
+//-----------------------------------------------------------------------------
+void ReadSRI512Iso14443(DWORD parameter)
+{
+     ReadSTMemoryIso14443(parameter,0x0F);
+}
+void ReadSRIX4KIso14443(DWORD parameter)
+{
+     ReadSTMemoryIso14443(parameter,0x7F);
+}
+
+void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast)
+{
+    BYTE i = 0x00;
+
+    // Make sure that we start from off, since the tags are stateful;
+    // confusing things will happen if we don't reset them between reads.
+    LED_D_OFF();
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+    SpinDelay(200);
+
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+    FpgaSetupSsc();
+
+    // Now give it time to spin up.
+    // Signal field is on with the appropriate LED
+    LED_D_ON();
+    FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
+    SpinDelay(200);
+
+    // First command: wake up the tag using the INITIATE command
+    BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b};
+    CodeIso14443bAsReader(cmd1, sizeof(cmd1));
+    TransmitFor14443();
+//    LED_A_ON();
+    GetSamplesFor14443Demod(TRUE, 2000,TRUE);
+//    LED_A_OFF();
+
+    if (Demod.len == 0) {
+       DbpString("No response from tag");
+       return;
+    } else {
+       Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x",
+               Demod.output[0], Demod.output[1],Demod.output[2]);
+    }
+    // There is a response, SELECT the uid
+    DbpString("Now SELECT tag:");
+    cmd1[0] = 0x0E; // 0x0E is SELECT
+    cmd1[1] = Demod.output[0];
+    ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
+    CodeIso14443bAsReader(cmd1, sizeof(cmd1));
+    TransmitFor14443();
+//    LED_A_ON();
+    GetSamplesFor14443Demod(TRUE, 2000,TRUE);
+//    LED_A_OFF();
+    if (Demod.len != 3) {
+       Dbprintf("Expected 3 bytes from tag, got %d", Demod.len);
+       return;
+    }
+    // Check the CRC of the answer:
+    ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);
+    if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {
+       DbpString("CRC Error reading select response.");
+       return;
+    }
+    // Check response from the tag: should be the same UID as the command we just sent:
+    if (cmd1[1] != Demod.output[0]) {
+       Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]);
+       return;
+    }
+    // Tag is now selected,
+    // First get the tag's UID:
+    cmd1[0] = 0x0B;
+    ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
+    CodeIso14443bAsReader(cmd1, 3); // Only first three bytes for this one
+    TransmitFor14443();
+//    LED_A_ON();
+    GetSamplesFor14443Demod(TRUE, 2000,TRUE);
+//    LED_A_OFF();
+    if (Demod.len != 10) {
+       Dbprintf("Expected 10 bytes from tag, got %d", Demod.len);
+       return;
+    }
+    // The check the CRC of the answer (use cmd1 as temporary variable):
+    ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);
+           if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {
+       Dbprintf("CRC Error reading block! - Below: expected, got %x %x",
+               (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]);
+       // Do not return;, let's go on... (we should retry, maybe ?)
+    }
+    Dbprintf("Tag UID (64 bits): %08x %08x",
+       (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4],
+       (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]);
+
+    // Now loop to read all 16 blocks, address from 0 to 15
+    DbpString("Tag memory dump, block 0 to 15");
+    cmd1[0] = 0x08;
+    i = 0x00;
+    dwLast++;
+    for (;;) {
+           if (i == dwLast) {
+                   DbpString("System area block (0xff):");
+                   i = 0xff;
+           }
+           cmd1[1] = i;
+           ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);
+           CodeIso14443bAsReader(cmd1, sizeof(cmd1));
+           TransmitFor14443();
+//         LED_A_ON();
+           GetSamplesFor14443Demod(TRUE, 2000,TRUE);
+//         LED_A_OFF();
+           if (Demod.len != 6) { // Check if we got an answer from the tag
+               DbpString("Expected 6 bytes from tag, got less...");
+               return;
+           }
+           // The check the CRC of the answer (use cmd1 as temporary variable):
+           ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);
+            if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {
+               Dbprintf("CRC Error reading block! - Below: expected, got %x %x",
+                       (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]);
+               // Do not return;, let's go on... (we should retry, maybe ?)
+           }
+           // Now print out the memory location:
+           Dbprintf("Address=%x, Contents=%x, CRC=%x", i,
+               (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0],
+               (Demod.output[4]<<8)+Demod.output[5]);
+           if (i == 0xff) {
+               break;
+           }
+           i++;
+    }
+}
+
+
+//=============================================================================
+// Finally, the `sniffer' combines elements from both the reader and
+// simulated tag, to show both sides of the conversation.
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Record the sequence of commands sent by the reader to the tag, with
+// triggering so that we start recording at the point that the tag is moved
+// near the reader.
+//-----------------------------------------------------------------------------
+/*
+ * Memory usage for this function, (within BigBuf)
+ * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE
+ * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE
+ * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE
+ * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DMA_BUFFER_SIZE
+ */
+void SnoopIso14443(void)
+{
+    // 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
+    // response from the tag.
+    BOOL triggered = FALSE;
+
+    // The command (reader -> tag) that we're working on receiving.
+    BYTE *receivedCmd = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE;
+    // The response (tag -> reader) that we're working on receiving.
+    BYTE *receivedResponse = (BYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE;
+
+    // As we receive stuff, we copy it from receivedCmd or receivedResponse
+    // into trace, along with its length and other annotations.
+    BYTE *trace = (BYTE *)BigBuf;
+    int traceLen = 0;
+
+    // The DMA buffer, used to stream samples from the FPGA.
+    SBYTE *dmaBuf = (SBYTE *)(BigBuf) + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE + TAG_READER_BUFFER_SIZE;
+    int lastRxCounter;
+    SBYTE *upTo;
+    int ci, cq;
+    int maxBehindBy = 0;
+
+    // Count of samples received so far, so that we can include timing
+    // information in the trace buffer.
+    int samples = 0;
+
+    // Initialize the trace buffer
+    memset(trace, 0x44, DEMOD_TRACE_SIZE);
+
+    // Set up the demodulator for tag -> reader responses.
+    Demod.output = receivedResponse;
+    Demod.len = 0;
+    Demod.state = DEMOD_UNSYNCD;
+
+    // And the reader -> tag commands
+    memset(&Uart, 0, sizeof(Uart));
+    Uart.output = receivedCmd;
+    Uart.byteCntMax = 100;
+    Uart.state = STATE_UNSYNCD;
+
+       // Print some debug information about the buffer sizes
+       Dbprintf("Snooping buffers initialized:");
+       Dbprintf("  Trace: %i bytes", DEMOD_TRACE_SIZE);
+       Dbprintf("  Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE);
+       Dbprintf("  tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE);
+       Dbprintf("  DMA: %i bytes", DMA_BUFFER_SIZE);
+       
+       // Use a counter for blinking the LED
+       long ledCount=0;
+       long ledFlashAt=200000;
+       
+    // And put the FPGA in the appropriate mode
+    // Signal field is off with the appropriate LED
+    LED_D_OFF();
+    FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
+       FPGA_HF_READER_RX_XCORR_SNOOP);
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+    // Setup for the DMA.
+    FpgaSetupSsc();
+    upTo = dmaBuf;
+    lastRxCounter = DMA_BUFFER_SIZE;
+    FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);
+    // And now we loop, receiving samples.
+    for(;;) {
+               // Blink the LED while Snooping
+               ledCount++;
+               if (ledCount == ledFlashAt) {
+                       LED_D_ON();
+               }
+               if (ledCount >= 2*ledFlashAt) {
+                       LED_D_OFF();
+                       ledCount=0;
+               }
+               
+       int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
+                                (DMA_BUFFER_SIZE-1);
+        if(behindBy > maxBehindBy) {
+            maxBehindBy = behindBy;
+            if(behindBy > (DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not?
+                Dbprintf("blew circular buffer! behindBy=%x", behindBy);
+                goto done;
+            }
+        }
+        if(behindBy < 2) continue;
+
+        ci = upTo[0];
+        cq = upTo[1];
+        upTo += 2;
+        lastRxCounter -= 2;
+        if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
+            upTo -= DMA_BUFFER_SIZE;
+            lastRxCounter += DMA_BUFFER_SIZE;
+            AT91C_BASE_PDC_SSC->PDC_RNPR = (DWORD) upTo;
+            AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+        }
+
+        samples += 2;
+
+#define HANDLE_BIT_IF_BODY \
+            if(triggered) { \
+                               ledFlashAt=30000; \
+                trace[traceLen++] = ((samples >>  0) & 0xff); \
+                trace[traceLen++] = ((samples >>  8) & 0xff); \
+                trace[traceLen++] = ((samples >> 16) & 0xff); \
+                trace[traceLen++] = ((samples >> 24) & 0xff); \
+                trace[traceLen++] = 0; \
+                trace[traceLen++] = 0; \
+                trace[traceLen++] = 0; \
+                trace[traceLen++] = 0; \
+                trace[traceLen++] = Uart.byteCnt; \
+                memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \
+                traceLen += Uart.byteCnt; \
+                if(traceLen > 1000) break; \
+            } \
+            /* And ready to receive another command. */ \
+            memset(&Uart, 0, sizeof(Uart)); \
+            Uart.output = receivedCmd; \
+            Uart.byteCntMax = 100; \
+            Uart.state = STATE_UNSYNCD; \
+            /* And also reset the demod code, which might have been */ \
+            /* false-triggered by the commands from the reader. */ \
+            memset(&Demod, 0, sizeof(Demod)); \
+            Demod.output = receivedResponse; \
+            Demod.state = DEMOD_UNSYNCD; \
+
+        if(Handle14443UartBit(ci & 1)) {
+            HANDLE_BIT_IF_BODY
+        }
+        if(Handle14443UartBit(cq & 1)) {
+            HANDLE_BIT_IF_BODY
+        }
+
+        if(Handle14443SamplesDemod(ci, cq)) {
+            // timestamp, as a count of samples
+            trace[traceLen++] = ((samples >>  0) & 0xff);
+            trace[traceLen++] = ((samples >>  8) & 0xff);
+            trace[traceLen++] = ((samples >> 16) & 0xff);
+            trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);
+            // correlation metric (~signal strength estimate)
+            if(Demod.metricN != 0) {
+                Demod.metric /= Demod.metricN;
+            }
+            trace[traceLen++] = ((Demod.metric >>  0) & 0xff);
+            trace[traceLen++] = ((Demod.metric >>  8) & 0xff);
+            trace[traceLen++] = ((Demod.metric >> 16) & 0xff);
+            trace[traceLen++] = ((Demod.metric >> 24) & 0xff);
+            // length
+            trace[traceLen++] = Demod.len;
+            memcpy(trace+traceLen, receivedResponse, Demod.len);
+            traceLen += Demod.len;
+            if(traceLen > DEMOD_TRACE_SIZE) {          
+                               DbpString("Reached trace limit");
+                               goto done;
+                       }
+
+            triggered = TRUE;
+
+            // And ready to receive another response.
+            memset(&Demod, 0, sizeof(Demod));
+            Demod.output = receivedResponse;
+            Demod.state = DEMOD_UNSYNCD;
+        }
+               WDT_HIT();
+
+        if(BUTTON_PRESS()) {
+            DbpString("cancelled");
+            goto done;
+        }
+    }
+
+done:
+       LED_D_OFF();
+    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+       DbpString("Snoop statistics:");
+    Dbprintf("  Max behind by: %i", maxBehindBy);
+       Dbprintf("  Uart State: %x", Uart.state);
+       Dbprintf("  Uart ByteCnt: %i", Uart.byteCnt);
+       Dbprintf("  Uart ByteCntMax: %i", Uart.byteCntMax);
+       Dbprintf("  Trace length: %i", traceLen);
+}
index 02d912e7b3136f60a73d27dabac3dd467af609c5..ce653f299c639b4ae4a725a36f3b6652e162b44b 100644 (file)
-//-----------------------------------------------------------------------------\r
-// Routines to support ISO 14443 type A.\r
-//\r
-// Gerhard de Koning Gans - May 2008\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-#include "iso14443crc.h"\r
-\r
-static BYTE *trace = (BYTE *) BigBuf;\r
-static int traceLen = 0;\r
-static int rsamples = 0;\r
-static BOOL tracing = TRUE;\r
-\r
-typedef enum {\r
-       SEC_D = 1,\r
-       SEC_E = 2,\r
-       SEC_F = 3,\r
-       SEC_X = 4,\r
-       SEC_Y = 5,\r
-       SEC_Z = 6\r
-} SecType;\r
-\r
-static const BYTE OddByteParity[256] = {\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,\r
-  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1\r
-};\r
-\r
-// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT\r
-#define RECV_CMD_OFFSET   3032\r
-#define RECV_RES_OFFSET   3096\r
-#define DMA_BUFFER_OFFSET 3160\r
-#define DMA_BUFFER_SIZE   4096\r
-#define TRACE_LENGTH      3000\r
-\r
-//-----------------------------------------------------------------------------\r
-// Generate the parity value for a byte sequence\r
-// \r
-//-----------------------------------------------------------------------------\r
-DWORD GetParity(const BYTE * pbtCmd, int iLen)\r