]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
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
-{\r
-  int i;\r
-  DWORD dwPar = 0;\r
-  \r
-  // Generate the encrypted data\r
-  for (i = 0; i < iLen; i++) {\r
-    // Save the encrypted parity bit\r
-    dwPar |= ((OddByteParity[pbtCmd[i]]) << i);\r
-  }\r
-  return dwPar;\r
-}\r
-\r
-static void AppendCrc14443a(BYTE* data, int len)\r
-{\r
-  ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);\r
-}\r
-\r
-BOOL LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL bReader)\r
-{\r
-  // Return when trace is full\r
-  if (traceLen >= TRACE_LENGTH) return FALSE;\r
-  \r
-  // Trace the random, i'm curious\r
-  rsamples += iSamples;\r
-  trace[traceLen++] = ((rsamples >> 0) & 0xff);\r
-  trace[traceLen++] = ((rsamples >> 8) & 0xff);\r
-  trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-  trace[traceLen++] = ((rsamples >> 24) & 0xff);\r
-  if (!bReader) {\r
-    trace[traceLen - 1] |= 0x80;\r
-  }\r
-  trace[traceLen++] = ((dwParity >> 0) & 0xff);\r
-  trace[traceLen++] = ((dwParity >> 8) & 0xff);\r
-  trace[traceLen++] = ((dwParity >> 16) & 0xff);\r
-  trace[traceLen++] = ((dwParity >> 24) & 0xff);\r
-  trace[traceLen++] = iLen;\r
-  memcpy(trace + traceLen, btBytes, iLen);\r
-  traceLen += iLen;\r
-  return TRUE;\r
-}\r
-\r
-BOOL LogTraceInfo(byte_t* data, size_t len)\r
-{\r
-  return LogTrace(data,len,0,GetParity(data,len),TRUE);\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_START_OF_COMMUNICATION,\r
-               STATE_MILLER_X,\r
-               STATE_MILLER_Y,\r
-               STATE_MILLER_Z,\r
-        STATE_ERROR_WAIT\r
-    }       state;\r
-    WORD    shiftReg;\r
-    int     bitCnt;\r
-    int     byteCnt;\r
-    int     byteCntMax;\r
-    int     posCnt;\r
-    int     syncBit;\r
-       int     parityBits;\r
-       int     samples;\r
-    int     highCnt;\r
-    int     bitBuffer;\r
-       enum {\r
-               DROP_NONE,\r
-               DROP_FIRST_HALF,\r
-               DROP_SECOND_HALF\r
-       }               drop;\r
-    BYTE   *output;\r
-} Uart;\r
-\r
-static BOOL MillerDecoding(int bit)\r
-{\r
-       int error = 0;\r
-       int bitright;\r
-\r
-       if(!Uart.bitBuffer) {\r
-               Uart.bitBuffer = bit ^ 0xFF0;\r
-               return FALSE;\r
-       }\r
-       else {\r
-               Uart.bitBuffer <<= 4;\r
-               Uart.bitBuffer ^= bit;\r
-       }\r
-\r
-       BOOL EOC = FALSE;\r
-\r
-       if(Uart.state != STATE_UNSYNCD) {\r
-               Uart.posCnt++;\r
-\r
-               if((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) {\r
-                       bit = 0x00;\r
-               }\r
-               else {\r
-                       bit = 0x01;\r
-               }\r
-               if(((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) {\r
-                       bitright = 0x00;\r
-               }\r
-               else {\r
-                       bitright = 0x01;\r
-               }\r
-               if(bit != bitright) { bit = bitright; }\r
-\r
-               if(Uart.posCnt == 1) {\r
-                       // measurement first half bitperiod\r
-                       if(!bit) {\r
-                               Uart.drop = DROP_FIRST_HALF;\r
-                       }\r
-               }\r
-               else {\r
-                       // measurement second half bitperiod\r
-                       if(!bit & (Uart.drop == DROP_NONE)) {\r
-                               Uart.drop = DROP_SECOND_HALF;\r
-                       }\r
-                       else if(!bit) {\r
-                               // measured a drop in first and second half\r
-                               // which should not be possible\r
-                               Uart.state = STATE_ERROR_WAIT;\r
-                               error = 0x01;\r
-                       }\r
-\r
-                       Uart.posCnt = 0;\r
-\r
-                       switch(Uart.state) {\r
-                               case STATE_START_OF_COMMUNICATION:\r
-                                       Uart.shiftReg = 0;\r
-                                       if(Uart.drop == DROP_SECOND_HALF) {\r
-                                               // error, should not happen in SOC\r
-                                               Uart.state = STATE_ERROR_WAIT;\r
-                                               error = 0x02;\r
-                                       }\r
-                                       else {\r
-                                               // correct SOC\r
-                                               Uart.state = STATE_MILLER_Z;\r
-                                       }\r
-                                       break;\r
-\r
-                               case STATE_MILLER_Z:\r
-                                       Uart.bitCnt++;\r
-                                       Uart.shiftReg >>= 1;\r
-                                       if(Uart.drop == DROP_NONE) {\r
-                                               // logic '0' followed by sequence Y\r
-                                               // end of communication\r
-                                               Uart.state = STATE_UNSYNCD;\r
-                                               EOC = TRUE;\r
-                                       }\r
-                                       // if(Uart.drop == DROP_FIRST_HALF) {\r
-                                       //      Uart.state = STATE_MILLER_Z; stay the same\r
-                                       //      we see a logic '0' }\r
-                                       if(Uart.drop == DROP_SECOND_HALF) {\r
-                                               // we see a logic '1'\r
-                                               Uart.shiftReg |= 0x100;\r
-                                               Uart.state = STATE_MILLER_X;\r
-                                       }\r
-                                       break;\r
-\r
-                               case STATE_MILLER_X:\r
-                                       Uart.shiftReg >>= 1;\r
-                                       if(Uart.drop == DROP_NONE) {\r
-                                               // sequence Y, we see a '0'\r
-                                               Uart.state = STATE_MILLER_Y;\r
-                                               Uart.bitCnt++;\r
-                                       }\r
-                                       if(Uart.drop == DROP_FIRST_HALF) {\r
-                                               // Would be STATE_MILLER_Z\r
-                                               // but Z does not follow X, so error\r
-                                               Uart.state = STATE_ERROR_WAIT;\r
-                                               error = 0x03;\r
-                                       }\r
-                                       if(Uart.drop == DROP_SECOND_HALF) {\r
-                                               // We see a '1' and stay in state X\r
-                                               Uart.shiftReg |= 0x100;\r
-                                               Uart.bitCnt++;\r
-                                       }\r
-                                       break;\r
-\r
-                               case STATE_MILLER_Y:\r
-                                       Uart.bitCnt++;\r
-                                       Uart.shiftReg >>= 1;\r
-                                       if(Uart.drop == DROP_NONE) {\r
-                                               // logic '0' followed by sequence Y\r
-                                               // end of communication\r
-                                               Uart.state = STATE_UNSYNCD;\r
-                                               EOC = TRUE;\r
-                                       }\r
-                                       if(Uart.drop == DROP_FIRST_HALF) {\r
-                                               // we see a '0'\r
-                                               Uart.state = STATE_MILLER_Z;\r
-                                       }\r
-                                       if(Uart.drop == DROP_SECOND_HALF) {\r
-                                               // We see a '1' and go to state X\r
-                                               Uart.shiftReg |= 0x100;\r
-                                               Uart.state = STATE_MILLER_X;\r
-                                       }\r
-                                       break;\r
-\r
-                               case STATE_ERROR_WAIT:\r
-                                       // That went wrong. Now wait for at least two bit periods\r
-                                       // and try to sync again\r
-                                       if(Uart.drop == DROP_NONE) {\r
-                                               Uart.highCnt = 6;\r
-                                               Uart.state = STATE_UNSYNCD;\r
-                                       }\r
-                                       break;\r
-\r
-                               default:\r
-                                       Uart.state = STATE_UNSYNCD;\r
-                                       Uart.highCnt = 0;\r
-                                       break;\r
-                       }\r
-\r
-                       Uart.drop = DROP_NONE;\r
-\r
-                       // should have received at least one whole byte...\r
-                       if((Uart.bitCnt == 2) && EOC && (Uart.byteCnt > 0)) {\r
-                               return TRUE;\r
-                       }\r
-\r
-                       if(Uart.bitCnt == 9) {\r
-                               Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff);\r
-                               Uart.byteCnt++;\r
-\r
-                               Uart.parityBits <<= 1;\r
-                               Uart.parityBits ^= ((Uart.shiftReg >> 8) & 0x01);\r
-\r
-                               if(EOC) {\r
-                                       // when End of Communication received and\r
-                                       // all data bits processed..\r
-                                       return TRUE;\r
-                               }\r
-                               Uart.bitCnt = 0;\r
-                       }\r
-\r
-                       /*if(error) {\r
-                               Uart.output[Uart.byteCnt] = 0xAA;\r
-                               Uart.byteCnt++;\r
-                               Uart.output[Uart.byteCnt] = error & 0xFF;\r
-                               Uart.byteCnt++;\r
-                               Uart.output[Uart.byteCnt] = 0xAA;\r
-                               Uart.byteCnt++;\r
-                               Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF;\r
-                               Uart.byteCnt++;\r
-                               Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;\r
-                               Uart.byteCnt++;\r
-                               Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF;\r
-                               Uart.byteCnt++;\r
-                               Uart.output[Uart.byteCnt] = 0xAA;\r
-                               Uart.byteCnt++;\r
-                               return TRUE;\r
-                       }*/\r
-               }\r
-\r
-       }\r
-       else {\r
-               bit = Uart.bitBuffer & 0xf0;\r
-               bit >>= 4;\r
-               bit ^= 0x0F;\r
-               if(bit) {\r
-                       // should have been high or at least (4 * 128) / fc\r
-                       // according to ISO this should be at least (9 * 128 + 20) / fc\r
-                       if(Uart.highCnt == 8) {\r
-                               // we went low, so this could be start of communication\r
-                               // it turns out to be safer to choose a less significant\r
-                               // syncbit... so we check whether the neighbour also represents the drop\r
-                               Uart.posCnt = 1;   // apparently we are busy with our first half bit period\r
-                               Uart.syncBit = bit & 8;\r
-                               Uart.samples = 3;\r
-                               if(!Uart.syncBit)       { Uart.syncBit = bit & 4; Uart.samples = 2; }\r
-                               else if(bit & 4)        { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; }\r
-                               if(!Uart.syncBit)       { Uart.syncBit = bit & 2; Uart.samples = 1; }\r
-                               else if(bit & 2)        { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; }\r
-                               if(!Uart.syncBit)       { Uart.syncBit = bit & 1; Uart.samples = 0;\r
-                                       if(Uart.syncBit & (Uart.bitBuffer & 8)) {\r
-                                               Uart.syncBit = 8;\r
-\r
-                                               // the first half bit period is expected in next sample\r
-                                               Uart.posCnt = 0;\r
-                                               Uart.samples = 3;\r
-                                       }\r
-                               }\r
-                               else if(bit & 1)        { Uart.syncBit = bit & 1; Uart.samples = 0; }\r
-\r
-                               Uart.syncBit <<= 4;\r
-                               Uart.state = STATE_START_OF_COMMUNICATION;\r
-                               Uart.drop = DROP_FIRST_HALF;\r
-                               Uart.bitCnt = 0;\r
-                               Uart.byteCnt = 0;\r
-                               Uart.parityBits = 0;\r
-                               error = 0;\r
-                       }\r
-                       else {\r
-                               Uart.highCnt = 0;\r
-                       }\r
-               }\r
-               else {\r
-                       if(Uart.highCnt < 8) {\r
-                               Uart.highCnt++;\r
-                       }\r
-               }\r
-       }\r
-\r
-    return FALSE;\r
-}\r
-\r
-//=============================================================================\r
-// ISO 14443 Type A - Manchester\r
-//=============================================================================\r
-\r
-static struct {\r
-    enum {\r
-        DEMOD_UNSYNCD,\r
-               DEMOD_START_OF_COMMUNICATION,\r
-               DEMOD_MANCHESTER_D,\r
-               DEMOD_MANCHESTER_E,\r
-               DEMOD_MANCHESTER_F,\r
-        DEMOD_ERROR_WAIT\r
-    }       state;\r
-    int     bitCount;\r
-    int     posCount;\r
-       int     syncBit;\r
-       int     parityBits;\r
-    WORD    shiftReg;\r
-       int     buffer;\r
-       int     buff;\r
-       int     samples;\r
-    int     len;\r
-       enum {\r
-               SUB_NONE,\r
-               SUB_FIRST_HALF,\r
-               SUB_SECOND_HALF\r
-       }               sub;\r
-    BYTE   *output;\r
-} Demod;\r
-\r
-static BOOL ManchesterDecoding(int v)\r
-{\r
-       int bit;\r
-       int modulation;\r
-       int error = 0;\r
-\r
-       if(!Demod.buff) {\r
-               Demod.buff = 1;\r
-               Demod.buffer = v;\r
-               return FALSE;\r
-       }\r
-       else {\r
-               bit = Demod.buffer;\r
-               Demod.buffer = v;\r
-       }\r
-\r
-       if(Demod.state==DEMOD_UNSYNCD) {\r
-               Demod.output[Demod.len] = 0xfa;\r
-               Demod.syncBit = 0;\r
-               //Demod.samples = 0;\r
-               Demod.posCount = 1;             // This is the first half bit period, so after syncing handle the second part\r
-               if(bit & 0x08) { Demod.syncBit = 0x08; }\r
-               if(!Demod.syncBit)      {\r
-                       if(bit & 0x04) { Demod.syncBit = 0x04; }\r
-               }\r
-               else if(bit & 0x04) { Demod.syncBit = 0x04; bit <<= 4; }\r
-               if(!Demod.syncBit)      {\r
-                       if(bit & 0x02) { Demod.syncBit = 0x02; }\r
-               }\r
-               else if(bit & 0x02) { Demod.syncBit = 0x02; bit <<= 4; }\r
-               if(!Demod.syncBit)      {\r
-                       if(bit & 0x01) { Demod.syncBit = 0x01; }\r
-\r
-                       if(Demod.syncBit & (Demod.buffer & 0x08)) {\r
-                               Demod.syncBit = 0x08;\r
-\r
-                               // The first half bitperiod is expected in next sample\r
-                               Demod.posCount = 0;\r
-                               Demod.output[Demod.len] = 0xfb;\r
-                       }\r
-               }\r
-               else if(bit & 0x01) { Demod.syncBit = 0x01; }\r
-\r
-               if(Demod.syncBit) {\r
-                       Demod.len = 0;\r
-                       Demod.state = DEMOD_START_OF_COMMUNICATION;\r
-                       Demod.sub = SUB_FIRST_HALF;\r
-                       Demod.bitCount = 0;\r
-                       Demod.shiftReg = 0;\r
-                       Demod.parityBits = 0;\r
-                       Demod.samples = 0;\r
-                       if(Demod.posCount) {\r
-                               switch(Demod.syncBit) {\r
-                                       case 0x08: Demod.samples = 3; break;\r
-                                       case 0x04: Demod.samples = 2; break;\r
-                                       case 0x02: Demod.samples = 1; break;\r
-                                       case 0x01: Demod.samples = 0; break;\r
-                               }\r
-                       }\r
-                       error = 0;\r
-               }\r
-       }\r
-       else {\r
-               //modulation = bit & Demod.syncBit;\r
-               modulation = ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit;\r
-\r
-               Demod.samples += 4;\r
-\r
-               if(Demod.posCount==0) {\r
-                       Demod.posCount = 1;\r
-                       if(modulation) {\r
-                               Demod.sub = SUB_FIRST_HALF;\r
-                       }\r
-                       else {\r
-                               Demod.sub = SUB_NONE;\r
-                       }\r
-               }\r
-               else {\r
-                       Demod.posCount = 0;\r
-                       if(modulation && (Demod.sub == SUB_FIRST_HALF)) {\r
-                               if(Demod.state!=DEMOD_ERROR_WAIT) {\r
-                                       Demod.state = DEMOD_ERROR_WAIT;\r
-                                       Demod.output[Demod.len] = 0xaa;\r
-                                       error = 0x01;\r
-                               }\r
-                       }\r
-                       else if(modulation) {\r
-                               Demod.sub = SUB_SECOND_HALF;\r
-                       }\r
-\r
-                       switch(Demod.state) {\r
-                               case DEMOD_START_OF_COMMUNICATION:\r
-                                       if(Demod.sub == SUB_FIRST_HALF) {\r
-                                               Demod.state = DEMOD_MANCHESTER_D;\r
-                                       }\r
-                                       else {\r
-                                               Demod.output[Demod.len] = 0xab;\r
-                                               Demod.state = DEMOD_ERROR_WAIT;\r
-                                               error = 0x02;\r
-                                       }\r
-                                       break;\r
-\r
-                               case DEMOD_MANCHESTER_D:\r
-                               case DEMOD_MANCHESTER_E:\r
-                                       if(Demod.sub == SUB_FIRST_HALF) {\r
-                                               Demod.bitCount++;\r
-                                               Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100;\r
-                                               Demod.state = DEMOD_MANCHESTER_D;\r
-                                       }\r
-                                       else if(Demod.sub == SUB_SECOND_HALF) {\r
-                                               Demod.bitCount++;\r
-                                               Demod.shiftReg >>= 1;\r
-                                               Demod.state = DEMOD_MANCHESTER_E;\r
-                                       }\r
-                                       else {\r
-                                               Demod.state = DEMOD_MANCHESTER_F;\r
-                                       }\r
-                                       break;\r
-\r
-                               case DEMOD_MANCHESTER_F:\r
-                                       // Tag response does not need to be a complete byte!\r
-                                       if(Demod.len > 0 || Demod.bitCount > 0) {\r
-                                               if(Demod.bitCount > 0) {\r
-                                                       Demod.shiftReg >>= (9 - Demod.bitCount);\r
-                                                       Demod.output[Demod.len] = Demod.shiftReg & 0xff;\r
-                                                       Demod.len++;\r
-                                                       // No parity bit, so just shift a 0\r
-                                                       Demod.parityBits <<= 1;\r
-                                               }\r
-\r
-                                               Demod.state = DEMOD_UNSYNCD;\r
-                                               return TRUE;\r
-                                       }\r
-                                       else {\r
-                                               Demod.output[Demod.len] = 0xad;\r
-                                               Demod.state = DEMOD_ERROR_WAIT;\r
-                                               error = 0x03;\r
-                                       }\r
-                                       break;\r
-\r
-                               case DEMOD_ERROR_WAIT:\r
-                                       Demod.state = DEMOD_UNSYNCD;\r
-                                       break;\r
-\r
-                               default:\r
-                                       Demod.output[Demod.len] = 0xdd;\r
-                                       Demod.state = DEMOD_UNSYNCD;\r
-                                       break;\r
-                       }\r
-\r
-                       if(Demod.bitCount>=9) {\r
-                               Demod.output[Demod.len] = Demod.shiftReg & 0xff;\r
-                               Demod.len++;\r
-\r
-                               Demod.parityBits <<= 1;\r
-                               Demod.parityBits ^= ((Demod.shiftReg >> 8) & 0x01);\r
-\r
-                               Demod.bitCount = 0;\r
-                               Demod.shiftReg = 0;\r
-                       }\r
-\r
-                       /*if(error) {\r
-                               Demod.output[Demod.len] = 0xBB;\r
-                               Demod.len++;\r
-                               Demod.output[Demod.len] = error & 0xFF;\r
-                               Demod.len++;\r
-                               Demod.output[Demod.len] = 0xBB;\r
-                               Demod.len++;\r
-                               Demod.output[Demod.len] = bit & 0xFF;\r
-                               Demod.len++;\r
-                               Demod.output[Demod.len] = Demod.buffer & 0xFF;\r
-                               Demod.len++;\r
-                               Demod.output[Demod.len] = Demod.syncBit & 0xFF;\r
-                               Demod.len++;\r
-                               Demod.output[Demod.len] = 0xBB;\r
-                               Demod.len++;\r
-                               return TRUE;\r
-                       }*/\r
-\r
-               }\r
-\r
-       } // end (state != UNSYNCED)\r
-\r
-    return FALSE;\r
-}\r
-\r
-//=============================================================================\r
-// Finally, a `sniffer' for ISO 14443 Type A\r
-// Both sides of communication!\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
-void SnoopIso14443a(void)\r
-{\r
-//     #define RECV_CMD_OFFSET         2032    // original (working as of 21/2/09) values\r
-//     #define RECV_RES_OFFSET         2096    // original (working as of 21/2/09) values\r
-//     #define DMA_BUFFER_OFFSET       2160    // original (working as of 21/2/09) values\r
-//     #define DMA_BUFFER_SIZE         4096    // original (working as of 21/2/09) values\r
-//     #define TRACE_LENGTH            2000    // original (working as of 21/2/09) values\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 = TRUE; // FALSE to wait first for card\r
-\r
-    // The command (reader -> tag) that we're receiving.\r
-       // The length of a received command will in most cases be no more than 18 bytes.\r
-       // So 32 should be enough!\r
-    BYTE *receivedCmd = (((BYTE *)BigBuf) + RECV_CMD_OFFSET);\r
-    // The response (tag -> reader) that we're receiving.\r
-    BYTE *receivedResponse = (((BYTE *)BigBuf) + RECV_RES_OFFSET);\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) + DMA_BUFFER_OFFSET;\r
-    int lastRxCounter;\r
-    SBYTE *upTo;\r
-    int smpl;\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
-       int rsamples = 0;\r
-\r
-    memset(trace, 0x44, RECV_CMD_OFFSET);\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 = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////\r
-    Uart.state = STATE_UNSYNCD;\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(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);\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
-\r
-    LED_A_ON();\r
-\r
-    // And now we loop, receiving samples.\r
-    for(;;) {\r
-               WDT_HIT();\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 > 400) {\r
-                DbpString("blew circular buffer!");\r
-                goto done;\r
-            }\r
-        }\r
-        if(behindBy < 1) continue;\r
-\r
-        smpl = upTo[0];\r
-        upTo++;\r
-        lastRxCounter -= 1;\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 += 4;\r
-#define HANDLE_BIT_IF_BODY \\r
-            LED_C_ON(); \\r
-                       if(triggered) { \\r
-                               trace[traceLen++] = ((rsamples >>  0) & 0xff); \\r
-                trace[traceLen++] = ((rsamples >>  8) & 0xff); \\r
-                trace[traceLen++] = ((rsamples >> 16) & 0xff); \\r
-                trace[traceLen++] = ((rsamples >> 24) & 0xff); \\r
-                               trace[traceLen++] = ((Uart.parityBits >>  0) & 0xff); \\r
-                               trace[traceLen++] = ((Uart.parityBits >>  8) & 0xff); \\r
-                               trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff); \\r
-                               trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff); \\r
-                trace[traceLen++] = Uart.byteCnt; \\r
-                memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \\r
-                traceLen += Uart.byteCnt; \\r
-                if(traceLen > TRACE_LENGTH) break; \\r
-            } \\r
-            /* And ready to receive another command. */ \\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
-            Demod.state = DEMOD_UNSYNCD; \\r
-                       LED_B_OFF(); \\r
-\r
-               if(MillerDecoding((smpl & 0xF0) >> 4)) {\r
-            rsamples = samples - Uart.samples;\r
-                       HANDLE_BIT_IF_BODY\r
-        }\r
-               if(ManchesterDecoding(smpl & 0x0F)) {\r
-                       rsamples = samples - Demod.samples;\r
-                       LED_B_ON();\r
-\r
-                       // timestamp, as a count of samples\r
-                       trace[traceLen++] = ((rsamples >>  0) & 0xff);\r
-                       trace[traceLen++] = ((rsamples >>  8) & 0xff);\r
-                       trace[traceLen++] = ((rsamples >> 16) & 0xff);\r
-                       trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);\r
-                       trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);\r
-                       trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);\r
-                       trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);\r
-                       trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);\r
-                       // length\r
-                       trace[traceLen++] = Demod.len;\r
-                       memcpy(trace+traceLen, receivedResponse, Demod.len);\r
-                       traceLen += Demod.len;\r
-                       if(traceLen > TRACE_LENGTH) break;\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
-                       LED_C_OFF();\r
-               }\r
-\r
-        if(BUTTON_PRESS()) {\r
-            DbpString("cancelled_a");\r
-            goto done;\r
-        }\r
-    }\r
-\r
-    DbpString("COMMAND FINISHED");\r
-\r
-    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);\r
-    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
-\r
-done:\r
-    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;\r
-    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);\r
-    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);\r
-    LED_A_OFF();\r
-    LED_B_OFF();\r
-       LED_C_OFF();\r
-       LED_D_OFF();\r
-}\r
-\r
-// Prepare communication bits to send to FPGA\r
-void Sequence(SecType seq)\r
-{\r
-       ToSendMax++;\r
-       switch(seq) {\r
-       // CARD TO READER\r
-       case SEC_D:\r
-               // Sequence D: 11110000\r
-               // modulation with subcarrier during first half\r
-        ToSend[ToSendMax] = 0xf0;\r
-               break;\r
-       case SEC_E:\r
-               // Sequence E: 00001111\r
-               // modulation with subcarrier during second half\r
-        ToSend[ToSendMax] = 0x0f;\r
-               break;\r
-       case SEC_F:\r
-               // Sequence F: 00000000\r
-               // no modulation with subcarrier\r
-        ToSend[ToSendMax] = 0x00;\r
-               break;\r
-       // READER TO CARD\r
-       case SEC_X:\r
-               // Sequence X: 00001100\r
-               // drop after half a period\r
-        ToSend[ToSendMax] = 0x0c;\r
-               break;\r
-       case SEC_Y:\r
-       default:\r
-               // Sequence Y: 00000000\r
-               // no drop\r
-        ToSend[ToSendMax] = 0x00;\r
-               break;\r
-       case SEC_Z:\r
-               // Sequence Z: 11000000\r
-               // drop at start\r
-        ToSend[ToSendMax] = 0xc0;\r
-               break;\r
-       }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Prepare tag messages\r
-//-----------------------------------------------------------------------------\r
-static void CodeIso14443aAsTag(const BYTE *cmd, int len)\r
-{\r
-    int i;\r
-       int oddparity;\r
-\r
-    ToSendReset();\r
-\r
-       // Correction bit, might be removed when not needed\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(1);  // 1\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-\r
-       // Send startbit\r
-       Sequence(SEC_D);\r
-\r
-    for(i = 0; i < len; i++) {\r
-        int j;\r
-        BYTE b = cmd[i];\r
-\r
-               // Data bits\r
-        oddparity = 0x01;\r
-               for(j = 0; j < 8; j++) {\r
-            oddparity ^= (b & 1);\r
-                       if(b & 1) {\r
-                               Sequence(SEC_D);\r
-                       } else {\r
-                               Sequence(SEC_E);\r
-            }\r
-            b >>= 1;\r
-        }\r
-\r
-        // Parity bit\r
-        if(oddparity) {\r
-                       Sequence(SEC_D);\r
-               } else {\r
-                       Sequence(SEC_E);\r
-               }\r
-    }\r
-\r
-    // Send stopbit\r
-       Sequence(SEC_F);\r
-\r
-       // Flush the buffer in FPGA!!\r
-       for(i = 0; i < 5; i++) {\r
-               Sequence(SEC_F);\r
-       }\r
-\r
-    // Convert from last byte pos to length\r
-    ToSendMax++;\r
-\r
-    // Add a few more for slop\r
-    ToSend[ToSendMax++] = 0x00;\r
-       ToSend[ToSendMax++] = 0x00;\r
-    //ToSendMax += 2;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// This is to send a NACK kind of answer, its only 3 bits, I know it should be 4\r
-//-----------------------------------------------------------------------------\r
-static void CodeStrangeAnswer()\r
-{\r
-       int i;\r
-\r
-    ToSendReset();\r
-\r
-       // Correction bit, might be removed when not needed\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(1);  // 1\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(0);\r
-\r
-       // Send startbit\r
-       Sequence(SEC_D);\r
-\r
-       // 0\r
-       Sequence(SEC_E);\r
-\r
-       // 0\r
-       Sequence(SEC_E);\r
-\r
-       // 1\r
-       Sequence(SEC_D);\r
-\r
-    // Send stopbit\r
-       Sequence(SEC_F);\r
-\r
-       // Flush the buffer in FPGA!!\r
-       for(i = 0; i < 5; i++) {\r
-               Sequence(SEC_F);\r
-       }\r
-\r
-    // Convert from last byte pos to length\r
-    ToSendMax++;\r
-\r
-    // Add a few more for slop\r
-    ToSend[ToSendMax++] = 0x00;\r
-       ToSend[ToSendMax++] = 0x00;\r
-    //ToSendMax += 2;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Wait for commands from reader\r
-// Stop when button is pressed\r
-// Or return TRUE when command is captured\r
-//-----------------------------------------------------------------------------\r
-static BOOL GetIso14443aCommandFromReader(BYTE *received, int *len, int maxLen)\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(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);\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
-                       if(MillerDecoding((b & 0xf0) >> 4)) {\r
-                               *len = Uart.byteCnt;\r
-                               return TRUE;\r
-                       }\r
-                       if(MillerDecoding(b & 0x0f)) {\r
-                               *len = Uart.byteCnt;\r
-                               return TRUE;\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 SimulateIso14443aTag(int tagType, int TagUid)\r
-{\r
-       // This function contains the tag emulation\r
-\r
-       // Prepare protocol messages\r
-    // static const BYTE cmd1[] = { 0x26 };\r
-//     static const BYTE response1[] = { 0x02, 0x00 }; // Says: I am Mifare 4k - original line - greg\r
-//\r
-       static const BYTE response1[] = { 0x44, 0x03 }; // Says: I am a DESFire Tag, ph33r me\r
-//     static const BYTE response1[] = { 0x44, 0x00 }; // Says: I am a ULTRALITE Tag, 0wn me\r
-\r
-       // UID response\r
-    // static const BYTE cmd2[] = { 0x93, 0x20 };\r
-    //static const BYTE response2[] = { 0x9a, 0xe5, 0xe4, 0x43, 0xd8 }; // original value - greg\r
-\r
-\r
-\r
-// my desfire\r
-    static const BYTE response2[] = { 0x88, 0x04, 0x21, 0x3f, 0x4d }; // known uid - note cascade (0x88), 2nd byte (0x04) = NXP/Phillips\r
-\r
-\r
-// When reader selects us during cascade1 it will send cmd3\r
-//BYTE response3[] = { 0x04, 0x00, 0x00 }; // SAK Select (cascade1) successful response (ULTRALITE)\r
-BYTE response3[] = { 0x24, 0x00, 0x00 }; // SAK Select (cascade1) successful response (DESFire)\r
-ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);\r
-\r
-// send cascade2 2nd half of UID\r
-static const BYTE response2a[] = { 0x51, 0x48, 0x1d, 0x80, 0x84 }; //  uid - cascade2 - 2nd half (4 bytes) of UID+ BCCheck\r
-// NOTE : THE CRC on the above may be wrong as I have obfuscated the actual UID\r
-\r
-\r
-// When reader selects us during cascade2 it will send cmd3a\r
-//BYTE response3a[] = { 0x00, 0x00, 0x00 }; // SAK Select (cascade2) successful response (ULTRALITE)\r
-BYTE response3a[] = { 0x20, 0x00, 0x00 }; // SAK Select (cascade2) successful response (DESFire)\r
-ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);\r
-\r
-    static const BYTE response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce\r
-\r
-    BYTE *resp;\r
-    int respLen;\r
-\r
-    // Longest possible response will be 16 bytes + 2 CRC = 18 bytes\r
-       // This will need\r
-       //    144        data bits (18 * 8)\r
-       //     18        parity bits\r
-       //      2        Start and stop\r
-       //      1        Correction bit (Answer in 1172 or 1236 periods, see FPGA)\r
-       //      1        just for the case\r
-       // ----------- +\r
-       //    166\r
-       //\r
-       // 166 bytes, since every bit that needs to be send costs us a byte\r
-       //\r
-\r
-\r
-    // Respond with card type\r
-    BYTE *resp1 = (((BYTE *)BigBuf) + 800);\r
-    int resp1Len;\r
-\r
-    // Anticollision cascade1 - respond with uid\r
-    BYTE *resp2 = (((BYTE *)BigBuf) + 970);\r
-    int resp2Len;\r
-\r
-    // Anticollision cascade2 - respond with 2nd half of uid if asked\r
-    // we're only going to be asked if we set the 1st byte of the UID (during cascade1) to 0x88\r
-    BYTE *resp2a = (((BYTE *)BigBuf) + 1140);\r
-    int resp2aLen;\r
-\r
-    // Acknowledge select - cascade 1\r
-    BYTE *resp3 = (((BYTE *)BigBuf) + 1310);\r
-    int resp3Len;\r
-\r
-    // Acknowledge select - cascade 2\r
-    BYTE *resp3a = (((BYTE *)BigBuf) + 1480);\r
-    int resp3aLen;\r
-\r
-    // Response to a read request - not implemented atm\r
-    BYTE *resp4 = (((BYTE *)BigBuf) + 1550);\r
-    int resp4Len;\r
-\r
-    // Authenticate response - nonce\r
-    BYTE *resp5 = (((BYTE *)BigBuf) + 1720);\r
-    int resp5Len;\r
-\r
-    BYTE *receivedCmd = (BYTE *)BigBuf;\r
-    int len;\r
-\r
-    int i;\r
-       int u;\r
-       BYTE b;\r
-\r
-       // To control where we are in the protocol\r
-       int order = 0;\r
-       int lastorder;\r
-\r
-       // Just to allow some checks\r
-       int happened = 0;\r
-       int happened2 = 0;\r
-\r
-    int cmdsRecvd = 0;\r
-\r
-       BOOL fdt_indicator;\r
-\r
-    memset(receivedCmd, 0x44, 400);\r
-\r
-       // Prepare the responses of the anticollision phase\r
-       // there will be not enough time to do this at the moment the reader sends it REQA\r
-\r
-       // Answer to request\r
-       CodeIso14443aAsTag(response1, sizeof(response1));\r
-    memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;\r
-\r
-       // Send our UID (cascade 1)\r
-       CodeIso14443aAsTag(response2, sizeof(response2));\r
-    memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;\r
-\r
-       // Answer to select (cascade1)\r
-       CodeIso14443aAsTag(response3, sizeof(response3));\r
-    memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;\r
-\r
-       // Send the cascade 2 2nd part of the uid\r
-       CodeIso14443aAsTag(response2a, sizeof(response2a));\r
-    memcpy(resp2a, ToSend, ToSendMax); resp2aLen = ToSendMax;\r
-\r
-       // Answer to select (cascade 2)\r
-       CodeIso14443aAsTag(response3a, sizeof(response3a));\r
-    memcpy(resp3a, ToSend, ToSendMax); resp3aLen = ToSendMax;\r
-\r
-       // Strange answer is an example of rare message size (3 bits)\r
-       CodeStrangeAnswer();\r
-       memcpy(resp4, ToSend, ToSendMax); resp4Len = ToSendMax;\r
-\r
-       // Authentication answer (random nonce)\r
-       CodeIso14443aAsTag(response5, sizeof(response5));\r
-    memcpy(resp5, ToSend, ToSendMax); resp5Len = 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
-    LED_A_ON();\r
-       for(;;) {\r
-\r
-               if(!GetIso14443aCommandFromReader(receivedCmd, &len, 100)) {\r
-            DbpString("button press");\r
-            break;\r
-        }\r
-       // doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated\r
-        // Okay, look at the command now.\r
-        lastorder = order;\r
-               i = 1; // first byte transmitted\r
-        if(receivedCmd[0] == 0x26) {\r
-                       // Received a REQUEST\r
-                       resp = resp1; respLen = resp1Len; order = 1;\r
-                       //DbpString("Hello request from reader:");\r
-               } else if(receivedCmd[0] == 0x52) {\r
-                       // Received a WAKEUP\r
-                       resp = resp1; respLen = resp1Len; order = 6;\r
-//                     //DbpString("Wakeup request from reader:");\r
-\r
-               } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) {   // greg - cascade 1 anti-collision\r
-                       // Received request for UID (cascade 1)\r
-                       resp = resp2; respLen = resp2Len; order = 2;\r
-//                     DbpString("UID (cascade 1) request from reader:");\r
-//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-\r
-\r
-               } else if(receivedCmd[1] == 0x20 && receivedCmd[0] ==0x95) {    // greg - cascade 2 anti-collision\r
-                       // Received request for UID (cascade 2)\r
-                       resp = resp2a; respLen = resp2aLen; order = 20;\r
-//                     DbpString("UID (cascade 2) request from reader:");\r
-//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-\r
-\r
-               } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x93) {    // greg - cascade 1 select\r
-                       // Received a SELECT\r
-                       resp = resp3; respLen = resp3Len; order = 3;\r
-//                     DbpString("Select (cascade 1) request from reader:");\r
-//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-\r
-\r
-               } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x95) {    // greg - cascade 2 select\r
-                       // Received a SELECT\r
-                       resp = resp3a; respLen = resp3aLen; order = 30;\r
-//                     DbpString("Select (cascade 2) request from reader:");\r
-//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-\r
-\r
-               } else if(receivedCmd[0] == 0x30) {\r
-                       // Received a READ\r
-                       resp = resp4; respLen = resp4Len; order = 4; // Do nothing\r
-                       Dbprintf("Read request from reader: %x %x %x",\r
-                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-\r
-\r
-               } else if(receivedCmd[0] == 0x50) {\r
-                       // Received a HALT\r
-                       resp = resp1; respLen = 0; order = 5; // Do nothing\r
-                       DbpString("Reader requested we HALT!:");\r
-\r
-               } else if(receivedCmd[0] == 0x60) {\r
-                       // Received an authentication request\r
-                       resp = resp5; respLen = resp5Len; order = 7;\r
-                       Dbprintf("Authenticate request from reader: %x %x %x",\r
-                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-\r
-               } else if(receivedCmd[0] == 0xE0) {\r
-                       // Received a RATS request\r
-                       resp = resp1; respLen = 0;order = 70;\r
-                       Dbprintf("RATS request from reader: %x %x %x",\r
-                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);\r
-        } else {\r
-            // Never seen this command before\r
-               Dbprintf("Unknown command received from reader: %x %x %x %x %x %x %x %x %x",\r
-                       receivedCmd[0], receivedCmd[1], receivedCmd[2],\r
-                       receivedCmd[3], receivedCmd[3], receivedCmd[4],\r
-                       receivedCmd[5], receivedCmd[6], receivedCmd[7]);\r
-                       // Do not respond\r
-                       resp = resp1; respLen = 0; order = 0;\r
-        }\r
-\r
-               // Count number of wakeups received after a halt\r
-               if(order == 6 && lastorder == 5) { happened++; }\r
-\r
-               // Count number of other messages after a halt\r
-               if(order != 6 && lastorder == 5) { happened2++; }\r
-\r
-               // Look at last parity bit to determine timing of answer\r
-               if((Uart.parityBits & 0x01) || receivedCmd[0] == 0x52) {\r
-                       // 1236, so correction bit needed\r
-                       i = 0;\r
-               }\r
-\r
-        memset(receivedCmd, 0x44, 32);\r
-\r
-               if(cmdsRecvd > 999) {\r
-                       DbpString("1000 commands later...");\r
-            break;\r
-        }\r
-               else {\r
-                       cmdsRecvd++;\r
-               }\r
-\r
-        if(respLen <= 0) continue;\r
-\r
-        // Modulate Manchester\r
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);\r
-        AT91C_BASE_SSC->SSC_THR = 0x00;\r
-        FpgaSetupSsc();\r
-\r
-               // ### Transmit the response ###\r
-               u = 0;\r
-               b = 0x00;\r
-               fdt_indicator = FALSE;\r
-        for(;;) {\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
-            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-                               if(i > respLen) {\r
-                                       b = 0x00;\r
-                                       u++;\r
-                               } else {\r
-                                       b = resp[i];\r
-                                       i++;\r
-                               }\r
-                               AT91C_BASE_SSC->SSC_THR = b;\r
-\r
-                if(u > 4) {\r
-                    break;\r
-                }\r
-            }\r
-                       if(BUTTON_PRESS()) {\r
-                           break;\r
-                       }\r
-        }\r
-\r
-    }\r
-\r
-       Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);\r
-       LED_A_OFF();\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Transmit the command (to the tag) that was placed in ToSend[].\r
-//-----------------------------------------------------------------------------\r
-static void TransmitFor14443a(const BYTE *cmd, int len, int *samples, int *wait)\r
-{\r
-  int c;\r
-  \r
-  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
-  \r
-       if (wait)\r
-    if(*wait < 10)\r
-      *wait = 10;\r
-  \r
-  for(c = 0; c < *wait;) {\r
-    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-      AT91C_BASE_SSC->SSC_THR = 0x00;          // For exact timing!\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 = cmd[c];\r
-      c++;\r
-      if(c >= len) {\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
-       if (samples) *samples = (c + *wait) << 3;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// To generate an arbitrary stream from reader\r
-//\r
-//-----------------------------------------------------------------------------\r
-void ArbitraryFromReader(const BYTE *cmd, int parity, int len)\r
-{\r
-       int i;\r
-       int j;\r
-       int last;\r
-    BYTE b;\r
-\r
-       ToSendReset();\r
-\r
-       // Start of Communication (Seq. Z)\r
-       Sequence(SEC_Z);\r
-       last = 0;\r
-\r
-       for(i = 0; i < len; i++) {\r
-        // Data bits\r
-        b = cmd[i];\r
-               for(j = 0; j < 8; j++) {\r
-                       if(b & 1) {\r
-                               // Sequence X\r
-                               Sequence(SEC_X);\r
-                               last = 1;\r
-                       } else {\r
-                               if(last == 0) {\r
-                                       // Sequence Z\r
-                                       Sequence(SEC_Z);\r
-                               }\r
-                               else {\r
-                                       // Sequence Y\r
-                                       Sequence(SEC_Y);\r
-                                       last = 0;\r
-                               }\r
-                       }\r
-                       b >>= 1;\r
-\r
-               }\r
-\r
-               // Predefined parity bit, the flipper flips when needed, because of flips in byte sent\r
-               if(((parity >> (len - i - 1)) & 1)) {\r
-                       // Sequence X\r
-                       Sequence(SEC_X);\r
-                       last = 1;\r
-               } else {\r
-                       if(last == 0) {\r
-                               // Sequence Z\r
-                               Sequence(SEC_Z);\r
-                       }\r
-                       else {\r
-                               // Sequence Y\r
-                               Sequence(SEC_Y);\r
-                               last = 0;\r
-                       }\r
-               }\r
-       }\r
-\r
-       // End of Communication\r
-       if(last == 0) {\r
-               // Sequence Z\r
-               Sequence(SEC_Z);\r
-       }\r
-       else {\r
-               // Sequence Y\r
-               Sequence(SEC_Y);\r
-               last = 0;\r
-       }\r
-       // Sequence Y\r
-       Sequence(SEC_Y);\r
-\r
-       // Just to be sure!\r
-       Sequence(SEC_Y);\r
-       Sequence(SEC_Y);\r
-       Sequence(SEC_Y);\r
-\r
-    // Convert from last character reference to length\r
-    ToSendMax++;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Code a 7-bit command without parity bit\r
-// This is especially for 0x26 and 0x52 (REQA and WUPA)\r
-//-----------------------------------------------------------------------------\r
-void ShortFrameFromReader(const BYTE bt)\r
-{\r
-       int j;\r
-       int last;\r
-  BYTE b;\r
-\r
-       ToSendReset();\r
-\r
-       // Start of Communication (Seq. Z)\r
-       Sequence(SEC_Z);\r
-       last = 0;\r
-\r
-       b = bt;\r
-       for(j = 0; j < 7; j++) {\r
-               if(b & 1) {\r
-                       // Sequence X\r
-                       Sequence(SEC_X);\r
-                       last = 1;\r
-               } else {\r
-                       if(last == 0) {\r
-                               // Sequence Z\r
-                               Sequence(SEC_Z);\r
-                       }\r
-                       else {\r
-                               // Sequence Y\r
-                               Sequence(SEC_Y);\r
-                               last = 0;\r
-                       }\r
-               }\r
-               b >>= 1;\r
-       }\r
-\r
-       // End of Communication\r
-       if(last == 0) {\r
-               // Sequence Z\r
-               Sequence(SEC_Z);\r
-       }\r
-       else {\r
-               // Sequence Y\r
-               Sequence(SEC_Y);\r
-               last = 0;\r
-       }\r
-       // Sequence Y\r
-       Sequence(SEC_Y);\r
-\r
-       // Just to be sure!\r
-       Sequence(SEC_Y);\r
-       Sequence(SEC_Y);\r
-       Sequence(SEC_Y);\r
-\r
-    // Convert from last character reference to length\r
-    ToSendMax++;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Prepare reader command to send to FPGA\r
-// \r
-//-----------------------------------------------------------------------------\r
-void CodeIso14443aAsReaderPar(const BYTE * cmd, int len, DWORD dwParity)\r
-{\r
-  int i, j;\r
-  int last;\r
-  BYTE b;\r
-  \r
-  ToSendReset();\r
-  \r
-  // Start of Communication (Seq. Z)\r
-  Sequence(SEC_Z);\r
-  last = 0;\r
-  \r
-  // Generate send structure for the data bits\r
-  for (i = 0; i < len; i++) {\r
-    // Get the current byte to send\r
-    b = cmd[i];\r
-    \r
-    for (j = 0; j < 8; j++) {\r
-      if (b & 1) {\r
-        // Sequence X\r
-        Sequence(SEC_X);\r
-        last = 1;\r
-      } else {\r
-        if (last == 0) {\r
-          // Sequence Z\r
-          Sequence(SEC_Z);\r
-        } else {\r
-          // Sequence Y\r
-          Sequence(SEC_Y);\r
-          last = 0;\r
-        }\r
-      }\r
-      b >>= 1;\r
-    }\r
-    \r
-    // Get the parity bit\r
-    if ((dwParity >> i) & 0x01) {\r
-      // Sequence X\r
-      Sequence(SEC_X);\r
-      last = 1;\r
-    } else {\r
-      if (last == 0) {\r
-        // Sequence Z\r
-        Sequence(SEC_Z);\r
-      } else {\r
-        // Sequence Y\r
-        Sequence(SEC_Y);\r
-        last = 0;\r
-      }\r
-    }\r
-  }\r
-  \r
-  // End of Communication\r
-  if (last == 0) {\r
-    // Sequence Z\r
-    Sequence(SEC_Z);\r
-  } else {\r
-    // Sequence Y\r
-    Sequence(SEC_Y);\r
-    last = 0;\r
-  }\r
-  // Sequence Y\r
-  Sequence(SEC_Y);\r
-  \r
-  // Just to be sure!\r
-  Sequence(SEC_Y);\r
-  Sequence(SEC_Y);\r
-  Sequence(SEC_Y);\r
-  \r
-  // Convert from last character reference to length\r
-  ToSendMax++;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Wait a certain time for tag response\r
-//  If a response is captured return TRUE\r
-//  If it takes to long return FALSE\r
-//-----------------------------------------------------------------------------\r
-static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed) //BYTE *buffer\r
-{\r
-       // buffer needs to be 512 bytes\r
-       int c;\r
-\r
-       // Set FPGA mode to "reader listen mode", no modulation (listen\r
-    // only, since we are receiving, not transmitting).\r
-    // Signal field is on with the appropriate LED\r
-    LED_D_ON();\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);\r
-\r
-    // Now get the answer from the card\r
-    Demod.output = receivedResponse;\r
-    Demod.len = 0;\r
-    Demod.state = DEMOD_UNSYNCD;\r
-\r
-       BYTE b;\r
-       if (elapsed) *elapsed = 0;\r
-\r
-       c = 0;\r
-       for(;;) {\r
-        WDT_HIT();\r
-\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = 0x00;  // To make use of exact timing of next command from reader!!\r
-                       if (elapsed) (*elapsed)++;\r
-        }\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-                       if(c < 512) { c++; } else { return FALSE; }\r
-            b = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
-                       if(ManchesterDecoding((b & 0xf0) >> 4)) {\r
-                               *samples = ((c - 1) << 3) + 4;\r
-                               return TRUE;\r
-                       }\r
-                       if(ManchesterDecoding(b & 0x0f)) {\r
-                               *samples = c << 3;\r
-                               return TRUE;\r
-                       }\r
-        }\r
-    }\r
-}\r
-\r
-void ReaderTransmitShort(const BYTE* bt)\r
-{\r
-  int wait = 0;\r
-  int samples = 0;\r
-\r
-  ShortFrameFromReader(*bt);\r
-  \r
-  // Select the card\r
-  TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);               \r
-  \r
-  // Store reader command in buffer\r
-  if (tracing) LogTrace(bt,1,0,GetParity(bt,1),TRUE);\r
-}\r
-\r
-void ReaderTransmitPar(BYTE* frame, int len, DWORD par)\r
-{\r
-  int wait = 0;\r
-  int samples = 0;\r
-  \r
-  // This is tied to other size changes\r
-  //   BYTE* frame_addr = ((BYTE*)BigBuf) + 2024; \r
-  CodeIso14443aAsReaderPar(frame,len,par);\r
-  \r
-  // Select the card\r
-  TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);               \r
-  \r
-  // Store reader command in buffer\r
-  if (tracing) LogTrace(frame,len,0,par,TRUE);\r
-}\r
-\r
-\r
-void ReaderTransmit(BYTE* frame, int len)\r
-{\r
-  // Generate parity and redirect\r
-  ReaderTransmitPar(frame,len,GetParity(frame,len));\r
-}\r
-\r
-BOOL ReaderReceive(BYTE* receivedAnswer)\r
-{\r
-  int samples = 0;\r
-  if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE;\r
-  if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);\r
-  return TRUE;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Read an ISO 14443a tag. Send out commands and store answers.\r
-//\r
-//-----------------------------------------------------------------------------\r
-void ReaderIso14443a(DWORD parameter)\r
-{\r
-       // Anticollision\r
-       BYTE wupa[]       = { 0x52 };\r
-       BYTE sel_all[]    = { 0x93,0x20 };\r
-       BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
-       BYTE sel_all_c2[] = { 0x95,0x20 };\r
-       BYTE sel_uid_c2[] = { 0x95,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
-\r
-       // Mifare AUTH\r
-       BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };\r
-//     BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00 };\r
-  \r
-  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);    // was 3560 - tied to other size changes\r
-  traceLen = 0;\r
-\r
-       // Setup SSC\r
-       FpgaSetupSsc();\r
-\r
-       // Start from off (no field generated)\r
-  // Signal field is off with the appropriate LED\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(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
-       SpinDelay(200);\r
-\r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
-\r
-       while(traceLen < TRACE_LENGTH)\r
-  {\r
-    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field\r
-    ReaderTransmitShort(wupa);\r
-    \r
-    // Test if the action was cancelled\r
-    if(BUTTON_PRESS()) {\r
-      break;\r
-    }\r
-    \r
-    // Receive the ATQA\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-\r
-    // Transmit SELECT_ALL\r
-    ReaderTransmit(sel_all,sizeof(sel_all));\r
-\r
-    // Receive the UID\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-    \r
-               // Construct SELECT UID command\r
-               // First copy the 5 bytes (Mifare Classic) after the 93 70\r
-               memcpy(sel_uid+2,receivedAnswer,5);\r
-               // Secondly compute the two CRC bytes at the end\r
-    AppendCrc14443a(sel_uid,7);\r
-\r
-    // Transmit SELECT_UID\r
-    ReaderTransmit(sel_uid,sizeof(sel_uid));\r
-    \r
-    // Receive the SAK\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-\r
-    // OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in\r
-    // which case we need to make a cascade 2 request and select - this is a long UID\r
-    // When the UID is not complete, the 3nd bit (from the right) is set in the SAK. \r
-               if (receivedAnswer[0] &= 0x04)\r
-               {\r
-      // Transmit SELECT_ALL\r
-      ReaderTransmit(sel_all_c2,sizeof(sel_all_c2));\r
-      \r
-      // Receive the UID\r
-      if (!ReaderReceive(receivedAnswer)) continue;\r
-      \r
-      // Construct SELECT UID command\r
-      memcpy(sel_uid_c2+2,receivedAnswer,5);\r
-      // Secondly compute the two CRC bytes at the end\r
-      AppendCrc14443a(sel_uid_c2,7);\r
-      \r
-      // Transmit SELECT_UID\r
-      ReaderTransmit(sel_uid_c2,sizeof(sel_uid_c2));\r
-      \r
-      // Receive the SAK\r
-      if (!ReaderReceive(receivedAnswer)) continue;\r
-               }\r
-\r
-    // Transmit MIFARE_CLASSIC_AUTH\r
-    ReaderTransmit(mf_auth,sizeof(mf_auth));\r
-\r
-    // Receive the (16 bit) "random" nonce\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-       }\r
-\r
-  // Thats it...\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       LEDsoff();\r
-       Dbprintf("%x %x %x", rsamples, 0xCC, 0xCC);\r
-       DbpString("ready..");\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Read an ISO 14443a tag. Send out commands and store answers.\r
-//\r
-//-----------------------------------------------------------------------------\r
-void ReaderMifare(DWORD parameter)\r
-{\r
-  \r
-       // Anticollision\r
-       BYTE wupa[]       = { 0x52 };\r
-       BYTE sel_all[]    = { 0x93,0x20 };\r
-       BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
-  \r
-       // Mifare AUTH\r
-       BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };\r
-  BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
-  \r
-  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);    // was 3560 - tied to other size changes\r
-  traceLen = 0;\r
-  tracing = false;\r
-  \r
-       // Setup SSC\r
-       FpgaSetupSsc();\r
-  \r
-       // Start from off (no field generated)\r
-  // Signal field is off with the appropriate LED\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(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
-       SpinDelay(200);\r
-  \r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
-  \r
-  // Broadcast for a card, WUPA (0x52) will force response from all cards in the field\r
-  ReaderTransmitShort(wupa);\r
-  // Receive the ATQA\r
-  ReaderReceive(receivedAnswer);\r
-  // Transmit SELECT_ALL\r
-  ReaderTransmit(sel_all,sizeof(sel_all));\r
-  // Receive the UID\r
-  ReaderReceive(receivedAnswer);\r
-  // Construct SELECT UID command\r
-  // First copy the 5 bytes (Mifare Classic) after the 93 70\r
-  memcpy(sel_uid+2,receivedAnswer,5);\r
-  // Secondly compute the two CRC bytes at the end\r
-  AppendCrc14443a(sel_uid,7);\r
-    \r
-  byte_t nt_diff = 0;\r
-  LED_A_OFF();\r
-  byte_t par = 0;\r
-  byte_t par_mask = 0xff;\r
-  byte_t par_low = 0;\r
-  BOOL led_on = TRUE;\r
-  \r
-  tracing = FALSE;\r
-  byte_t nt[4];\r
-  byte_t nt_attacked[4];\r
-  byte_t par_list[8];\r
-  byte_t ks_list[8];\r
-  num_to_bytes(parameter,4,nt_attacked);\r
-\r
-  while(TRUE)\r
-  {\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-    SpinDelay(200);\r
-    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
-    \r
-    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field\r
-    ReaderTransmitShort(wupa);\r
-    \r
-    // Test if the action was cancelled\r
-    if(BUTTON_PRESS()) {\r
-      break;\r
-    }\r
-    \r
-    // Receive the ATQA\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-    \r
-    // Transmit SELECT_ALL\r
-    ReaderTransmit(sel_all,sizeof(sel_all));\r
-    \r
-    // Receive the UID\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-    \r
-    // Transmit SELECT_UID\r
-    ReaderTransmit(sel_uid,sizeof(sel_uid));\r
-    \r
-    // Receive the SAK\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-    \r
-    // Transmit MIFARE_CLASSIC_AUTH\r
-    ReaderTransmit(mf_auth,sizeof(mf_auth));\r
-    \r
-    // Receive the (16 bit) "random" nonce\r
-    if (!ReaderReceive(receivedAnswer)) continue;\r
-    memcpy(nt,receivedAnswer,4);\r
-\r
-    // Transmit reader nonce and reader answer\r
-    ReaderTransmitPar(mf_nr_ar,sizeof(mf_nr_ar),par);\r
-    \r
-    // Receive 4 bit answer\r
-    if (ReaderReceive(receivedAnswer))\r
-    {\r
-      if (nt_diff == 0)        \r
-      {\r
-        LED_A_ON();\r
-        memcpy(nt_attacked,nt,4);\r
-        par_mask = 0xf8;\r
-        par_low = par & 0x07;\r
-      }\r
-\r
-      if (memcmp(nt,nt_attacked,4) != 0) continue;\r
-\r
-      led_on = !led_on;\r
-      if(led_on) LED_B_ON(); else LED_B_OFF();\r
-      par_list[nt_diff] = par;\r
-      ks_list[nt_diff] = receivedAnswer[0]^0x05;\r
-      \r
-      // Test if the information is complete\r
-      if (nt_diff == 0x07) break;\r
-      \r
-      nt_diff = (nt_diff+1) & 0x07;\r
-      mf_nr_ar[3] = nt_diff << 5;\r
-      par = par_low;\r
-    } else {\r
-      if (nt_diff == 0)\r
-      {\r
-        par++;\r
-      } else {\r
-        par = (((par>>3)+1) << 3) | par_low;\r
-      }\r
-    }\r
-  }\r
-  \r
-  LogTraceInfo(sel_uid+2,4);\r
-  LogTraceInfo(nt,4);\r
-  LogTraceInfo(par_list,8);\r
-  LogTraceInfo(ks_list,8);\r
-  \r
-  // Thats it...\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       LEDsoff();\r
-  tracing = TRUE;\r
-}\r
+//-----------------------------------------------------------------------------
+// Routines to support ISO 14443 type A.
+//
+// Gerhard de Koning Gans - May 2008
+//-----------------------------------------------------------------------------
+#include <proxmark3.h>
+#include "apps.h"
+#include "iso14443crc.h"
+
+static BYTE *trace = (BYTE *) BigBuf;
+static int traceLen = 0;
+static int rsamples = 0;
+static BOOL tracing = TRUE;
+
+typedef enum {
+       SEC_D = 1,
+       SEC_E = 2,
+       SEC_F = 3,
+       SEC_X = 4,
+       SEC_Y = 5,
+       SEC_Z = 6
+} SecType;
+
+static const BYTE OddByteParity[256] = {
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT
+#define RECV_CMD_OFFSET   3032
+#define RECV_RES_OFFSET   3096
+#define DMA_BUFFER_OFFSET 3160
+#define DMA_BUFFER_SIZE   4096
+#define TRACE_LENGTH      3000
+
+//-----------------------------------------------------------------------------
+// Generate the parity value for a byte sequence
+// 
+//-----------------------------------------------------------------------------
+DWORD GetParity(const BYTE * pbtCmd, int iLen)
+{
+  int i;
+  DWORD dwPar = 0;
+  
+  // Generate the encrypted data
+  for (i = 0; i < iLen; i++) {
+    // Save the encrypted parity bit
+    dwPar |= ((OddByteParity[pbtCmd[i]]) << i);
+  }
+  return dwPar;
+}
+
+static void AppendCrc14443a(BYTE* data, int len)
+{
+  ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
+}
+
+BOOL LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL bReader)
+{
+  // Return when trace is full
+  if (traceLen >= TRACE_LENGTH) return FALSE;
+  
+  // Trace the random, i'm curious
+  rsamples += iSamples;
+  trace[traceLen++] = ((rsamples >> 0) & 0xff);
+  trace[traceLen++] = ((rsamples >> 8) & 0xff);
+  trace[traceLen++] = ((rsamples >> 16) & 0xff);
+  trace[traceLen++] = ((rsamples >> 24) & 0xff);
+  if (!bReader) {
+    trace[traceLen - 1] |= 0x80;
+  }
+  trace[traceLen++] = ((dwParity >> 0) & 0xff);
+  trace[traceLen++] = ((dwParity >> 8) & 0xff);
+  trace[traceLen++] = ((dwParity >> 16) & 0xff);
+  trace[traceLen++] = ((dwParity >> 24) & 0xff);
+  trace[traceLen++] = iLen;
+  memcpy(trace + traceLen, btBytes, iLen);
+  traceLen += iLen;
+  return TRUE;
+}
+
+BOOL LogTraceInfo(byte_t* data, size_t len)
+{
+  return LogTrace(data,len,0,GetParity(data,len),TRUE);
+}
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+    enum {
+        STATE_UNSYNCD,
+        STATE_START_OF_COMMUNICATION,
+               STATE_MILLER_X,
+               STATE_MILLER_Y,
+               STATE_MILLER_Z,
+        STATE_ERROR_WAIT
+    }       state;
+    WORD    shiftReg;
+    int     bitCnt;
+    int     byteCnt;
+    int     byteCntMax;
+    int     posCnt;
+    int     syncBit;
+       int     parityBits;
+       int     samples;
+    int     highCnt;
+    int     bitBuffer;
+       enum {
+               DROP_NONE,
+               DROP_FIRST_HALF,
+               DROP_SECOND_HALF
+       }               drop;
+    BYTE   *output;
+} Uart;
+
+static BOOL MillerDecoding(int bit)
+{
+       int error = 0;
+       int bitright;
+
+       if(!Uart.bitBuffer) {
+               Uart.bitBuffer = bit ^ 0xFF0;
+               return FALSE;
+       }
+       else {
+               Uart.bitBuffer <<= 4;
+               Uart.bitBuffer ^= bit;
+       }
+
+       BOOL EOC = FALSE;
+
+       if(Uart.state != STATE_UNSYNCD) {
+               Uart.posCnt++;
+
+               if((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) {
+                       bit = 0x00;
+               }
+               else {
+                       bit = 0x01;
+               }
+               if(((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) {
+                       bitright = 0x00;
+               }
+               else {
+                       bitright = 0x01;
+               }
+               if(bit != bitright) { bit = bitright; }
+
+               if(Uart.posCnt == 1) {
+                       // measurement first half bitperiod
+                       if(!bit) {
+                               Uart.drop = DROP_FIRST_HALF;
+                       }
+               }
+               else {
+                       // measurement second half bitperiod
+                       if(!bit & (Uart.drop == DROP_NONE)) {
+                               Uart.drop = DROP_SECOND_HALF;
+                       }
+                       else if(!bit) {
+                               // measured a drop in first and second half
+                               // which should not be possible
+                               Uart.state = STATE_ERROR_WAIT;
+                               error = 0x01;
+                       }
+
+                       Uart.posCnt = 0;
+
+                       switch(Uart.state) {
+                               case STATE_START_OF_COMMUNICATION:
+                                       Uart.shiftReg = 0;
+                                       if(Uart.drop == DROP_SECOND_HALF) {
+                                               // error, should not happen in SOC
+                                               Uart.state = STATE_ERROR_WAIT;
+                                               error = 0x02;
+                                       }
+                                       else {
+                                               // correct SOC
+                                               Uart.state = STATE_MILLER_Z;
+                                       }
+                                       break;
+
+                               case STATE_MILLER_Z:
+                                       Uart.bitCnt++;
+                                       Uart.shiftReg >>= 1;
+                                       if(Uart.drop == DROP_NONE) {
+                                               // logic '0' followed by sequence Y
+                                               // end of communication
+                                               Uart.state = STATE_UNSYNCD;
+                                               EOC = TRUE;
+                                       }
+                                       // if(Uart.drop == DROP_FIRST_HALF) {
+                                       //      Uart.state = STATE_MILLER_Z; stay the same
+                                       //      we see a logic '0' }
+                                       if(Uart.drop == DROP_SECOND_HALF) {
+                                               // we see a logic '1'
+                                               Uart.shiftReg |= 0x100;
+                                               Uart.state = STATE_MILLER_X;
+                                       }
+                                       break;
+
+                               case STATE_MILLER_X:
+                                       Uart.shiftReg >>= 1;
+                                       if(Uart.drop == DROP_NONE) {
+                                               // sequence Y, we see a '0'
+                                               Uart.state = STATE_MILLER_Y;
+                                               Uart.bitCnt++;
+                                       }
+                                       if(Uart.drop == DROP_FIRST_HALF) {
+                                               // Would be STATE_MILLER_Z
+                                               // but Z does not follow X, so error
+                                               Uart.state = STATE_ERROR_WAIT;
+                                               error = 0x03;
+                                       }
+                                       if(Uart.drop == DROP_SECOND_HALF) {
+                                               // We see a '1' and stay in state X
+                                               Uart.shiftReg |= 0x100;
+                                               Uart.bitCnt++;
+                                       }
+                                       break;
+
+                               case STATE_MILLER_Y:
+                                       Uart.bitCnt++;
+                                       Uart.shiftReg >>= 1;
+                                       if(Uart.drop == DROP_NONE) {
+                                               // logic '0' followed by sequence Y
+                                               // end of communication
+                                               Uart.state = STATE_UNSYNCD;
+                                               EOC = TRUE;
+                                       }
+                                       if(Uart.drop == DROP_FIRST_HALF) {
+                                               // we see a '0'
+                                               Uart.state = STATE_MILLER_Z;
+                                       }
+                                       if(Uart.drop == DROP_SECOND_HALF) {
+                                               // We see a '1' and go to state X
+                                               Uart.shiftReg |= 0x100;
+                                               Uart.state = STATE_MILLER_X;
+                                       }
+                                       break;
+
+                               case STATE_ERROR_WAIT:
+                                       // That went wrong. Now wait for at least two bit periods
+                                       // and try to sync again
+                                       if(Uart.drop == DROP_NONE) {
+                                               Uart.highCnt = 6;
+                                               Uart.state = STATE_UNSYNCD;
+                                       }
+                                       break;
+
+                               default:
+                                       Uart.state = STATE_UNSYNCD;
+                                       Uart.highCnt = 0;
+                                       break;
+                       }
+
+                       Uart.drop = DROP_NONE;
+
+                       // should have received at least one whole byte...
+                       if((Uart.bitCnt == 2) && EOC && (Uart.byteCnt > 0)) {
+                               return TRUE;
+                       }
+
+                       if(Uart.bitCnt == 9) {
+                               Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff);
+                               Uart.byteCnt++;
+
+                               Uart.parityBits <<= 1;
+                               Uart.parityBits ^= ((Uart.shiftReg >> 8) & 0x01);
+
+                               if(EOC) {
+                                       // when End of Communication received and
+                                       // all data bits processed..
+                                       return TRUE;
+                               }
+                               Uart.bitCnt = 0;
+                       }
+
+                       /*if(error) {
+                               Uart.output[Uart.byteCnt] = 0xAA;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = error & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = 0xAA;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = 0xAA;
+                               Uart.byteCnt++;
+                               return TRUE;
+                       }*/
+               }
+
+       }
+       else {
+               bit = Uart.bitBuffer & 0xf0;
+               bit >>= 4;
+               bit ^= 0x0F;
+               if(bit) {
+                       // should have been high or at least (4 * 128) / fc
+                       // according to ISO this should be at least (9 * 128 + 20) / fc
+                       if(Uart.highCnt == 8) {
+                               // we went low, so this could be start of communication
+                               // it turns out to be safer to choose a less significant
+                               // syncbit... so we check whether the neighbour also represents the drop
+                               Uart.posCnt = 1;   // apparently we are busy with our first half bit period
+                               Uart.syncBit = bit & 8;
+                               Uart.samples = 3;
+                               if(!Uart.syncBit)       { Uart.syncBit = bit & 4; Uart.samples = 2; }
+                               else if(bit & 4)        { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; }
+                               if(!Uart.syncBit)       { Uart.syncBit = bit & 2; Uart.samples = 1; }
+                               else if(bit & 2)        { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; }
+                               if(!Uart.syncBit)       { Uart.syncBit = bit & 1; Uart.samples = 0;
+                                       if(Uart.syncBit & (Uart.bitBuffer & 8)) {
+                                               Uart.syncBit = 8;
+
+                                               // the first half bit period is expected in next sample
+                                               Uart.posCnt = 0;
+                                               Uart.samples = 3;
+                                       }
+                               }
+                               else if(bit & 1)        { Uart.syncBit = bit & 1; Uart.samples = 0; }
+
+                               Uart.syncBit <<= 4;
+                               Uart.state = STATE_START_OF_COMMUNICATION;
+                               Uart.drop = DROP_FIRST_HALF;
+                               Uart.bitCnt = 0;
+                               Uart.byteCnt = 0;
+                               Uart.parityBits = 0;
+                               error = 0;
+                       }
+                       else {
+                               Uart.highCnt = 0;
+                       }
+               }
+               else {
+                       if(Uart.highCnt < 8) {
+                               Uart.highCnt++;
+                       }
+               }
+       }
+
+    return FALSE;
+}
+
+//=============================================================================
+// ISO 14443 Type A - Manchester
+//=============================================================================
+
+static struct {
+    enum {
+        DEMOD_UNSYNCD,
+               DEMOD_START_OF_COMMUNICATION,
+               DEMOD_MANCHESTER_D,
+               DEMOD_MANCHESTER_E,
+               DEMOD_MANCHESTER_F,
+        DEMOD_ERROR_WAIT
+    }       state;
+    int     bitCount;
+    int     posCount;
+       int     syncBit;
+       int     parityBits;
+    WORD    shiftReg;
+       int     buffer;
+       int     buff;
+       int     samples;
+    int     len;
+       enum {
+               SUB_NONE,
+               SUB_FIRST_HALF,
+               SUB_SECOND_HALF
+       }               sub;
+    BYTE   *output;
+} Demod;
+
+static BOOL ManchesterDecoding(int v)
+{
+       int bit;
+       int modulation;
+       int error = 0;
+
+       if(!Demod.buff) {
+               Demod.buff = 1;
+               Demod.buffer = v;
+               return FALSE;
+       }
+       else {
+               bit = Demod.buffer;
+               Demod.buffer = v;
+       }
+
+       if(Demod.state==DEMOD_UNSYNCD) {
+               Demod.output[Demod.len] = 0xfa;
+               Demod.syncBit = 0;
+               //Demod.samples = 0;
+               Demod.posCount = 1;             // This is the first half bit period, so after syncing handle the second part
+               if(bit & 0x08) { Demod.syncBit = 0x08; }
+               if(!Demod.syncBit)      {
+                       if(bit & 0x04) { Demod.syncBit = 0x04; }
+               }
+               else if(bit & 0x04) { Demod.syncBit = 0x04; bit <<= 4; }
+               if(!Demod.syncBit)      {
+                       if(bit & 0x02) { Demod.syncBit = 0x02; }
+               }
+               else if(bit & 0x02) { Demod.syncBit = 0x02; bit <<= 4; }
+               if(!Demod.syncBit)      {
+                       if(bit & 0x01) { Demod.syncBit = 0x01; }
+
+                       if(Demod.syncBit & (Demod.buffer & 0x08)) {
+                               Demod.syncBit = 0x08;
+
+                               // The first half bitperiod is expected in next sample
+                               Demod.posCount = 0;
+                               Demod.output[Demod.len] = 0xfb;
+                       }
+               }
+               else if(bit & 0x01) { Demod.syncBit = 0x01; }
+
+               if(Demod.syncBit) {
+                       Demod.len = 0;
+                       Demod.state = DEMOD_START_OF_COMMUNICATION;
+                       Demod.sub = SUB_FIRST_HALF;
+                       Demod.bitCount = 0;
+                       Demod.shiftReg = 0;
+                       Demod.parityBits = 0;
+                       Demod.samples = 0;
+                       if(Demod.posCount) {
+                               switch(Demod.syncBit) {
+                                       case 0x08: Demod.samples = 3; break;
+                                       case 0x04: Demod.samples = 2; break;
+                                       case 0x02: Demod.samples = 1; break;
+                                       case 0x01: Demod.samples = 0; break;
+                               }
+                       }
+                       error = 0;
+               }
+       }
+       else {
+               //modulation = bit & Demod.syncBit;
+               modulation = ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit;
+
+               Demod.samples += 4;
+
+               if(Demod.posCount==0) {
+                       Demod.posCount = 1;
+                       if(modulation) {
+                               Demod.sub = SUB_FIRST_HALF;
+                       }
+                       else {
+                               Demod.sub = SUB_NONE;
+                       }
+               }
+               else {
+                       Demod.posCount = 0;
+                       if(modulation && (Demod.sub == SUB_FIRST_HALF)) {
+                               if(Demod.state!=DEMOD_ERROR_WAIT) {
+                                       Demod.state = DEMOD_ERROR_WAIT;
+                                       Demod.output[Demod.len] = 0xaa;
+                                       error = 0x01;
+                               }
+                       }
+                       else if(modulation) {
+                               Demod.sub = SUB_SECOND_HALF;
+                       }
+
+                       switch(Demod.state) {
+                               case DEMOD_START_OF_COMMUNICATION:
+                                       if(Demod.sub == SUB_FIRST_HALF) {
+                                               Demod.state = DEMOD_MANCHESTER_D;
+                                       }
+                                       else {
+                                               Demod.output[Demod.len] = 0xab;
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0x02;
+                                       }
+                                       break;
+
+                               case DEMOD_MANCHESTER_D:
+                               case DEMOD_MANCHESTER_E:
+                                       if(Demod.sub == SUB_FIRST_HALF) {
+                                               Demod.bitCount++;
+                                               Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100;
+                                               Demod.state = DEMOD_MANCHESTER_D;
+                                       }
+                                       else if(Demod.sub == SUB_SECOND_HALF) {
+                                               Demod.bitCount++;
+                                               Demod.shiftReg >>= 1;
+                                               Demod.state = DEMOD_MANCHESTER_E;
+                                       }
+                                       else {
+                                               Demod.state = DEMOD_MANCHESTER_F;
+                                       }
+                                       break;
+
+                               case DEMOD_MANCHESTER_F:
+                                       // Tag response does not need to be a complete byte!
+                                       if(Demod.len > 0 || Demod.bitCount > 0) {
+                                               if(Demod.bitCount > 0) {
+                                                       Demod.shiftReg >>= (9 - Demod.bitCount);
+                                                       Demod.output[Demod.len] = Demod.shiftReg & 0xff;
+                                                       Demod.len++;
+                                                       // No parity bit, so just shift a 0
+                                                       Demod.parityBits <<= 1;
+                                               }
+
+                                               Demod.state = DEMOD_UNSYNCD;
+                                               return TRUE;
+                                       }
+                                       else {
+                                               Demod.output[Demod.len] = 0xad;
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0x03;
+                                       }
+                                       break;
+
+                               case DEMOD_ERROR_WAIT:
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       break;
+
+                               default:
+                                       Demod.output[Demod.len] = 0xdd;
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       break;
+                       }
+
+                       if(Demod.bitCount>=9) {
+                               Demod.output[Demod.len] = Demod.shiftReg & 0xff;
+                               Demod.len++;
+
+                               Demod.parityBits <<= 1;
+                               Demod.parityBits ^= ((Demod.shiftReg >> 8) & 0x01);
+
+                               Demod.bitCount = 0;
+                               Demod.shiftReg = 0;
+                       }
+
+                       /*if(error) {
+                               Demod.output[Demod.len] = 0xBB;
+                               Demod.len++;
+                               Demod.output[Demod.len] = error & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = 0xBB;
+                               Demod.len++;
+                               Demod.output[Demod.len] = bit & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = Demod.buffer & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = Demod.syncBit & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = 0xBB;
+                               Demod.len++;
+                               return TRUE;
+                       }*/
+
+               }
+
+       } // end (state != UNSYNCED)
+
+    return FALSE;
+}
+
+//=============================================================================
+// Finally, a `sniffer' for ISO 14443 Type A
+// Both sides of communication!
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+void SnoopIso14443a(void)
+{
+//     #define RECV_CMD_OFFSET         2032    // original (working as of 21/2/09) values
+//     #define RECV_RES_OFFSET         2096    // original (working as of 21/2/09) values
+//     #define DMA_BUFFER_OFFSET       2160    // original (working as of 21/2/09) values
+//     #define DMA_BUFFER_SIZE         4096    // original (working as of 21/2/09) values
+//     #define TRACE_LENGTH            2000    // original (working as of 21/2/09) values
+
+    // 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 = TRUE; // FALSE to wait first for card
+
+    // The command (reader -> tag) that we're receiving.
+       // The length of a received command will in most cases be no more than 18 bytes.
+       // So 32 should be enough!
+    BYTE *receivedCmd = (((BYTE *)BigBuf) + RECV_CMD_OFFSET);
+    // The response (tag -> reader) that we're receiving.
+    BYTE *receivedResponse = (((BYTE *)BigBuf) + RECV_RES_OFFSET);
+
+    // 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) + DMA_BUFFER_OFFSET;
+    int lastRxCounter;
+    SBYTE *upTo;
+    int smpl;
+    int maxBehindBy = 0;
+
+    // Count of samples received so far, so that we can include timing
+    // information in the trace buffer.
+    int samples = 0;
+       int rsamples = 0;
+
+    memset(trace, 0x44, RECV_CMD_OFFSET);
+
+    // 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 = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////
+    Uart.state = STATE_UNSYNCD;
+
+    // And put the FPGA in the appropriate mode
+    // Signal field is off with the appropriate LED
+    LED_D_OFF();
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+       // Setup for the DMA.
+    FpgaSetupSsc();
+    upTo = dmaBuf;
+    lastRxCounter = DMA_BUFFER_SIZE;
+    FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);
+
+    LED_A_ON();
+
+    // And now we loop, receiving samples.
+    for(;;) {
+               WDT_HIT();
+        int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
+                                (DMA_BUFFER_SIZE-1);
+        if(behindBy > maxBehindBy) {
+            maxBehindBy = behindBy;
+            if(behindBy > 400) {
+                DbpString("blew circular buffer!");
+                goto done;
+            }
+        }
+        if(behindBy < 1) continue;
+
+        smpl = upTo[0];
+        upTo++;
+        lastRxCounter -= 1;
+        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 += 4;
+#define HANDLE_BIT_IF_BODY \
+            LED_C_ON(); \
+                       if(triggered) { \
+                               trace[traceLen++] = ((rsamples >>  0) & 0xff); \
+                trace[traceLen++] = ((rsamples >>  8) & 0xff); \
+                trace[traceLen++] = ((rsamples >> 16) & 0xff); \
+                trace[traceLen++] = ((rsamples >> 24) & 0xff); \
+                               trace[traceLen++] = ((Uart.parityBits >>  0) & 0xff); \
+                               trace[traceLen++] = ((Uart.parityBits >>  8) & 0xff); \
+                               trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff); \
+                               trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff); \
+                trace[traceLen++] = Uart.byteCnt; \
+                memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \
+                traceLen += Uart.byteCnt; \
+                if(traceLen > TRACE_LENGTH) break; \
+            } \
+            /* And ready to receive another command. */ \
+            Uart.state = STATE_UNSYNCD; \
+            /* And also reset the demod code, which might have been */ \
+            /* false-triggered by the commands from the reader. */ \
+            Demod.state = DEMOD_UNSYNCD; \
+                       LED_B_OFF(); \
+
+               if(MillerDecoding((smpl & 0xF0) >> 4)) {
+            rsamples = samples - Uart.samples;
+                       HANDLE_BIT_IF_BODY
+        }
+               if(ManchesterDecoding(smpl & 0x0F)) {
+                       rsamples = samples - Demod.samples;
+                       LED_B_ON();
+
+                       // timestamp, as a count of samples
+                       trace[traceLen++] = ((rsamples >>  0) & 0xff);
+                       trace[traceLen++] = ((rsamples >>  8) & 0xff);
+                       trace[traceLen++] = ((rsamples >> 16) & 0xff);
+                       trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);
+                       trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);
+                       trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);
+                       trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);
+                       trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);
+                       // length
+                       trace[traceLen++] = Demod.len;
+                       memcpy(trace+traceLen, receivedResponse, Demod.len);
+                       traceLen += Demod.len;
+                       if(traceLen > TRACE_LENGTH) break;
+
+               triggered = TRUE;
+
+            // And ready to receive another response.
+            memset(&Demod, 0, sizeof(Demod));
+            Demod.output = receivedResponse;
+            Demod.state = DEMOD_UNSYNCD;
+                       LED_C_OFF();
+               }
+
+        if(BUTTON_PRESS()) {
+            DbpString("cancelled_a");
+            goto done;
+        }
+    }
+
+    DbpString("COMMAND FINISHED");
+
+    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);
+    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+
+done:
+    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);
+    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+    LED_A_OFF();
+    LED_B_OFF();
+       LED_C_OFF();
+       LED_D_OFF();
+}
+
+// Prepare communication bits to send to FPGA
+void Sequence(SecType seq)
+{
+       ToSendMax++;
+       switch(seq) {
+       // CARD TO READER
+       case SEC_D:
+               // Sequence D: 11110000
+               // modulation with subcarrier during first half
+        ToSend[ToSendMax] = 0xf0;
+               break;
+       case SEC_E:
+               // Sequence E: 00001111
+               // modulation with subcarrier during second half
+        ToSend[ToSendMax] = 0x0f;
+               break;
+       case SEC_F:
+               // Sequence F: 00000000
+               // no modulation with subcarrier
+        ToSend[ToSendMax] = 0x00;
+               break;
+       // READER TO CARD
+       case SEC_X:
+               // Sequence X: 00001100
+               // drop after half a period
+        ToSend[ToSendMax] = 0x0c;
+               break;
+       case SEC_Y:
+       default:
+               // Sequence Y: 00000000
+               // no drop
+        ToSend[ToSendMax] = 0x00;
+               break;
+       case SEC_Z:
+               // Sequence Z: 11000000
+               // drop at start
+        ToSend[ToSendMax] = 0xc0;
+               break;
+       }
+}
+
+//-----------------------------------------------------------------------------
+// Prepare tag messages
+//-----------------------------------------------------------------------------
+static void CodeIso14443aAsTag(const BYTE *cmd, int len)
+{
+    int i;
+       int oddparity;
+
+    ToSendReset();
+
+       // Correction bit, might be removed when not needed
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(1);  // 1
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+
+       // Send startbit
+       Sequence(SEC_D);
+
+    for(i = 0; i < len; i++) {
+        int j;
+        BYTE b = cmd[i];
+
+               // Data bits
+        oddparity = 0x01;
+               for(j = 0; j < 8; j++) {
+            oddparity ^= (b & 1);
+                       if(b & 1) {
+                               Sequence(SEC_D);
+                       } else {
+                               Sequence(SEC_E);
+            }
+            b >>= 1;
+        }
+
+        // Parity bit
+        if(oddparity) {
+                       Sequence(SEC_D);
+               } else {
+                       Sequence(SEC_E);
+               }
+    }
+
+    // Send stopbit
+       Sequence(SEC_F);
+
+       // Flush the buffer in FPGA!!
+       for(i = 0; i < 5; i++) {
+               Sequence(SEC_F);
+       }
+
+    // Convert from last byte pos to length
+    ToSendMax++;
+
+    // Add a few more for slop
+    ToSend[ToSendMax++] = 0x00;
+       ToSend[ToSendMax++] = 0x00;
+    //ToSendMax += 2;
+}
+
+//-----------------------------------------------------------------------------
+// This is to send a NACK kind of answer, its only 3 bits, I know it should be 4
+//-----------------------------------------------------------------------------
+static void CodeStrangeAnswer()
+{
+       int i;
+
+    ToSendReset();
+
+       // Correction bit, might be removed when not needed
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(1);  // 1
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+       ToSendStuffBit(0);
+
+       // Send startbit
+       Sequence(SEC_D);
+
+       // 0
+       Sequence(SEC_E);
+
+       // 0
+       Sequence(SEC_E);
+
+       // 1
+       Sequence(SEC_D);
+
+    // Send stopbit
+       Sequence(SEC_F);
+
+       // Flush the buffer in FPGA!!
+       for(i = 0; i < 5; i++) {
+               Sequence(SEC_F);
+       }
+
+    // Convert from last byte pos to length
+    ToSendMax++;
+
+    // Add a few more for slop
+    ToSend[ToSendMax++] = 0x00;
+       ToSend[ToSendMax++] = 0x00;
+    //ToSendMax += 2;
+}
+
+//-----------------------------------------------------------------------------
+// Wait for commands from reader
+// Stop when button is pressed
+// Or return TRUE when command is captured
+//-----------------------------------------------------------------------------
+static BOOL GetIso14443aCommandFromReader(BYTE *received, int *len, int maxLen)
+{
+    // 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_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
+
+    // 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;
+                       if(MillerDecoding((b & 0xf0) >> 4)) {
+                               *len = Uart.byteCnt;
+                               return TRUE;
+                       }
+                       if(MillerDecoding(b & 0x0f)) {
+                               *len = Uart.byteCnt;
+                               return TRUE;
+                       }
+        }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Main loop of simulated tag: receive commands from reader, decide what
+// response to send, and send it.
+//-----------------------------------------------------------------------------
+void SimulateIso14443aTag(int tagType, int TagUid)
+{
+       // This function contains the tag emulation
+
+       // Prepare protocol messages
+    // static const BYTE cmd1[] = { 0x26 };
+//     static const BYTE response1[] = { 0x02, 0x00 }; // Says: I am Mifare 4k - original line - greg
+//
+       static const BYTE response1[] = { 0x44, 0x03 }; // Says: I am a DESFire Tag, ph33r me
+//     static const BYTE response1[] = { 0x44, 0x00 }; // Says: I am a ULTRALITE Tag, 0wn me
+
+       // UID response
+    // static const BYTE cmd2[] = { 0x93, 0x20 };
+    //static const BYTE response2[] = { 0x9a, 0xe5, 0xe4, 0x43, 0xd8 }; // original value - greg
+
+
+
+// my desfire
+    static const BYTE response2[] = { 0x88, 0x04, 0x21, 0x3f, 0x4d }; // known uid - note cascade (0x88), 2nd byte (0x04) = NXP/Phillips
+
+
+// When reader selects us during cascade1 it will send cmd3
+//BYTE response3[] = { 0x04, 0x00, 0x00 }; // SAK Select (cascade1) successful response (ULTRALITE)
+BYTE response3[] = { 0x24, 0x00, 0x00 }; // SAK Select (cascade1) successful response (DESFire)
+ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]);
+
+// send cascade2 2nd half of UID
+static const BYTE response2a[] = { 0x51, 0x48, 0x1d, 0x80, 0x84 }; //  uid - cascade2 - 2nd half (4 bytes) of UID+ BCCheck
+// NOTE : THE CRC on the above may be wrong as I have obfuscated the actual UID
+
+
+// When reader selects us during cascade2 it will send cmd3a
+//BYTE response3a[] = { 0x00, 0x00, 0x00 }; // SAK Select (cascade2) successful response (ULTRALITE)
+BYTE response3a[] = { 0x20, 0x00, 0x00 }; // SAK Select (cascade2) successful response (DESFire)
+ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
+
+    static const BYTE response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce
+
+    BYTE *resp;
+    int respLen;
+
+    // Longest possible response will be 16 bytes + 2 CRC = 18 bytes
+       // This will need
+       //    144        data bits (18 * 8)
+       //     18        parity bits
+       //      2        Start and stop
+       //      1        Correction bit (Answer in 1172 or 1236 periods, see FPGA)
+       //      1        just for the case
+       // ----------- +
+       //    166
+       //
+       // 166 bytes, since every bit that needs to be send costs us a byte
+       //
+
+
+    // Respond with card type
+    BYTE *resp1 = (((BYTE *)BigBuf) + 800);
+    int resp1Len;
+
+    // Anticollision cascade1 - respond with uid
+    BYTE *resp2 = (((BYTE *)BigBuf) + 970);
+    int resp2Len;
+
+    // Anticollision cascade2 - respond with 2nd half of uid if asked
+    // we're only going to be asked if we set the 1st byte of the UID (during cascade1) to 0x88
+    BYTE *resp2a = (((BYTE *)BigBuf) + 1140);
+    int resp2aLen;
+
+    // Acknowledge select - cascade 1
+    BYTE *resp3 = (((BYTE *)BigBuf) + 1310);
+    int resp3Len;
+
+    // Acknowledge select - cascade 2
+    BYTE *resp3a = (((BYTE *)BigBuf) + 1480);
+    int resp3aLen;
+
+    // Response to a read request - not implemented atm
+    BYTE *resp4 = (((BYTE *)BigBuf) + 1550);
+    int resp4Len;
+
+    // Authenticate response - nonce
+    BYTE *resp5 = (((BYTE *)BigBuf) + 1720);
+    int resp5Len;
+
+    BYTE *receivedCmd = (BYTE *)BigBuf;
+    int len;
+
+    int i;
+       int u;
+       BYTE b;
+
+       // To control where we are in the protocol
+       int order = 0;
+       int lastorder;
+
+       // Just to allow some checks
+       int happened = 0;
+       int happened2 = 0;
+
+    int cmdsRecvd = 0;
+
+       BOOL fdt_indicator;
+
+    memset(receivedCmd, 0x44, 400);
+
+       // Prepare the responses of the anticollision phase
+       // there will be not enough time to do this at the moment the reader sends it REQA
+
+       // Answer to request
+       CodeIso14443aAsTag(response1, sizeof(response1));
+    memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
+
+       // Send our UID (cascade 1)
+       CodeIso14443aAsTag(response2, sizeof(response2));
+    memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
+
+       // Answer to select (cascade1)
+       CodeIso14443aAsTag(response3, sizeof(response3));
+    memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
+
+       // Send the cascade 2 2nd part of the uid
+       CodeIso14443aAsTag(response2a, sizeof(response2a));
+    memcpy(resp2a, ToSend, ToSendMax); resp2aLen = ToSendMax;
+
+       // Answer to select (cascade 2)
+       CodeIso14443aAsTag(response3a, sizeof(response3a));
+    memcpy(resp3a, ToSend, ToSendMax); resp3aLen = ToSendMax;
+
+       // Strange answer is an example of rare message size (3 bits)
+       CodeStrangeAnswer();
+       memcpy(resp4, ToSend, ToSendMax); resp4Len = ToSendMax;
+
+       // Authentication answer (random nonce)
+       CodeIso14443aAsTag(response5, sizeof(response5));
+    memcpy(resp5, ToSend, ToSendMax); resp5Len = ToSendMax;
+
+    // We need to listen to the high-frequency, peak-detected path.
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+    FpgaSetupSsc();
+
+    cmdsRecvd = 0;
+
+    LED_A_ON();
+       for(;;) {
+
+               if(!GetIso14443aCommandFromReader(receivedCmd, &len, 100)) {
+            DbpString("button press");
+            break;
+        }
+       // doob - added loads of debug strings so we can see what the reader is saying to us during the sim as hi14alist is not populated
+        // Okay, look at the command now.
+        lastorder = order;
+               i = 1; // first byte transmitted
+        if(receivedCmd[0] == 0x26) {
+                       // Received a REQUEST
+                       resp = resp1; respLen = resp1Len; order = 1;
+                       //DbpString("Hello request from reader:");
+               } else if(receivedCmd[0] == 0x52) {
+                       // Received a WAKEUP
+                       resp = resp1; respLen = resp1Len; order = 6;
+//                     //DbpString("Wakeup request from reader:");
+
+               } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == 0x93) {   // greg - cascade 1 anti-collision
+                       // Received request for UID (cascade 1)
+                       resp = resp2; respLen = resp2Len; order = 2;
+//                     DbpString("UID (cascade 1) request from reader:");
+//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+
+
+               } else if(receivedCmd[1] == 0x20 && receivedCmd[0] ==0x95) {    // greg - cascade 2 anti-collision
+                       // Received request for UID (cascade 2)
+                       resp = resp2a; respLen = resp2aLen; order = 20;
+//                     DbpString("UID (cascade 2) request from reader:");
+//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+
+
+               } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x93) {    // greg - cascade 1 select
+                       // Received a SELECT
+                       resp = resp3; respLen = resp3Len; order = 3;
+//                     DbpString("Select (cascade 1) request from reader:");
+//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+
+
+               } else if(receivedCmd[1] == 0x70 && receivedCmd[0] ==0x95) {    // greg - cascade 2 select
+                       // Received a SELECT
+                       resp = resp3a; respLen = resp3aLen; order = 30;
+//                     DbpString("Select (cascade 2) request from reader:");
+//                     DbpIntegers(receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+
+
+               } else if(receivedCmd[0] == 0x30) {
+                       // Received a READ
+                       resp = resp4; respLen = resp4Len; order = 4; // Do nothing
+                       Dbprintf("Read request from reader: %x %x %x",
+                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+
+
+               } else if(receivedCmd[0] == 0x50) {
+                       // Received a HALT
+                       resp = resp1; respLen = 0; order = 5; // Do nothing
+                       DbpString("Reader requested we HALT!:");
+
+               } else if(receivedCmd[0] == 0x60) {
+                       // Received an authentication request
+                       resp = resp5; respLen = resp5Len; order = 7;
+                       Dbprintf("Authenticate request from reader: %x %x %x",
+                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+
+               } else if(receivedCmd[0] == 0xE0) {
+                       // Received a RATS request
+                       resp = resp1; respLen = 0;order = 70;
+                       Dbprintf("RATS request from reader: %x %x %x",
+                               receivedCmd[0], receivedCmd[1], receivedCmd[2]);
+        } else {
+            // Never seen this command before
+               Dbprintf("Unknown command received from reader: %x %x %x %x %x %x %x %x %x",
+                       receivedCmd[0], receivedCmd[1], receivedCmd[2],
+                       receivedCmd[3], receivedCmd[3], receivedCmd[4],
+                       receivedCmd[5], receivedCmd[6], receivedCmd[7]);
+                       // Do not respond
+                       resp = resp1; respLen = 0; order = 0;
+        }
+
+               // Count number of wakeups received after a halt
+               if(order == 6 && lastorder == 5) { happened++; }
+
+               // Count number of other messages after a halt
+               if(order != 6 && lastorder == 5) { happened2++; }
+
+               // Look at last parity bit to determine timing of answer
+               if((Uart.parityBits & 0x01) || receivedCmd[0] == 0x52) {
+                       // 1236, so correction bit needed
+                       i = 0;
+               }
+
+        memset(receivedCmd, 0x44, 32);
+
+               if(cmdsRecvd > 999) {
+                       DbpString("1000 commands later...");
+            break;
+        }
+               else {
+                       cmdsRecvd++;
+               }
+
+        if(respLen <= 0) continue;
+
+        // Modulate Manchester
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
+        AT91C_BASE_SSC->SSC_THR = 0x00;
+        FpgaSetupSsc();
+
+               // ### Transmit the response ###
+               u = 0;
+               b = 0x00;
+               fdt_indicator = FALSE;
+        for(;;) {
+            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                               volatile BYTE b = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+                (void)b;
+            }
+            if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                               if(i > respLen) {
+                                       b = 0x00;
+                                       u++;
+                               } else {
+                                       b = resp[i];
+                                       i++;
+                               }
+                               AT91C_BASE_SSC->SSC_THR = b;
+
+                if(u > 4) {
+                    break;
+                }
+            }
+                       if(BUTTON_PRESS()) {
+                           break;
+                       }
+        }
+
+    }
+
+       Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
+       LED_A_OFF();
+}
+
+//-----------------------------------------------------------------------------
+// Transmit the command (to the tag) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitFor14443a(const BYTE *cmd, int len, int *samples, int *wait)
+{
+  int c;
+  
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+  
+       if (wait)
+    if(*wait < 10)
+      *wait = 10;
+  
+  for(c = 0; c < *wait;) {
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+      AT91C_BASE_SSC->SSC_THR = 0x00;          // For exact timing!
+      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 = cmd[c];
+      c++;
+      if(c >= len) {
+        break;
+      }
+    }
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+      volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
+      (void)r;
+    }
+    WDT_HIT();
+  }
+       if (samples) *samples = (c + *wait) << 3;
+}
+
+//-----------------------------------------------------------------------------
+// To generate an arbitrary stream from reader
+//
+//-----------------------------------------------------------------------------
+void ArbitraryFromReader(const BYTE *cmd, int parity, int len)
+{
+       int i;
+       int j;
+       int last;
+    BYTE b;
+
+       ToSendReset();
+
+       // Start of Communication (Seq. Z)
+       Sequence(SEC_Z);
+       last = 0;
+
+       for(i = 0; i < len; i++) {
+        // Data bits
+        b = cmd[i];
+               for(j = 0; j < 8; j++) {
+                       if(b & 1) {
+                               // Sequence X
+                               Sequence(SEC_X);
+                               last = 1;
+                       } else {
+                               if(last == 0) {
+                                       // Sequence Z
+                                       Sequence(SEC_Z);
+                               }
+                               else {
+                                       // Sequence Y
+                                       Sequence(SEC_Y);
+                                       last = 0;
+                               }
+                       }
+                       b >>= 1;
+
+               }
+
+               // Predefined parity bit, the flipper flips when needed, because of flips in byte sent
+               if(((parity >> (len - i - 1)) & 1)) {
+                       // Sequence X
+                       Sequence(SEC_X);
+                       last = 1;
+               } else {
+                       if(last == 0) {
+                               // Sequence Z
+                               Sequence(SEC_Z);
+                       }
+                       else {
+                               // Sequence Y
+                               Sequence(SEC_Y);
+                               last = 0;
+                       }
+               }
+       }
+
+       // End of Communication
+       if(last == 0) {
+               // Sequence Z
+               Sequence(SEC_Z);
+       }
+       else {
+               // Sequence Y
+               Sequence(SEC_Y);
+               last = 0;
+       }
+       // Sequence Y
+       Sequence(SEC_Y);
+
+       // Just to be sure!
+       Sequence(SEC_Y);
+       Sequence(SEC_Y);
+       Sequence(SEC_Y);
+
+    // Convert from last character reference to length
+    ToSendMax++;
+}
+
+//-----------------------------------------------------------------------------
+// Code a 7-bit command without parity bit
+// This is especially for 0x26 and 0x52 (REQA and WUPA)
+//-----------------------------------------------------------------------------
+void ShortFrameFromReader(const BYTE bt)
+{
+       int j;
+       int last;
+  BYTE b;
+
+       ToSendReset();
+
+       // Start of Communication (Seq. Z)
+       Sequence(SEC_Z);
+       last = 0;
+
+       b = bt;
+       for(j = 0; j < 7; j++) {
+               if(b & 1) {
+                       // Sequence X
+                       Sequence(SEC_X);
+                       last = 1;
+               } else {
+                       if(last == 0) {
+                               // Sequence Z
+                               Sequence(SEC_Z);
+                       }
+                       else {
+                               // Sequence Y
+                               Sequence(SEC_Y);
+                               last = 0;
+                       }
+               }
+               b >>= 1;
+       }
+
+       // End of Communication
+       if(last == 0) {
+               // Sequence Z
+               Sequence(SEC_Z);
+       }
+       else {
+               // Sequence Y
+               Sequence(SEC_Y);
+               last = 0;
+       }
+       // Sequence Y
+       Sequence(SEC_Y);
+
+       // Just to be sure!
+       Sequence(SEC_Y);
+       Sequence(SEC_Y);
+       Sequence(SEC_Y);
+
+    // Convert from last character reference to length
+    ToSendMax++;
+}
+
+//-----------------------------------------------------------------------------
+// Prepare reader command to send to FPGA
+// 
+//-----------------------------------------------------------------------------
+void CodeIso14443aAsReaderPar(const BYTE * cmd, int len, DWORD dwParity)
+{
+  int i, j;
+  int last;
+  BYTE b;
+  
+  ToSendReset();
+  
+  // Start of Communication (Seq. Z)
+  Sequence(SEC_Z);
+  last = 0;
+  
+  // Generate send structure for the data bits
+  for (i = 0; i < len; i++) {
+    // Get the current byte to send
+    b = cmd[i];
+    
+    for (j = 0; j < 8; j++) {
+      if (b & 1) {
+        // Sequence X
+        Sequence(SEC_X);
+        last = 1;
+      } else {
+        if (last == 0) {
+          // Sequence Z
+          Sequence(SEC_Z);
+        } else {
+          // Sequence Y
+          Sequence(SEC_Y);
+          last = 0;
+        }
+      }
+      b >>= 1;
+    }
+    
+    // Get the parity bit
+    if ((dwParity >> i) & 0x01) {
+      // Sequence X
+      Sequence(SEC_X);
+      last = 1;
+    } else {
+      if (last == 0) {
+        // Sequence Z
+        Sequence(SEC_Z);
+      } else {
+        // Sequence Y
+        Sequence(SEC_Y);
+        last = 0;
+      }
+    }
+  }
+  
+  // End of Communication
+  if (last == 0) {
+    // Sequence Z
+    Sequence(SEC_Z);
+  } else {
+    // Sequence Y
+    Sequence(SEC_Y);
+    last = 0;
+  }
+  // Sequence Y
+  Sequence(SEC_Y);
+  
+  // Just to be sure!
+  Sequence(SEC_Y);
+  Sequence(SEC_Y);
+  Sequence(SEC_Y);
+  
+  // Convert from last character reference to length
+  ToSendMax++;
+}
+
+//-----------------------------------------------------------------------------
+// Wait a certain time for tag response
+//  If a response is captured return TRUE
+//  If it takes to long return FALSE
+//-----------------------------------------------------------------------------
+static BOOL GetIso14443aAnswerFromTag(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed) //BYTE *buffer
+{
+       // buffer needs to be 512 bytes
+       int c;
+
+       // Set FPGA mode to "reader listen mode", no modulation (listen
+    // only, since we are receiving, not transmitting).
+    // Signal field is on with the appropriate LED
+    LED_D_ON();
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
+
+    // Now get the answer from the card
+    Demod.output = receivedResponse;
+    Demod.len = 0;
+    Demod.state = DEMOD_UNSYNCD;
+
+       BYTE b;
+       if (elapsed) *elapsed = 0;
+
+       c = 0;
+       for(;;) {
+        WDT_HIT();
+
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+            AT91C_BASE_SSC->SSC_THR = 0x00;  // To make use of exact timing of next command from reader!!
+                       if (elapsed) (*elapsed)++;
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       if(c < 512) { c++; } else { return FALSE; }
+            b = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+                       if(ManchesterDecoding((b & 0xf0) >> 4)) {
+                               *samples = ((c - 1) << 3) + 4;
+                               return TRUE;
+                       }
+                       if(ManchesterDecoding(b & 0x0f)) {
+                               *samples = c << 3;
+                               return TRUE;
+                       }
+        }
+    }
+}
+
+void ReaderTransmitShort(const BYTE* bt)
+{
+  int wait = 0;
+  int samples = 0;
+
+  ShortFrameFromReader(*bt);
+  
+  // Select the card
+  TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);               
+  
+  // Store reader command in buffer
+  if (tracing) LogTrace(bt,1,0,GetParity(bt,1),TRUE);
+}
+
+void ReaderTransmitPar(BYTE* frame, int len, DWORD par)
+{
+  int wait = 0;
+  int samples = 0;
+  
+  // This is tied to other size changes
+  //   BYTE* frame_addr = ((BYTE*)BigBuf) + 2024; 
+  CodeIso14443aAsReaderPar(frame,len,par);
+  
+  // Select the card
+  TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);               
+  
+  // Store reader command in buffer
+  if (tracing) LogTrace(frame,len,0,par,TRUE);
+}
+
+
+void ReaderTransmit(BYTE* frame, int len)
+{
+  // Generate parity and redirect
+  ReaderTransmitPar(frame,len,GetParity(frame,len));
+}
+
+BOOL ReaderReceive(BYTE* receivedAnswer)
+{
+  int samples = 0;
+  if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE;
+  if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);
+  return TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// Read an ISO 14443a tag. Send out commands and store answers.
+//
+//-----------------------------------------------------------------------------
+void ReaderIso14443a(DWORD parameter)
+{
+       // Anticollision
+       BYTE wupa[]       = { 0x52 };
+       BYTE sel_all[]    = { 0x93,0x20 };
+       BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+       BYTE sel_all_c2[] = { 0x95,0x20 };
+       BYTE sel_uid_c2[] = { 0x95,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+
+       // Mifare AUTH
+       BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };
+//     BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00 };
+  
+  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);    // was 3560 - tied to other size changes
+  traceLen = 0;
+
+       // Setup SSC
+       FpgaSetupSsc();
+
+       // Start from off (no field generated)
+  // Signal field is off with the appropriate LED
+  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_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+       SpinDelay(200);
+
+       LED_A_ON();
+       LED_B_OFF();
+       LED_C_OFF();
+
+       while(traceLen < TRACE_LENGTH)
+  {
+    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
+    ReaderTransmitShort(wupa);
+    
+    // Test if the action was cancelled
+    if(BUTTON_PRESS()) {
+      break;
+    }
+    
+    // Receive the ATQA
+    if (!ReaderReceive(receivedAnswer)) continue;
+
+    // Transmit SELECT_ALL
+    ReaderTransmit(sel_all,sizeof(sel_all));
+
+    // Receive the UID
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+               // Construct SELECT UID command
+               // First copy the 5 bytes (Mifare Classic) after the 93 70
+               memcpy(sel_uid+2,receivedAnswer,5);
+               // Secondly compute the two CRC bytes at the end
+    AppendCrc14443a(sel_uid,7);
+
+    // Transmit SELECT_UID
+    ReaderTransmit(sel_uid,sizeof(sel_uid));
+    
+    // Receive the SAK
+    if (!ReaderReceive(receivedAnswer)) continue;
+
+    // OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in
+    // which case we need to make a cascade 2 request and select - this is a long UID
+    // When the UID is not complete, the 3nd bit (from the right) is set in the SAK. 
+               if (receivedAnswer[0] &= 0x04)
+               {
+      // Transmit SELECT_ALL
+      ReaderTransmit(sel_all_c2,sizeof(sel_all_c2));
+      
+      // Receive the UID
+      if (!ReaderReceive(receivedAnswer)) continue;
+      
+      // Construct SELECT UID command
+      memcpy(sel_uid_c2+2,receivedAnswer,5);
+      // Secondly compute the two CRC bytes at the end
+      AppendCrc14443a(sel_uid_c2,7);
+      
+      // Transmit SELECT_UID
+      ReaderTransmit(sel_uid_c2,sizeof(sel_uid_c2));
+      
+      // Receive the SAK
+      if (!ReaderReceive(receivedAnswer)) continue;
+               }
+
+    // Transmit MIFARE_CLASSIC_AUTH
+    ReaderTransmit(mf_auth,sizeof(mf_auth));
+
+    // Receive the (16 bit) "random" nonce
+    if (!ReaderReceive(receivedAnswer)) continue;
+       }
+
+  // Thats it...
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LEDsoff();
+       Dbprintf("%x %x %x", rsamples, 0xCC, 0xCC);
+       DbpString("ready..");
+}
+
+//-----------------------------------------------------------------------------
+// Read an ISO 14443a tag. Send out commands and store answers.
+//
+//-----------------------------------------------------------------------------
+void ReaderMifare(DWORD parameter)
+{
+  
+       // Anticollision
+       BYTE wupa[]       = { 0x52 };
+       BYTE sel_all[]    = { 0x93,0x20 };
+       BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+  
+       // Mifare AUTH
+       BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };
+  BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+  
+  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);    // was 3560 - tied to other size changes
+  traceLen = 0;
+  tracing = false;
+  
+       // Setup SSC
+       FpgaSetupSsc();
+  
+       // Start from off (no field generated)
+  // Signal field is off with the appropriate LED
+  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_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+       SpinDelay(200);
+  
+       LED_A_ON();
+       LED_B_OFF();
+       LED_C_OFF();
+  
+  // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
+  ReaderTransmitShort(wupa);
+  // Receive the ATQA
+  ReaderReceive(receivedAnswer);
+  // Transmit SELECT_ALL
+  ReaderTransmit(sel_all,sizeof(sel_all));
+  // Receive the UID
+  ReaderReceive(receivedAnswer);
+  // Construct SELECT UID command
+  // First copy the 5 bytes (Mifare Classic) after the 93 70
+  memcpy(sel_uid+2,receivedAnswer,5);
+  // Secondly compute the two CRC bytes at the end
+  AppendCrc14443a(sel_uid,7);
+    
+  byte_t nt_diff = 0;
+  LED_A_OFF();
+  byte_t par = 0;
+  byte_t par_mask = 0xff;
+  byte_t par_low = 0;
+  BOOL led_on = TRUE;
+  
+  tracing = FALSE;
+  byte_t nt[4];
+  byte_t nt_attacked[4];
+  byte_t par_list[8];
+  byte_t ks_list[8];
+  num_to_bytes(parameter,4,nt_attacked);
+
+  while(TRUE)
+  {
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+    SpinDelay(200);
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+    
+    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
+    ReaderTransmitShort(wupa);
+    
+    // Test if the action was cancelled
+    if(BUTTON_PRESS()) {
+      break;
+    }
+    
+    // Receive the ATQA
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+    // Transmit SELECT_ALL
+    ReaderTransmit(sel_all,sizeof(sel_all));
+    
+    // Receive the UID
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+    // Transmit SELECT_UID
+    ReaderTransmit(sel_uid,sizeof(sel_uid));
+    
+    // Receive the SAK
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+    // Transmit MIFARE_CLASSIC_AUTH
+    ReaderTransmit(mf_auth,sizeof(mf_auth));
+    
+    // Receive the (16 bit) "random" nonce
+    if (!ReaderReceive(receivedAnswer)) continue;
+    memcpy(nt,receivedAnswer,4);
+
+    // Transmit reader nonce and reader answer
+    ReaderTransmitPar(mf_nr_ar,sizeof(mf_nr_ar),par);
+    
+    // Receive 4 bit answer
+    if (ReaderReceive(receivedAnswer))
+    {
+      if (nt_diff == 0)        
+      {
+        LED_A_ON();
+        memcpy(nt_attacked,nt,4);
+        par_mask = 0xf8;
+        par_low = par & 0x07;
+      }
+
+      if (memcmp(nt,nt_attacked,4) != 0) continue;
+
+      led_on = !led_on;
+      if(led_on) LED_B_ON(); else LED_B_OFF();
+      par_list[nt_diff] = par;
+      ks_list[nt_diff] = receivedAnswer[0]^0x05;
+      
+      // Test if the information is complete
+      if (nt_diff == 0x07) break;
+      
+      nt_diff = (nt_diff+1) & 0x07;
+      mf_nr_ar[3] = nt_diff << 5;
+      par = par_low;
+    } else {
+      if (nt_diff == 0)
+      {
+        par++;
+      } else {
+        par = (((par>>3)+1) << 3) | par_low;
+      }
+    }
+  }
+  
+  LogTraceInfo(sel_uid+2,4);
+  LogTraceInfo(nt,4);
+  LogTraceInfo(par_list,8);
+  LogTraceInfo(ks_list,8);
+  
+  // Thats it...
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LEDsoff();
+  tracing = TRUE;
+}
index acace2954aeab29c510042fa05036a31f3d465be..e36baad2a9688f17f9679f88c3be6ffd6cbd782c 100644 (file)
-//-----------------------------------------------------------------------------\r
-// Routines to support ISO 15693. This includes both the reader software and\r
-// the `fake tag' modes, but at the moment I've implemented only the reader\r
-// stuff, and that barely.\r
-// Jonathan Westhues, split Nov 2006\r
-\r
-// Modified by Greg Jones, Jan 2009 to perform modulation onboard in arm rather than on PC\r
-// Also added additional reader commands (SELECT, READ etc.)\r
-\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-\r
-// FROM winsrc\prox.h //////////////////////////////////\r
-#define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
-\r
-//-----------------------------------------------------------------------------\r
-// Map a sequence of octets (~layer 2 command) into the set of bits to feed\r
-// to the FPGA, to transmit that command to the tag.\r
-//-----------------------------------------------------------------------------\r
-\r
-       // The sampling rate is 106.353 ksps/s, for T = 18.8 us\r
-\r
-       // SOF defined as\r
-       // 1) Unmodulated time of 56.64us\r
-       // 2) 24 pulses of 423.75khz\r
-       // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)\r
-\r
-       static const int FrameSOF[] = {\r
-               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\r
-                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\r
-               -1, -1, -1, -1,\r
-               -1, -1, -1, -1,\r
-                1,  1,  1,  1,\r
-                1,  1,  1,  1\r
-       };\r
-       static const int Logic0[] = {\r
-                1,  1,  1,  1,\r
-                1,  1,  1,  1,\r
-               -1, -1, -1, -1,\r
-               -1, -1, -1, -1\r
-       };\r
-       static const int Logic1[] = {\r
-               -1, -1, -1, -1,\r
-               -1, -1, -1, -1,\r
-                1,  1,  1,  1,\r
-                1,  1,  1,  1\r
-       };\r
-\r
-       // EOF defined as\r
-       // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)\r
-       // 2) 24 pulses of 423.75khz\r
-       // 3) Unmodulated time of 56.64us\r
-\r
-       static const int FrameEOF[] = {\r
-                1,  1,  1,  1,\r
-                1,  1,  1,  1,\r
-               -1, -1, -1, -1,\r
-               -1, -1, -1, -1,\r
-                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\r
-                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,\r
-               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
-               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\r
-       };\r
-\r
-static void CodeIso15693AsReader(BYTE *cmd, int n)\r
-{\r
-       int i, j;\r
-\r
-       ToSendReset();\r
-\r
-       // Give it a bit of slack at the beginning\r
-       for(i = 0; i < 24; i++) {\r
-               ToSendStuffBit(1);\r
-       }\r
-\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(1);\r
-       for(i = 0; i < n; i++) {\r
-               for(j = 0; j < 8; j += 2) {\r
-                       int these = (cmd[i] >> j) & 3;\r
-                       switch(these) {\r
-                               case 0:\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(0);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       break;\r
-                               case 1:\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(0);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       break;\r
-                               case 2:\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(0);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       break;\r
-                               case 3:\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(1);\r
-                                       ToSendStuffBit(0);\r
-                                       break;\r
-                       }\r
-               }\r
-       }\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(1);\r
-       ToSendStuffBit(0);\r
-       ToSendStuffBit(1);\r
-\r
-       // And slack at the end, too.\r
-       for(i = 0; i < 24; i++) {\r
-               ToSendStuffBit(1);\r
-       }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// The CRC used by ISO 15693.\r
-//-----------------------------------------------------------------------------\r
-static WORD Crc(BYTE *v, int n)\r
-{\r
-       DWORD reg;\r
-       int i, j;\r
-\r
-       reg = 0xffff;\r
-       for(i = 0; i < n; i++) {\r
-               reg = reg ^ ((DWORD)v[i]);\r
-               for (j = 0; j < 8; j++) {\r
-                       if (reg & 0x0001) {\r
-                               reg = (reg >> 1) ^ 0x8408;\r
-                       } else {\r
-                               reg = (reg >> 1);\r
-                       }\r
-               }\r
-       }\r
-\r
-       return ~reg;\r
-}\r
-\r
-char *strcat(char *dest, const char *src)\r
-{\r
-       size_t dest_len = strlen(dest);\r
-       size_t i;\r
\r
-       for (i = 0 ; src[i] != '\0' ; i++)\r
-               dest[dest_len + i] = src[i];\r
-       dest[dest_len + i] = '\0';\r
\r
-       return dest;\r
-}\r
-\r
-////////////////////////////////////////// code to do 'itoa'\r
-\r
-/* reverse:  reverse string s in place */\r
-void reverse(char s[])\r
-{\r
-    int c, i, j;\r
-\r
-    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {\r
-        c = s[i];\r
-        s[i] = s[j];\r
-        s[j] = c;\r
-    }\r
-}\r
-\r
-/* itoa:  convert n to characters in s */\r
-void itoa(int n, char s[])\r
-{\r
-    int i, sign;\r
-\r
-    if ((sign = n) < 0)  /* record sign */\r
-        n = -n;          /* make n positive */\r
-    i = 0;\r
-    do {       /* generate digits in reverse order */\r
-        s[i++] = n % 10 + '0';   /* get next digit */\r
-    } while ((n /= 10) > 0);     /* delete it */\r
-    if (sign < 0)\r
-        s[i++] = '-';\r
-    s[i] = '\0';\r
-    reverse(s);\r
-}\r
-\r
-//////////////////////////////////////// END 'itoa' CODE\r
-\r
-//-----------------------------------------------------------------------------\r
-// Encode (into the ToSend buffers) an identify request, which is the first\r
-// thing that you must send to a tag to get a response.\r
-//-----------------------------------------------------------------------------\r
-static void BuildIdentifyRequest(void)\r
-{\r
-       BYTE cmd[5];\r
-\r
-       WORD crc;\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       // AFI is at bit 5 (1<<4) when doing an INVENTORY\r
-       cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);\r
-       // inventory command code\r
-       cmd[1] = 0x01;\r
-       // no mask\r
-       cmd[2] = 0x00;\r
-       //Now the CRC\r
-       crc = Crc(cmd, 3);\r
-       cmd[3] = crc & 0xff;\r
-       cmd[4] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-static void __attribute__((unused)) BuildSysInfoRequest(BYTE *uid)\r
-{\r
-       BYTE cmd[12];\r
-\r
-       WORD crc;\r
-       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
-       // followed by teh block data\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       cmd[0] =  (1 << 5) | (1 << 1); // no SELECT bit\r
-       // System Information command code\r
-       cmd[1] = 0x2B;\r
-       // UID may be optionally specified here\r
-       // 64-bit UID\r
-       cmd[2] = 0x32;\r
-       cmd[3]= 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05;\r
-       cmd[9]= 0xe0; // always e0 (not exactly unique)\r
-       //Now the CRC\r
-       crc = Crc(cmd, 10); // the crc needs to be calculated over 2 bytes\r
-       cmd[10] = crc & 0xff;\r
-       cmd[11] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-static void BuildSelectRequest( BYTE uid[])\r
-{\r
-\r
-//     uid[6]=0x31;  // this is getting ignored - the uid array is not happening...\r
-       BYTE cmd[12];\r
-\r
-       WORD crc;\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       //cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);      // INVENTROY FLAGS\r
-       cmd[0] = (1 << 4) | (1 << 5) | (1 << 1);        // Select and addressed FLAGS\r
-       // SELECT command code\r
-       cmd[1] = 0x25;\r
-       // 64-bit UID\r
-//     cmd[2] = uid[0];//0x32;\r
-//     cmd[3]= uid[1];//0x4b;\r
-//     cmd[4] = uid[2];//0x03;\r
-//     cmd[5] = uid[3];//0x01;\r
-//     cmd[6] = uid[4];//0x00;\r
-//     cmd[7] = uid[5];//0x10;\r
-//     cmd[8] = uid[6];//0x05;\r
-       cmd[2] = 0x32;//\r
-       cmd[3] = 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05; // infineon?\r
-\r
-       cmd[9]= 0xe0; // always e0 (not exactly unique)\r
-\r
-//     DbpIntegers(cmd[8],cmd[7],cmd[6]);\r
-       // Now the CRC\r
-       crc = Crc(cmd, 10); // the crc needs to be calculated over 10 bytes\r
-       cmd[10] = crc & 0xff;\r
-       cmd[11] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-static void __attribute__((unused)) BuildReadBlockRequest(BYTE *uid, BYTE blockNumber )\r
-{\r
-       BYTE cmd[13];\r
-\r
-       WORD crc;\r
-       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
-       // followed by teh block data\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit\r
-       // READ BLOCK command code\r
-       cmd[1] = 0x20;\r
-       // UID may be optionally specified here\r
-       // 64-bit UID\r
-       cmd[2] = 0x32;\r
-       cmd[3]= 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05;\r
-       cmd[9]= 0xe0; // always e0 (not exactly unique)\r
-       // Block number to read\r
-       cmd[10] = blockNumber;//0x00;\r
-       //Now the CRC\r
-       crc = Crc(cmd, 11); // the crc needs to be calculated over 2 bytes\r
-       cmd[11] = crc & 0xff;\r
-       cmd[12] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-static void __attribute__((unused)) BuildReadMultiBlockRequest(BYTE *uid)\r
-{\r
-       BYTE cmd[14];\r
-\r
-       WORD crc;\r
-       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
-       // followed by teh block data\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       cmd[0] =  (1 << 5) | (1 << 1); // no SELECT bit\r
-       // READ Multi BLOCK command code\r
-       cmd[1] = 0x23;\r
-       // UID may be optionally specified here\r
-       // 64-bit UID\r
-       cmd[2] = 0x32;\r
-       cmd[3]= 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05;\r
-       cmd[9]= 0xe0; // always e0 (not exactly unique)\r
-       // First Block number to read\r
-       cmd[10] = 0x00;\r
-       // Number of Blocks to read\r
-       cmd[11] = 0x2f; // read quite a few\r
-       //Now the CRC\r
-       crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes\r
-       cmd[12] = crc & 0xff;\r
-       cmd[13] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-static void __attribute__((unused)) BuildArbitraryRequest(BYTE *uid,BYTE CmdCode)\r
-{\r
-       BYTE cmd[14];\r
-\r
-       WORD crc;\r
-       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
-       // followed by teh block data\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       cmd[0] =   (1 << 5) | (1 << 1); // no SELECT bit\r
-       // READ BLOCK command code\r
-       cmd[1] = CmdCode;\r
-       // UID may be optionally specified here\r
-       // 64-bit UID\r
-       cmd[2] = 0x32;\r
-       cmd[3]= 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05;\r
-       cmd[9]= 0xe0; // always e0 (not exactly unique)\r
-       // Parameter\r
-       cmd[10] = 0x00;\r
-       cmd[11] = 0x0a;\r
-\r
-//     cmd[12] = 0x00;\r
-//     cmd[13] = 0x00; //Now the CRC\r
-       crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes\r
-       cmd[12] = crc & 0xff;\r
-       cmd[13] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-static void __attribute__((unused)) BuildArbitraryCustomRequest(BYTE uid[], BYTE CmdCode)\r
-{\r
-       BYTE cmd[14];\r
-\r
-       WORD crc;\r
-       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block\r
-       // followed by teh block data\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       cmd[0] =   (1 << 5) | (1 << 1); // no SELECT bit\r
-       // READ BLOCK command code\r
-       cmd[1] = CmdCode;\r
-       // UID may be optionally specified here\r
-       // 64-bit UID\r
-       cmd[2] = 0x32;\r
-       cmd[3]= 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05;\r
-       cmd[9]= 0xe0; // always e0 (not exactly unique)\r
-       // Parameter\r
-       cmd[10] = 0x05; // for custom codes this must be manufcturer code\r
-       cmd[11] = 0x00;\r
-\r
-//     cmd[12] = 0x00;\r
-//     cmd[13] = 0x00; //Now the CRC\r
-       crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes\r
-       cmd[12] = crc & 0xff;\r
-       cmd[13] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-/////////////////////////////////////////////////////////////////////////\r
-// Now the VICC>VCD responses when we are simulating a tag\r
-////////////////////////////////////////////////////////////////////\r
-\r
- static void BuildInventoryResponse(void)\r
-{\r
-       BYTE cmd[12];\r
-\r
-       WORD crc;\r
-       // one sub-carrier, inventory, 1 slot, fast rate\r
-       // AFI is at bit 5 (1<<4) when doing an INVENTORY\r
-       cmd[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);\r
-       cmd[1] = 0;\r
-       // 64-bit UID\r
-       cmd[2] = 0x32;\r
-       cmd[3]= 0x4b;\r
-       cmd[4] = 0x03;\r
-       cmd[5] = 0x01;\r
-       cmd[6] = 0x00;\r
-       cmd[7] = 0x10;\r
-       cmd[8] = 0x05;\r
-       cmd[9]= 0xe0;\r
-       //Now the CRC\r
-       crc = Crc(cmd, 10);\r
-       cmd[10] = crc & 0xff;\r
-       cmd[11] = crc >> 8;\r
-\r
-       CodeIso15693AsReader(cmd, sizeof(cmd));\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Transmit the command (to the tag) that was placed in ToSend[].\r
-//-----------------------------------------------------------------------------\r
-static void TransmitTo15693Tag(const BYTE *cmd, int len, int *samples, int *wait)\r
-{\r
-    int c;\r
-\r
-//    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);\r
-       if(*wait < 10) { *wait = 10; }\r
-\r
-//    for(c = 0; c < *wait;) {\r
-//        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-//            AT91C_BASE_SSC->SSC_THR = 0x00;          // For exact timing!\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 = cmd[c];\r
-            c++;\r
-            if(c >= len) {\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
-       *samples = (c + *wait) << 3;\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Transmit the command (to the reader) that was placed in ToSend[].\r
-//-----------------------------------------------------------------------------\r
-static void TransmitTo15693Reader(const BYTE *cmd, int len, int *samples, int *wait)\r
-{\r
-    int c;\r
-\r
-//     FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR);        // No requirement to energise my coils\r
-       if(*wait < 10) { *wait = 10; }\r
-\r
-    c = 0;\r
-    for(;;) {\r
-        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-            AT91C_BASE_SSC->SSC_THR = cmd[c];\r
-            c++;\r
-            if(c >= len) {\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
-       *samples = (c + *wait) << 3;\r
-}\r
-\r
-static int GetIso15693AnswerFromTag(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed)\r
-{\r
-       int c = 0;\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int getNext = 0;\r
-\r
-       SBYTE prev = 0;\r
-\r
-// NOW READ RESPONSE\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-       //spindelay(60);        // greg - experiment to get rid of some of the 0 byte/failed reads\r
-       c = 0;\r
-       getNext = FALSE;\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
-                       // The samples are correlations against I and Q versions of the\r
-                       // tone that the tag AM-modulates, so every other sample is I,\r
-                       // every other is Q. We just want power, so abs(I) + abs(Q) is\r
-                       // close to what we want.\r
-                       if(getNext) {\r
-                               SBYTE r;\r
-\r
-                               if(b < 0) {\r
-                                       r = -b;\r
-                               } else {\r
-                                       r = b;\r
-                               }\r
-                               if(prev < 0) {\r
-                                       r -= prev;\r
-                               } else {\r
-                                       r += prev;\r
-                               }\r
-\r
-                               dest[c++] = (BYTE)r;\r
-\r
-                               if(c >= 2000) {\r
-                                       break;\r
-                               }\r
-                       } else {\r
-                               prev = b;\r
-                       }\r
-\r
-                       getNext = !getNext;\r
-               }\r
-       }\r
-\r
-//////////////////////////////////////////\r
-/////////// DEMODULATE ///////////////////\r
-//////////////////////////////////////////\r
-\r
-       int i, j;\r
-       int max = 0, maxPos=0;\r
-\r
-       int skip = 4;\r
-\r
-//     if(GraphTraceLen < 1000) return;        // THIS CHECKS FOR A BUFFER TO SMALL\r
-\r
-       // First, correlate for SOF\r
-       for(i = 0; i < 100; i++) {\r
-               int corr = 0;\r
-               for(j = 0; j < arraylen(FrameSOF); j += skip) {\r
-                       corr += FrameSOF[j]*dest[i+(j/skip)];\r
-               }\r
-               if(corr > max) {\r
-                       max = corr;\r
-                       maxPos = i;\r
-               }\r
-       }\r
-//     DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));\r
-\r
-       int k = 0; // this will be our return value\r
-\r
-       // greg - If correlation is less than 1 then there's little point in continuing\r
-       if ((max/(arraylen(FrameSOF)/skip)) >= 1)\r
-       {\r
-\r
-       i = maxPos + arraylen(FrameSOF)/skip;\r
-\r
-       BYTE outBuf[20];\r
-       memset(outBuf, 0, sizeof(outBuf));\r
-       BYTE mask = 0x01;\r
-       for(;;) {\r
-               int corr0 = 0, corr1 = 0, corrEOF = 0;\r
-               for(j = 0; j < arraylen(Logic0); j += skip) {\r
-                       corr0 += Logic0[j]*dest[i+(j/skip)];\r
-               }\r
-               for(j = 0; j < arraylen(Logic1); j += skip) {\r
-                       corr1 += Logic1[j]*dest[i+(j/skip)];\r
-               }\r
-               for(j = 0; j < arraylen(FrameEOF); j += skip) {\r
-                       corrEOF += FrameEOF[j]*dest[i+(j/skip)];\r
-               }\r
-               // Even things out by the length of the target waveform.\r
-               corr0 *= 4;\r
-               corr1 *= 4;\r
-\r
-               if(corrEOF > corr1 && corrEOF > corr0) {\r
-//                     DbpString("EOF at %d", i);\r
-                       break;\r
-               } else if(corr1 > corr0) {\r
-                       i += arraylen(Logic1)/skip;\r
-                       outBuf[k] |= mask;\r
-               } else {\r
-                       i += arraylen(Logic0)/skip;\r
-               }\r
-               mask <<= 1;\r
-               if(mask == 0) {\r
-                       k++;\r
-                       mask = 0x01;\r
-               }\r
-               if((i+(int)arraylen(FrameEOF)) >= 2000) {\r
-                       DbpString("ran off end!");\r
-                       break;\r
-               }\r
-       }\r
-       if(mask != 0x01) {\r
-               DbpString("error, uneven octet! (discard extra bits!)");\r
-///            DbpString("   mask=%02x", mask);\r
-       }\r
-//     BYTE str1 [8];\r
-//     itoa(k,str1);\r
-//     strcat(str1," octets read");\r
-\r
-//     DbpString(  str1);    // DbpString("%d octets", k);\r
-\r
-//     for(i = 0; i < k; i+=3) {\r
-//             //DbpString("# %2d: %02x ", i, outBuf[i]);\r
-//             DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);\r
-//     }\r
-\r
-       for(i = 0; i < k; i++) {\r
-               receivedResponse[i] = outBuf[i];\r
-       }\r
-       } // "end if correlation > 0"   (max/(arraylen(FrameSOF)/skip))\r
-       return k; // return the number of bytes demodulated\r
-\r
-///    DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));\r
-\r
-}\r
-\r
-// Now the GetISO15693 message from sniffing command\r
-static int GetIso15693AnswerFromSniff(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed)\r
-{\r
-       int c = 0;\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int getNext = 0;\r
-\r
-       SBYTE prev = 0;\r
-\r
-// NOW READ RESPONSE\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-       //spindelay(60);        // greg - experiment to get rid of some of the 0 byte/failed reads\r
-       c = 0;\r
-       getNext = FALSE;\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
-                       // The samples are correlations against I and Q versions of the\r
-                       // tone that the tag AM-modulates, so every other sample is I,\r
-                       // every other is Q. We just want power, so abs(I) + abs(Q) is\r
-                       // close to what we want.\r
-                       if(getNext) {\r
-                               SBYTE r;\r
-\r
-                               if(b < 0) {\r
-                                       r = -b;\r
-                               } else {\r
-                                       r = b;\r
-                               }\r
-                               if(prev < 0) {\r
-                                       r -= prev;\r
-                               } else {\r
-                                       r += prev;\r
-                               }\r
-\r
-                               dest[c++] = (BYTE)r;\r
-\r
-                               if(c >= 20000) {\r
-                                       break;\r
-                               }\r
-                       } else {\r
-                               prev = b;\r
-                       }\r
-\r
-                       getNext = !getNext;\r
-               }\r
-       }\r
-\r
-//////////////////////////////////////////\r
-/////////// DEMODULATE ///////////////////\r
-//////////////////////////////////////////\r
-\r
-       int i, j;\r
-       int max = 0, maxPos=0;\r
-\r
-       int skip = 4;\r
-\r
-//     if(GraphTraceLen < 1000) return;        // THIS CHECKS FOR A BUFFER TO SMALL\r
-\r
-       // First, correlate for SOF\r
-       for(i = 0; i < 19000; i++) {\r
-               int corr = 0;\r
-               for(j = 0; j < arraylen(FrameSOF); j += skip) {\r
-                       corr += FrameSOF[j]*dest[i+(j/skip)];\r
-               }\r
-               if(corr > max) {\r
-                       max = corr;\r
-                       maxPos = i;\r
-               }\r
-       }\r
-//     DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));\r
-\r
-       int k = 0; // this will be our return value\r
-\r
-       // greg - If correlation is less than 1 then there's little point in continuing\r
-       if ((max/(arraylen(FrameSOF)/skip)) >= 1)       // THIS SHOULD BE 1\r
-       {\r
-\r
-       i = maxPos + arraylen(FrameSOF)/skip;\r
-\r
-       BYTE outBuf[20];\r
-       memset(outBuf, 0, sizeof(outBuf));\r
-       BYTE mask = 0x01;\r
-       for(;;) {\r
-               int corr0 = 0, corr1 = 0, corrEOF = 0;\r
-               for(j = 0; j < arraylen(Logic0); j += skip) {\r
-                       corr0 += Logic0[j]*dest[i+(j/skip)];\r
-               }\r
-               for(j = 0; j < arraylen(Logic1); j += skip) {\r
-                       corr1 += Logic1[j]*dest[i+(j/skip)];\r
-               }\r
-               for(j = 0; j < arraylen(FrameEOF); j += skip) {\r
-                       corrEOF += FrameEOF[j]*dest[i+(j/skip)];\r
-               }\r
-               // Even things out by the length of the target waveform.\r
-               corr0 *= 4;\r
-               corr1 *= 4;\r
-\r
-               if(corrEOF > corr1 && corrEOF > corr0) {\r
-//                     DbpString("EOF at %d", i);\r
-                       break;\r
-               } else if(corr1 > corr0) {\r
-                       i += arraylen(Logic1)/skip;\r
-                       outBuf[k] |= mask;\r
-               } else {\r
-                       i += arraylen(Logic0)/skip;\r
-               }\r
-               mask <<= 1;\r
-               if(mask == 0) {\r
-                       k++;\r
-                       mask = 0x01;\r
-               }\r
-               if((i+(int)arraylen(FrameEOF)) >= 2000) {\r
-                       DbpString("ran off end!");\r
-                       break;\r
-               }\r
-       }\r
-       if(mask != 0x01) {\r
-               DbpString("error, uneven octet! (discard extra bits!)");\r
-///            DbpString("   mask=%02x", mask);\r
-       }\r
-//     BYTE str1 [8];\r
-//     itoa(k,str1);\r
-//     strcat(str1," octets read");\r
-\r
-//     DbpString(  str1);    // DbpString("%d octets", k);\r
-\r
-//     for(i = 0; i < k; i+=3) {\r
-//             //DbpString("# %2d: %02x ", i, outBuf[i]);\r
-//             DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);\r
-//     }\r
-\r
-       for(i = 0; i < k; i++) {\r
-               receivedResponse[i] = outBuf[i];\r
-       }\r
-       } // "end if correlation > 0"   (max/(arraylen(FrameSOF)/skip))\r
-       return k; // return the number of bytes demodulated\r
-\r
-///    DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Start to read an ISO 15693 tag. We send an identify request, then wait\r
-// for the response. The response is not demodulated, just left in the buffer\r
-// so that it can be downloaded to a PC and processed there.\r
-//-----------------------------------------------------------------------------\r
-void AcquireRawAdcSamplesIso15693(void)\r
-{\r
-       int c = 0;\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int getNext = 0;\r
-\r
-       SBYTE prev = 0;\r
-\r
-       BuildIdentifyRequest();\r
-\r
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-\r
-       // Give the tags time to energize\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-       SpinDelay(100);\r
-\r
-       // Now send the command\r
-       FpgaSetupSsc();\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);\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+3) {\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
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-\r
-       c = 0;\r
-       getNext = FALSE;\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
-                       // The samples are correlations against I and Q versions of the\r
-                       // tone that the tag AM-modulates, so every other sample is I,\r
-                       // every other is Q. We just want power, so abs(I) + abs(Q) is\r
-                       // close to what we want.\r
-                       if(getNext) {\r
-                               SBYTE r;\r
-\r
-                               if(b < 0) {\r
-                                       r = -b;\r
-                               } else {\r
-                                       r = b;\r
-                               }\r
-                               if(prev < 0) {\r
-                                       r -= prev;\r
-                               } else {\r
-                                       r += prev;\r
-                               }\r
-\r
-                               dest[c++] = (BYTE)r;\r
-\r
-                               if(c >= 2000) {\r
-                                       break;\r
-                               }\r
-                       } else {\r
-                               prev = b;\r
-                       }\r
-\r
-                       getNext = !getNext;\r
-               }\r
-       }\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector\r
-// all demodulation performed in arm rather than host. - greg\r
-//-----------------------------------------------------------------------------\r
-void ReaderIso15693(DWORD parameter)\r
-{\r
-       LED_A_ON();\r
-       LED_B_ON();\r
-       LED_C_OFF();\r
-       LED_D_OFF();\r
-\r
-//DbpString(parameter);\r
-\r
-       //BYTE *answer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)\r
-       BYTE *answer1 = (((BYTE *)BigBuf) + 3660); //\r
-       BYTE *answer2 = (((BYTE *)BigBuf) + 3760);\r
-       BYTE *answer3 = (((BYTE *)BigBuf) + 3860);\r
-       //BYTE *TagUID= (((BYTE *)BigBuf) + 3960);              // where we hold the uid for hi15reader\r
-//     int answerLen0 = 0;\r
-       int answerLen1 = 0;\r
-       int answerLen2 = 0;\r
-       int answerLen3 = 0;\r
-\r
-       // Blank arrays\r
-       memset(BigBuf + 3660, 0, 300);\r
-\r
-       // Setup SSC\r
-       FpgaSetupSsc();\r
-\r
-       // Start from off (no field generated)\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       SpinDelay(200);\r
-\r
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-       FpgaSetupSsc();\r
-\r
-       // Give the tags time to energize\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);\r
-       SpinDelay(200);\r
-\r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
-       LED_D_OFF();\r
-\r
-       int samples = 0;\r
-       int tsamples = 0;\r
-       int wait = 0;\r
-       int elapsed = 0;\r
-\r
-       // FIRST WE RUN AN INVENTORY TO GET THE TAG UID\r
-       // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME\r
- BYTE TagUID[7];               // where we hold the uid for hi15reader\r
-\r
-//     BuildIdentifyRequest();\r
-//     //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);\r
-//     TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3\r
-//     // Now wait for a response\r
-//     responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;\r
-//     if (responseLen0 >=12) // we should do a better check than this\r
-//     {\r
-//             // really we should check it is a valid mesg\r
-//             // but for now just grab what we think is the uid\r
-//             TagUID[0] = receivedAnswer0[2];\r
-//             TagUID[1] = receivedAnswer0[3];\r
-//             TagUID[2] = receivedAnswer0[4];\r
-//             TagUID[3] = receivedAnswer0[5];\r
-//             TagUID[4] = receivedAnswer0[6];\r
-//             TagUID[5] = receivedAnswer0[7];\r
-//             TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code\r
-//     DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);\r
-//}\r
-\r
-       // Now send the IDENTIFY command\r
-       BuildIdentifyRequest();\r
-       //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);\r
-       TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3\r
-       // Now wait for a response\r
-       answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;\r
-\r
-       if (answerLen1 >=12) // we should do a better check than this\r
-       {\r
-\r
-               TagUID[0] = answer1[2];\r
-               TagUID[1] = answer1[3];\r
-               TagUID[2] = answer1[4];\r
-               TagUID[3] = answer1[5];\r
-               TagUID[4] = answer1[6];\r
-               TagUID[5] = answer1[7];\r
-               TagUID[6] = answer1[8]; // IC Manufacturer code\r
-\r
-               // Now send the SELECT command\r
-               BuildSelectRequest(TagUID);\r
-               TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3\r
-               // Now wait for a response\r
-               answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);\r
-\r
-               // Now send the MULTI READ command\r
-//             BuildArbitraryRequest(*TagUID,parameter);\r
-               BuildArbitraryCustomRequest(TagUID,parameter);\r
-//             BuildReadBlockRequest(*TagUID,parameter);\r
-//             BuildSysInfoRequest(*TagUID);\r
-               //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);\r
-               TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3\r
-               // Now wait for a response\r
-               answerLen3 = GetIso15693AnswerFromTag(answer3, 100, &samples, &elapsed) ;\r
-\r
-       }\r
-\r
-       Dbprintf("%d octets read from IDENTIFY request: %x %x %x %x %x %x %x %x %x", answerLen1,\r
-               answer1[0], answer1[1], answer1[2],\r
-               answer1[3], answer1[4], answer1[5],\r
-               answer1[6], answer1[7], answer1[8]);\r
-\r
-       Dbprintf("%d octets read from SELECT request: %x %x %x %x %x %x %x %x %x", answerLen2,\r
-               answer2[0], answer2[1], answer2[2],\r
-               answer2[3], answer2[4], answer2[5],\r
-               answer2[6], answer2[7], answer2[8]);\r
-\r
-       Dbprintf("%d octets read from XXX request: %x %x %x %x %x %x %x %x %x", answerLen3,\r
-               answer3[0], answer3[1], answer3[2],\r
-               answer3[3], answer3[4], answer3[5],\r
-               answer3[6], answer3[7], answer3[8]);\r
-\r
-\r
-//     str2[0]=0;\r
-//     for(i = 0; i < responseLen3; i++) {\r
-//             itoa(str1,receivedAnswer3[i]);\r
-//             strcat(str2,str1);\r
-//     }\r
-//     DbpString(str2);\r
-\r
-       LED_A_OFF();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
-       LED_D_OFF();\r
-}\r
-\r
-//-----------------------------------------------------------------------------\r
-// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands\r
-// all demodulation performed in arm rather than host. - greg\r
-//-----------------------------------------------------------------------------\r
-void SimTagIso15693(DWORD parameter)\r
-{\r
-       LED_A_ON();\r
-       LED_B_ON();\r
-       LED_C_OFF();\r
-       LED_D_OFF();\r
-\r
-       BYTE *answer1 = (((BYTE *)BigBuf) + 3660); //\r
-       int answerLen1 = 0;\r
-\r
-       // Blank arrays\r
-       memset(answer1, 0, 100);\r
-\r
-       // Setup SSC\r
-       FpgaSetupSsc();\r
-\r
-       // Start from off (no field generated)\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       SpinDelay(200);\r
-\r
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
-       FpgaSetupSsc();\r
-\r
-       // Give the tags time to energize\r
-//     FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);  // NO GOOD FOR SIM TAG!!!!\r
-       SpinDelay(200);\r
-\r
-       LED_A_OFF();\r
-       LED_B_OFF();\r
-       LED_C_ON();\r
-       LED_D_OFF();\r
-\r
-       int samples = 0;\r
-       int tsamples = 0;\r
-       int wait = 0;\r
-       int elapsed = 0;\r
-\r
-       answerLen1 = GetIso15693AnswerFromSniff(answer1, 100, &samples, &elapsed) ;\r
-\r
-       if (answerLen1 >=1) // we should do a better check than this\r
-       {\r
-               // Build a suitable reponse to the reader INVENTORY cocmmand\r
-               BuildInventoryResponse();\r
-               TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);\r
-       }\r
-\r
-       Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,\r
-               answer1[0], answer1[1], answer1[2],\r
-               answer1[3], answer1[4], answer1[5],\r
-               answer1[6], answer1[7], answer1[8]);\r
-\r
-       LED_A_OFF();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
-       LED_D_OFF();\r
-}\r
+//-----------------------------------------------------------------------------
+// Routines to support ISO 15693. This includes both the reader software and
+// the `fake tag' modes, but at the moment I've implemented only the reader
+// stuff, and that barely.
+// Jonathan Westhues, split Nov 2006
+
+// Modified by Greg Jones, Jan 2009 to perform modulation onboard in arm rather than on PC
+// Also added additional reader commands (SELECT, READ etc.)
+
+//-----------------------------------------------------------------------------
+#include <proxmark3.h>
+#include "apps.h"
+
+// FROM winsrc\prox.h //////////////////////////////////
+#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
+
+//-----------------------------------------------------------------------------
+// Map a sequence of octets (~layer 2 command) into the set of bits to feed
+// to the FPGA, to transmit that command to the tag.
+//-----------------------------------------------------------------------------
+
+       // The sampling rate is 106.353 ksps/s, for T = 18.8 us
+
+       // SOF defined as
+       // 1) Unmodulated time of 56.64us
+       // 2) 24 pulses of 423.75khz
+       // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
+
+       static const int FrameSOF[] = {
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+               -1, -1, -1, -1,
+               -1, -1, -1, -1,
+                1,  1,  1,  1,
+                1,  1,  1,  1
+       };
+       static const int Logic0[] = {
+                1,  1,  1,  1,
+                1,  1,  1,  1,
+               -1, -1, -1, -1,
+               -1, -1, -1, -1
+       };
+       static const int Logic1[] = {
+               -1, -1, -1, -1,
+               -1, -1, -1, -1,
+                1,  1,  1,  1,
+                1,  1,  1,  1
+       };
+
+       // EOF defined as
+       // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
+       // 2) 24 pulses of 423.75khz
+       // 3) Unmodulated time of 56.64us
+
+       static const int FrameEOF[] = {
+                1,  1,  1,  1,
+                1,  1,  1,  1,
+               -1, -1, -1, -1,
+               -1, -1, -1, -1,
+                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+                1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+               -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+       };
+
+static void CodeIso15693AsReader(BYTE *cmd, int n)
+{
+       int i, j;
+
+       ToSendReset();
+
+       // Give it a bit of slack at the beginning
+       for(i = 0; i < 24; i++) {
+               ToSendStuffBit(1);
+       }
+
+       ToSendStuffBit(0);
+       ToSendStuffBit(1);
+       ToSendStuffBit(1);
+       ToSendStuffBit(1);
+       ToSendStuffBit(1);
+       ToSendStuffBit(0);
+       ToSendStuffBit(1);
+       ToSendStuffBit(1);
+       for(i = 0; i < n; i++) {
+               for(j = 0; j < 8; j += 2) {
+                       int these = (cmd[i] >> j) & 3;
+                       switch(these) {
+                               case 0:
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(0);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       break;
+                               case 1:
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(0);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       break;
+                               case 2:
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(0);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       break;
+                               case 3:
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(1);
+                                       ToSendStuffBit(0);
+                                       break;
+                       }
+               }
+       }
+       ToSendStuffBit(1);
+       ToSendStuffBit(1);
+       ToSendStuffBit(0);
+       ToSendStuffBit(1);
+
+       // And slack at the end, too.
+       for(i = 0; i < 24; i++) {
+               ToSendStuffBit(1);
+       }
+}
+
+//-----------------------------------------------------------------------------
+// The CRC used by ISO 15693.
+//-----------------------------------------------------------------------------
+static WORD Crc(BYTE *v, int n)
+{
+       DWORD reg;
+       int i, j;
+
+       reg = 0xffff;
+       for(i = 0; i < n; i++) {
+               reg = reg ^ ((DWORD)v[i]);
+               for (j = 0; j < 8; j++) {
+                       if (reg & 0x0001) {
+                               reg = (reg >> 1) ^ 0x8408;
+                       } else {
+                               reg = (reg >> 1);
+                       }
+               }
+       }
+
+       return ~reg;
+}
+
+char *strcat(char *dest, const char *src)
+{
+       size_t dest_len = strlen(dest);
+       size_t i;
+       for (i = 0 ; src[i] != '\0' ; i++)
+               dest[dest_len + i] = src[i];
+       dest[dest_len + i] = '\0';
+       return dest;
+}
+
+////////////////////////////////////////// code to do 'itoa'
+
+/* reverse:  reverse string s in place */
+void reverse(char s[])
+{
+    int c, i, j;
+
+    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
+        c = s[i];
+        s[i] = s[j];
+        s[j] = c;
+    }
+}
+
+/* itoa:  convert n to characters in s */
+void itoa(int n, char s[])
+{
+    int i, sign;
+
+    if ((sign = n) < 0)  /* record sign */
+        n = -n;          /* make n positive */
+    i = 0;
+    do {       /* generate digits in reverse order */
+        s[i++] = n % 10 + '0';   /* get next digit */
+    } while ((n /= 10) > 0);     /* delete it */
+    if (sign < 0)
+        s[i++] = '-';
+    s[i] = '\0';
+    reverse(s);
+}
+
+//////////////////////////////////////// END 'itoa' CODE
+
+//-----------------------------------------------------------------------------
+// Encode (into the ToSend buffers) an identify request, which is the first
+// thing that you must send to a tag to get a response.
+//-----------------------------------------------------------------------------
+static void BuildIdentifyRequest(void)
+{
+       BYTE cmd[5];
+
+       WORD crc;
+       // one sub-carrier, inventory, 1 slot, fast rate
+       // AFI is at bit 5 (1<<4) when doing an INVENTORY
+       cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);
+       // inventory command code
+       cmd[1] = 0x01;
+       // no mask
+       cmd[2] = 0x00;
+       //Now the CRC
+       crc = Crc(cmd, 3);
+       cmd[3] = crc & 0xff;
+       cmd[4] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+static void __attribute__((unused)) BuildSysInfoRequest(BYTE *uid)
+{
+       BYTE cmd[12];
+
+       WORD crc;
+       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
+       // followed by teh block data
+       // one sub-carrier, inventory, 1 slot, fast rate
+       cmd[0] =  (1 << 5) | (1 << 1); // no SELECT bit
+       // System Information command code
+       cmd[1] = 0x2B;
+       // UID may be optionally specified here
+       // 64-bit UID
+       cmd[2] = 0x32;
+       cmd[3]= 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05;
+       cmd[9]= 0xe0; // always e0 (not exactly unique)
+       //Now the CRC
+       crc = Crc(cmd, 10); // the crc needs to be calculated over 2 bytes
+       cmd[10] = crc & 0xff;
+       cmd[11] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+static void BuildSelectRequest( BYTE uid[])
+{
+
+//     uid[6]=0x31;  // this is getting ignored - the uid array is not happening...
+       BYTE cmd[12];
+
+       WORD crc;
+       // one sub-carrier, inventory, 1 slot, fast rate
+       //cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);      // INVENTROY FLAGS
+       cmd[0] = (1 << 4) | (1 << 5) | (1 << 1);        // Select and addressed FLAGS
+       // SELECT command code
+       cmd[1] = 0x25;
+       // 64-bit UID
+//     cmd[2] = uid[0];//0x32;
+//     cmd[3]= uid[1];//0x4b;
+//     cmd[4] = uid[2];//0x03;
+//     cmd[5] = uid[3];//0x01;
+//     cmd[6] = uid[4];//0x00;
+//     cmd[7] = uid[5];//0x10;
+//     cmd[8] = uid[6];//0x05;
+       cmd[2] = 0x32;//
+       cmd[3] = 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05; // infineon?
+
+       cmd[9]= 0xe0; // always e0 (not exactly unique)
+
+//     DbpIntegers(cmd[8],cmd[7],cmd[6]);
+       // Now the CRC
+       crc = Crc(cmd, 10); // the crc needs to be calculated over 10 bytes
+       cmd[10] = crc & 0xff;
+       cmd[11] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+static void __attribute__((unused)) BuildReadBlockRequest(BYTE *uid, BYTE blockNumber )
+{
+       BYTE cmd[13];
+
+       WORD crc;
+       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
+       // followed by teh block data
+       // one sub-carrier, inventory, 1 slot, fast rate
+       cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit
+       // READ BLOCK command code
+       cmd[1] = 0x20;
+       // UID may be optionally specified here
+       // 64-bit UID
+       cmd[2] = 0x32;
+       cmd[3]= 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05;
+       cmd[9]= 0xe0; // always e0 (not exactly unique)
+       // Block number to read
+       cmd[10] = blockNumber;//0x00;
+       //Now the CRC
+       crc = Crc(cmd, 11); // the crc needs to be calculated over 2 bytes
+       cmd[11] = crc & 0xff;
+       cmd[12] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+static void __attribute__((unused)) BuildReadMultiBlockRequest(BYTE *uid)
+{
+       BYTE cmd[14];
+
+       WORD crc;
+       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
+       // followed by teh block data
+       // one sub-carrier, inventory, 1 slot, fast rate
+       cmd[0] =  (1 << 5) | (1 << 1); // no SELECT bit
+       // READ Multi BLOCK command code
+       cmd[1] = 0x23;
+       // UID may be optionally specified here
+       // 64-bit UID
+       cmd[2] = 0x32;
+       cmd[3]= 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05;
+       cmd[9]= 0xe0; // always e0 (not exactly unique)
+       // First Block number to read
+       cmd[10] = 0x00;
+       // Number of Blocks to read
+       cmd[11] = 0x2f; // read quite a few
+       //Now the CRC
+       crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
+       cmd[12] = crc & 0xff;
+       cmd[13] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+static void __attribute__((unused)) BuildArbitraryRequest(BYTE *uid,BYTE CmdCode)
+{
+       BYTE cmd[14];
+
+       WORD crc;
+       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
+       // followed by teh block data
+       // one sub-carrier, inventory, 1 slot, fast rate
+       cmd[0] =   (1 << 5) | (1 << 1); // no SELECT bit
+       // READ BLOCK command code
+       cmd[1] = CmdCode;
+       // UID may be optionally specified here
+       // 64-bit UID
+       cmd[2] = 0x32;
+       cmd[3]= 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05;
+       cmd[9]= 0xe0; // always e0 (not exactly unique)
+       // Parameter
+       cmd[10] = 0x00;
+       cmd[11] = 0x0a;
+
+//     cmd[12] = 0x00;
+//     cmd[13] = 0x00; //Now the CRC
+       crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
+       cmd[12] = crc & 0xff;
+       cmd[13] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+static void __attribute__((unused)) BuildArbitraryCustomRequest(BYTE uid[], BYTE CmdCode)
+{
+       BYTE cmd[14];
+
+       WORD crc;
+       // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
+       // followed by teh block data
+       // one sub-carrier, inventory, 1 slot, fast rate
+       cmd[0] =   (1 << 5) | (1 << 1); // no SELECT bit
+       // READ BLOCK command code
+       cmd[1] = CmdCode;
+       // UID may be optionally specified here
+       // 64-bit UID
+       cmd[2] = 0x32;
+       cmd[3]= 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05;
+       cmd[9]= 0xe0; // always e0 (not exactly unique)
+       // Parameter
+       cmd[10] = 0x05; // for custom codes this must be manufcturer code
+       cmd[11] = 0x00;
+
+//     cmd[12] = 0x00;
+//     cmd[13] = 0x00; //Now the CRC
+       crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
+       cmd[12] = crc & 0xff;
+       cmd[13] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+/////////////////////////////////////////////////////////////////////////
+// Now the VICC>VCD responses when we are simulating a tag
+////////////////////////////////////////////////////////////////////
+
+ static void BuildInventoryResponse(void)
+{
+       BYTE cmd[12];
+
+       WORD crc;
+       // one sub-carrier, inventory, 1 slot, fast rate
+       // AFI is at bit 5 (1<<4) when doing an INVENTORY
+       cmd[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);
+       cmd[1] = 0;
+       // 64-bit UID
+       cmd[2] = 0x32;
+       cmd[3]= 0x4b;
+       cmd[4] = 0x03;
+       cmd[5] = 0x01;
+       cmd[6] = 0x00;
+       cmd[7] = 0x10;
+       cmd[8] = 0x05;
+       cmd[9]= 0xe0;
+       //Now the CRC
+       crc = Crc(cmd, 10);
+       cmd[10] = crc & 0xff;
+       cmd[11] = crc >> 8;
+
+       CodeIso15693AsReader(cmd, sizeof(cmd));
+}
+
+//-----------------------------------------------------------------------------
+// Transmit the command (to the tag) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitTo15693Tag(const BYTE *cmd, int len, int *samples, int *wait)
+{
+    int c;
+
+//    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
+       if(*wait < 10) { *wait = 10; }
+
+//    for(c = 0; c < *wait;) {
+//        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+//            AT91C_BASE_SSC->SSC_THR = 0x00;          // For exact timing!
+//            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 = cmd[c];
+            c++;
+            if(c >= len) {
+                break;
+            }
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
+            (void)r;
+        }
+        WDT_HIT();
+    }
+       *samples = (c + *wait) << 3;
+}
+
+//-----------------------------------------------------------------------------
+// Transmit the command (to the reader) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitTo15693Reader(const BYTE *cmd, int len, int *samples, int *wait)
+{
+    int c;
+
+//     FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR);        // No requirement to energise my coils
+       if(*wait < 10) { *wait = 10; }
+
+    c = 0;
+    for(;;) {
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+            AT91C_BASE_SSC->SSC_THR = cmd[c];
+            c++;
+            if(c >= len) {
+                break;
+            }
+        }
+        if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+            volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
+            (void)r;
+        }
+        WDT_HIT();
+    }
+       *samples = (c + *wait) << 3;
+}
+
+static int GetIso15693AnswerFromTag(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed)
+{
+       int c = 0;
+       BYTE *dest = (BYTE *)BigBuf;
+       int getNext = 0;
+
+       SBYTE prev = 0;
+
+// NOW READ RESPONSE
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+       //spindelay(60);        // greg - experiment to get rid of some of the 0 byte/failed reads
+       c = 0;
+       getNext = FALSE;
+       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;
+
+                       // The samples are correlations against I and Q versions of the
+                       // tone that the tag AM-modulates, so every other sample is I,
+                       // every other is Q. We just want power, so abs(I) + abs(Q) is
+                       // close to what we want.
+                       if(getNext) {
+                               SBYTE r;
+
+                               if(b < 0) {
+                                       r = -b;
+                               } else {
+                                       r = b;
+                               }
+                               if(prev < 0) {
+                                       r -= prev;
+                               } else {
+                                       r += prev;
+                               }
+
+                               dest[c++] = (BYTE)r;
+
+                               if(c >= 2000) {
+                                       break;
+                               }
+                       } else {
+                               prev = b;
+                       }
+
+                       getNext = !getNext;
+               }
+       }
+
+//////////////////////////////////////////
+/////////// DEMODULATE ///////////////////
+//////////////////////////////////////////
+
+       int i, j;
+       int max = 0, maxPos=0;
+
+       int skip = 4;
+
+//     if(GraphTraceLen < 1000) return;        // THIS CHECKS FOR A BUFFER TO SMALL
+
+       // First, correlate for SOF
+       for(i = 0; i < 100; i++) {
+               int corr = 0;
+               for(j = 0; j < arraylen(FrameSOF); j += skip) {
+                       corr += FrameSOF[j]*dest[i+(j/skip)];
+               }
+               if(corr > max) {
+                       max = corr;
+                       maxPos = i;
+               }
+       }
+//     DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
+
+       int k = 0; // this will be our return value
+
+       // greg - If correlation is less than 1 then there's little point in continuing
+       if ((max/(arraylen(FrameSOF)/skip)) >= 1)
+       {
+
+       i = maxPos + arraylen(FrameSOF)/skip;
+
+       BYTE outBuf[20];
+       memset(outBuf, 0, sizeof(outBuf));
+       BYTE mask = 0x01;
+       for(;;) {
+               int corr0 = 0, corr1 = 0, corrEOF = 0;
+               for(j = 0; j < arraylen(Logic0); j += skip) {
+                       corr0 += Logic0[j]*dest[i+(j/skip)];
+               }
+               for(j = 0; j < arraylen(Logic1); j += skip) {
+                       corr1 += Logic1[j]*dest[i+(j/skip)];
+               }
+               for(j = 0; j < arraylen(FrameEOF); j += skip) {
+                       corrEOF += FrameEOF[j]*dest[i+(j/skip)];
+               }
+               // Even things out by the length of the target waveform.
+               corr0 *= 4;
+               corr1 *= 4;
+
+               if(corrEOF > corr1 && corrEOF > corr0) {
+//                     DbpString("EOF at %d", i);
+                       break;
+               } else if(corr1 > corr0) {
+                       i += arraylen(Logic1)/skip;
+                       outBuf[k] |= mask;
+               } else {
+                       i += arraylen(Logic0)/skip;
+               }
+               mask <<= 1;
+               if(mask == 0) {
+                       k++;
+                       mask = 0x01;
+               }
+               if((i+(int)arraylen(FrameEOF)) >= 2000) {
+                       DbpString("ran off end!");
+                       break;
+               }
+       }
+       if(mask != 0x01) {
+               DbpString("error, uneven octet! (discard extra bits!)");
+///            DbpString("   mask=%02x", mask);
+       }
+//     BYTE str1 [8];
+//     itoa(k,str1);
+//     strcat(str1," octets read");
+
+//     DbpString(  str1);    // DbpString("%d octets", k);
+
+//     for(i = 0; i < k; i+=3) {
+//             //DbpString("# %2d: %02x ", i, outBuf[i]);
+//             DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
+//     }
+
+       for(i = 0; i < k; i++) {
+               receivedResponse[i] = outBuf[i];
+       }
+       } // "end if correlation > 0"   (max/(arraylen(FrameSOF)/skip))
+       return k; // return the number of bytes demodulated
+
+///    DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
+
+}
+
+// Now the GetISO15693 message from sniffing command
+static int GetIso15693AnswerFromSniff(BYTE *receivedResponse, int maxLen, int *samples, int *elapsed)
+{
+       int c = 0;
+       BYTE *dest = (BYTE *)BigBuf;
+       int getNext = 0;
+
+       SBYTE prev = 0;
+
+// NOW READ RESPONSE
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+       //spindelay(60);        // greg - experiment to get rid of some of the 0 byte/failed reads
+       c = 0;
+       getNext = FALSE;
+       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;
+
+                       // The samples are correlations against I and Q versions of the
+                       // tone that the tag AM-modulates, so every other sample is I,
+                       // every other is Q. We just want power, so abs(I) + abs(Q) is
+                       // close to what we want.
+                       if(getNext) {
+                               SBYTE r;
+
+                               if(b < 0) {
+                                       r = -b;
+                               } else {
+                                       r = b;
+                               }
+                               if(prev < 0) {
+                                       r -= prev;
+                               } else {
+                                       r += prev;
+                               }
+
+                               dest[c++] = (BYTE)r;
+
+                               if(c >= 20000) {
+                                       break;
+                               }
+                       } else {
+                               prev = b;
+                       }
+
+                       getNext = !getNext;
+               }
+       }
+
+//////////////////////////////////////////
+/////////// DEMODULATE ///////////////////
+//////////////////////////////////////////
+
+       int i, j;
+       int max = 0, maxPos=0;
+
+       int skip = 4;
+
+//     if(GraphTraceLen < 1000) return;        // THIS CHECKS FOR A BUFFER TO SMALL
+
+       // First, correlate for SOF
+       for(i = 0; i < 19000; i++) {
+               int corr = 0;
+               for(j = 0; j < arraylen(FrameSOF); j += skip) {
+                       corr += FrameSOF[j]*dest[i+(j/skip)];
+               }
+               if(corr > max) {
+                       max = corr;
+                       maxPos = i;
+               }
+       }
+//     DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
+
+       int k = 0; // this will be our return value
+
+       // greg - If correlation is less than 1 then there's little point in continuing
+       if ((max/(arraylen(FrameSOF)/skip)) >= 1)       // THIS SHOULD BE 1
+       {
+
+       i = maxPos + arraylen(FrameSOF)/skip;
+
+       BYTE outBuf[20];
+       memset(outBuf, 0, sizeof(outBuf));
+       BYTE mask = 0x01;
+       for(;;) {
+               int corr0 = 0, corr1 = 0, corrEOF = 0;
+               for(j = 0; j < arraylen(Logic0); j += skip) {
+                       corr0 += Logic0[j]*dest[i+(j/skip)];
+               }
+               for(j = 0; j < arraylen(Logic1); j += skip) {
+                       corr1 += Logic1[j]*dest[i+(j/skip)];
+               }
+               for(j = 0; j < arraylen(FrameEOF); j += skip) {
+                       corrEOF += FrameEOF[j]*dest[i+(j/skip)];
+               }
+               // Even things out by the length of the target waveform.
+               corr0 *= 4;
+               corr1 *= 4;
+
+               if(corrEOF > corr1 && corrEOF > corr0) {
+//                     DbpString("EOF at %d", i);
+                       break;
+               } else if(corr1 > corr0) {
+                       i += arraylen(Logic1)/skip;
+                       outBuf[k] |= mask;
+               } else {
+                       i += arraylen(Logic0)/skip;
+               }
+               mask <<= 1;
+               if(mask == 0) {
+                       k++;
+                       mask = 0x01;
+               }
+               if((i+(int)arraylen(FrameEOF)) >= 2000) {
+                       DbpString("ran off end!");
+                       break;
+               }
+       }
+       if(mask != 0x01) {
+               DbpString("error, uneven octet! (discard extra bits!)");
+///            DbpString("   mask=%02x", mask);
+       }
+//     BYTE str1 [8];
+//     itoa(k,str1);
+//     strcat(str1," octets read");
+
+//     DbpString(  str1);    // DbpString("%d octets", k);
+
+//     for(i = 0; i < k; i+=3) {
+//             //DbpString("# %2d: %02x ", i, outBuf[i]);
+//             DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
+//     }
+
+       for(i = 0; i < k; i++) {
+               receivedResponse[i] = outBuf[i];
+       }
+       } // "end if correlation > 0"   (max/(arraylen(FrameSOF)/skip))
+       return k; // return the number of bytes demodulated
+
+///    DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
+}
+
+//-----------------------------------------------------------------------------
+// Start to read an ISO 15693 tag. We send an identify request, then wait
+// for the response. The response is not demodulated, just left in the buffer
+// so that it can be downloaded to a PC and processed there.
+//-----------------------------------------------------------------------------
+void AcquireRawAdcSamplesIso15693(void)
+{
+       int c = 0;
+       BYTE *dest = (BYTE *)BigBuf;
+       int getNext = 0;
+
+       SBYTE prev = 0;
+
+       BuildIdentifyRequest();
+
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+       // Give the tags time to energize
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+       SpinDelay(100);
+
+       // Now send the command
+       FpgaSetupSsc();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
+
+       c = 0;
+       for(;;) {
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                       AT91C_BASE_SSC->SSC_THR = ToSend[c];
+                       c++;
+                       if(c == ToSendMax+3) {
+                               break;
+                       }
+               }
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       volatile DWORD r = AT91C_BASE_SSC->SSC_RHR;
+                       (void)r;
+               }
+               WDT_HIT();
+       }
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+
+       c = 0;
+       getNext = FALSE;
+       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;
+
+                       // The samples are correlations against I and Q versions of the
+                       // tone that the tag AM-modulates, so every other sample is I,
+                       // every other is Q. We just want power, so abs(I) + abs(Q) is
+                       // close to what we want.
+                       if(getNext) {
+                               SBYTE r;
+
+                               if(b < 0) {
+                                       r = -b;
+                               } else {
+                                       r = b;
+                               }
+                               if(prev < 0) {
+                                       r -= prev;
+                               } else {
+                                       r += prev;
+                               }
+
+                               dest[c++] = (BYTE)r;
+
+                               if(c >= 2000) {
+                                       break;
+                               }
+                       } else {
+                               prev = b;
+                       }
+
+                       getNext = !getNext;
+               }
+       }
+}
+
+//-----------------------------------------------------------------------------
+// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
+// all demodulation performed in arm rather than host. - greg
+//-----------------------------------------------------------------------------
+void ReaderIso15693(DWORD parameter)
+{
+       LED_A_ON();
+       LED_B_ON();
+       LED_C_OFF();
+       LED_D_OFF();
+
+//DbpString(parameter);
+
+       //BYTE *answer0 = (((BYTE *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
+       BYTE *answer1 = (((BYTE *)BigBuf) + 3660); //
+       BYTE *answer2 = (((BYTE *)BigBuf) + 3760);
+       BYTE *answer3 = (((BYTE *)BigBuf) + 3860);
+       //BYTE *TagUID= (((BYTE *)BigBuf) + 3960);              // where we hold the uid for hi15reader
+//     int answerLen0 = 0;
+       int answerLen1 = 0;
+       int answerLen2 = 0;
+       int answerLen3 = 0;
+
+       // Blank arrays
+       memset(BigBuf + 3660, 0, 300);
+
+       // Setup SSC
+       FpgaSetupSsc();
+
+       // Start from off (no field generated)
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       SpinDelay(200);
+
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+       FpgaSetupSsc();
+
+       // Give the tags time to energize
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+       SpinDelay(200);
+
+       LED_A_ON();
+       LED_B_OFF();
+       LED_C_OFF();
+       LED_D_OFF();
+
+       int samples = 0;
+       int tsamples = 0;
+       int wait = 0;
+       int elapsed = 0;
+
+       // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
+       // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
+ BYTE TagUID[7];               // where we hold the uid for hi15reader
+
+//     BuildIdentifyRequest();
+//     //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
+//     TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3
+//     // Now wait for a response
+//     responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
+//     if (responseLen0 >=12) // we should do a better check than this
+//     {
+//             // really we should check it is a valid mesg
+//             // but for now just grab what we think is the uid
+//             TagUID[0] = receivedAnswer0[2];
+//             TagUID[1] = receivedAnswer0[3];
+//             TagUID[2] = receivedAnswer0[4];
+//             TagUID[3] = receivedAnswer0[5];
+//             TagUID[4] = receivedAnswer0[6];
+//             TagUID[5] = receivedAnswer0[7];
+//             TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
+//     DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
+//}
+
+       // Now send the IDENTIFY command
+       BuildIdentifyRequest();
+       //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
+       TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3
+       // Now wait for a response
+       answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;
+
+       if (answerLen1 >=12) // we should do a better check than this
+       {
+
+               TagUID[0] = answer1[2];
+               TagUID[1] = answer1[3];
+               TagUID[2] = answer1[4];
+               TagUID[3] = answer1[5];
+               TagUID[4] = answer1[6];
+               TagUID[5] = answer1[7];
+               TagUID[6] = answer1[8]; // IC Manufacturer code
+
+               // Now send the SELECT command
+               BuildSelectRequest(TagUID);
+               TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3
+               // Now wait for a response
+               answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
+
+               // Now send the MULTI READ command
+//             BuildArbitraryRequest(*TagUID,parameter);
+               BuildArbitraryCustomRequest(TagUID,parameter);
+//             BuildReadBlockRequest(*TagUID,parameter);
+//             BuildSysInfoRequest(*TagUID);
+               //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
+               TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);  // No longer ToSendMax+3
+               // Now wait for a response
+               answerLen3 = GetIso15693AnswerFromTag(answer3, 100, &samples, &elapsed) ;
+
+       }
+
+       Dbprintf("%d octets read from IDENTIFY request: %x %x %x %x %x %x %x %x %x", answerLen1,
+               answer1[0], answer1[1], answer1[2],
+               answer1[3], answer1[4], answer1[5],
+               answer1[6], answer1[7], answer1[8]);
+
+       Dbprintf("%d octets read from SELECT request: %x %x %x %x %x %x %x %x %x", answerLen2,
+               answer2[0], answer2[1], answer2[2],
+               answer2[3], answer2[4], answer2[5],
+               answer2[6], answer2[7], answer2[8]);
+
+       Dbprintf("%d octets read from XXX request: %x %x %x %x %x %x %x %x %x", answerLen3,
+               answer3[0], answer3[1], answer3[2],
+               answer3[3], answer3[4], answer3[5],
+               answer3[6], answer3[7], answer3[8]);
+
+
+//     str2[0]=0;
+//     for(i = 0; i < responseLen3; i++) {
+//             itoa(str1,receivedAnswer3[i]);
+//             strcat(str2,str1);
+//     }
+//     DbpString(str2);
+
+       LED_A_OFF();
+       LED_B_OFF();
+       LED_C_OFF();
+       LED_D_OFF();
+}
+
+//-----------------------------------------------------------------------------
+// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
+// all demodulation performed in arm rather than host. - greg
+//-----------------------------------------------------------------------------
+void SimTagIso15693(DWORD parameter)
+{
+       LED_A_ON();
+       LED_B_ON();
+       LED_C_OFF();
+       LED_D_OFF();
+
+       BYTE *answer1 = (((BYTE *)BigBuf) + 3660); //
+       int answerLen1 = 0;
+
+       // Blank arrays
+       memset(answer1, 0, 100);
+
+       // Setup SSC
+       FpgaSetupSsc();
+
+       // Start from off (no field generated)
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       SpinDelay(200);
+
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+       FpgaSetupSsc();
+
+       // Give the tags time to energize
+//     FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);  // NO GOOD FOR SIM TAG!!!!
+       SpinDelay(200);
+
+       LED_A_OFF();
+       LED_B_OFF();
+       LED_C_ON();
+       LED_D_OFF();
+
+       int samples = 0;
+       int tsamples = 0;
+       int wait = 0;
+       int elapsed = 0;
+
+       answerLen1 = GetIso15693AnswerFromSniff(answer1, 100, &samples, &elapsed) ;
+
+       if (answerLen1 >=1) // we should do a better check than this
+       {
+               // Build a suitable reponse to the reader INVENTORY cocmmand
+               BuildInventoryResponse();
+               TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
+       }
+
+       Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,
+               answer1[0], answer1[1], answer1[2],
+               answer1[3], answer1[4], answer1[5],
+               answer1[6], answer1[7], answer1[8]);
+
+       LED_A_OFF();
+       LED_B_OFF();
+       LED_C_OFF();
+       LED_D_OFF();
+}
index cc5ce4e02e4b1ea0d9dece8561fa4200de60b706..61eaa5d79c91ad46704bd4e98447d18020df4cc1 100644 (file)
@@ -1,41 +1,41 @@
-INCLUDE ../common/ldscript.common\r
-\r
-ENTRY(Vector)\r
-SECTIONS\r
-{\r
-       .fpgaimage : {\r
-               *(fpga_bit.data)\r
-       } >fpgaimage\r
-       .start : { *(.startos) } >osimage\r
-       .text : { \r
-               *(.text)\r
-               *(.text.*)\r
-               *(.eh_frame)\r
-               *(.glue_7)\r
-               *(.glue_7t)\r
-               *(.rodata) \r
-               *(.rodata*) \r
-               *(.version_information)\r
-       } >osimage\r
-       __end_of_text__ = .;\r
-       \r
-       .data : {\r
-               __data_start__ = .;\r
-               __data_src_start__ = __end_of_text__; \r
-               *(.data)\r
-               *(.data.*)\r
-               __data_end__ = .;\r
-       } >ram AT>osimage\r
-       \r
-       .bss : {\r
-               __bss_start__ = .; \r
-               *(.bss)\r
-               *(.bss.*) \r
-       } >ram\r
-       . = ALIGN(32 / 8);\r
-       __bss_end__ = .;\r
-\r
-       .commonarea (NOLOAD) : {\r
-               *(.commonarea)\r
-       } >commonarea\r
-}\r
+INCLUDE ../common/ldscript.common
+
+ENTRY(Vector)
+SECTIONS
+{
+       .fpgaimage : {
+               *(fpga_bit.data)
+       } >fpgaimage
+       .start : { *(.startos) } >osimage
+       .text : { 
+               *(.text)
+               *(.text.*)
+               *(.eh_frame)
+               *(.glue_7)
+               *(.glue_7t)
+               *(.rodata) 
+               *(.rodata*) 
+               *(.version_information)
+       } >osimage
+       __end_of_text__ = .;
+       
+       .data : {
+               __data_start__ = .;
+               __data_src_start__ = __end_of_text__; 
+               *(.data)
+               *(.data.*)
+               __data_end__ = .;
+       } >ram AT>osimage
+       
+       .bss : {
+               __bss_start__ = .; 
+               *(.bss)
+               *(.bss.*) 
+       } >ram
+       . = ALIGN(32 / 8);
+       __bss_end__ = .;
+
+       .commonarea (NOLOAD) : {
+               *(.commonarea)
+       } >commonarea
+}
index a7e1f1df160f7adbce283ce510f55d98f6d1f106..14cc33a4ab297396515200a1e2d0f0cc711f8481 100644 (file)
-//-----------------------------------------------------------------------------\r
-// Miscellaneous routines for low frequency tag operations.\r
-// Tags supported here so far are Texas Instruments (TI), HID\r
-// Also routines for raw mode reading/simulating of LF waveform\r
-//\r
-//-----------------------------------------------------------------------------\r
-#include <proxmark3.h>\r
-#include "apps.h"\r
-#include "hitag2.h"\r
-#include "crc16.h"\r
-\r
-void AcquireRawAdcSamples125k(BOOL at134khz)\r
-{\r
-       if (at134khz)\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
-       else\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
-\r
-       // Connect the A/D to the peak-detected low-frequency path.\r
-       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
-\r
-       // Give it a bit of time for the resonant antenna to settle.\r
-       SpinDelay(50);\r
-\r
-       // Now set up the SSC to get the ADC samples that are now streaming at us.\r
-       FpgaSetupSsc();\r
-\r
-       // Now call the acquisition routine\r
-       DoAcquisition125k();\r
-}\r
-\r
-// split into two routines so we can avoid timing issues after sending commands //\r
-void DoAcquisition125k(void)\r
-{\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int n = sizeof(BigBuf);\r
-       int i;\r
-       \r
-       memset(dest, 0, n);\r
-       i = 0;\r
-       for(;;) {\r
-               if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {\r
-                       AT91C_BASE_SSC->SSC_THR = 0x43;\r
-                       LED_D_ON();\r
-               }\r
-               if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {\r
-                       dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
-                       i++;\r
-                       LED_D_OFF();\r
-                       if (i >= n) break;\r
-               }\r
-       }\r
-       Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",\r
-                       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);\r
-}\r
-\r
-void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, BYTE *command)\r
-{\r
-       BOOL at134khz;\r
-\r
-       /* Make sure the tag is reset */\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       SpinDelay(2500);\r
-       \r
-       // see if 'h' was specified\r
-       if (command[strlen((char *) command) - 1] == 'h')\r
-               at134khz = TRUE;\r
-       else\r
-               at134khz = FALSE;\r
-\r
-       if (at134khz)\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
-       else\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
-\r
-       // Give it a bit of time for the resonant antenna to settle.\r
-       SpinDelay(50);\r
-       // And a little more time for the tag to fully power up\r
-       SpinDelay(2000);\r
-\r
-       // Now set up the SSC to get the ADC samples that are now streaming at us.\r
-       FpgaSetupSsc();\r
-\r
-       // now modulate the reader field\r
-       while(*command != '\0' && *command != ' ') {\r
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-               LED_D_OFF();\r
-               SpinDelayUs(delay_off);\r
-               if (at134khz)\r
-                       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
-               else\r
-                       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
-\r
-               FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
-               LED_D_ON();\r
-               if(*(command++) == '0')\r
-                       SpinDelayUs(period_0);\r
-               else\r
-                       SpinDelayUs(period_1);\r
-       }\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       LED_D_OFF();\r
-       SpinDelayUs(delay_off);\r
-       if (at134khz)\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
-       else\r
-               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
-\r
-       // now do the read\r
-       DoAcquisition125k();\r
-}\r
-\r
-/* blank r/w tag data stream\r
-...0000000000000000 01111111\r
-1010101010101010101010101010101010101010101010101010101010101010\r
-0011010010100001\r
-01111111\r
-101010101010101[0]000...\r
-\r
-[5555fe852c5555555555555555fe0000]\r
-*/\r
-void ReadTItag(void)\r
-{\r
-       // some hardcoded initial params\r
-       // when we read a TI tag we sample the zerocross line at 2Mhz\r
-       // TI tags modulate a 1 as 16 cycles of 123.2Khz\r
-       // TI tags modulate a 0 as 16 cycles of 134.2Khz\r
-       #define FSAMPLE 2000000\r
-       #define FREQLO 123200\r
-       #define FREQHI 134200\r
-\r
-       signed char *dest = (signed char *)BigBuf;\r
-       int n = sizeof(BigBuf);\r
-//     int *dest = GraphBuffer;\r
-//     int n = GraphTraceLen;\r
-\r
-       // 128 bit shift register [shift3:shift2:shift1:shift0]\r
-       DWORD shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;\r
-\r
-       int i, cycles=0, samples=0;\r
-       // how many sample points fit in 16 cycles of each frequency\r
-       DWORD sampleslo = (FSAMPLE<<4)/FREQLO, sampleshi = (FSAMPLE<<4)/FREQHI;\r
-       // when to tell if we're close enough to one freq or another\r
-       DWORD threshold = (sampleslo - sampleshi + 1)>>1;\r
-\r
-       // TI tags charge at 134.2Khz\r
-       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
-\r
-       // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
-       // connects to SSP_DIN and the SSP_DOUT logic level controls\r
-       // whether we're modulating the antenna (high)\r
-       // or listening to the antenna (low)\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
-\r
-       // get TI tag data into the buffer\r
-       AcquireTiType();\r
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-\r
-       for (i=0; i<n-1; i++) {\r
-               // count cycles by looking for lo to hi zero crossings\r
-               if ( (dest[i]<0) && (dest[i+1]>0) ) {\r
-                       cycles++;\r
-                       // after 16 cycles, measure the frequency\r
-                       if (cycles>15) {\r
-                               cycles=0;\r
-                               samples=i-samples; // number of samples in these 16 cycles\r
-\r
-                               // TI bits are coming to us lsb first so shift them\r
-                               // right through our 128 bit right shift register\r
-                         shift0 = (shift0>>1) | (shift1 << 31);\r
-                         shift1 = (shift1>>1) | (shift2 << 31);\r
-                         shift2 = (shift2>>1) | (shift3 << 31);\r
-                         shift3 >>= 1;\r
-\r
-                               // check if the cycles fall close to the number\r
-                               // expected for either the low or high frequency\r
-                               if ( (samples>(sampleslo-threshold)) && (samples<(sampleslo+threshold)) ) {\r
-                                       // low frequency represents a 1\r
-                                       shift3 |= (1<<31);\r
-                               } else if ( (samples>(sampleshi-threshold)) && (samples<(sampleshi+threshold)) ) {\r
-                                       // high frequency represents a 0\r
-                               } else {\r
-                                       // probably detected a gay waveform or noise\r
-                                       // use this as gaydar or discard shift register and start again\r
-                                       shift3 = shift2 = shift1 = shift0 = 0;\r
-                               }\r
-                               samples = i;\r
-\r
-                               // for each bit we receive, test if we've detected a valid tag\r
-\r
-                               // if we see 17 zeroes followed by 6 ones, we might have a tag\r
-                               // remember the bits are backwards\r
-                               if ( ((shift0 & 0x7fffff) == 0x7e0000) ) {\r
-                                       // if start and end bytes match, we have a tag so break out of the loop\r
-                                       if ( ((shift0>>16)&0xff) == ((shift3>>8)&0xff) ) {\r
-                                               cycles = 0xF0B; //use this as a flag (ugly but whatever)\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-       }\r
-\r
-       // if flag is set we have a tag\r
-       if (cycles!=0xF0B) {\r
-               DbpString("Info: No valid tag detected.");\r
-       } else {\r
-         // put 64 bit data into shift1 and shift0\r
-         shift0 = (shift0>>24) | (shift1 << 8);\r
-         shift1 = (shift1>>24) | (shift2 << 8);\r
-\r
-               // align 16 bit crc into lower half of shift2\r
-         shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff;\r
-\r
-               // if r/w tag, check ident match\r
-               if ( shift3&(1<<15) ) {\r
-                       DbpString("Info: TI tag is rewriteable");\r
-                       // only 15 bits compare, last bit of ident is not valid\r
-                       if ( ((shift3>>16)^shift0)&0x7fff ) {\r
-                               DbpString("Error: Ident mismatch!");\r
-                       } else {\r
-                               DbpString("Info: TI tag ident is valid");\r
-                       }\r
-               } else {\r
-                       DbpString("Info: TI tag is readonly");\r
-               }\r
-\r
-               // WARNING the order of the bytes in which we calc crc below needs checking\r
-               // i'm 99% sure the crc algorithm is correct, but it may need to eat the\r
-               // bytes in reverse or something\r
-               // calculate CRC\r
-               DWORD crc=0;\r
-\r
-               crc = update_crc16(crc, (shift0)&0xff);\r
-               crc = update_crc16(crc, (shift0>>8)&0xff);\r
-               crc = update_crc16(crc, (shift0>>16)&0xff);\r
-               crc = update_crc16(crc, (shift0>>24)&0xff);\r
-               crc = update_crc16(crc, (shift1)&0xff);\r
-               crc = update_crc16(crc, (shift1>>8)&0xff);\r
-               crc = update_crc16(crc, (shift1>>16)&0xff);\r
-               crc = update_crc16(crc, (shift1>>24)&0xff);\r
-\r
-               Dbprintf("Info: Tag data: %x%08x, crc=%x",\r
-                       (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF);\r
-               if (crc != (shift2&0xffff)) {\r
-                       Dbprintf("Error: CRC mismatch, expected %x", (unsigned int)crc);\r
-               } else {\r
-                       DbpString("Info: CRC is good");\r
-               }\r
-       }\r
-}\r
-\r
-void WriteTIbyte(BYTE b)\r
-{\r
-       int i = 0;\r
-\r
-       // modulate 8 bits out to the antenna\r
-       for (i=0; i<8; i++)\r
-       {\r
-               if (b&(1<<i)) {\r
-                       // stop modulating antenna\r
-                       LOW(GPIO_SSC_DOUT);\r
-                       SpinDelayUs(1000);\r
-                       // modulate antenna\r
-                       HIGH(GPIO_SSC_DOUT);\r
-                       SpinDelayUs(1000);\r
-               } else {\r
-                       // stop modulating antenna\r
-                       LOW(GPIO_SSC_DOUT);\r
-                       SpinDelayUs(300);\r
-                       // modulate antenna\r
-                       HIGH(GPIO_SSC_DOUT);\r
-                       SpinDelayUs(1700);\r
-               }\r
-       }\r
-}\r
-\r
-void AcquireTiType(void)\r
-{\r
-       int i, j, n;\r
-       // tag transmission is <20ms, sampling at 2M gives us 40K samples max\r
-       // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS\r
-       #define TIBUFLEN 1250\r
-\r
-       // clear buffer\r
-       memset(BigBuf,0,sizeof(BigBuf));\r
-\r
-       // Set up the synchronous serial port\r
-       AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;\r
-       AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN;\r
-\r
-       // steal this pin from the SSP and use it to control the modulation\r
-       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;\r
-       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
-\r
-       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;\r
-       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;\r
-\r
-       // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long\r
-       // 48/2 = 24 MHz clock must be divided by 12\r
-       AT91C_BASE_SSC->SSC_CMR = 12;\r
-\r
-       AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(0);\r
-       AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(32) | AT91C_SSC_MSBF;\r
-       AT91C_BASE_SSC->SSC_TCMR = 0;\r
-       AT91C_BASE_SSC->SSC_TFMR = 0;\r
-\r
-       LED_D_ON();\r
-\r
-       // modulate antenna\r
-       HIGH(GPIO_SSC_DOUT);\r
-\r
-       // Charge TI tag for 50ms.\r
-       SpinDelay(50);\r
-\r
-       // stop modulating antenna and listen\r
-       LOW(GPIO_SSC_DOUT);\r
-\r
-       LED_D_OFF();\r
-\r
-       i = 0;\r
-       for(;;) {\r
-               if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {\r
-                       BigBuf[i] = AT91C_BASE_SSC->SSC_RHR;    // store 32 bit values in buffer\r
-                       i++; if(i >= TIBUFLEN) break;\r
-               }\r
-               WDT_HIT();\r
-       }\r
-\r
-       // return stolen pin to SSP\r
-       AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;\r
-       AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;\r
-\r
-       char *dest = (char *)BigBuf;\r
-       n = TIBUFLEN*32;\r
-       // unpack buffer\r
-       for (i=TIBUFLEN-1; i>=0; i--) {\r
-               for (j=0; j<32; j++) {\r
-                       if(BigBuf[i] & (1 << j)) {\r
-                               dest[--n] = 1;\r
-                       } else {\r
-                               dest[--n] = -1;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc\r
-// if crc provided, it will be written with the data verbatim (even if bogus)\r
-// if not provided a valid crc will be computed from the data and written.\r
-void WriteTItag(DWORD idhi, DWORD idlo, WORD crc)\r
-{\r
-       if(crc == 0) {\r
-               crc = update_crc16(crc, (idlo)&0xff);\r
-               crc = update_crc16(crc, (idlo>>8)&0xff);\r
-               crc = update_crc16(crc, (idlo>>16)&0xff);\r
-               crc = update_crc16(crc, (idlo>>24)&0xff);\r
-               crc = update_crc16(crc, (idhi)&0xff);\r
-               crc = update_crc16(crc, (idhi>>8)&0xff);\r
-               crc = update_crc16(crc, (idhi>>16)&0xff);\r
-               crc = update_crc16(crc, (idhi>>24)&0xff);\r
-       }\r
-       Dbprintf("Writing to tag: %x%08x, crc=%x",\r
-               (unsigned int) idhi, (unsigned int) idlo, crc);\r
-\r
-       // TI tags charge at 134.2Khz\r
-       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz\r
-       // Place FPGA in passthrough mode, in this mode the CROSS_LO line\r
-       // connects to SSP_DIN and the SSP_DOUT logic level controls\r
-       // whether we're modulating the antenna (high)\r
-       // or listening to the antenna (low)\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);\r
-       LED_A_ON();\r
-\r
-       // steal this pin from the SSP and use it to control the modulation\r
-       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;\r
-       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
-\r
-       // writing algorithm:\r
-       // a high bit consists of a field off for 1ms and field on for 1ms\r
-       // a low bit consists of a field off for 0.3ms and field on for 1.7ms\r
-       // initiate a charge time of 50ms (field on) then immediately start writing bits\r
-       // start by writing 0xBB (keyword) and 0xEB (password)\r
-       // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)\r
-       // finally end with 0x0300 (write frame)\r
-       // all data is sent lsb firts\r
-       // finish with 15ms programming time\r
-\r
-       // modulate antenna\r
-       HIGH(GPIO_SSC_DOUT);\r
-       SpinDelay(50);  // charge time\r
-\r
-       WriteTIbyte(0xbb); // keyword\r
-       WriteTIbyte(0xeb); // password\r
-       WriteTIbyte( (idlo    )&0xff );\r
-       WriteTIbyte( (idlo>>8 )&0xff );\r
-       WriteTIbyte( (idlo>>16)&0xff );\r
-       WriteTIbyte( (idlo>>24)&0xff );\r
-       WriteTIbyte( (idhi    )&0xff );\r
-       WriteTIbyte( (idhi>>8 )&0xff );\r
-       WriteTIbyte( (idhi>>16)&0xff );\r
-       WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo\r
-       WriteTIbyte( (crc     )&0xff ); // crc lo\r
-       WriteTIbyte( (crc>>8  )&0xff ); // crc hi\r
-       WriteTIbyte(0x00); // write frame lo\r
-       WriteTIbyte(0x03); // write frame hi\r
-       HIGH(GPIO_SSC_DOUT);\r
-       SpinDelay(50);  // programming time\r
-\r
-       LED_A_OFF();\r
-\r
-       // get TI tag data into the buffer\r
-       AcquireTiType();\r
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-       DbpString("Now use tiread to check");\r
-}\r
-\r
-void SimulateTagLowFrequency(int period, int gap, int ledcontrol)\r
-{\r
-       int i;\r
-       BYTE *tab = (BYTE *)BigBuf;\r
-\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
-\r
-       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;\r
-\r
-       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
-       AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;\r
-\r
-#define SHORT_COIL()   LOW(GPIO_SSC_DOUT)\r
-#define OPEN_COIL()            HIGH(GPIO_SSC_DOUT)\r
-\r
-       i = 0;\r
-       for(;;) {\r
-               while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {\r
-                       if(BUTTON_PRESS()) {\r
-                               DbpString("Stopped");\r
-                               return;\r
-                       }\r
-                       WDT_HIT();\r
-               }\r
-\r
-               if (ledcontrol)\r
-                       LED_D_ON();\r
-\r
-               if(tab[i])\r
-                       OPEN_COIL();\r
-               else\r
-                       SHORT_COIL();\r
-\r
-               if (ledcontrol)\r
-                       LED_D_OFF();\r
-\r
-               while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {\r
-                       if(BUTTON_PRESS()) {\r
-                               DbpString("Stopped");\r
-                               return;\r
-                       }\r
-                       WDT_HIT();\r
-               }\r
-\r
-               i++;\r
-               if(i == period) {\r
-                       i = 0;\r
-                       if (gap) { \r
-                               SHORT_COIL();\r
-                               SpinDelayUs(gap);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-/* Provides a framework for bidirectional LF tag communication\r
- * Encoding is currently Hitag2, but the general idea can probably\r
- * be transferred to other encodings.\r
- * \r
- * The new FPGA code will, for the LF simulator mode, give on SSC_FRAME\r
- * (PA15) a thresholded version of the signal from the ADC. Setting the\r
- * ADC path to the low frequency peak detection signal, will enable a\r
- * somewhat reasonable receiver for modulation on the carrier signal\r
- * that is generated by the reader. The signal is low when the reader\r
- * field is switched off, and high when the reader field is active. Due\r
- * to the way that the signal looks like, mostly only the rising edge is\r
- * useful, your mileage may vary.\r
- * \r
- * Neat perk: PA15 can not only be used as a bit-banging GPIO, but is also\r
- * TIOA1, which can be used as the capture input for timer 1. This should\r
- * make it possible to measure the exact edge-to-edge time, without processor\r
- * intervention.\r
- * \r
- * Arguments: divisor is the divisor to be sent to the FPGA (e.g. 95 for 125kHz)\r
- * t0 is the carrier frequency cycle duration in terms of MCK (384 for 125kHz)\r
- * \r
- * The following defines are in carrier periods: \r
- */\r
-#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ \r
-#define HITAG_T_1_MIN 24 /* T[1] should be 26..30 */\r
-#define HITAG_T_EOF   40 /* T_EOF should be > 36 */\r
-#define HITAG_T_WRESP 208 /* T_wresp should be 204..212 */\r
-\r
-static void hitag_handle_frame(int t0, int frame_len, char *frame);\r
-//#define DEBUG_RA_VALUES 1\r
-#define DEBUG_FRAME_CONTENTS 1\r
-void SimulateTagLowFrequencyBidir(int divisor, int t0)\r
-{\r
-#if DEBUG_RA_VALUES || DEBUG_FRAME_CONTENTS\r
-       int i = 0;\r
-#endif\r
-       char frame[10];\r
-       int frame_pos=0;\r
-       \r
-       DbpString("Starting Hitag2 emulator, press button to end");\r
-       hitag2_init();\r
-       \r
-       /* Set up simulator mode, frequency divisor which will drive the FPGA\r
-        * and analog mux selection.\r
-        */\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);\r
-       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);\r
-       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
-       RELAY_OFF();\r
-       \r
-       /* Set up Timer 1:\r
-        * Capture mode, timer source MCK/2 (TIMER_CLOCK1), TIOA is external trigger,\r
-        * external trigger rising edge, load RA on rising edge of TIOA, load RB on rising\r
-        * edge of TIOA. Assign PA15 to TIOA1 (peripheral B)\r
-        */\r
-       \r
-       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);\r
-       AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;\r
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;\r
-       AT91C_BASE_TC1->TC_CMR =        TC_CMR_TCCLKS_TIMER_CLOCK1 |\r
-                                                               AT91C_TC_ETRGEDG_RISING |\r
-                                                               AT91C_TC_ABETRG |\r
-                                                               AT91C_TC_LDRA_RISING |\r
-                                                               AT91C_TC_LDRB_RISING;\r
-       AT91C_BASE_TC1->TC_CCR =        AT91C_TC_CLKEN |\r
-                                                               AT91C_TC_SWTRG;\r
-       \r
-       /* calculate the new value for the carrier period in terms of TC1 values */\r
-       t0 = t0/2;\r
-       \r
-       int overflow = 0;\r
-       while(!BUTTON_PRESS()) {\r
-               WDT_HIT();\r
-               if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {\r
-                       int ra = AT91C_BASE_TC1->TC_RA;\r
-                       if((ra > t0*HITAG_T_EOF) | overflow) ra = t0*HITAG_T_EOF+1;\r
-#if DEBUG_RA_VALUES\r
-                       if(ra > 255 || overflow) ra = 255;\r
-                       ((char*)BigBuf)[i] = ra;\r
-                       i = (i+1) % 8000;\r
-#endif\r
-                       \r
-                       if(overflow || (ra > t0*HITAG_T_EOF) || (ra < t0*HITAG_T_0_MIN)) {\r
-                               /* Ignore */\r
-                       } else if(ra >= t0*HITAG_T_1_MIN ) {\r
-                               /* '1' bit */\r
-                               if(frame_pos < 8*sizeof(frame)) {\r
-                                       frame[frame_pos / 8] |= 1<<( 7-(frame_pos%8) );\r
-                                       frame_pos++;\r
-                               }\r
-                       } else if(ra >= t0*HITAG_T_0_MIN) {\r
-                               /* '0' bit */\r
-                               if(frame_pos < 8*sizeof(frame)) {\r
-                                       frame[frame_pos / 8] |= 0<<( 7-(frame_pos%8) );\r
-                                       frame_pos++;\r
-                               }\r
-                       }\r
-                       \r
-                       overflow = 0;\r
-                       LED_D_ON();\r
-               } else {\r
-                       if(AT91C_BASE_TC1->TC_CV > t0*HITAG_T_EOF) {\r
-                               /* Minor nuisance: In Capture mode, the timer can not be\r
-                                * stopped by a Compare C. There's no way to stop the clock\r
-                                * in software, so we'll just have to note the fact that an\r
-                                * overflow happened and the next loaded timer value might\r
-                                * have wrapped. Also, this marks the end of frame, and the\r
-                                * still running counter can be used to determine the correct\r
-                                * time for the start of the reply.\r
-                                */ \r
-                               overflow = 1;\r
-                               \r
-                               if(frame_pos > 0) {\r
-                                       /* Have a frame, do something with it */\r
-#if DEBUG_FRAME_CONTENTS\r
-                                       ((char*)BigBuf)[i++] = frame_pos;\r
-                                       memcpy( ((char*)BigBuf)+i, frame, 7);\r
-                                       i+=7;\r
-                                       i = i % sizeof(BigBuf);\r
-#endif\r
-                                       hitag_handle_frame(t0, frame_pos, frame);\r
-                                       memset(frame, 0, sizeof(frame));\r
-                               }\r
-                               frame_pos = 0;\r
-\r
-                       }\r
-                       LED_D_OFF();\r
-               }\r
-       }\r
-       DbpString("All done");\r
-}\r
-\r
-static void hitag_send_bit(int t0, int bit) {\r
-       if(bit == 1) {\r
-               /* Manchester: Loaded, then unloaded */\r
-               LED_A_ON();\r
-               SHORT_COIL();\r
-               while(AT91C_BASE_TC1->TC_CV < t0*15);\r
-               OPEN_COIL();\r
-               while(AT91C_BASE_TC1->TC_CV < t0*31);\r
-               LED_A_OFF();\r
-       } else if(bit == 0) {\r
-               /* Manchester: Unloaded, then loaded */\r
-               LED_B_ON();\r
-               OPEN_COIL();\r
-               while(AT91C_BASE_TC1->TC_CV < t0*15);\r
-               SHORT_COIL();\r
-               while(AT91C_BASE_TC1->TC_CV < t0*31);\r
-               LED_B_OFF();\r
-       }\r
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset clock for the next bit */\r
-       \r
-}\r
-static void hitag_send_frame(int t0, int frame_len, const char const * frame, int fdt)\r
-{\r
-       OPEN_COIL();\r
-       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;\r
-       \r
-       /* Wait for HITAG_T_WRESP carrier periods after the last reader bit,\r
-        * not that since the clock counts since the rising edge, but T_wresp is\r
-        * with respect to the falling edge, we need to wait actually (T_wresp - T_g)\r
-        * periods. The gap time T_g varies (4..10).\r
-        */\r
-       while(AT91C_BASE_TC1->TC_CV < t0*(fdt-8));\r
-\r
-       int saved_cmr = AT91C_BASE_TC1->TC_CMR;\r
-       AT91C_BASE_TC1->TC_CMR &= ~AT91C_TC_ETRGEDG; /* Disable external trigger for the clock */\r
-       AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset the clock and use it for response timing */\r
-       \r
-       int i;\r
-       for(i=0; i<5; i++)\r
-               hitag_send_bit(t0, 1); /* Start of frame */\r
-       \r
-       for(i=0; i<frame_len; i++) {\r
-               hitag_send_bit(t0, !!(frame[i/ 8] & (1<<( 7-(i%8) ))) );\r
-       }\r
-       \r
-       OPEN_COIL();\r
-       AT91C_BASE_TC1->TC_CMR = saved_cmr;\r
-}\r
-\r
-/* Callback structure to cleanly separate tag emulation code from the radio layer. */\r
-static int hitag_cb(const char* response_data, const int response_length, const int fdt, void *cb_cookie)\r
-{\r
-       hitag_send_frame(*(int*)cb_cookie, response_length, response_data, fdt);\r
-       return 0;\r
-}\r
-/* Frame length in bits, frame contents in MSBit first format */\r
-static void hitag_handle_frame(int t0, int frame_len, char *frame)\r
-{\r
-       hitag2_handle_command(frame, frame_len, hitag_cb, &t0);\r
-}\r
-\r
-// compose fc/8 fc/10 waveform\r
-static void fc(int c, int *n) {\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int idx;\r
-\r
-       // for when we want an fc8 pattern every 4 logical bits\r
-       if(c==0) {\r
-               dest[((*n)++)]=1;\r
-               dest[((*n)++)]=1;\r
-               dest[((*n)++)]=0;\r
-               dest[((*n)++)]=0;\r
-               dest[((*n)++)]=0;\r
-               dest[((*n)++)]=0;\r
-               dest[((*n)++)]=0;\r
-               dest[((*n)++)]=0;\r
-       }\r
-       //      an fc/8  encoded bit is a bit pattern of  11000000  x6 = 48 samples\r
-       if(c==8) {\r
-               for (idx=0; idx<6; idx++) {\r
-                       dest[((*n)++)]=1;\r
-                       dest[((*n)++)]=1;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-               }\r
-       }\r
-\r
-       //      an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples\r
-       if(c==10) {\r
-               for (idx=0; idx<5; idx++) {\r
-                       dest[((*n)++)]=1;\r
-                       dest[((*n)++)]=1;\r
-                       dest[((*n)++)]=1;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-                       dest[((*n)++)]=0;\r
-               }\r
-       }\r
-}\r
-\r
-// prepare a waveform pattern in the buffer based on the ID given then\r
-// simulate a HID tag until the button is pressed\r
-void CmdHIDsimTAG(int hi, int lo, int ledcontrol)\r
-{\r
-       int n=0, i=0;\r
-       /*\r
-        HID tag bitstream format\r
-        The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits\r
-        A 1 bit is represented as 6 fc8 and 5 fc10 patterns\r
-        A 0 bit is represented as 5 fc10 and 6 fc8 patterns\r
-        A fc8 is inserted before every 4 bits\r
-        A special start of frame pattern is used consisting a0b0 where a and b are neither 0\r
-        nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)\r
-       */\r
-\r
-       if (hi>0xFFF) {\r
-               DbpString("Tags can only have 44 bits.");\r
-               return;\r
-       }\r
-       fc(0,&n);\r
-       // special start of frame marker containing invalid bit sequences\r
-       fc(8,  &n);     fc(8,  &n);     // invalid\r
-       fc(8,  &n);     fc(10, &n); // logical 0\r
-       fc(10, &n);     fc(10, &n); // invalid\r
-       fc(8,  &n);     fc(10, &n); // logical 0\r
-\r
-       WDT_HIT();\r
-       // manchester encode bits 43 to 32\r
-       for (i=11; i>=0; i--) {\r
-               if ((i%4)==3) fc(0,&n);\r
-               if ((hi>>i)&1) {\r
-                       fc(10, &n);     fc(8,  &n);             // low-high transition\r
-               } else {\r
-                       fc(8,  &n);     fc(10, &n);             // high-low transition\r
-               }\r
-       }\r
-\r
-       WDT_HIT();\r
-       // manchester encode bits 31 to 0\r
-       for (i=31; i>=0; i--) {\r
-               if ((i%4)==3) fc(0,&n);\r
-               if ((lo>>i)&1) {\r
-                       fc(10, &n);     fc(8,  &n);             // low-high transition\r
-               } else {\r
-                       fc(8,  &n);     fc(10, &n);             // high-low transition\r
-               }\r
-       }\r
-\r
-       if (ledcontrol)\r
-               LED_A_ON();\r
-       SimulateTagLowFrequency(n, 0, ledcontrol);\r
-\r
-       if (ledcontrol)\r
-               LED_A_OFF();\r
-}\r
-\r
-\r
-// loop to capture raw HID waveform then FSK demodulate the TAG ID from it\r
-void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)\r
-{\r
-       BYTE *dest = (BYTE *)BigBuf;\r
-       int m=0, n=0, i=0, idx=0, found=0, lastval=0;\r
-       DWORD hi=0, lo=0;\r
-\r
-       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz\r
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);\r
-\r
-       // Connect the A/D to the peak-detected low-frequency path.\r
-       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);\r
-\r
-       // Give it a bit of time for the resonant antenna to settle.\r
-       SpinDelay(50);\r
-\r
-       // Now set up the SSC to get the ADC samples that are now streaming at us.\r
-       FpgaSetupSsc();\r
-\r
-       for(;;) {\r
-               WDT_HIT();\r
-               if (ledcontrol)\r
-                       LED_A_ON();\r
-               if(BUTTON_PRESS()) {\r
-                       DbpString("Stopped");\r
-                       if (ledcontrol)\r
-                               LED_A_OFF();\r
-                       return;\r
-               }\r
-\r
-               i = 0;\r
-               m = sizeof(BigBuf);\r
-               memset(dest,128,m);\r
-               for(;;) {\r
-                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {\r
-                               AT91C_BASE_SSC->SSC_THR = 0x43;\r
-                               if (ledcontrol)\r
-                                       LED_D_ON();\r
-                       }\r
-                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {\r
-                               dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR;\r
-                               // we don't care about actual value, only if it's more or less than a\r
-                               // threshold essentially we capture zero crossings for later analysis\r
-                               if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;\r
-                               i++;\r
-                               if (ledcontrol)\r
-                                       LED_D_OFF();\r
-                               if(i >= m) {\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // FSK demodulator\r
-\r
-               // sync to first lo-hi transition\r
-               for( idx=1; idx<m; idx++) {\r
-                       if (dest[idx-1]<dest[idx])\r
-                               lastval=idx;\r
-                               break;\r
-               }\r
-               WDT_HIT();\r
-\r
-               // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)\r
-               // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere\r
-               // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10\r
-               for( i=0; idx<m; idx++) {\r
-                       if (dest[idx-1]<dest[idx]) {\r
-                               dest[i]=idx-lastval;\r
-                               if (dest[i] <= 8) {\r
-                                               dest[i]=1;\r
-                               } else {\r
-                                               dest[i]=0;\r
-                               }\r
-\r
-                               lastval=idx;\r
-                               i++;\r
-                       }\r
-               }\r
-               m=i;\r
-               WDT_HIT();\r
-\r
-               // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns\r
-               lastval=dest[0];\r
-               idx=0;\r
-               i=0;\r
-               n=0;\r
-               for( idx=0; idx<m; idx++) {\r
-                       if (dest[idx]==lastval) {\r
-                               n++;\r
-                       } else {\r
-                               // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,\r
-                               // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets\r
-                               // swallowed up by rounding\r
-                               // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding\r
-                               // special start of frame markers use invalid manchester states (no transitions) by using sequences\r
-                               // like 111000\r
-                               if (dest[idx-1]) {\r
-                                       n=(n+1)/6;                      // fc/8 in sets of 6\r
-                               } else {\r
-                                       n=(n+1)/5;                      // fc/10 in sets of 5\r
-                               }\r
-                               switch (n) {                    // stuff appropriate bits in buffer\r
-                                       case 0:\r
-                                       case 1: // one bit\r
-                                               dest[i++]=dest[idx-1];\r
-                                               break;\r
-                                       case 2: // two bits\r
-                                               dest[i++]=dest[idx-1];\r
-                                               dest[i++]=dest[idx-1];\r
-                                               break;\r
-                                       case 3: // 3 bit start of frame markers\r
-                                               dest[i++]=dest[idx-1];\r
-                                               dest[i++]=dest[idx-1];\r
-                                               dest[i++]=dest[idx-1];\r
-                                               break;\r
-                                       // When a logic 0 is immediately followed by the start of the next transmisson\r
-                                       // (special pattern) a pattern of 4 bit duration lengths is created.\r
-                                       case 4:\r
-                                               dest[i++]=dest[idx-1];\r
-                                               dest[i++]=dest[idx-1];\r
-                                               dest[i++]=dest[idx-1];\r
-                                               dest[i++]=dest[idx-1];\r
-                                               break;\r
-                                       default:        // this shouldn't happen, don't stuff any bits\r
-                                               break;\r
-                               }\r
-                               n=0;\r
-                               lastval=dest[idx];\r
-                       }\r
-               }\r
-               m=i;\r
-               WDT_HIT();\r
-\r
-               // final loop, go over previously decoded manchester data and decode into usable tag ID\r
-               // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0\r
-               for( idx=0; idx<m-6; idx++) {\r
-                       // search for a start of frame marker\r
-                       if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
-                       {\r
-                               found=1;\r
-                               idx+=6;\r
-                               if (found && (hi|lo)) {\r
-                                       Dbprintf("TAG ID: %x%08x (%d)",\r
-                                               (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);\r
-                                       /* if we're only looking for one tag */\r
-                                       if (findone)\r
-                                       {\r
-                                               *high = hi;\r
-                                               *low = lo;\r
-                                               return;\r
-                                       }\r
-                                       hi=0;\r
-                                       lo=0;\r
-                                       found=0;\r
-                               }\r
-                       }\r
-                       if (found) {\r
-                               if (dest[idx] && (!dest[idx+1]) ) {\r
-                                       hi=(hi<<1)|(lo>>31);\r
-                                       lo=(lo<<1)|0;\r
-                               } else if ( (!dest[idx]) && dest[idx+1]) {\r
-                                       hi=(hi<<1)|(lo>>31);\r
-                                       lo=(lo<<1)|1;\r
-                               } else {\r
-                                       found=0;\r
-                                       hi=0;\r
-                                       lo=0;\r
-                               }\r
-                               idx++;\r
-                       }\r
-                       if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )\r
-                       {\r
-                               found=1;\r
-                               idx+=6;\r
-                               if (found && (hi|lo)) {\r
-                                       Dbprintf("TAG ID: %x%08x (%d)",\r
-                                               (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);\r
-                                       /* if we're only looking for one tag */\r
-                                       if (findone)\r
-                                       {\r
-                                               *high = hi;\r
-                                               *low = lo;\r
-                                               return;\r
-                                       }\r
-                                       hi=0;\r
-                                       lo=0;\r
-                                       found=0;\r
-                               }\r
-                       }\r
-               }\r
-               WDT_HIT();\r
-       }\r
-}\r
+//-----------------------------------------------------------------------------
+// Miscellaneous routines for low frequency tag operations.
+// Tags supported here so far are Texas Instruments (TI), HID
+// Also routines for raw mode reading/simulating of LF waveform
+//
+//-----------------------------------------------------------------------------
+#include <proxmark3.h>
+#include "apps.h"
+#include "hitag2.h"
+#include "crc16.h"
+
+void AcquireRawAdcSamples125k(BOOL at134khz)
+{
+       if (at134khz)
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+       else
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+       // Connect the A/D to the peak-detected low-frequency path.
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+       // Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(50);
+
+       // Now set up the SSC to get the ADC samples that are now streaming at us.
+       FpgaSetupSsc();
+
+       // Now call the acquisition routine
+       DoAcquisition125k();
+}
+
+// split into two routines so we can avoid timing issues after sending commands //
+void DoAcquisition125k(void)
+{
+       BYTE *dest = (BYTE *)BigBuf;
+       int n = sizeof(BigBuf);
+       int i;
+       
+       memset(dest, 0, n);
+       i = 0;
+       for(;;) {
+               if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
+                       AT91C_BASE_SSC->SSC_THR = 0x43;
+                       LED_D_ON();
+               }
+               if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
+                       dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+                       i++;
+                       LED_D_OFF();
+                       if (i >= n) break;
+               }
+       }
+       Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
+                       dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
+}
+
+void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1, BYTE *command)
+{
+       BOOL at134khz;
+
+       /* Make sure the tag is reset */
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       SpinDelay(2500);
+       
+       // see if 'h' was specified
+       if (command[strlen((char *) command) - 1] == 'h')
+               at134khz = TRUE;
+       else
+               at134khz = FALSE;
+
+       if (at134khz)
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+       else
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+       // Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(50);
+       // And a little more time for the tag to fully power up
+       SpinDelay(2000);
+
+       // Now set up the SSC to get the ADC samples that are now streaming at us.
+       FpgaSetupSsc();
+
+       // now modulate the reader field
+       while(*command != '\0' && *command != ' ') {
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+               LED_D_OFF();
+               SpinDelayUs(delay_off);
+               if (at134khz)
+                       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+               else
+                       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+               LED_D_ON();
+               if(*(command++) == '0')
+                       SpinDelayUs(period_0);
+               else
+                       SpinDelayUs(period_1);
+       }
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LED_D_OFF();
+       SpinDelayUs(delay_off);
+       if (at134khz)
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+       else
+               FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+       // now do the read
+       DoAcquisition125k();
+}
+
+/* blank r/w tag data stream
+...0000000000000000 01111111
+1010101010101010101010101010101010101010101010101010101010101010
+0011010010100001
+01111111
+101010101010101[0]000...
+
+[5555fe852c5555555555555555fe0000]
+*/
+void ReadTItag(void)
+{
+       // some hardcoded initial params
+       // when we read a TI tag we sample the zerocross line at 2Mhz
+       // TI tags modulate a 1 as 16 cycles of 123.2Khz
+       // TI tags modulate a 0 as 16 cycles of 134.2Khz
+       #define FSAMPLE 2000000
+       #define FREQLO 123200
+       #define FREQHI 134200
+
+       signed char *dest = (signed char *)BigBuf;
+       int n = sizeof(BigBuf);
+//     int *dest = GraphBuffer;
+//     int n = GraphTraceLen;
+
+       // 128 bit shift register [shift3:shift2:shift1:shift0]
+       DWORD shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;
+
+       int i, cycles=0, samples=0;
+       // how many sample points fit in 16 cycles of each frequency
+       DWORD sampleslo = (FSAMPLE<<4)/FREQLO, sampleshi = (FSAMPLE<<4)/FREQHI;
+       // when to tell if we're close enough to one freq or another
+       DWORD threshold = (sampleslo - sampleshi + 1)>>1;
+
+       // TI tags charge at 134.2Khz
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+
+       // Place FPGA in passthrough mode, in this mode the CROSS_LO line
+       // connects to SSP_DIN and the SSP_DOUT logic level controls
+       // whether we're modulating the antenna (high)
+       // or listening to the antenna (low)
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
+
+       // get TI tag data into the buffer
+       AcquireTiType();
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+
+       for (i=0; i<n-1; i++) {
+               // count cycles by looking for lo to hi zero crossings
+               if ( (dest[i]<0) && (dest[i+1]>0) ) {
+                       cycles++;
+                       // after 16 cycles, measure the frequency
+                       if (cycles>15) {
+                               cycles=0;
+                               samples=i-samples; // number of samples in these 16 cycles
+
+                               // TI bits are coming to us lsb first so shift them
+                               // right through our 128 bit right shift register
+                         shift0 = (shift0>>1) | (shift1 << 31);
+                         shift1 = (shift1>>1) | (shift2 << 31);
+                         shift2 = (shift2>>1) | (shift3 << 31);
+                         shift3 >>= 1;
+
+                               // check if the cycles fall close to the number
+                               // expected for either the low or high frequency
+                               if ( (samples>(sampleslo-threshold)) && (samples<(sampleslo+threshold)) ) {
+                                       // low frequency represents a 1
+                                       shift3 |= (1<<31);
+                               } else if ( (samples>(sampleshi-threshold)) && (samples<(sampleshi+threshold)) ) {
+                                       // high frequency represents a 0
+                               } else {
+                                       // probably detected a gay waveform or noise
+                                       // use this as gaydar or discard shift register and start again
+                                       shift3 = shift2 = shift1 = shift0 = 0;
+                               }
+                               samples = i;
+
+                               // for each bit we receive, test if we've detected a valid tag
+
+                               // if we see 17 zeroes followed by 6 ones, we might have a tag
+                               // remember the bits are backwards
+                               if ( ((shift0 & 0x7fffff) == 0x7e0000) ) {
+                                       // if start and end bytes match, we have a tag so break out of the loop
+                                       if ( ((shift0>>16)&0xff) == ((shift3>>8)&0xff) ) {
+                                               cycles = 0xF0B; //use this as a flag (ugly but whatever)
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       // if flag is set we have a tag
+       if (cycles!=0xF0B) {
+               DbpString("Info: No valid tag detected.");
+       } else {
+         // put 64 bit data into shift1 and shift0
+         shift0 = (shift0>>24) | (shift1 << 8);
+         shift1 = (shift1>>24) | (shift2 << 8);
+
+               // align 16 bit crc into lower half of shift2
+         shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff;
+
+               // if r/w tag, check ident match
+               if ( shift3&(1<<15) ) {
+                       DbpString("Info: TI tag is rewriteable");
+                       // only 15 bits compare, last bit of ident is not valid
+                       if ( ((shift3>>16)^shift0)&0x7fff ) {
+                               DbpString("Error: Ident mismatch!");
+                       } else {
+                               DbpString("Info: TI tag ident is valid");
+                       }
+               } else {
+                       DbpString("Info: TI tag is readonly");
+               }
+
+               // WARNING the order of the bytes in which we calc crc below needs checking
+               // i'm 99% sure the crc algorithm is correct, but it may need to eat the
+               // bytes in reverse or something
+               // calculate CRC
+               DWORD crc=0;
+
+               crc = update_crc16(crc, (shift0)&0xff);
+               crc = update_crc16(crc, (shift0>>8)&0xff);
+               crc = update_crc16(crc, (shift0>>16)&0xff);
+               crc = update_crc16(crc, (shift0>>24)&0xff);
+               crc = update_crc16(crc, (shift1)&0xff);
+               crc = update_crc16(crc, (shift1>>8)&0xff);
+               crc = update_crc16(crc, (shift1>>16)&0xff);
+               crc = update_crc16(crc, (shift1>>24)&0xff);
+
+               Dbprintf("Info: Tag data: %x%08x, crc=%x",
+                       (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF);
+               if (crc != (shift2&0xffff)) {
+                       Dbprintf("Error: CRC mismatch, expected %x", (unsigned int)crc);
+               } else {
+                       DbpString("Info: CRC is good");
+               }
+       }
+}
+
+void WriteTIbyte(BYTE b)
+{
+       int i = 0;
+
+       // modulate 8 bits out to the antenna
+       for (i=0; i<8; i++)
+       {
+               if (b&(1<<i)) {
+                       // stop modulating antenna
+                       LOW(GPIO_SSC_DOUT);
+                       SpinDelayUs(1000);
+                       // modulate antenna
+                       HIGH(GPIO_SSC_DOUT);
+                       SpinDelayUs(1000);
+               } else {
+                       // stop modulating antenna
+                       LOW(GPIO_SSC_DOUT);
+                       SpinDelayUs(300);
+                       // modulate antenna
+                       HIGH(GPIO_SSC_DOUT);
+                       SpinDelayUs(1700);
+               }
+       }
+}
+
+void AcquireTiType(void)
+{
+       int i, j, n;
+       // tag transmission is <20ms, sampling at 2M gives us 40K samples max
+       // each sample is 1 bit stuffed into a DWORD so we need 1250 DWORDS
+       #define TIBUFLEN 1250
+
+       // clear buffer
+       memset(BigBuf,0,sizeof(BigBuf));
+
+       // Set up the synchronous serial port
+       AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;
+       AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN;
+
+       // steal this pin from the SSP and use it to control the modulation
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+
+       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
+       AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;
+
+       // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long
+       // 48/2 = 24 MHz clock must be divided by 12
+       AT91C_BASE_SSC->SSC_CMR = 12;
+
+       AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(0);
+       AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(32) | AT91C_SSC_MSBF;
+       AT91C_BASE_SSC->SSC_TCMR = 0;
+       AT91C_BASE_SSC->SSC_TFMR = 0;
+
+       LED_D_ON();
+
+       // modulate antenna
+       HIGH(GPIO_SSC_DOUT);
+
+       // Charge TI tag for 50ms.
+       SpinDelay(50);
+
+       // stop modulating antenna and listen
+       LOW(GPIO_SSC_DOUT);
+
+       LED_D_OFF();
+
+       i = 0;
+       for(;;) {
+               if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
+                       BigBuf[i] = AT91C_BASE_SSC->SSC_RHR;    // store 32 bit values in buffer
+                       i++; if(i >= TIBUFLEN) break;
+               }
+               WDT_HIT();
+       }
+
+       // return stolen pin to SSP
+       AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT;
+
+       char *dest = (char *)BigBuf;
+       n = TIBUFLEN*32;
+       // unpack buffer
+       for (i=TIBUFLEN-1; i>=0; i--) {
+               for (j=0; j<32; j++) {
+                       if(BigBuf[i] & (1 << j)) {
+                               dest[--n] = 1;
+                       } else {
+                               dest[--n] = -1;
+                       }
+               }
+       }
+}
+
+// arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc
+// if crc provided, it will be written with the data verbatim (even if bogus)
+// if not provided a valid crc will be computed from the data and written.
+void WriteTItag(DWORD idhi, DWORD idlo, WORD crc)
+{
+       if(crc == 0) {
+               crc = update_crc16(crc, (idlo)&0xff);
+               crc = update_crc16(crc, (idlo>>8)&0xff);
+               crc = update_crc16(crc, (idlo>>16)&0xff);
+               crc = update_crc16(crc, (idlo>>24)&0xff);
+               crc = update_crc16(crc, (idhi)&0xff);
+               crc = update_crc16(crc, (idhi>>8)&0xff);
+               crc = update_crc16(crc, (idhi>>16)&0xff);
+               crc = update_crc16(crc, (idhi>>24)&0xff);
+       }
+       Dbprintf("Writing to tag: %x%08x, crc=%x",
+               (unsigned int) idhi, (unsigned int) idlo, crc);
+
+       // TI tags charge at 134.2Khz
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
+       // Place FPGA in passthrough mode, in this mode the CROSS_LO line
+       // connects to SSP_DIN and the SSP_DOUT logic level controls
+       // whether we're modulating the antenna (high)
+       // or listening to the antenna (low)
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
+       LED_A_ON();
+
+       // steal this pin from the SSP and use it to control the modulation
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+
+       // writing algorithm:
+       // a high bit consists of a field off for 1ms and field on for 1ms
+       // a low bit consists of a field off for 0.3ms and field on for 1.7ms
+       // initiate a charge time of 50ms (field on) then immediately start writing bits
+       // start by writing 0xBB (keyword) and 0xEB (password)
+       // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer)
+       // finally end with 0x0300 (write frame)
+       // all data is sent lsb firts
+       // finish with 15ms programming time
+
+       // modulate antenna
+       HIGH(GPIO_SSC_DOUT);
+       SpinDelay(50);  // charge time
+
+       WriteTIbyte(0xbb); // keyword
+       WriteTIbyte(0xeb); // password
+       WriteTIbyte( (idlo    )&0xff );
+       WriteTIbyte( (idlo>>8 )&0xff );
+       WriteTIbyte( (idlo>>16)&0xff );
+       WriteTIbyte( (idlo>>24)&0xff );
+       WriteTIbyte( (idhi    )&0xff );
+       WriteTIbyte( (idhi>>8 )&0xff );
+       WriteTIbyte( (idhi>>16)&0xff );
+       WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo
+       WriteTIbyte( (crc     )&0xff ); // crc lo
+       WriteTIbyte( (crc>>8  )&0xff ); // crc hi
+       WriteTIbyte(0x00); // write frame lo
+       WriteTIbyte(0x03); // write frame hi
+       HIGH(GPIO_SSC_DOUT);
+       SpinDelay(50);  // programming time
+
+       LED_A_OFF();
+
+       // get TI tag data into the buffer
+       AcquireTiType();
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       DbpString("Now use tiread to check");
+}
+
+void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
+{
+       int i;
+       BYTE *tab = (BYTE *)BigBuf;
+
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
+
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
+
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
+
+#define SHORT_COIL()   LOW(GPIO_SSC_DOUT)
+#define OPEN_COIL()            HIGH(GPIO_SSC_DOUT)
+
+       i = 0;
+       for(;;) {
+               while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
+                       if(BUTTON_PRESS()) {
+                               DbpString("Stopped");
+                               return;
+                       }
+                       WDT_HIT();
+               }
+
+               if (ledcontrol)
+                       LED_D_ON();
+
+               if(tab[i])
+                       OPEN_COIL();
+               else
+                       SHORT_COIL();
+
+               if (ledcontrol)
+                       LED_D_OFF();
+
+               while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
+                       if(BUTTON_PRESS()) {
+                               DbpString("Stopped");
+                               return;
+                       }
+                       WDT_HIT();
+               }
+
+               i++;
+               if(i == period) {
+                       i = 0;
+                       if (gap) { 
+                               SHORT_COIL();
+                               SpinDelayUs(gap);
+                       }
+               }
+       }
+}
+
+/* Provides a framework for bidirectional LF tag communication
+ * Encoding is currently Hitag2, but the general idea can probably
+ * be transferred to other encodings.
+ * 
+ * The new FPGA code will, for the LF simulator mode, give on SSC_FRAME
+ * (PA15) a thresholded version of the signal from the ADC. Setting the
+ * ADC path to the low frequency peak detection signal, will enable a
+ * somewhat reasonable receiver for modulation on the carrier signal
+ * that is generated by the reader. The signal is low when the reader
+ * field is switched off, and high when the reader field is active. Due
+ * to the way that the signal looks like, mostly only the rising edge is
+ * useful, your mileage may vary.
+ * 
+ * Neat perk: PA15 can not only be used as a bit-banging GPIO, but is also
+ * TIOA1, which can be used as the capture input for timer 1. This should
+ * make it possible to measure the exact edge-to-edge time, without processor
+ * intervention.
+ * 
+ * Arguments: divisor is the divisor to be sent to the FPGA (e.g. 95 for 125kHz)
+ * t0 is the carrier frequency cycle duration in terms of MCK (384 for 125kHz)
+ * 
+ * The following defines are in carrier periods: 
+ */
+#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ 
+#define HITAG_T_1_MIN 24 /* T[1] should be 26..30 */
+#define HITAG_T_EOF   40 /* T_EOF should be > 36 */
+#define HITAG_T_WRESP 208 /* T_wresp should be 204..212 */
+
+static void hitag_handle_frame(int t0, int frame_len, char *frame);
+//#define DEBUG_RA_VALUES 1
+#define DEBUG_FRAME_CONTENTS 1
+void SimulateTagLowFrequencyBidir(int divisor, int t0)
+{
+#if DEBUG_RA_VALUES || DEBUG_FRAME_CONTENTS
+       int i = 0;
+#endif
+       char frame[10];
+       int frame_pos=0;
+       
+       DbpString("Starting Hitag2 emulator, press button to end");
+       hitag2_init();
+       
+       /* Set up simulator mode, frequency divisor which will drive the FPGA
+        * and analog mux selection.
+        */
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+       RELAY_OFF();
+       
+       /* Set up Timer 1:
+        * Capture mode, timer source MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+        * external trigger rising edge, load RA on rising edge of TIOA, load RB on rising
+        * edge of TIOA. Assign PA15 to TIOA1 (peripheral B)
+        */
+       
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+       AT91C_BASE_TC1->TC_CMR =        TC_CMR_TCCLKS_TIMER_CLOCK1 |
+                                                               AT91C_TC_ETRGEDG_RISING |
+                                                               AT91C_TC_ABETRG |
+                                                               AT91C_TC_LDRA_RISING |
+                                                               AT91C_TC_LDRB_RISING;
+       AT91C_BASE_TC1->TC_CCR =        AT91C_TC_CLKEN |
+                                                               AT91C_TC_SWTRG;
+       
+       /* calculate the new value for the carrier period in terms of TC1 values */
+       t0 = t0/2;
+       
+       int overflow = 0;
+       while(!BUTTON_PRESS()) {
+               WDT_HIT();
+               if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+                       int ra = AT91C_BASE_TC1->TC_RA;
+                       if((ra > t0*HITAG_T_EOF) | overflow) ra = t0*HITAG_T_EOF+1;
+#if DEBUG_RA_VALUES
+                       if(ra > 255 || overflow) ra = 255;
+                       ((char*)BigBuf)[i] = ra;
+                       i = (i+1) % 8000;
+#endif
+                       
+                       if(overflow || (ra > t0*HITAG_T_EOF) || (ra < t0*HITAG_T_0_MIN)) {
+                               /* Ignore */
+                       } else if(ra >= t0*HITAG_T_1_MIN ) {
+                               /* '1' bit */
+                               if(frame_pos < 8*sizeof(frame)) {
+                                       frame[frame_pos / 8] |= 1<<( 7-(frame_pos%8) );
+                                       frame_pos++;
+                               }
+                       } else if(ra >= t0*HITAG_T_0_MIN) {
+                               /* '0' bit */
+                               if(frame_pos < 8*sizeof(frame)) {
+                                       frame[frame_pos / 8] |= 0<<( 7-(frame_pos%8) );
+                                       frame_pos++;
+                               }
+                       }
+                       
+                       overflow = 0;
+                       LED_D_ON();
+               } else {
+                       if(AT91C_BASE_TC1->TC_CV > t0*HITAG_T_EOF) {
+                               /* Minor nuisance: In Capture mode, the timer can not be
+                                * stopped by a Compare C. There's no way to stop the clock
+                                * in software, so we'll just have to note the fact that an
+                                * overflow happened and the next loaded timer value might
+                                * have wrapped. Also, this marks the end of frame, and the
+                                * still running counter can be used to determine the correct
+                                * time for the start of the reply.
+                                */ 
+                               overflow = 1;
+                               
+                               if(frame_pos > 0) {
+                                       /* Have a frame, do something with it */
+#if DEBUG_FRAME_CONTENTS
+                                       ((char*)BigBuf)[i++] = frame_pos;
+                                       memcpy( ((char*)BigBuf)+i, frame, 7);
+                                       i+=7;
+                                       i = i % sizeof(BigBuf);
+#endif
+                                       hitag_handle_frame(t0, frame_pos, frame);
+                                       memset(frame, 0, sizeof(frame));
+                               }
+                               frame_pos = 0;
+
+                       }
+                       LED_D_OFF();
+               }
+       }
+       DbpString("All done");
+}
+
+static void hitag_send_bit(int t0, int bit) {
+       if(bit == 1) {
+               /* Manchester: Loaded, then unloaded */
+               LED_A_ON();
+               SHORT_COIL();
+               while(AT91C_BASE_TC1->TC_CV < t0*15);
+               OPEN_COIL();
+               while(AT91C_BASE_TC1->TC_CV < t0*31);
+               LED_A_OFF();
+       } else if(bit == 0) {
+               /* Manchester: Unloaded, then loaded */
+               LED_B_ON();
+               OPEN_COIL();
+               while(AT91C_BASE_TC1->TC_CV < t0*15);
+               SHORT_COIL();
+               while(AT91C_BASE_TC1->TC_CV < t0*31);
+               LED_B_OFF();
+       }
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset clock for the next bit */
+       
+}
+static void hitag_send_frame(int t0, int frame_len, const char const * frame, int fdt)
+{
+       OPEN_COIL();
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       
+       /* Wait for HITAG_T_WRESP carrier periods after the last reader bit,
+        * not that since the clock counts since the rising edge, but T_wresp is
+        * with respect to the falling edge, we need to wait actually (T_wresp - T_g)
+        * periods. The gap time T_g varies (4..10).
+        */
+       while(AT91C_BASE_TC1->TC_CV < t0*(fdt-8));
+
+       int saved_cmr = AT91C_BASE_TC1->TC_CMR;
+       AT91C_BASE_TC1->TC_CMR &= ~AT91C_TC_ETRGEDG; /* Disable external trigger for the clock */
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset the clock and use it for response timing */
+       
+       int i;
+       for(i=0; i<5; i++)
+               hitag_send_bit(t0, 1); /* Start of frame */
+       
+       for(i=0; i<frame_len; i++) {
+               hitag_send_bit(t0, !!(frame[i/ 8] & (1<<( 7-(i%8) ))) );
+       }
+       
+       OPEN_COIL();
+       AT91C_BASE_TC1->TC_CMR = saved_cmr;
+}
+
+/* Callback structure to cleanly separate tag emulation code from the radio layer. */
+static int hitag_cb(const char* response_data, const int response_length, const int fdt, void *cb_cookie)
+{
+       hitag_send_frame(*(int*)cb_cookie, response_length, response_data, fdt);
+       return 0;
+}
+/* Frame length in bits, frame contents in MSBit first format */
+static void hitag_handle_frame(int t0, int frame_len, char *frame)
+{
+       hitag2_handle_command(frame, frame_len, hitag_cb, &t0);
+}
+
+// compose fc/8 fc/10 waveform
+static void fc(int c, int *n) {
+       BYTE *dest = (BYTE *)BigBuf;
+       int idx;
+
+       // for when we want an fc8 pattern every 4 logical bits
+       if(c==0) {
+               dest[((*n)++)]=1;
+               dest[((*n)++)]=1;
+               dest[((*n)++)]=0;
+               dest[((*n)++)]=0;
+               dest[((*n)++)]=0;
+               dest[((*n)++)]=0;
+               dest[((*n)++)]=0;
+               dest[((*n)++)]=0;
+       }
+       //      an fc/8  encoded bit is a bit pattern of  11000000  x6 = 48 samples
+       if(c==8) {
+               for (idx=0; idx<6; idx++) {
+                       dest[((*n)++)]=1;
+                       dest[((*n)++)]=1;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+               }
+       }
+
+       //      an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples
+       if(c==10) {
+               for (idx=0; idx<5; idx++) {
+                       dest[((*n)++)]=1;
+                       dest[((*n)++)]=1;
+                       dest[((*n)++)]=1;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+                       dest[((*n)++)]=0;
+               }
+       }
+}
+
+// prepare a waveform pattern in the buffer based on the ID given then
+// simulate a HID tag until the button is pressed
+void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
+{
+       int n=0, i=0;
+       /*
+        HID tag bitstream format
+        The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits
+        A 1 bit is represented as 6 fc8 and 5 fc10 patterns
+        A 0 bit is represented as 5 fc10 and 6 fc8 patterns
+        A fc8 is inserted before every 4 bits
+        A special start of frame pattern is used consisting a0b0 where a and b are neither 0
+        nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)
+       */
+
+       if (hi>0xFFF) {
+               DbpString("Tags can only have 44 bits.");
+               return;
+       }
+       fc(0,&n);
+       // special start of frame marker containing invalid bit sequences
+       fc(8,  &n);     fc(8,  &n);     // invalid
+       fc(8,  &n);     fc(10, &n); // logical 0
+       fc(10, &n);     fc(10, &n); // invalid
+       fc(8,  &n);     fc(10, &n); // logical 0
+
+       WDT_HIT();
+       // manchester encode bits 43 to 32
+       for (i=11; i>=0; i--) {
+               if ((i%4)==3) fc(0,&n);
+               if ((hi>>i)&1) {
+                       fc(10, &n);     fc(8,  &n);             // low-high transition
+               } else {
+                       fc(8,  &n);     fc(10, &n);             // high-low transition
+               }
+       }
+
+       WDT_HIT();
+       // manchester encode bits 31 to 0
+       for (i=31; i>=0; i--) {
+               if ((i%4)==3) fc(0,&n);
+               if ((lo>>i)&1) {
+                       fc(10, &n);     fc(8,  &n);             // low-high transition
+               } else {
+                       fc(8,  &n);     fc(10, &n);             // high-low transition
+               }
+       }
+
+       if (ledcontrol)
+               LED_A_ON();
+       SimulateTagLowFrequency(n, 0, ledcontrol);
+
+       if (ledcontrol)
+               LED_A_OFF();
+}
+
+
+// loop to capture raw HID waveform then FSK demodulate the TAG ID from it
+void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
+{
+       BYTE *dest = (BYTE *)BigBuf;
+       int m=0, n=0, i=0, idx=0, found=0, lastval=0;
+       DWORD hi=0, lo=0;
+
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
+
+       // Connect the A/D to the peak-detected low-frequency path.
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+
+       // Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(50);
+
+       // Now set up the SSC to get the ADC samples that are now streaming at us.
+       FpgaSetupSsc();
+
+       for(;;) {
+               WDT_HIT();
+               if (ledcontrol)
+                       LED_A_ON();
+               if(BUTTON_PRESS()) {
+                       DbpString("Stopped");
+                       if (ledcontrol)
+                               LED_A_OFF();
+                       return;
+               }
+
+               i = 0;
+               m = sizeof(BigBuf);
+               memset(dest,128,m);
+               for(;;) {
+                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                               AT91C_BASE_SSC->SSC_THR = 0x43;
+                               if (ledcontrol)
+                                       LED_D_ON();
+                       }
+                       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                               dest[i] = (BYTE)AT91C_BASE_SSC->SSC_RHR;
+                               // we don't care about actual value, only if it's more or less than a
+                               // threshold essentially we capture zero crossings for later analysis
+                               if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
+                               i++;
+                               if (ledcontrol)
+                                       LED_D_OFF();
+                               if(i >= m) {
+                                       break;
+                               }
+                       }
+               }
+
+               // FSK demodulator
+
+               // sync to first lo-hi transition
+               for( idx=1; idx<m; idx++) {
+                       if (dest[idx-1]<dest[idx])
+                               lastval=idx;
+                               break;
+               }
+               WDT_HIT();
+
+               // count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
+               // or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
+               // between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
+               for( i=0; idx<m; idx++) {
+                       if (dest[idx-1]<dest[idx]) {
+                               dest[i]=idx-lastval;
+                               if (dest[i] <= 8) {
+                                               dest[i]=1;
+                               } else {
+                                               dest[i]=0;
+                               }
+
+                               lastval=idx;
+                               i++;
+                       }
+               }
+               m=i;
+               WDT_HIT();
+
+               // we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
+               lastval=dest[0];
+               idx=0;
+               i=0;
+               n=0;
+               for( idx=0; idx<m; idx++) {
+                       if (dest[idx]==lastval) {
+                               n++;
+                       } else {
+                               // a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
+                               // an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
+                               // swallowed up by rounding
+                               // expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
+                               // special start of frame markers use invalid manchester states (no transitions) by using sequences
+                               // like 111000
+                               if (dest[idx-1]) {
+                                       n=(n+1)/6;                      // fc/8 in sets of 6
+                               } else {
+                                       n=(n+1)/5;                      // fc/10 in sets of 5
+                               }
+                               switch (n) {                    // stuff appropriate bits in buffer
+                                       case 0:
+                                       case 1: // one bit
+                                               dest[i++]=dest[idx-1];
+                                               break;
+                                       case 2: // two bits
+                                               dest[i++]=dest[idx-1];
+                                               dest[i++]=dest[idx-1];
+                                               break;
+                                       case 3: // 3 bit start of frame markers
+                                               dest[i++]=dest[idx-1];
+                                               dest[i++]=dest[idx-1];
+                                               dest[i++]=dest[idx-1];
+                                               break;
+                                       // When a logic 0 is immediately followed by the start of the next transmisson
+                                       // (special pattern) a pattern of 4 bit duration lengths is created.
+                                       case 4:
+                                               dest[i++]=dest[idx-1];
+                                               dest[i++]=dest[idx-1];
+                                               dest[i++]=dest[idx-1];
+                                               dest[i++]=dest[idx-1];
+                                               break;
+                                       default:        // this shouldn't happen, don't stuff any bits
+                                               break;
+                               }
+                               n=0;
+                               lastval=dest[idx];
+                       }
+               }
+               m=i;
+               WDT_HIT();
+
+               // final loop, go over previously decoded manchester data and decode into usable tag ID
+               // 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
+               for( idx=0; idx<m-6; idx++) {
+                       // search for a start of frame marker
+                       if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
+                       {
+                               found=1;
+                               idx+=6;
+                               if (found && (hi|lo)) {
+                                       Dbprintf("TAG ID: %x%08x (%d)",
+                                               (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
+                                       /* if we're only looking for one tag */
+                                       if (findone)
+                                       {
+                                               *high = hi;
+                                               *low = lo;
+                                               return;
+                                       }
+                                       hi=0;
+                                       lo=0;
+                                       found=0;
+                               }
+                       }
+                       if (found) {
+                               if (dest[idx] && (!dest[idx+1]) ) {
+                                       hi=(hi<<1)|(lo>>31);
+                                       lo=(lo<<1)|0;
+                               } else if ( (!dest[idx]) && dest[idx+1]) {
+                                       hi=(hi<<1)|(lo>>31);
+                                       lo=(lo<<1)|1;
+                               } else {
+                                       found=0;
+                                       hi=0;
+                                       lo=0;
+                               }
+                               idx++;
+                       }
+                       if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
+                       {
+                               found=1;
+                               idx+=6;
+                               if (found && (hi|lo)) {
+                                       Dbprintf("TAG ID: %x%08x (%d)",
+                                               (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
+                                       /* if we're only looking for one tag */
+                                       if (findone)
+                                       {
+                                               *high = hi;
+                                               *low = lo;
+                                               return;
+                                       }
+                                       hi=0;
+                                       lo=0;
+                                       found=0;
+                               }
+                       }
+               }
+               WDT_HIT();
+       }
+}
index cae1a079a84706bd2bcb31f458f17fdc94eb5fe0..f6b16ba3b771b990a10ca9fd3c72f0619bdbdcb3 100644 (file)
@@ -1,39 +1,39 @@
-# Makefile for bootrom, see ../common/Makefile.common for common settings\r
-\r
-# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code\r
-ARMSRC = fromflash.c \r
-THUMBSRC = usb.c bootrom.c\r
-ASMSRC = ram-reset.s flash-reset.s\r
-\r
-## There is a strange bug with the linker: Sometimes it will not emit the glue to call\r
-## BootROM from ARM mode. The symbol is emitted, but the section will be filled with\r
-## zeroes. As a temporary workaround, do not use thumb for the phase 2 bootloader\r
-## -- Henryk Plötz <henryk@ploetzli.ch> 2009-09-01\r
-ARMSRC := $(ARMSRC) $(THUMBSRC)\r
-THUMBSRC := \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)/bootrom.s19\r
-\r
-$(OBJDIR)/bootrom.elf: $(VERSIONOBJ) $(ASMOBJ) $(ARMOBJ) $(THUMBOBJ)\r
-       $(LD) -g -Tldscript-flash --oformat elf32-littlearm -Map=$(patsubst %.elf,%.map,$@) -o $@ $^\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 $(OBJDIR)/bootrom.s19, the main bootrom\r
-       @echo + clean - Clean $(OBJDIR)\r
+# Makefile for bootrom, see ../common/Makefile.common for common settings
+
+# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code
+ARMSRC = fromflash.c 
+THUMBSRC = usb.c bootrom.c
+ASMSRC = ram-reset.s flash-reset.s
+
+## There is a strange bug with the linker: Sometimes it will not emit the glue to call
+## BootROM from ARM mode. The symbol is emitted, but the section will be filled with
+## zeroes. As a temporary workaround, do not use thumb for the phase 2 bootloader
+## -- Henryk Plötz <henryk@ploetzli.ch> 2009-09-01
+ARMSRC := $(ARMSRC) $(THUMBSRC)
+THUMBSRC := 
+
+# 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)/bootrom.s19
+
+$(OBJDIR)/bootrom.elf: $(VERSIONOBJ) $(ASMOBJ) $(ARMOBJ) $(THUMBOBJ)
+       $(LD) -g -Tldscript-flash --oformat elf32-littlearm -Map=$(patsubst %.elf,%.map,$@) -o $@ $^
+
+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 $(OBJDIR)/bootrom.s19, the main bootrom
+       @echo + clean - Clean $(OBJDIR)
index c0522dfad66bd89023a4256ca3cfe4a100df659a..e46297f91a426e55db037ab5742c9a3aecb01c84 100644 (file)
-#include <proxmark3.h>\r
-\r
-struct common_area common_area __attribute__((section(".commonarea")));\r
-unsigned int start_addr, end_addr, bootrom_unlocked;\r
-extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end;\r
-\r
-static void ConfigClocks(void)\r
-{\r
-    // we are using a 16 MHz crystal as the basis for everything\r
-    // slow clock runs at 32Khz typical regardless of crystal\r
-\r
-    // enable system clock and USB clock\r
-    AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK | AT91C_PMC_UDP;\r
-\r
-       // enable the clock to the following peripherals\r
-    AT91C_BASE_PMC->PMC_PCER =\r
-               (1<<AT91C_ID_PIOA)      |\r
-               (1<<AT91C_ID_ADC)       |\r
-               (1<<AT91C_ID_SPI)       |\r
-               (1<<AT91C_ID_SSC)       |\r
-               (1<<AT91C_ID_PWMC)      |\r
-               (1<<AT91C_ID_UDP);\r
-\r
-       // worst case scenario, with 16Mhz xtal startup delay is 14.5ms\r
-       // with a slow clock running at it worst case (max) frequency of 42khz\r
-       // max startup delay = (14.5ms*42k)/8 = 76 = 0x4C round up to 0x50\r
-\r
-       // enable main oscillator and set startup delay\r
-    AT91C_BASE_PMC->PMC_MOR =\r
-       PMC_MAIN_OSC_ENABLE |\r
-        PMC_MAIN_OSC_STARTUP_DELAY(0x50);\r
-\r
-       // wait for main oscillator to stabilize\r
-       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_STABILIZED) )\r
-               ;\r
-\r
-    // minimum PLL clock frequency is 80 MHz in range 00 (96 here so okay)\r
-    // frequency is crystal * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz\r
-    AT91C_BASE_PMC->PMC_PLLR =\r
-       PMC_PLL_DIVISOR(2) |\r
-               PMC_PLL_COUNT_BEFORE_LOCK(0x50) |\r
-               PMC_PLL_FREQUENCY_RANGE(0) |\r
-               PMC_PLL_MULTIPLIER(12) |\r
-               PMC_PLL_USB_DIVISOR(1);\r
-\r
-       // wait for PLL to lock\r
-       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_PLL_LOCK) )\r
-               ;\r
-\r
-       // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz\r
-       // as per datasheet, this register must be programmed in two operations\r
-       // when changing to PLL, program the prescaler first then the source\r
-    AT91C_BASE_PMC->PMC_MCKR = PMC_CLK_PRESCALE_DIV_2;\r
-\r
-       // wait for main clock ready signal\r
-       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_MCK_READY) )\r
-               ;\r
-\r
-       // set the source to PLL\r
-    AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | PMC_CLK_PRESCALE_DIV_2;\r
-\r
-       // wait for main clock ready signal\r
-       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_MCK_READY) )\r
-               ;\r
-}\r
-\r
-static void Fatal(void)\r
-{\r
-    for(;;);\r
-}\r
-\r
-void UsbPacketReceived(BYTE *packet, int len)\r
-{\r
-    int i, dont_ack=0;\r
-    UsbCommand *c = (UsbCommand *)packet;\r
-    volatile DWORD *p;\r
-\r
-    if(len != sizeof(*c)) {\r
-        Fatal();\r
-    }\r
-\r
-    switch(c->cmd) {\r
-        case CMD_DEVICE_INFO:\r
-            dont_ack = 1;\r
-            c->cmd = CMD_DEVICE_INFO;\r
-            c->arg[0] = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |\r
-                DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;\r
-            if(common_area.flags.osimage_present) c->arg[0] |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;\r
-            UsbSendPacket(packet, len);\r
-            break;\r
-\r
-        case CMD_SETUP_WRITE:\r
-            /* The temporary write buffer of the embedded flash controller is mapped to the\r
-             * whole memory region, only the last 8 bits are decoded.\r
-             */\r
-            p = (volatile DWORD *)&_flash_start;\r
-            for(i = 0; i < 12; i++) {\r
-                p[i+c->arg[0]] = c->d.asDwords[i];\r
-            }\r
-            break;\r
-\r
-        case CMD_FINISH_WRITE:\r
-            p = (volatile DWORD *)&_flash_start;\r
-            for(i = 0; i < 4; i++) {\r
-                p[i+60] = c->d.asDwords[i];\r
-            }\r
-\r
-            /* Check that the address that we are supposed to write to is within our allowed region */\r
-            if( ((c->arg[0]+AT91C_IFLASH_PAGE_SIZE-1) >= end_addr) || (c->arg[0] < start_addr) ) {\r
-                /* Disallow write */\r
-                dont_ack = 1;\r
-                c->cmd = CMD_NACK;\r
-                UsbSendPacket(packet, len);\r
-            } else {\r
-                /* Translate address to flash page and do flash, update here for the 512k part */\r
-                AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY |\r
-                    MC_FLASH_COMMAND_PAGEN((c->arg[0]-(int)&_flash_start)/AT91C_IFLASH_PAGE_SIZE) |\r
-                    AT91C_MC_FCMD_START_PROG;\r
-            }\r
-            \r
-            uint32_t sr;\r
-            \r
-            while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & MC_FLASH_STATUS_READY))\r
-                ;\r
-            if(sr & (MC_FLASH_STATUS_LOCKE | MC_FLASH_STATUS_PROGE)) { \r
-                   dont_ack = 1;\r
-                    c->cmd = CMD_NACK;\r
-                    UsbSendPacket(packet, len);\r
-            }\r
-            break;\r
-\r
-        case CMD_HARDWARE_RESET:\r
-            USB_D_PLUS_PULLUP_OFF();\r
-            AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
-            break;\r
-\r
-        case CMD_START_FLASH:\r
-            if(c->arg[2] == START_FLASH_MAGIC) bootrom_unlocked = 1;\r
-            else bootrom_unlocked = 0;\r
-            {\r
-                int prot_start = (int)&_bootrom_start;\r
-                int prot_end = (int)&_bootrom_end;\r
-                int allow_start = (int)&_flash_start;\r
-                int allow_end = (int)&_flash_end;\r
-                int cmd_start = c->arg[0];\r
-                int cmd_end = c->arg[1];\r
-\r
-                /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected\r
-                 * bootrom area. In any case they must be within the flash area.\r
-                 */\r
-                if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start)))\r
-                    && (cmd_start >= allow_start) && (cmd_end <= allow_end) ) {\r
-                    start_addr = cmd_start;\r
-                    end_addr = cmd_end;\r
-                } else {\r
-                    start_addr = end_addr = 0;\r
-                    dont_ack = 1;\r
-                    c->cmd = CMD_NACK;\r
-                    UsbSendPacket(packet, len);\r
-                }\r
-            }\r
-            break;\r
-\r
-        default:\r
-            Fatal();\r
-            break;\r
-    }\r
-\r
-    if(!dont_ack) {\r
-        c->cmd = CMD_ACK;\r
-        UsbSendPacket(packet, len);\r
-    }\r
-}\r
-\r
-static void flash_mode(int externally_entered)\r
-{\r
-       start_addr = 0;\r
-       end_addr = 0;\r
-       bootrom_unlocked = 0;\r
-\r
-       UsbStart();\r
-       for(;;) {\r
-               WDT_HIT();\r
-\r
-               UsbPoll(TRUE);\r
-\r
-               if(!externally_entered && !BUTTON_PRESS()) {\r
-                       /* Perform a reset to leave flash mode */\r
-                       USB_D_PLUS_PULLUP_OFF();\r
-                       LED_B_ON();\r
-                       AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;\r
-                       for(;;);\r
-               }\r
-               if(externally_entered && BUTTON_PRESS()) {\r
-                       /* Let the user's button press override the automatic leave */\r
-                       externally_entered = 0;\r
-               }\r
-       }\r
-}\r
-\r
-extern char _osimage_entry;\r
-void BootROM(void)\r
-{\r
-    //------------\r
-    // First set up all the I/O pins; GPIOs configured directly, other ones\r
-    // just need to be assigned to the appropriate peripheral.\r
-\r
-    // Kill all the pullups, especially the one on USB D+; leave them for\r
-    // the unused pins, though.\r
-    AT91C_BASE_PIOA->PIO_PPUDR =\r
-       GPIO_USB_PU                     |\r
-               GPIO_LED_A                      |\r
-               GPIO_LED_B                      |\r
-               GPIO_LED_C                      |\r
-               GPIO_LED_D                      |\r
-               GPIO_FPGA_DIN           |\r
-               GPIO_FPGA_DOUT          |\r
-               GPIO_FPGA_CCLK          |\r
-               GPIO_FPGA_NINIT         |\r
-               GPIO_FPGA_NPROGRAM      |\r
-               GPIO_FPGA_DONE          |\r
-               GPIO_MUXSEL_HIPKD       |\r
-               GPIO_MUXSEL_HIRAW       |\r
-               GPIO_MUXSEL_LOPKD       |\r
-               GPIO_MUXSEL_LORAW       |\r
-               GPIO_RELAY                      |\r
-               GPIO_NVDD_ON;\r
-               // (and add GPIO_FPGA_ON)\r
-       // These pins are outputs\r
-    AT91C_BASE_PIOA->PIO_OER =\r
-       GPIO_LED_A                      |\r
-               GPIO_LED_B                      |\r
-               GPIO_LED_C                      |\r
-               GPIO_LED_D                      |\r
-               GPIO_RELAY                      |\r
-               GPIO_NVDD_ON;\r
-       // PIO controls the following pins\r
-    AT91C_BASE_PIOA->PIO_PER =\r
-       GPIO_USB_PU                     |\r
-               GPIO_LED_A                      |\r
-               GPIO_LED_B                      |\r
-               GPIO_LED_C                      |\r
-               GPIO_LED_D;\r
-\r
-    USB_D_PLUS_PULLUP_OFF();\r
-    LED_D_OFF();\r
-    LED_C_ON();\r
-    LED_B_OFF();\r
-    LED_A_OFF();\r
-\r
-    // if 512K FLASH part - TODO make some defines :)\r
-    if ((AT91C_BASE_DBGU->DBGU_CIDR | 0xf00) == 0xa00) {\r
-           AT91C_BASE_EFC0->EFC_FMR =\r
-               MC_FLASH_MODE_FLASH_WAIT_STATES(1) |\r
-                       MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);\r
-           AT91C_BASE_EFC1->EFC_FMR =\r
-               MC_FLASH_MODE_FLASH_WAIT_STATES(1) |\r
-                       MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);\r
-    } else {\r
-           AT91C_BASE_EFC0->EFC_FMR =\r
-               MC_FLASH_MODE_FLASH_WAIT_STATES(0) |\r
-                       MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);\r
-    }\r
-\r
-    // Initialize all system clocks\r
-    ConfigClocks();\r
-\r
-    LED_A_ON();\r
-\r
-    int common_area_present = 0;\r
-    switch(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_RSTTYP) {\r
-    case AT91C_RSTC_RSTTYP_WATCHDOG:\r
-    case AT91C_RSTC_RSTTYP_SOFTWARE:\r
-    case AT91C_RSTC_RSTTYP_USER:\r
-           /* In these cases the common_area in RAM should be ok, retain it if it's there */\r
-           if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1) {\r
-                   common_area_present = 1;\r
-           }\r
-           break;\r
-    default: /* Otherwise, initialize it from scratch */\r
-           break;\r
-    }\r
-\r
-    if(!common_area_present){\r
-           /* Common area not ok, initialize it */\r
-           int i; for(i=0; i<sizeof(common_area); i++) { /* Makeshift memset, no need to drag util.c into this */\r
-                   ((char*)&common_area)[i] = 0;\r
-           }\r
-           common_area.magic = COMMON_AREA_MAGIC;\r
-           common_area.version = 1;\r
-           common_area.flags.bootrom_present = 1;\r
-    }\r
-\r
-    common_area.flags.bootrom_present = 1;\r
-    if(common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) {\r
-           common_area.command = COMMON_AREA_COMMAND_NONE;\r
-           flash_mode(1);\r
-    } else if(BUTTON_PRESS()) {\r
-           flash_mode(0);\r
-    } else if(*(uint32_t*)&_osimage_entry == 0xffffffffU) {\r
-           flash_mode(1);\r
-    } else {\r
-           // jump to Flash address of the osimage entry point (LSBit set for thumb mode)\r
-           asm("bx %0\n" : : "r" ( ((int)&_osimage_entry) | 0x1 ) );\r
-    }\r
-}\r
+#include <proxmark3.h>
+
+struct common_area common_area __attribute__((section(".commonarea")));
+unsigned int start_addr, end_addr, bootrom_unlocked;
+extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end;
+
+static void ConfigClocks(void)
+{
+    // we are using a 16 MHz crystal as the basis for everything
+    // slow clock runs at 32Khz typical regardless of crystal
+
+    // enable system clock and USB clock
+    AT91C_BASE_PMC->PMC_SCER = AT91C_PMC_PCK | AT91C_PMC_UDP;
+
+       // enable the clock to the following peripherals
+    AT91C_BASE_PMC->PMC_PCER =
+               (1<<AT91C_ID_PIOA)      |
+               (1<<AT91C_ID_ADC)       |
+               (1<<AT91C_ID_SPI)       |
+               (1<<AT91C_ID_SSC)       |
+               (1<<AT91C_ID_PWMC)      |
+               (1<<AT91C_ID_UDP);
+
+       // worst case scenario, with 16Mhz xtal startup delay is 14.5ms
+       // with a slow clock running at it worst case (max) frequency of 42khz
+       // max startup delay = (14.5ms*42k)/8 = 76 = 0x4C round up to 0x50
+
+       // enable main oscillator and set startup delay
+    AT91C_BASE_PMC->PMC_MOR =
+       PMC_MAIN_OSC_ENABLE |
+        PMC_MAIN_OSC_STARTUP_DELAY(0x50);
+
+       // wait for main oscillator to stabilize
+       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_STABILIZED) )
+               ;
+
+    // minimum PLL clock frequency is 80 MHz in range 00 (96 here so okay)
+    // frequency is crystal * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz
+    AT91C_BASE_PMC->PMC_PLLR =
+       PMC_PLL_DIVISOR(2) |
+               PMC_PLL_COUNT_BEFORE_LOCK(0x50) |
+               PMC_PLL_FREQUENCY_RANGE(0) |
+               PMC_PLL_MULTIPLIER(12) |
+               PMC_PLL_USB_DIVISOR(1);
+
+       // wait for PLL to lock
+       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_PLL_LOCK) )
+               ;
+
+       // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz
+       // as per datasheet, this register must be programmed in two operations
+       // when changing to PLL, program the prescaler first then the source
+    AT91C_BASE_PMC->PMC_MCKR = PMC_CLK_PRESCALE_DIV_2;
+
+       // wait for main clock ready signal
+       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_MCK_READY) )
+               ;
+
+       // set the source to PLL
+    AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_PLL_CLK | PMC_CLK_PRESCALE_DIV_2;
+
+       // wait for main clock ready signal
+       while ( !(AT91C_BASE_PMC->PMC_SR & PMC_MAIN_OSC_MCK_READY) )
+               ;
+}
+
+static void Fatal(void)
+{
+    for(;;);
+}
+
+void UsbPacketReceived(BYTE *packet, int len)
+{
+    int i, dont_ack=0;
+    UsbCommand *c = (UsbCommand *)packet;
+    volatile DWORD *p;
+
+    if(len != sizeof(*c)) {
+        Fatal();
+    }
+
+    switch(c->cmd) {
+        case CMD_DEVICE_INFO:
+            dont_ack = 1;
+            c->cmd = CMD_DEVICE_INFO;
+            c->arg[0] = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
+                DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;
+            if(common_area.flags.osimage_present) c->arg[0] |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
+            UsbSendPacket(packet, len);
+            break;
+
+        case CMD_SETUP_WRITE:
+            /* The temporary write buffer of the embedded flash controller is mapped to the
+             * whole memory region, only the last 8 bits are decoded.
+             */
+            p = (volatile DWORD *)&_flash_start;
+            for(i = 0; i < 12; i++) {
+                p[i+c->arg[0]] = c->d.asDwords[i];
+            }
+            break;
+
+        case CMD_FINISH_WRITE:
+            p = (volatile DWORD *)&_flash_start;
+            for(i = 0; i < 4; i++) {
+                p[i+60] = c->d.asDwords[i];
+            }
+
+            /* Check that the address that we are supposed to write to is within our allowed region */
+            if( ((c->arg[0]+AT91C_IFLASH_PAGE_SIZE-1) >= end_addr) || (c->arg[0] < start_addr) ) {
+                /* Disallow write */
+                dont_ack = 1;
+                c->cmd = CMD_NACK;
+                UsbSendPacket(packet, len);
+            } else {
+                /* Translate address to flash page and do flash, update here for the 512k part */
+                AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY |
+                    MC_FLASH_COMMAND_PAGEN((c->arg[0]-(int)&_flash_start)/AT91C_IFLASH_PAGE_SIZE) |
+                    AT91C_MC_FCMD_START_PROG;
+            }
+            
+            uint32_t sr;
+            
+            while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & MC_FLASH_STATUS_READY))
+                ;
+            if(sr & (MC_FLASH_STATUS_LOCKE | MC_FLASH_STATUS_PROGE)) { 
+                   dont_ack = 1;
+                    c->cmd = CMD_NACK;
+                    UsbSendPacket(packet, len);
+            }
+            break;
+
+        case CMD_HARDWARE_RESET:
+            USB_D_PLUS_PULLUP_OFF();
+            AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
+            break;
+
+        case CMD_START_FLASH:
+            if(c->arg[2] == START_FLASH_MAGIC) bootrom_unlocked = 1;
+            else bootrom_unlocked = 0;
+            {
+                int prot_start = (int)&_bootrom_start;
+                int prot_end = (int)&_bootrom_end;
+                int allow_start = (int)&_flash_start;
+                int allow_end = (int)&_flash_end;
+                int cmd_start = c->arg[0];
+                int cmd_end = c->arg[1];
+
+                /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected
+                 * bootrom area. In any case they must be within the flash area.
+                 */
+                if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start)))
+                    && (cmd_start >= allow_start) && (cmd_end <= allow_end) ) {
+                    start_addr = cmd_start;
+                    end_addr = cmd_end;
+                } else {
+                    start_addr = end_addr = 0;
+                    dont_ack = 1;
+                    c->cmd = CMD_NACK;
+                    UsbSendPacket(packet, len);
+                }
+            }
+            break;
+
+        default:
+            Fatal();
+            break;
+    }
+
+    if(!dont_ack) {
+        c->cmd = CMD_ACK;
+        UsbSendPacket(packet, len);
+    }
+}
+
+static void flash_mode(int externally_entered)
+{
+       start_addr = 0;
+       end_addr = 0;
+       bootrom_unlocked = 0;
+
+       UsbStart();
+       for(;;) {
+               WDT_HIT();
+
+               UsbPoll(TRUE);
+
+               if(!externally_entered && !BUTTON_PRESS()) {
+                       /* Perform a reset to leave flash mode */
+                       USB_D_PLUS_PULLUP_OFF();
+                       LED_B_ON();
+                       AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
+                       for(;;);
+               }
+               if(externally_entered && BUTTON_PRESS()) {
+                       /* Let the user's button press override the automatic leave */
+                       externally_entered = 0;
+               }
+       }
+}
+
+extern char _osimage_entry;
+void BootROM(void)
+{
+    //------------
+    // First set up all the I/O pins; GPIOs configured directly, other ones
+    // just need to be assigned to the appropriate peripheral.
+
+    // Kill all the pullups, especially the one on USB D+; leave them for
+    // the unused pins, though.
+    AT91C_BASE_PIOA->PIO_PPUDR =
+       GPIO_USB_PU                     |
+               GPIO_LED_A                      |
+               GPIO_LED_B                      |
+               GPIO_LED_C                      |
+               GPIO_LED_D                      |
+               GPIO_FPGA_DIN           |
+               GPIO_FPGA_DOUT          |
+               GPIO_FPGA_CCLK          |
+               GPIO_FPGA_NINIT         |
+               GPIO_FPGA_NPROGRAM      |
+               GPIO_FPGA_DONE          |
+               GPIO_MUXSEL_HIPKD       |
+               GPIO_MUXSEL_HIRAW       |
+               GPIO_MUXSEL_LOPKD       |
+               GPIO_MUXSEL_LORAW       |
+               GPIO_RELAY                      |
+               GPIO_NVDD_ON;
+               // (and add GPIO_FPGA_ON)
+       // These pins are outputs
+    AT91C_BASE_PIOA->PIO_OER =
+       GPIO_LED_A                      |
+               GPIO_LED_B                      |
+               GPIO_LED_C                      |
+               GPIO_LED_D                      |
+               GPIO_RELAY                      |
+               GPIO_NVDD_ON;
+       // PIO controls the following pins
+    AT91C_BASE_PIOA->PIO_PER =
+       GPIO_USB_PU                     |
+               GPIO_LED_A                      |
+               GPIO_LED_B                      |
+               GPIO_LED_C                      |
+               GPIO_LED_D;
+
+    USB_D_PLUS_PULLUP_OFF();
+    LED_D_OFF();
+    LED_C_ON();
+    LED_B_OFF();
+    LED_A_OFF();
+
+    // if 512K FLASH part - TODO make some defines :)
+    if ((AT91C_BASE_DBGU->DBGU_CIDR | 0xf00) == 0xa00) {
+           AT91C_BASE_EFC0->EFC_FMR =
+               MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
+                       MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
+           AT91C_BASE_EFC1->EFC_FMR =
+               MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
+                       MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
+    } else {
+           AT91C_BASE_EFC0->EFC_FMR =
+               MC_FLASH_MODE_FLASH_WAIT_STATES(0) |
+                       MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
+    }
+
+    // Initialize all system clocks
+    ConfigClocks();
+
+    LED_A_ON();
+
+    int common_area_present = 0;
+    switch(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_RSTTYP) {
+    case AT91C_RSTC_RSTTYP_WATCHDOG:
+    case AT91C_RSTC_RSTTYP_SOFTWARE:
+    case AT91C_RSTC_RSTTYP_USER:
+           /* In these cases the common_area in RAM should be ok, retain it if it's there */
+           if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1) {
+                   common_area_present = 1;
+           }
+           break;
+    default: /* Otherwise, initialize it from scratch */
+           break;
+    }
+
+    if(!common_area_present){
+           /* Common area not ok, initialize it */
+           int i; for(i=0; i<sizeof(common_area); i++) { /* Makeshift memset, no need to drag util.c into this */
+                   ((char*)&common_area)[i] = 0;
+           }
+           common_area.magic = COMMON_AREA_MAGIC;
+           common_area.version = 1;
+           common_area.flags.bootrom_present = 1;
+    }
+
+    common_area.flags.bootrom_present = 1;
+    if(common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) {
+           common_area.command = COMMON_AREA_COMMAND_NONE;
+           flash_mode(1);
+    } else if(BUTTON_PRESS()) {
+           flash_mode(0);
+    } else if(*(uint32_t*)&_osimage_entry == 0xffffffffU) {
+           flash_mode(1);
+    } else {
+           // jump to Flash address of the osimage entry point (LSBit set for thumb mode)
+           asm("bx %0\n" : : "r" ( ((int)&_osimage_entry) | 0x1 ) );
+    }
+}
index 64134033c630c4b8ac1414f2a555a7d5efd76e26..a94d048aed47ec961b48e2d6729ebee2fc11c424 100644 (file)
@@ -1,43 +1,43 @@
-.extern CopyBootToRAM\r
-    \r
-.section .startup,"ax"\r
-         .code 32\r
-         .align 0\r
-\r
-.global flashstart\r
-flashstart:\r
-    b       Reset\r
-    b       UndefinedInstruction\r
-    b       SoftwareInterrupt\r
-    b       PrefetchAbort\r
-    b       DataAbort\r
-    b       Reserved\r
-    b       Irq\r
-    b       Fiq\r
-\r
-Reset:\r
-    ldr     sp,     .stack_end @ initialize stack pointer to top of RAM\r
-    bl      CopyBootToRAM                      @ copy bootloader to RAM (in case the\r
-                                                               @ user re-flashes the bootloader)\r
-    ldr     r3,     .bootphase2_start  @ start address of RAM bootloader\r
-    bx      r3                                         @ jump to it\r
-\r
-       .stack_end:\r
-       .word _stack_end\r
-       .bootphase2_start:\r
-       .word __bootphase2_start__\r
-\r
-Fiq:\r
-    b       Fiq\r
-UndefinedInstruction:\r
-    b       UndefinedInstruction\r
-SoftwareInterrupt:\r
-    b       SoftwareInterrupt\r
-PrefetchAbort:\r
-    b       PrefetchAbort\r
-DataAbort:\r
-    b       DataAbort\r
-Reserved:\r
-    b       Reserved\r
-Irq:\r
-    b       Irq\r
+.extern CopyBootToRAM
+    
+.section .startup,"ax"
+         .code 32
+         .align 0
+
+.global flashstart
+flashstart:
+    b       Reset
+    b       UndefinedInstruction
+    b       SoftwareInterrupt
+    b       PrefetchAbort
+    b       DataAbort
+    b       Reserved
+    b       Irq
+    b       Fiq
+
+Reset:
+    ldr     sp,     .stack_end @ initialize stack pointer to top of RAM
+    bl      CopyBootToRAM                      @ copy bootloader to RAM (in case the
+                                                               @ user re-flashes the bootloader)
+    ldr     r3,     .bootphase2_start  @ start address of RAM bootloader
+    bx      r3                                         @ jump to it
+
+       .stack_end:
+       .word _stack_end
+       .bootphase2_start:
+       .word __bootphase2_start__
+
+Fiq:
+    b       Fiq
+UndefinedInstruction:
+    b       UndefinedInstruction
+SoftwareInterrupt:
+    b       SoftwareInterrupt
+PrefetchAbort:
+    b       PrefetchAbort
+DataAbort:
+    b       DataAbort
+Reserved:
+    b       Reserved
+Irq:
+    b       Irq
index 6b41c408c3a6968711675ac0a343100a578f5f2e..80403e5f7cdf8ab130a099a9aca5df080604115d 100644 (file)
@@ -1,13 +1,13 @@
-#include <proxmark3.h>\r
-\r
-extern char __bootphase2_src_start__, __bootphase2_start__, __bootphase2_end__;\r
-void __attribute__((section(".bootphase1"))) CopyBootToRAM(void)\r
-{\r
-       int i;\r
-\r
-       volatile DWORD *s = (volatile DWORD *)&__bootphase2_src_start__;\r
-       volatile DWORD *d = (volatile DWORD *)&__bootphase2_start__;\r
-       unsigned int l = (int)&__bootphase2_end__ - (int)&__bootphase2_start__;\r
-\r
-       for(i = 0; i < l/sizeof(DWORD); i++) *d++ = *s++;\r
-}\r
+#include <proxmark3.h>
+
+extern char __bootphase2_src_start__, __bootphase2_start__, __bootphase2_end__;
+void __attribute__((section(".bootphase1"))) CopyBootToRAM(void)
+{
+       int i;
+
+       volatile DWORD *s = (volatile DWORD *)&__bootphase2_src_start__;
+       volatile DWORD *d = (volatile DWORD *)&__bootphase2_start__;
+       unsigned int l = (int)&__bootphase2_end__ - (int)&__bootphase2_start__;
+
+       for(i = 0; i < l/sizeof(DWORD); i++) *d++ = *s++;
+}
index ccc0db2ffef2e297f6faeda354d7bca7af52b9b4..0c637113572ea2e6a0d2bc54b1e64b036c37f6f1 100644 (file)
@@ -1,53 +1,53 @@
-INCLUDE ../common/ldscript.common\r
-\r
-ENTRY(flashstart)\r
-SECTIONS\r
-{\r
-    . = 0;\r
-    \r
-    .bootphase1 : {\r
-       *(.startup) \r
-       *(.bootphase1)\r
-       \r
-       /* It seems to be impossible to flush align a section at the\r
-          end of a memory segment. Instead, we'll put the version_information\r
-          wherever the linker wants it, and then put a pointer to the start\r
-          of the version information at the end of the section.\r
-          -- Henryk Plötz <henryk@ploetzli.ch> 2009-08-28 */\r
-          \r
-       _version_information_start = ABSOLUTE(.);\r
-       *(.version_information);\r
-       \r
-       /* Why doesn't this work even though _bootphase1_version_pointer = 0x1001fc?\r
-         . = _bootphase1_version_pointer - ORIGIN(bootphase1); */\r
-       /* This works, apparently it fools the linker into accepting an absolute address */\r
-       . = _bootphase1_version_pointer - ORIGIN(bootphase1) + ORIGIN(bootphase1);\r
-       LONG(_version_information_start)\r
-    } >bootphase1\r
-    \r
-    __bootphase2_src_start__ = ORIGIN(bootphase2);\r
-    .bootphase2 : {\r
-       __bootphase2_start__ = .;\r
-       *(.startphase2)\r
-       *(.text)\r
-       *(.eh_frame)\r
-       *(.glue_7)\r
-       *(.glue_7t)\r
-       *(.rodata)\r
-        *(.data)\r
-       . = ALIGN( 32 / 8 );\r
-       __bootphase2_end__ = .;\r
-    } >ram AT>bootphase2\r
-    \r
-    .bss : {\r
-       __bss_start__ = .; \r
-       *(.bss)\r
-    } >ram\r
-    \r
-    . = ALIGN( 32 / 8 );\r
-    __bss_end__ = .;\r
-    \r
-    .commonarea (NOLOAD) : {\r
-       *(.commonarea)\r
-    } >commonarea\r
-}\r
+INCLUDE ../common/ldscript.common
+
+ENTRY(flashstart)
+SECTIONS
+{
+    . = 0;
+    
+    .bootphase1 : {
+       *(.startup) 
+       *(.bootphase1)
+       
+       /* It seems to be impossible to flush align a section at the
+          end of a memory segment. Instead, we'll put the version_information
+          wherever the linker wants it, and then put a pointer to the start
+          of the version information at the end of the section.
+          -- Henryk Plötz <henryk@ploetzli.ch> 2009-08-28 */
+          
+       _version_information_start = ABSOLUTE(.);
+       *(.version_information);
+       
+       /* Why doesn't this work even though _bootphase1_version_pointer = 0x1001fc?
+         . = _bootphase1_version_pointer - ORIGIN(bootphase1); */
+       /* This works, apparently it fools the linker into accepting an absolute address */
+       . = _bootphase1_version_pointer - ORIGIN(bootphase1) + ORIGIN(bootphase1);
+       LONG(_version_information_start)
+    } >bootphase1
+    
+    __bootphase2_src_start__ = ORIGIN(bootphase2);
+    .bootphase2 : {
+       __bootphase2_start__ = .;
+       *(.startphase2)
+       *(.text)
+       *(.eh_frame)
+       *(.glue_7)
+       *(.glue_7t)
+       *(.rodata)
+        *(.data)
+       . = ALIGN( 32 / 8 );
+       __bootphase2_end__ = .;
+    } >ram AT>bootphase2
+    
+    .bss : {
+       __bss_start__ = .; 
+       *(.bss)
+    } >ram
+    
+    . = ALIGN( 32 / 8 );
+    __bss_end__ = .;
+    
+    .commonarea (NOLOAD) : {
+       *(.commonarea)
+    } >commonarea
+}
Impressum, Datenschutz