Clean up line endings, switch everything to LF instead of CRLF

Doing this for bootrom and armsrc for now. If you're using Windows,
please configure your editor for LF line endings.
This commit is contained in:
marcansoft 2010-02-20 21:24:25 +00:00
parent 72c4af087f
commit 15c4dc5ace
18 changed files with 7685 additions and 7685 deletions

View file

@ -1,123 +1,123 @@
#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);
}
#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);
}

View file

@ -1,117 +1,117 @@
#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
#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

View file

@ -1,70 +1,70 @@
# 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)
# 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)

File diff suppressed because it is too large Load diff

View file

@ -1,131 +1,131 @@
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
// 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

View file

@ -1,300 +1,300 @@
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
};
*/
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
};
*/

View file

@ -1,6 +1,6 @@
#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
#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

View file

@ -1,419 +1,419 @@
//-----------------------------------------------------------------------------
// 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);
}
//-----------------------------------------------------------------------------
// 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);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,41 +1,41 @@
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
}
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
}

File diff suppressed because it is too large Load diff

View file

@ -1,39 +1,39 @@
# 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)
# 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)

View file

@ -1,306 +1,306 @@
#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 ) );
}
}
#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 ) );
}
}

View file

@ -1,43 +1,43 @@
.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
.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

View file

@ -1,13 +1,13 @@
#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++;
}
#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++;
}

View file

@ -1,53 +1,53 @@
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
}
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
}