mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-21 05:43:23 -07:00
Initial commit for the firmware. Used the 20090306_ela version as baseline.
It is identical to the popular 20081211, with the doob addition (20090301), a linux client, and two additional commands for LF analysis. Let me know if you find issues here!
This commit is contained in:
parent
b811cc51f9
commit
6658905f18
91 changed files with 16661 additions and 0 deletions
123
armsrc/LCD.c
Normal file
123
armsrc/LCD.c
Normal file
|
@ -0,0 +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 ((SPI_STATUS & SPI_STATUS_TX_EMPTY) == 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
|
||||
SPI_TX_DATA = 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);
|
||||
LCD_RESET_LOW();
|
||||
SpinDelay(100);
|
||||
|
||||
LCD_RESET_HIGH();
|
||||
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);
|
||||
}
|
120
armsrc/LCD.h
Normal file
120
armsrc/LCD.h
Normal file
|
@ -0,0 +1,120 @@
|
|||
#ifndef __LCD
|
||||
#define __LCD
|
||||
|
||||
#define LCD_RESET_HIGH() PIO_OUTPUT_DATA_SET |= (1<<GPIO_LRST)
|
||||
#define LCD_RESET_LOW() PIO_OUTPUT_DATA_CLEAR |= (1<<GPIO_LRST)
|
||||
|
||||
// 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
|
61
armsrc/Makefile
Normal file
61
armsrc/Makefile
Normal file
|
@ -0,0 +1,61 @@
|
|||
CC = arm-elf-gcc
|
||||
AS = arm-elf-as
|
||||
LD = arm-elf-ld
|
||||
OBJCOPY = arm-elf-objcopy
|
||||
|
||||
OBJDIR = obj
|
||||
|
||||
INCLUDE = -I../include
|
||||
|
||||
INCLUDES = ../include/proxmark3.h ../include/at91sam7s128.h ../include/config_gpio.h ../include/usb_cmd.h apps.h
|
||||
LIB = "..\..\devkitARM\lib\gcc\arm-elf\4.1.0\interwork"
|
||||
|
||||
CFLAGS = -O6 -c $(INCLUDE) -Wall
|
||||
|
||||
OBJ = $(OBJDIR)/start.o \
|
||||
$(OBJDIR)/appmain.o \
|
||||
$(OBJDIR)/fpga.o \
|
||||
$(OBJDIR)/iso14443.o \
|
||||
$(OBJDIR)/iso14443a.o \
|
||||
$(OBJDIR)/iso15693.o \
|
||||
$(OBJDIR)/util.o \
|
||||
$(OBJDIR)/fonts.o \
|
||||
$(OBJDIR)/LCD.o
|
||||
|
||||
OBJFPGA = \
|
||||
$(OBJDIR)/fpgaimg.o
|
||||
|
||||
OBJCOMMON = \
|
||||
$(OBJDIR)/usb.o
|
||||
|
||||
all: osimage.s19
|
||||
|
||||
$(OBJDIR)/fpgaimage.s19: $(OBJDIR)/fpgaimg.o
|
||||
@echo obj/fpgaimage.s19
|
||||
@$(LD) -g -Tldscript-fpga -o $(OBJDIR)\fpgaimage.elf $(OBJDIR)/fpgaimg.o
|
||||
@$(OBJCOPY) -Osrec --srec-forceS3 $(OBJDIR)\fpgaimage.elf $(OBJDIR)\fpgaimage.s19
|
||||
|
||||
$(OBJDIR)/osimage.s19: $(OBJ) $(OBJCOMMON)
|
||||
@echo obj/osimage.s19
|
||||
@$(LD) -g -Tldscript -o $(OBJDIR)\osimage.elf $(OBJ) $(OBJCOMMON) $(LIB)\libgcc.a
|
||||
@$(OBJCOPY) -Osrec --srec-forceS3 $(OBJDIR)\osimage.elf $(OBJDIR)\osimage.s19
|
||||
|
||||
osimage.s19: $(OBJDIR)/osimage.s19 $(OBJDIR)/fpgaimage.s19
|
||||
@echo osimage.s19
|
||||
|
||||
$(OBJ): $(@B).c $(INCLUDES)
|
||||
@echo $(@B).c
|
||||
@$(CC) $(CFLAGS) -mthumb -mthumb-interwork $(@B).c -o $(OBJDIR)/$(@B).o
|
||||
|
||||
$(OBJCOMMON): ../common/$(@B).c $(INCLUDES)
|
||||
@echo $(@B).c
|
||||
@$(CC) $(CFLAGS) -mthumb -mthumb-interwork ../common/$(@B).c -o $(OBJDIR)/$(@B).o
|
||||
|
||||
$(OBJFPGA): $(@B).c $(INCLUDES)
|
||||
@echo $(@B).c
|
||||
@$(CC) $(CFLAGS) -mthumb -mthumb-interwork $(@B).c -o $(OBJDIR)/$(@B).o
|
||||
|
||||
clean:
|
||||
del /q obj\*.o
|
||||
del /q obj\*.elf
|
||||
del /q obj\*.s19
|
757
armsrc/appmain.c
Normal file
757
armsrc/appmain.c
Normal file
|
@ -0,0 +1,757 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// The main application code. This is the first thing called after start.c
|
||||
// executes.
|
||||
// Jonathan Westhues, Mar 2006
|
||||
// Edits by Gerhard de Koning Gans, Sep 2007 (##)
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <proxmark3.h>
|
||||
#include "apps.h"
|
||||
#include "fonts.h"
|
||||
#include "LCD.h"
|
||||
|
||||
// The large multi-purpose buffer, typically used to hold A/D samples,
|
||||
// maybe pre-processed in some way.
|
||||
DWORD BigBuf[16000];
|
||||
|
||||
//=============================================================================
|
||||
// A buffer where we can queue things up to be sent through the FPGA, for
|
||||
// any purpose (fake tag, as reader, whatever). We go MSB first, since that
|
||||
// is the order in which they go out on the wire.
|
||||
//=============================================================================
|
||||
|
||||
BYTE ToSend[256];
|
||||
int ToSendMax;
|
||||
static int ToSendBit;
|
||||
|
||||
void ToSendReset(void)
|
||||
{
|
||||
ToSendMax = -1;
|
||||
ToSendBit = 8;
|
||||
}
|
||||
|
||||
void ToSendStuffBit(int b)
|
||||
{
|
||||
if(ToSendBit >= 8) {
|
||||
ToSendMax++;
|
||||
ToSend[ToSendMax] = 0;
|
||||
ToSendBit = 0;
|
||||
}
|
||||
|
||||
if(b) {
|
||||
ToSend[ToSendMax] |= (1 << (7 - ToSendBit));
|
||||
}
|
||||
|
||||
ToSendBit++;
|
||||
|
||||
if(ToSendBit >= sizeof(ToSend)) {
|
||||
ToSendBit = 0;
|
||||
DbpString("ToSendStuffBit overflowed!");
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Debug print functions, to go out over USB, to the usual PC-side client.
|
||||
//=============================================================================
|
||||
|
||||
void DbpString(char *str)
|
||||
{
|
||||
UsbCommand c;
|
||||
c.cmd = CMD_DEBUG_PRINT_STRING;
|
||||
c.ext1 = strlen(str);
|
||||
memcpy(c.d.asBytes, str, c.ext1);
|
||||
|
||||
UsbSendPacket((BYTE *)&c, sizeof(c));
|
||||
// TODO fix USB so stupid things like this aren't req'd
|
||||
SpinDelay(50);
|
||||
}
|
||||
|
||||
void DbpIntegers(int x1, int x2, int x3)
|
||||
{
|
||||
UsbCommand c;
|
||||
c.cmd = CMD_DEBUG_PRINT_INTEGERS;
|
||||
c.ext1 = x1;
|
||||
c.ext2 = x2;
|
||||
c.ext3 = x3;
|
||||
|
||||
UsbSendPacket((BYTE *)&c, sizeof(c));
|
||||
// XXX
|
||||
SpinDelay(50);
|
||||
}
|
||||
|
||||
void AcquireRawAdcSamples125k(BOOL at134khz)
|
||||
{
|
||||
BYTE *dest = (BYTE *)BigBuf;
|
||||
int n = sizeof(BigBuf);
|
||||
int i;
|
||||
|
||||
memset(dest,0,n);
|
||||
|
||||
if(at134khz) {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
|
||||
} else {
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
|
||||
}
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
// Give it a bit of time for the resonant antenna to settle.
|
||||
SpinDelay(50);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
|
||||
i = 0;
|
||||
for(;;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0x43;
|
||||
LED_D_ON();
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
|
||||
i++;
|
||||
LED_D_OFF();
|
||||
if(i >= n) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DbpIntegers(dest[0], dest[1], at134khz);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read an ADC channel and block till it completes, then return the result
|
||||
// in ADC units (0 to 1023). Also a routine to average sixteen samples and
|
||||
// return that.
|
||||
//-----------------------------------------------------------------------------
|
||||
static int ReadAdc(int ch)
|
||||
{
|
||||
DWORD d;
|
||||
|
||||
ADC_CONTROL = ADC_CONTROL_RESET;
|
||||
ADC_MODE = ADC_MODE_PRESCALE(32) | ADC_MODE_STARTUP_TIME(16) |
|
||||
ADC_MODE_SAMPLE_HOLD_TIME(8);
|
||||
ADC_CHANNEL_ENABLE = ADC_CHANNEL(ch);
|
||||
|
||||
ADC_CONTROL = ADC_CONTROL_START;
|
||||
while(!(ADC_STATUS & ADC_END_OF_CONVERSION(ch)))
|
||||
;
|
||||
d = ADC_CHANNEL_DATA(ch);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static int AvgAdc(int ch)
|
||||
{
|
||||
int i;
|
||||
int a = 0;
|
||||
|
||||
for(i = 0; i < 32; i++) {
|
||||
a += ReadAdc(ch);
|
||||
}
|
||||
|
||||
return (a + 15) >> 5;
|
||||
}
|
||||
|
||||
void MeasureAntennaTuning(void)
|
||||
{
|
||||
// Impedances are Zc = 1/(j*omega*C), in ohms
|
||||
#define LF_TUNING_CAP_Z 1273 // 1 nF @ 125 kHz
|
||||
#define HF_TUNING_CAP_Z 235 // 50 pF @ 13.56 MHz
|
||||
|
||||
int vLf125, vLf134, vHf; // in mV
|
||||
|
||||
UsbCommand c;
|
||||
|
||||
// Let the FPGA drive the low-frequency antenna around 125 kHz.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
|
||||
SpinDelay(20);
|
||||
vLf125 = AvgAdc(4);
|
||||
// Vref = 3.3V, and a 10000:240 voltage divider on the input
|
||||
// can measure voltages up to 137500 mV
|
||||
vLf125 = (137500 * vLf125) >> 10;
|
||||
|
||||
// Let the FPGA drive the low-frequency antenna around 134 kHz.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_134_KHZ);
|
||||
SpinDelay(20);
|
||||
vLf134 = AvgAdc(4);
|
||||
// Vref = 3.3V, and a 10000:240 voltage divider on the input
|
||||
// can measure voltages up to 137500 mV
|
||||
vLf134 = (137500 * vLf134) >> 10;
|
||||
|
||||
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
|
||||
SpinDelay(20);
|
||||
vHf = AvgAdc(5);
|
||||
// Vref = 3300mV, and an 10:1 voltage divider on the input
|
||||
// can measure voltages up to 33000 mV
|
||||
vHf = (33000 * vHf) >> 10;
|
||||
|
||||
c.cmd = CMD_MEASURED_ANTENNA_TUNING;
|
||||
c.ext1 = (vLf125 << 0) | (vLf134 << 16);
|
||||
c.ext2 = vHf;
|
||||
c.ext3 = (LF_TUNING_CAP_Z << 0) | (HF_TUNING_CAP_Z << 16);
|
||||
UsbSendPacket((BYTE *)&c, sizeof(c));
|
||||
}
|
||||
|
||||
void SimulateTagLowFrequency(int period)
|
||||
{
|
||||
int i;
|
||||
BYTE *tab = (BYTE *)BigBuf;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
|
||||
|
||||
PIO_ENABLE = (1 << GPIO_SSC_DOUT) | (1 << GPIO_SSC_CLK);
|
||||
|
||||
PIO_OUTPUT_ENABLE = (1 << GPIO_SSC_DOUT);
|
||||
PIO_OUTPUT_DISABLE = (1 << GPIO_SSC_CLK);
|
||||
|
||||
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
|
||||
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
|
||||
|
||||
i = 0;
|
||||
for(;;) {
|
||||
while(!(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK))) {
|
||||
if(BUTTON_PRESS()) {
|
||||
return;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
|
||||
LED_D_ON();
|
||||
if(tab[i]) {
|
||||
OPEN_COIL();
|
||||
} else {
|
||||
SHORT_COIL();
|
||||
}
|
||||
LED_D_OFF();
|
||||
|
||||
while(PIO_PIN_DATA_STATUS & (1<<GPIO_SSC_CLK)) {
|
||||
if(BUTTON_PRESS()) {
|
||||
return;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
|
||||
i++;
|
||||
if(i == period) i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// compose fc/8 fc/10 waveform
|
||||
static void fc(int c, int *n) {
|
||||
BYTE *dest = (BYTE *)BigBuf;
|
||||
int idx;
|
||||
|
||||
// for when we want an fc8 pattern every 4 logical bits
|
||||
if(c==0) {
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
}
|
||||
// an fc/8 encoded bit is a bit pattern of 11000000 x6 = 48 samples
|
||||
if(c==8) {
|
||||
for (idx=0; idx<6; idx++) {
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
}
|
||||
}
|
||||
|
||||
// an fc/10 encoded bit is a bit pattern of 1110000000 x5 = 50 samples
|
||||
if(c==10) {
|
||||
for (idx=0; idx<5; idx++) {
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=1;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
dest[((*n)++)]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prepare a waveform pattern in the buffer based on the ID given then
|
||||
// simulate a HID tag until the button is pressed
|
||||
static void CmdHIDsimTAG(int hi, int lo)
|
||||
{
|
||||
int n=0, i=0;
|
||||
/*
|
||||
HID tag bitstream format
|
||||
The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits
|
||||
A 1 bit is represented as 6 fc8 and 5 fc10 patterns
|
||||
A 0 bit is represented as 5 fc10 and 6 fc8 patterns
|
||||
A fc8 is inserted before every 4 bits
|
||||
A special start of frame pattern is used consisting a0b0 where a and b are neither 0
|
||||
nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)
|
||||
*/
|
||||
|
||||
if (hi>0xFFF) {
|
||||
DbpString("Tags can only have 44 bits.");
|
||||
return;
|
||||
}
|
||||
fc(0,&n);
|
||||
// special start of frame marker containing invalid bit sequences
|
||||
fc(8, &n); fc(8, &n); // invalid
|
||||
fc(8, &n); fc(10, &n); // logical 0
|
||||
fc(10, &n); fc(10, &n); // invalid
|
||||
fc(8, &n); fc(10, &n); // logical 0
|
||||
|
||||
WDT_HIT();
|
||||
// manchester encode bits 43 to 32
|
||||
for (i=11; i>=0; i--) {
|
||||
if ((i%4)==3) fc(0,&n);
|
||||
if ((hi>>i)&1) {
|
||||
fc(10, &n); fc(8, &n); // low-high transition
|
||||
} else {
|
||||
fc(8, &n); fc(10, &n); // high-low transition
|
||||
}
|
||||
}
|
||||
|
||||
WDT_HIT();
|
||||
// manchester encode bits 31 to 0
|
||||
for (i=31; i>=0; i--) {
|
||||
if ((i%4)==3) fc(0,&n);
|
||||
if ((lo>>i)&1) {
|
||||
fc(10, &n); fc(8, &n); // low-high transition
|
||||
} else {
|
||||
fc(8, &n); fc(10, &n); // high-low transition
|
||||
}
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
SimulateTagLowFrequency(n);
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
// loop to capture raw HID waveform then FSK demodulate the TAG ID from it
|
||||
static void CmdHIDdemodFSK(void)
|
||||
{
|
||||
BYTE *dest = (BYTE *)BigBuf;
|
||||
int m=0, n=0, i=0, idx=0, found=0, lastval=0;
|
||||
DWORD hi=0, lo=0;
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER | FPGA_LF_READER_USE_125_KHZ);
|
||||
|
||||
// Connect the A/D to the peak-detected low-frequency path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
// Give it a bit of time for the resonant antenna to settle.
|
||||
SpinDelay(50);
|
||||
|
||||
// Now set up the SSC to get the ADC samples that are now streaming at us.
|
||||
FpgaSetupSsc();
|
||||
|
||||
for(;;) {
|
||||
WDT_HIT();
|
||||
LED_A_ON();
|
||||
if(BUTTON_PRESS()) {
|
||||
LED_A_OFF();
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
m = sizeof(BigBuf);
|
||||
memset(dest,128,m);
|
||||
for(;;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0x43;
|
||||
LED_D_ON();
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
dest[i] = (BYTE)SSC_RECEIVE_HOLDING;
|
||||
// we don't care about actual value, only if it's more or less than a
|
||||
// threshold essentially we capture zero crossings for later analysis
|
||||
if(dest[i] < 127) dest[i] = 0; else dest[i] = 1;
|
||||
i++;
|
||||
LED_D_OFF();
|
||||
if(i >= m) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FSK demodulator
|
||||
|
||||
// sync to first lo-hi transition
|
||||
for( idx=1; idx<m; idx++) {
|
||||
if (dest[idx-1]<dest[idx])
|
||||
lastval=idx;
|
||||
break;
|
||||
}
|
||||
WDT_HIT();
|
||||
|
||||
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
|
||||
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
|
||||
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
|
||||
for( i=0; idx<m; idx++) {
|
||||
if (dest[idx-1]<dest[idx]) {
|
||||
dest[i]=idx-lastval;
|
||||
if (dest[i] <= 8) {
|
||||
dest[i]=1;
|
||||
} else {
|
||||
dest[i]=0;
|
||||
}
|
||||
|
||||
lastval=idx;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
m=i;
|
||||
WDT_HIT();
|
||||
|
||||
// we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
|
||||
lastval=dest[0];
|
||||
idx=0;
|
||||
i=0;
|
||||
n=0;
|
||||
for( idx=0; idx<m; idx++) {
|
||||
if (dest[idx]==lastval) {
|
||||
n++;
|
||||
} else {
|
||||
// a bit time is five fc/10 or six fc/8 cycles so figure out how many bits a pattern width represents,
|
||||
// an extra fc/8 pattern preceeds every 4 bits (about 200 cycles) just to complicate things but it gets
|
||||
// swallowed up by rounding
|
||||
// expected results are 1 or 2 bits, any more and it's an invalid manchester encoding
|
||||
// special start of frame markers use invalid manchester states (no transitions) by using sequences
|
||||
// like 111000
|
||||
if (dest[idx-1]) {
|
||||
n=(n+1)/6; // fc/8 in sets of 6
|
||||
} else {
|
||||
n=(n+1)/5; // fc/10 in sets of 5
|
||||
}
|
||||
switch (n) { // stuff appropriate bits in buffer
|
||||
case 0:
|
||||
case 1: // one bit
|
||||
dest[i++]=dest[idx-1];
|
||||
break;
|
||||
case 2: // two bits
|
||||
dest[i++]=dest[idx-1];
|
||||
dest[i++]=dest[idx-1];
|
||||
break;
|
||||
case 3: // 3 bit start of frame markers
|
||||
dest[i++]=dest[idx-1];
|
||||
dest[i++]=dest[idx-1];
|
||||
dest[i++]=dest[idx-1];
|
||||
break;
|
||||
// When a logic 0 is immediately followed by the start of the next transmisson
|
||||
// (special pattern) a pattern of 4 bit duration lengths is created.
|
||||
case 4:
|
||||
dest[i++]=dest[idx-1];
|
||||
dest[i++]=dest[idx-1];
|
||||
dest[i++]=dest[idx-1];
|
||||
dest[i++]=dest[idx-1];
|
||||
break;
|
||||
default: // this shouldn't happen, don't stuff any bits
|
||||
break;
|
||||
}
|
||||
n=0;
|
||||
lastval=dest[idx];
|
||||
}
|
||||
}
|
||||
m=i;
|
||||
WDT_HIT();
|
||||
|
||||
// final loop, go over previously decoded manchester data and decode into usable tag ID
|
||||
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
|
||||
for( idx=0; idx<m-6; idx++) {
|
||||
// search for a start of frame marker
|
||||
if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
|
||||
{
|
||||
found=1;
|
||||
idx+=6;
|
||||
if (found && (hi|lo)) {
|
||||
DbpString("TAG ID");
|
||||
DbpIntegers(hi, lo, (lo>>1)&0xffff);
|
||||
hi=0;
|
||||
lo=0;
|
||||
found=0;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
if (dest[idx] && (!dest[idx+1]) ) {
|
||||
hi=(hi<<1)|(lo>>31);
|
||||
lo=(lo<<1)|0;
|
||||
} else if ( (!dest[idx]) && dest[idx+1]) {
|
||||
hi=(hi<<1)|(lo>>31);
|
||||
lo=(lo<<1)|1;
|
||||
} else {
|
||||
found=0;
|
||||
hi=0;
|
||||
lo=0;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if ( dest[idx] && dest[idx+1] && dest[idx+2] && (!dest[idx+3]) && (!dest[idx+4]) && (!dest[idx+5]) )
|
||||
{
|
||||
found=1;
|
||||
idx+=6;
|
||||
if (found && (hi|lo)) {
|
||||
DbpString("TAG ID");
|
||||
DbpIntegers(hi, lo, (lo>>1)&0xffff);
|
||||
hi=0;
|
||||
lo=0;
|
||||
found=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
|
||||
void SimulateTagHfListen(void)
|
||||
{
|
||||
BYTE *dest = (BYTE *)BigBuf;
|
||||
int n = sizeof(BigBuf);
|
||||
BYTE v = 0;
|
||||
int i;
|
||||
int p = 0;
|
||||
|
||||
// We're using this mode just so that I can test it out; the simulated
|
||||
// tag mode would work just as well and be simpler.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
|
||||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
FpgaSetupSsc();
|
||||
|
||||
i = 0;
|
||||
for(;;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0xff;
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
BYTE r = (BYTE)SSC_RECEIVE_HOLDING;
|
||||
|
||||
v <<= 1;
|
||||
if(r & 1) {
|
||||
v |= 1;
|
||||
}
|
||||
p++;
|
||||
|
||||
if(p >= 8) {
|
||||
dest[i] = v;
|
||||
v = 0;
|
||||
p = 0;
|
||||
i++;
|
||||
|
||||
if(i >= n) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DbpString("simulate tag (now type bitsamples)");
|
||||
}
|
||||
|
||||
void UsbPacketReceived(BYTE *packet, int len)
|
||||
{
|
||||
UsbCommand *c = (UsbCommand *)packet;
|
||||
|
||||
switch(c->cmd) {
|
||||
case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
|
||||
AcquireRawAdcSamples125k(c->ext1);
|
||||
break;
|
||||
|
||||
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
|
||||
AcquireRawAdcSamplesIso15693();
|
||||
break;
|
||||
|
||||
case CMD_READER_ISO_15693:
|
||||
ReaderIso15693(c->ext1);
|
||||
break;
|
||||
|
||||
case CMD_SIMTAG_ISO_15693:
|
||||
SimTagIso15693(c->ext1);
|
||||
break;
|
||||
|
||||
|
||||
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443:
|
||||
AcquireRawAdcSamplesIso14443(c->ext1);
|
||||
break;
|
||||
|
||||
case CMD_READER_ISO_14443a:
|
||||
ReaderIso14443a(c->ext1);
|
||||
break;
|
||||
|
||||
case CMD_SNOOP_ISO_14443:
|
||||
SnoopIso14443();
|
||||
break;
|
||||
|
||||
case CMD_SNOOP_ISO_14443a:
|
||||
SnoopIso14443a();
|
||||
break;
|
||||
|
||||
case CMD_SIMULATE_TAG_HF_LISTEN:
|
||||
SimulateTagHfListen();
|
||||
break;
|
||||
|
||||
case CMD_SIMULATE_TAG_ISO_14443:
|
||||
SimulateIso14443Tag();
|
||||
break;
|
||||
|
||||
case CMD_SIMULATE_TAG_ISO_14443a:
|
||||
SimulateIso14443aTag(c->ext1, c->ext2); // ## Simulate iso14443a tag - pass tag type & UID
|
||||
break;
|
||||
|
||||
case CMD_MEASURE_ANTENNA_TUNING:
|
||||
MeasureAntennaTuning();
|
||||
break;
|
||||
|
||||
case CMD_HID_DEMOD_FSK:
|
||||
CmdHIDdemodFSK(); // Demodulate HID tag
|
||||
break;
|
||||
|
||||
case CMD_HID_SIM_TAG:
|
||||
CmdHIDsimTAG(c->ext1, c->ext2); // Simulate HID tag by ID
|
||||
break;
|
||||
|
||||
case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control
|
||||
LED_C_ON();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
LED_C_OFF();
|
||||
break;
|
||||
|
||||
case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K:
|
||||
case CMD_DOWNLOAD_RAW_BITS_TI_TYPE: {
|
||||
UsbCommand n;
|
||||
if(c->cmd == CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K) {
|
||||
n.cmd = CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K;
|
||||
} else {
|
||||
n.cmd = CMD_DOWNLOADED_RAW_BITS_TI_TYPE;
|
||||
}
|
||||
n.ext1 = c->ext1;
|
||||
memcpy(n.d.asDwords, BigBuf+c->ext1, 12*sizeof(DWORD));
|
||||
UsbSendPacket((BYTE *)&n, sizeof(n));
|
||||
break;
|
||||
}
|
||||
case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
|
||||
BYTE *b = (BYTE *)BigBuf;
|
||||
memcpy(b+c->ext1, c->d.asBytes, 48);
|
||||
break;
|
||||
}
|
||||
case CMD_SIMULATE_TAG_125K:
|
||||
LED_A_ON();
|
||||
SimulateTagLowFrequency(c->ext1);
|
||||
LED_A_OFF();
|
||||
break;
|
||||
|
||||
case CMD_LCD_RESET:
|
||||
LCDReset();
|
||||
break;
|
||||
|
||||
case CMD_LCD:
|
||||
LCDSend(c->ext1);
|
||||
break;
|
||||
|
||||
case CMD_SETUP_WRITE:
|
||||
case CMD_FINISH_WRITE:
|
||||
USB_D_PLUS_PULLUP_OFF();
|
||||
SpinDelay(1000);
|
||||
SpinDelay(1000);
|
||||
RSTC_CONTROL = RST_CONTROL_KEY | RST_CONTROL_PROCESSOR_RESET;
|
||||
for(;;) {
|
||||
// We're going to reset, and the bootrom will take control.
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
DbpString("unknown command");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AppMain(void)
|
||||
{
|
||||
memset(BigBuf,0,sizeof(BigBuf));
|
||||
SpinDelay(100);
|
||||
|
||||
LED_D_OFF();
|
||||
LED_C_OFF();
|
||||
LED_B_OFF();
|
||||
LED_A_OFF();
|
||||
|
||||
UsbStart();
|
||||
|
||||
// The FPGA gets its clock from us from PCK0 output, so set that up.
|
||||
PIO_PERIPHERAL_B_SEL = (1 << GPIO_PCK0);
|
||||
PIO_DISABLE = (1 << GPIO_PCK0);
|
||||
PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROGRAMMABLE_CLK_0;
|
||||
// PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz
|
||||
PMC_PROGRAMMABLE_CLK_0 = PMC_CLK_SELECTION_PLL_CLOCK |
|
||||
PMC_CLK_PRESCALE_DIV_4;
|
||||
PIO_OUTPUT_ENABLE = (1 << GPIO_PCK0);
|
||||
|
||||
// Reset SPI
|
||||
SPI_CONTROL = SPI_CONTROL_RESET;
|
||||
// Reset SSC
|
||||
SSC_CONTROL = SSC_CONTROL_RESET;
|
||||
|
||||
// Load the FPGA image, which we have stored in our flash.
|
||||
FpgaDownloadAndGo();
|
||||
|
||||
LCDInit();
|
||||
|
||||
// test text on different colored backgrounds
|
||||
LCDString(" The quick brown fox ", &FONT6x8,1,1+8*0,WHITE ,BLACK );
|
||||
LCDString(" jumped over the ", &FONT6x8,1,1+8*1,BLACK ,WHITE );
|
||||
LCDString(" lazy dog. ", &FONT6x8,1,1+8*2,YELLOW ,RED );
|
||||
LCDString(" AaBbCcDdEeFfGgHhIiJj ", &FONT6x8,1,1+8*3,RED ,GREEN );
|
||||
LCDString(" KkLlMmNnOoPpQqRrSsTt ", &FONT6x8,1,1+8*4,MAGENTA,BLUE );
|
||||
LCDString("UuVvWwXxYyZz0123456789", &FONT6x8,1,1+8*5,BLUE ,YELLOW);
|
||||
LCDString("`-=[]_;',./~!@#$%^&*()", &FONT6x8,1,1+8*6,BLACK ,CYAN );
|
||||
LCDString(" _+{}|:\\\"<>? ",&FONT6x8,1,1+8*7,BLUE ,MAGENTA);
|
||||
|
||||
// color bands
|
||||
LCDFill(0, 1+8* 8, 132, 8, BLACK);
|
||||
LCDFill(0, 1+8* 9, 132, 8, WHITE);
|
||||
LCDFill(0, 1+8*10, 132, 8, RED);
|
||||
LCDFill(0, 1+8*11, 132, 8, GREEN);
|
||||
LCDFill(0, 1+8*12, 132, 8, BLUE);
|
||||
LCDFill(0, 1+8*13, 132, 8, YELLOW);
|
||||
LCDFill(0, 1+8*14, 132, 8, CYAN);
|
||||
LCDFill(0, 1+8*15, 132, 8, MAGENTA);
|
||||
|
||||
for(;;) {
|
||||
UsbPoll(FALSE);
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
|
||||
void SpinDelay(int ms)
|
||||
{
|
||||
int ticks = (48000*ms) >> 10;
|
||||
|
||||
// Borrow a PWM unit for my real-time clock
|
||||
PWM_ENABLE = PWM_CHANNEL(0);
|
||||
// 48 MHz / 1024 gives 46.875 kHz
|
||||
PWM_CH_MODE(0) = PWM_CH_MODE_PRESCALER(10);
|
||||
PWM_CH_DUTY_CYCLE(0) = 0;
|
||||
PWM_CH_PERIOD(0) = 0xffff;
|
||||
|
||||
WORD start = (WORD)PWM_CH_COUNTER(0);
|
||||
|
||||
for(;;) {
|
||||
WORD now = (WORD)PWM_CH_COUNTER(0);
|
||||
if(now == (WORD)(start + ticks)) {
|
||||
return;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
77
armsrc/apps.h
Normal file
77
armsrc/apps.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
/// appmain.c
|
||||
void AppMain(void);
|
||||
void DbpIntegers(int a, int b, int c);
|
||||
void DbpString(char *str);
|
||||
void SpinDelay(int ms);
|
||||
void ToSendStuffBit(int b);
|
||||
void ToSendReset(void);
|
||||
extern int ToSendMax;
|
||||
extern BYTE ToSend[];
|
||||
extern DWORD BigBuf[];
|
||||
|
||||
/// fpga.c
|
||||
void FpgaWriteConfWord(BYTE v);
|
||||
void FpgaDownloadAndGo(void);
|
||||
void FpgaSetupSsc(void);
|
||||
void SetupSpi(int mode);
|
||||
void FpgaSetupSscDma(BYTE *buf, int len);
|
||||
void SetAdcMuxFor(int whichGpio);
|
||||
|
||||
// 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_UNUSED (6<<5)
|
||||
#define FPGA_MAJOR_MODE_OFF (7<<5)
|
||||
// Options for the LF reader
|
||||
#define FPGA_LF_READER_USE_125_KHZ (1<<3)
|
||||
#define FPGA_LF_READER_USE_134_KHZ (0<<3)
|
||||
// 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)
|
||||
// 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)
|
||||
// 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)
|
||||
|
||||
/// iso14443.h
|
||||
void SimulateIso14443Tag(void);
|
||||
void AcquireRawAdcSamplesIso14443(DWORD parameter);
|
||||
void SnoopIso14443(void);
|
||||
|
||||
/// iso14443a.h
|
||||
void SnoopIso14443a(void);
|
||||
void SimulateIso14443aTag(int tagType, int TagUid); // ## simulate iso14443a tag
|
||||
void ReaderIso14443a(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
|
||||
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);
|
||||
|
||||
#endif
|
269
armsrc/example_lcd.c
Normal file
269
armsrc/example_lcd.c
Normal file
|
@ -0,0 +1,269 @@
|
|||
unsigned char somestring[25];
|
||||
|
||||
//*********************************************************************
|
||||
//******************** SYSTERM HEARTBEAT @ 10 ms *********************
|
||||
//*********************************************************************
|
||||
void InitSPI (void)
|
||||
{
|
||||
//set functionalite to pins:
|
||||
//port0.11 -> NPCS0
|
||||
//port0.12 -> MISO
|
||||
//port0.13 -> MOSI
|
||||
//port0.14 -> SPCK
|
||||
PIOA_PDR = BIT11 | BIT12 | BIT13 | BIT14;
|
||||
PIOA_ASR = BIT11 | BIT12 | BIT13 | BIT14;
|
||||
PIOA_BSR = 0;
|
||||
|
||||
|
||||
PMC_PCER |= 1 << 5; // Enable SPI timer clock.
|
||||
|
||||
/**** Fixed mode ****/
|
||||
SPI_CR = 0x81; //SPI Enable, Sowtware reset
|
||||
SPI_CR = 0x01; //SPI Enable
|
||||
|
||||
|
||||
|
||||
SPI_MR = 0x000E0011; //Master mode
|
||||
SPI_CSR0 = 0x01010B11; //9 bit
|
||||
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
//*************************** Task 1 ********************************
|
||||
//*********************************************************************
|
||||
void Task_1(void *p)
|
||||
{
|
||||
char beat=0; // just flash the onboard LED for Heatbeat
|
||||
|
||||
while(1)
|
||||
{
|
||||
if(beat)
|
||||
{
|
||||
PIOA_SODR = BIT18;
|
||||
beat=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PIOA_CODR = BIT18;
|
||||
beat=1;
|
||||
}
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 150);
|
||||
|
||||
}
|
||||
}
|
||||
//*********************************************************************
|
||||
//*************************** Task 2 ********************************
|
||||
//*********************************************************************
|
||||
void Task_2(void *p)
|
||||
{
|
||||
unsigned long z;
|
||||
unsigned int x,y;
|
||||
unsigned char a,b,c,d,e;
|
||||
|
||||
char seconds,minutes,hours;
|
||||
|
||||
unsigned int nowold,tenths;
|
||||
|
||||
|
||||
InitLCD();
|
||||
|
||||
|
||||
/******* Put smiley face up in 4096 color mode *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
LCD_Set_Resolution(HIGH_RES); // set 4096 color mode
|
||||
|
||||
// ShowImage_4096(0,0,smiley);
|
||||
LCD_Set_Resolution(LOW_RES); // set 256 color mode
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 4000); // wait 4 seconds to view it
|
||||
|
||||
/******* Do some static on screen *******/
|
||||
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
for(z=0;z<100000;z++)
|
||||
{
|
||||
while( (a = rand()) > 132);
|
||||
while( (b = rand()) > 132);
|
||||
c = rand();
|
||||
LCD_PixelPut(a,b,c);
|
||||
}
|
||||
|
||||
/******* Do some lines on screen *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
for(z=1;z<300;z++)
|
||||
{
|
||||
while( (a = rand()) > 132);
|
||||
while( (b = rand()) > 132);
|
||||
while( (c = rand()) > 132);
|
||||
while( (d = rand()) > 132);
|
||||
e = rand(); // pick color
|
||||
|
||||
LCD_Line(a,b,c,d,e);
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 10);
|
||||
}
|
||||
|
||||
/******* Do some Boxes on screen *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
for(z=0;z<300;z++)
|
||||
{
|
||||
|
||||
while( (a = rand()) > 132);
|
||||
while( (b = rand()) > 132);
|
||||
while( (c = rand()) > 132);
|
||||
while( (d = rand()) > 132);
|
||||
|
||||
e = rand(); // pick color
|
||||
LCD_Box(a,b,c,d,e);
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 10);
|
||||
}
|
||||
/******* Do some Circles on screen *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
for(z=0;z<100;z++)
|
||||
{
|
||||
|
||||
while( (a = rand()) > 132);
|
||||
while( (b = rand()) > 132);
|
||||
while( (c = rand()) > 127); // diameter
|
||||
|
||||
d = rand(); // pick color
|
||||
LCD_Circle(a,b,c,d);
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 10);
|
||||
}
|
||||
|
||||
/******* Do some Thick Circles on screen *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
for(z=0;z<25;z++)
|
||||
{
|
||||
while( (a = rand()) > 132);
|
||||
while( (b = rand()) > 132);
|
||||
while( (c = rand()) > 40); // diameter
|
||||
while( (d = rand()) > 10); // wall thicknes
|
||||
e = rand(); // pick color
|
||||
LCD_Thick_Circle(a,b,c,d,e);
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 1);
|
||||
}
|
||||
|
||||
/******* Do something funky to wipe screen *******/
|
||||
b=0;
|
||||
|
||||
for(a=0;a<131;a++)
|
||||
{
|
||||
LCD_Line(a,b,65,65,0x62);
|
||||
}
|
||||
for(b=0;b<131;b++)
|
||||
{
|
||||
LCD_Line(a,b,65,65,0x62);
|
||||
}
|
||||
for(;a>1;a--)
|
||||
{
|
||||
LCD_Line(a,b,65,65,0x62);
|
||||
}
|
||||
for(;b>1;b--)
|
||||
{
|
||||
LCD_Line(a,b,65,65,0x62);
|
||||
}
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 1000);
|
||||
|
||||
/******* Show Image scrolling *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
ShowImage(0,50,sparkfun);
|
||||
|
||||
sprintf(somestring,"Thanks SparkFun");
|
||||
LCD_String(somestring,&FONT8x8F[0][0],5,10,LightGreen,Black);
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 2000); // hold sparkfun image for a bit
|
||||
|
||||
for(y=50;y<140;y++)
|
||||
{
|
||||
LCD_Line(0,y-1,132,y-1,Black); // wipe the white line as it moves down
|
||||
ShowImage(0,y,sparkfun); // move image to Y location
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 25); // wait a bit
|
||||
}
|
||||
|
||||
/******* Run radar in loop with example fonts displayed *******/
|
||||
LCD_Fill(0,0,132,132,Black);
|
||||
|
||||
LCD_Thick_Circle(66,66,30,2,DarkBlue);
|
||||
|
||||
y=0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
LCD_Circle_Line(66,66,28,0,y,LightGreen);
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 1);
|
||||
|
||||
tenths = ctl_current_time / 1000;
|
||||
|
||||
if(tenths != nowold)
|
||||
{
|
||||
nowold = tenths;
|
||||
|
||||
if(++seconds == 60)
|
||||
{
|
||||
seconds = 0;
|
||||
|
||||
if(++minutes == 60)
|
||||
{
|
||||
minutes=0;
|
||||
hours++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
printf("a=%6lu - b=%6lu - c=%6lu - d=%6lu : Time=%lu\r\n",a,b,c,d,ctl_current_time);
|
||||
|
||||
sprintf(somestring,"%05lu",y);
|
||||
LCD_String(somestring,&FONT6x8[0][0],52,25,White,Black);
|
||||
|
||||
sprintf(somestring,"Time:%02u:%02u:%02u",hours,minutes,seconds);
|
||||
LCD_String(somestring,&FONT8x8F[0][0],14,10,DarkRed,Black);
|
||||
|
||||
sprintf(somestring,"Time:%02u:%02u:%02u",hours,minutes,seconds);
|
||||
LCD_String(somestring,&FONT8x16[0][0],14,115,LightGreen,Black);
|
||||
|
||||
LCD_Circle_Line(66,66,28,0,y,Black);
|
||||
|
||||
if(++y==360)
|
||||
{
|
||||
y=0;
|
||||
}
|
||||
|
||||
ctl_timeout_wait(ctl_get_current_time()+ 10);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
********************* Main Module *************************
|
||||
********************* *************************
|
||||
********************* Initialize Program *************************
|
||||
********************* Sequences *************************
|
||||
********************* *************************
|
||||
*************************************************************************/
|
||||
int main(void)
|
||||
{
|
||||
BoardInit();
|
||||
|
||||
InitSPI();
|
||||
|
||||
while (1)
|
||||
{
|
||||
Idle();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
300
armsrc/fonts.c
Normal file
300
armsrc/fonts.c
Normal file
|
@ -0,0 +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
|
||||
};
|
||||
*/
|
6
armsrc/fonts.h
Normal file
6
armsrc/fonts.h
Normal file
|
@ -0,0 +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
|
222
armsrc/fpga.c
Normal file
222
armsrc/fpga.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
PIO_DISABLE = (1 << GPIO_NCS0) |
|
||||
(1 << GPIO_NCS2) |
|
||||
(1 << GPIO_MISO) |
|
||||
(1 << GPIO_MOSI) |
|
||||
(1 << GPIO_SPCK);
|
||||
|
||||
PIO_PERIPHERAL_A_SEL = (1 << GPIO_NCS0) |
|
||||
(1 << GPIO_MISO) |
|
||||
(1 << GPIO_MOSI) |
|
||||
(1 << GPIO_SPCK);
|
||||
|
||||
PIO_PERIPHERAL_B_SEL = (1 << GPIO_NCS2);
|
||||
|
||||
//enable the SPI Peripheral clock
|
||||
PMC_PERIPHERAL_CLK_ENABLE = (1<<PERIPH_SPI);
|
||||
// Enable SPI
|
||||
SPI_CONTROL = SPI_CONTROL_ENABLE;
|
||||
|
||||
switch (mode) {
|
||||
case SPI_FPGA_MODE:
|
||||
SPI_MODE =
|
||||
( 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
|
||||
SPI_FOR_CHIPSEL_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
|
||||
( 0 << 4) | // Bits per Transfer (8 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:
|
||||
SPI_MODE =
|
||||
( 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
|
||||
SPI_FOR_CHIPSEL_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
|
||||
SPI_CONTROL = SPI_CONTROL_DISABLE;
|
||||
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.
|
||||
PIO_PERIPHERAL_A_SEL = (1 << GPIO_SSC_FRAME) |
|
||||
(1 << GPIO_SSC_DIN) |
|
||||
(1 << GPIO_SSC_DOUT) |
|
||||
(1 << GPIO_SSC_CLK);
|
||||
PIO_DISABLE = (1 << GPIO_SSC_DOUT);
|
||||
|
||||
PMC_PERIPHERAL_CLK_ENABLE = (1 << PERIPH_SSC);
|
||||
|
||||
// Now set up the SSC proper, starting from a known state.
|
||||
SSC_CONTROL = SSC_CONTROL_RESET;
|
||||
|
||||
// RX clock comes from TX clock, RX starts when TX starts, data changes
|
||||
// on RX clock rising edge, sampled on falling edge
|
||||
SSC_RECEIVE_CLOCK_MODE = 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
|
||||
SSC_RECEIVE_FRAME_MODE = SSC_FRAME_MODE_BITS_IN_WORD(8) |
|
||||
SSC_FRAME_MODE_MSB_FIRST | 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
|
||||
SSC_TRANSMIT_CLOCK_MODE = SSC_CLOCK_MODE_SELECT(2) |
|
||||
SSC_CLOCK_MODE_START(5);
|
||||
|
||||
// tx framing is the same as the rx framing
|
||||
SSC_TRANSMIT_FRAME_MODE = SSC_RECEIVE_FRAME_MODE;
|
||||
|
||||
SSC_CONTROL = SSC_CONTROL_RX_ENABLE | SSC_CONTROL_TX_ENABLE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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)
|
||||
{
|
||||
PDC_RX_POINTER(SSC_BASE) = (DWORD)buf;
|
||||
PDC_RX_COUNTER(SSC_BASE) = len;
|
||||
PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)buf;
|
||||
PDC_RX_NEXT_COUNTER(SSC_BASE) = len;
|
||||
PDC_CONTROL(SSC_BASE) = PDC_RX_ENABLE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Download the FPGA image stored in flash (slave serial).
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaDownloadAndGo(void)
|
||||
{
|
||||
// FPGA image lives in FLASH at base address 0x2000
|
||||
// The current board design can not accomodate anything bigger than a XC2S30
|
||||
// FPGA and the config file size is fixed at 336,768 bits = 10,524 DWORDs
|
||||
const DWORD *FpgaImage=((DWORD *)0x2000);
|
||||
const DWORD FpgaImageLen=10524;
|
||||
|
||||
int i, j;
|
||||
|
||||
PIO_OUTPUT_ENABLE = (1 << GPIO_FPGA_ON);
|
||||
PIO_ENABLE = (1 << GPIO_FPGA_ON);
|
||||
PIO_OUTPUT_DATA_SET = (1 << GPIO_FPGA_ON);
|
||||
|
||||
SpinDelay(50);
|
||||
|
||||
LED_D_ON();
|
||||
|
||||
HIGH(GPIO_FPGA_NPROGRAM);
|
||||
LOW(GPIO_FPGA_CCLK);
|
||||
LOW(GPIO_FPGA_DIN);
|
||||
PIO_OUTPUT_ENABLE = (1 << GPIO_FPGA_NPROGRAM) |
|
||||
(1 << GPIO_FPGA_CCLK) |
|
||||
(1 << GPIO_FPGA_DIN);
|
||||
SpinDelay(1);
|
||||
|
||||
LOW(GPIO_FPGA_NPROGRAM);
|
||||
SpinDelay(50);
|
||||
HIGH(GPIO_FPGA_NPROGRAM);
|
||||
|
||||
for(i = 0; i < FpgaImageLen; i++) {
|
||||
DWORD v = FpgaImage[i];
|
||||
for(j = 0; j < 32; j++) {
|
||||
if(v & 0x80000000) {
|
||||
HIGH(GPIO_FPGA_DIN);
|
||||
} else {
|
||||
LOW(GPIO_FPGA_DIN);
|
||||
}
|
||||
HIGH(GPIO_FPGA_CCLK);
|
||||
LOW(GPIO_FPGA_CCLK);
|
||||
v <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
LED_D_OFF();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Write the FPGA setup word (that determines what mode the logic is in, read
|
||||
// vs. clone vs. etc.).
|
||||
//-----------------------------------------------------------------------------
|
||||
void FpgaWriteConfWord(BYTE v)
|
||||
{
|
||||
SetupSpi(SPI_FPGA_MODE);
|
||||
while ((SPI_STATUS & SPI_STATUS_TX_EMPTY) == 0); // wait for the transfer to complete
|
||||
SPI_TX_DATA = SPI_CONTROL_LAST_TRANSFER | v; // send the data
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// 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(int whichGpio)
|
||||
{
|
||||
PIO_OUTPUT_ENABLE = (1 << GPIO_MUXSEL_HIPKD) |
|
||||
(1 << GPIO_MUXSEL_LOPKD) |
|
||||
(1 << GPIO_MUXSEL_LORAW) |
|
||||
(1 << GPIO_MUXSEL_HIRAW);
|
||||
|
||||
PIO_ENABLE = (1 << GPIO_MUXSEL_HIPKD) |
|
||||
(1 << GPIO_MUXSEL_LOPKD) |
|
||||
(1 << GPIO_MUXSEL_LORAW) |
|
||||
(1 << GPIO_MUXSEL_HIRAW);
|
||||
|
||||
LOW(GPIO_MUXSEL_HIPKD);
|
||||
LOW(GPIO_MUXSEL_HIRAW);
|
||||
LOW(GPIO_MUXSEL_LORAW);
|
||||
LOW(GPIO_MUXSEL_LOPKD);
|
||||
|
||||
HIGH(whichGpio);
|
||||
}
|
0
armsrc/fpgaimg.c
Normal file
0
armsrc/fpgaimg.c
Normal file
988
armsrc/iso14443.c
Normal file
988
armsrc/iso14443.c
Normal file
|
@ -0,0 +1,988 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Routines to support ISO 14443. This includes both the reader software and
|
||||
// the `fake tag' modes. At the moment only the Type B modulation is
|
||||
// supported.
|
||||
// Jonathan Westhues, split Nov 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <proxmark3.h>
|
||||
#include "apps.h"
|
||||
#include "..\common\iso14443_crc.c"
|
||||
|
||||
|
||||
//static void GetSamplesFor14443(BOOL weTx, int n);
|
||||
|
||||
#define DMA_BUFFER_SIZE 256
|
||||
|
||||
//=============================================================================
|
||||
// An ISO 14443 Type B tag. We listen for commands from the reader, using
|
||||
// a UART kind of thing that's implemented in software. When we get a
|
||||
// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.
|
||||
// If it's good, then we can do something appropriate with it, and send
|
||||
// a response.
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Code up a string of octets at layer 2 (including CRC, we don't generate
|
||||
// that here) so that they can be transmitted to the reader. Doesn't transmit
|
||||
// them yet, just leaves them ready to send in ToSend[].
|
||||
//-----------------------------------------------------------------------------
|
||||
static void CodeIso14443bAsTag(const BYTE *cmd, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
ToSendReset();
|
||||
|
||||
// Transmit a burst of ones, as the initial thing that lets the
|
||||
// reader get phase sync. This (TR1) must be > 80/fs, per spec,
|
||||
// but tag that I've tried (a Paypass) exceeds that by a fair bit,
|
||||
// so I will too.
|
||||
for(i = 0; i < 20; i++) {
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
// Send SOF.
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
for(i = 0; i < 2; i++) {
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
int j;
|
||||
BYTE b = cmd[i];
|
||||
|
||||
// Start bit
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
|
||||
// Data bits
|
||||
for(j = 0; j < 8; j++) {
|
||||
if(b & 1) {
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
} else {
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
// Stop bit
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
// Send SOF.
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
// Convert from last byte pos to length
|
||||
ToSendMax++;
|
||||
|
||||
// Add a few more for slop
|
||||
ToSendMax += 2;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// The software UART that receives commands from the reader, and its state
|
||||
// variables.
|
||||
//-----------------------------------------------------------------------------
|
||||
static struct {
|
||||
enum {
|
||||
STATE_UNSYNCD,
|
||||
STATE_GOT_FALLING_EDGE_OF_SOF,
|
||||
STATE_AWAITING_START_BIT,
|
||||
STATE_RECEIVING_DATA,
|
||||
STATE_ERROR_WAIT
|
||||
} state;
|
||||
WORD shiftReg;
|
||||
int bitCnt;
|
||||
int byteCnt;
|
||||
int byteCntMax;
|
||||
int posCnt;
|
||||
BYTE *output;
|
||||
} Uart;
|
||||
|
||||
static BOOL Handle14443UartBit(int bit)
|
||||
{
|
||||
switch(Uart.state) {
|
||||
case STATE_UNSYNCD:
|
||||
if(!bit) {
|
||||
// we went low, so this could be the beginning
|
||||
// of an SOF
|
||||
Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
|
||||
Uart.posCnt = 0;
|
||||
Uart.bitCnt = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_GOT_FALLING_EDGE_OF_SOF:
|
||||
Uart.posCnt++;
|
||||
if(Uart.posCnt == 2) {
|
||||
if(bit) {
|
||||
if(Uart.bitCnt >= 10) {
|
||||
// we've seen enough consecutive
|
||||
// zeros that it's a valid SOF
|
||||
Uart.posCnt = 0;
|
||||
Uart.byteCnt = 0;
|
||||
Uart.state = STATE_AWAITING_START_BIT;
|
||||
} else {
|
||||
// didn't stay down long enough
|
||||
// before going high, error
|
||||
Uart.state = STATE_ERROR_WAIT;
|
||||
}
|
||||
} else {
|
||||
// do nothing, keep waiting
|
||||
}
|
||||
Uart.bitCnt++;
|
||||
}
|
||||
if(Uart.posCnt >= 4) Uart.posCnt = 0;
|
||||
if(Uart.bitCnt > 14) {
|
||||
// Give up if we see too many zeros without
|
||||
// a one, too.
|
||||
Uart.state = STATE_ERROR_WAIT;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_AWAITING_START_BIT:
|
||||
Uart.posCnt++;
|
||||
if(bit) {
|
||||
if(Uart.posCnt > 25) {
|
||||
// stayed high for too long between
|
||||
// characters, error
|
||||
Uart.state = STATE_ERROR_WAIT;
|
||||
}
|
||||
} else {
|
||||
// falling edge, this starts the data byte
|
||||
Uart.posCnt = 0;
|
||||
Uart.bitCnt = 0;
|
||||
Uart.shiftReg = 0;
|
||||
Uart.state = STATE_RECEIVING_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_RECEIVING_DATA:
|
||||
Uart.posCnt++;
|
||||
if(Uart.posCnt == 2) {
|
||||
// time to sample a bit
|
||||
Uart.shiftReg >>= 1;
|
||||
if(bit) {
|
||||
Uart.shiftReg |= 0x200;
|
||||
}
|
||||
Uart.bitCnt++;
|
||||
}
|
||||
if(Uart.posCnt >= 4) {
|
||||
Uart.posCnt = 0;
|
||||
}
|
||||
if(Uart.bitCnt == 10) {
|
||||
if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
|
||||
{
|
||||
// this is a data byte, with correct
|
||||
// start and stop bits
|
||||
Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
|
||||
Uart.byteCnt++;
|
||||
|
||||
if(Uart.byteCnt >= Uart.byteCntMax) {
|
||||
// Buffer overflowed, give up
|
||||
Uart.posCnt = 0;
|
||||
Uart.state = STATE_ERROR_WAIT;
|
||||
} else {
|
||||
// so get the next byte now
|
||||
Uart.posCnt = 0;
|
||||
Uart.state = STATE_AWAITING_START_BIT;
|
||||
}
|
||||
} else if(Uart.shiftReg == 0x000) {
|
||||
// this is an EOF byte
|
||||
return TRUE;
|
||||
} else {
|
||||
// this is an error
|
||||
Uart.posCnt = 0;
|
||||
Uart.state = STATE_ERROR_WAIT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_ERROR_WAIT:
|
||||
// We're all screwed up, so wait a little while
|
||||
// for whatever went wrong to finish, and then
|
||||
// start over.
|
||||
Uart.posCnt++;
|
||||
if(Uart.posCnt > 10) {
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Receive a command (from the reader to us, where we are the simulated tag),
|
||||
// and store it in the given buffer, up to the given maximum length. Keeps
|
||||
// spinning, waiting for a well-framed command, until either we get one
|
||||
// (returns TRUE) or someone presses the pushbutton on the board (FALSE).
|
||||
//
|
||||
// Assume that we're called with the SSC (to the FPGA) and ADC path set
|
||||
// correctly.
|
||||
//-----------------------------------------------------------------------------
|
||||
static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)
|
||||
{
|
||||
BYTE mask;
|
||||
int i, bit;
|
||||
|
||||
// Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
|
||||
|
||||
|
||||
// Now run a `software UART' on the stream of incoming samples.
|
||||
Uart.output = received;
|
||||
Uart.byteCntMax = maxLen;
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
|
||||
for(;;) {
|
||||
WDT_HIT();
|
||||
|
||||
if(BUTTON_PRESS()) return FALSE;
|
||||
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0x00;
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
BYTE b = (BYTE)SSC_RECEIVE_HOLDING;
|
||||
|
||||
mask = 0x80;
|
||||
for(i = 0; i < 8; i++, mask >>= 1) {
|
||||
bit = (b & mask);
|
||||
if(Handle14443UartBit(bit)) {
|
||||
*len = Uart.byteCnt;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main loop of simulated tag: receive commands from reader, decide what
|
||||
// response to send, and send it.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SimulateIso14443Tag(void)
|
||||
{
|
||||
static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
|
||||
static const BYTE response1[] = {
|
||||
0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,
|
||||
0x00, 0x21, 0x85, 0x5e, 0xd7
|
||||
};
|
||||
|
||||
BYTE *resp;
|
||||
int respLen;
|
||||
|
||||
BYTE *resp1 = (((BYTE *)BigBuf) + 800);
|
||||
int resp1Len;
|
||||
|
||||
BYTE *receivedCmd = (BYTE *)BigBuf;
|
||||
int len;
|
||||
|
||||
int i;
|
||||
|
||||
int cmdsRecvd = 0;
|
||||
|
||||
memset(receivedCmd, 0x44, 400);
|
||||
|
||||
CodeIso14443bAsTag(response1, sizeof(response1));
|
||||
memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
|
||||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
|
||||
cmdsRecvd = 0;
|
||||
|
||||
for(;;) {
|
||||
BYTE b1, b2;
|
||||
|
||||
if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {
|
||||
DbpIntegers(cmdsRecvd, 0, 0);
|
||||
DbpString("button press");
|
||||
break;
|
||||
}
|
||||
|
||||
// Good, look at the command now.
|
||||
|
||||
if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {
|
||||
resp = resp1; respLen = resp1Len;
|
||||
} else {
|
||||
DbpString("new cmd from reader:");
|
||||
DbpIntegers(len, 0x1234, cmdsRecvd);
|
||||
// And print whether the CRC fails, just for good measure
|
||||
ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);
|
||||
if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {
|
||||
// Not so good, try again.
|
||||
DbpString("+++CRC fail");
|
||||
} else {
|
||||
DbpString("CRC passes");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
memset(receivedCmd, 0x44, 32);
|
||||
|
||||
cmdsRecvd++;
|
||||
|
||||
if(cmdsRecvd > 0x30) {
|
||||
DbpString("many commands later...");
|
||||
break;
|
||||
}
|
||||
|
||||
if(respLen <= 0) continue;
|
||||
|
||||
// Modulate BPSK
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);
|
||||
SSC_TRANSMIT_HOLDING = 0xff;
|
||||
FpgaSetupSsc();
|
||||
|
||||
// Transmit the response.
|
||||
i = 0;
|
||||
for(;;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
BYTE b = resp[i];
|
||||
|
||||
SSC_TRANSMIT_HOLDING = b;
|
||||
|
||||
i++;
|
||||
if(i > respLen) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
volatile BYTE b = (BYTE)SSC_RECEIVE_HOLDING;
|
||||
(void)b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// An ISO 14443 Type B reader. We take layer two commands, code them
|
||||
// appropriately, and then send them to the tag. We then listen for the
|
||||
// tag's response, which we leave in the buffer to be demodulated on the
|
||||
// PC side.
|
||||
//=============================================================================
|
||||
|
||||
static struct {
|
||||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
DEMOD_PHASE_REF_TRAINING,
|
||||
DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
|
||||
DEMOD_GOT_FALLING_EDGE_OF_SOF,
|
||||
DEMOD_AWAITING_START_BIT,
|
||||
DEMOD_RECEIVING_DATA,
|
||||
DEMOD_ERROR_WAIT
|
||||
} state;
|
||||
int bitCount;
|
||||
int posCount;
|
||||
int thisBit;
|
||||
int metric;
|
||||
int metricN;
|
||||
WORD shiftReg;
|
||||
BYTE *output;
|
||||
int len;
|
||||
int sumI;
|
||||
int sumQ;
|
||||
} Demod;
|
||||
|
||||
static BOOL Handle14443SamplesDemod(int ci, int cq)
|
||||
{
|
||||
int v;
|
||||
|
||||
// The soft decision on the bit uses an estimate of just the
|
||||
// quadrant of the reference angle, not the exact angle.
|
||||
#define MAKE_SOFT_DECISION() { \
|
||||
if(Demod.sumI > 0) { \
|
||||
v = ci; \
|
||||
} else { \
|
||||
v = -ci; \
|
||||
} \
|
||||
if(Demod.sumQ > 0) { \
|
||||
v += cq; \
|
||||
} else { \
|
||||
v -= cq; \
|
||||
} \
|
||||
}
|
||||
|
||||
switch(Demod.state) {
|
||||
case DEMOD_UNSYNCD:
|
||||
v = ci;
|
||||
if(v < 0) v = -v;
|
||||
if(cq > 0) {
|
||||
v += cq;
|
||||
} else {
|
||||
v -= cq;
|
||||
}
|
||||
if(v > 40) {
|
||||
Demod.posCount = 0;
|
||||
Demod.state = DEMOD_PHASE_REF_TRAINING;
|
||||
Demod.sumI = 0;
|
||||
Demod.sumQ = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_PHASE_REF_TRAINING:
|
||||
if(Demod.posCount < 8) {
|
||||
Demod.sumI += ci;
|
||||
Demod.sumQ += cq;
|
||||
} else if(Demod.posCount > 100) {
|
||||
// error, waited too long
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
MAKE_SOFT_DECISION();
|
||||
if(v < 0) {
|
||||
Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
|
||||
Demod.posCount = 0;
|
||||
}
|
||||
}
|
||||
Demod.posCount++;
|
||||
break;
|
||||
|
||||
case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
|
||||
MAKE_SOFT_DECISION();
|
||||
if(v < 0) {
|
||||
Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
|
||||
Demod.posCount = 0;
|
||||
} else {
|
||||
if(Demod.posCount > 100) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
}
|
||||
Demod.posCount++;
|
||||
break;
|
||||
|
||||
case DEMOD_GOT_FALLING_EDGE_OF_SOF:
|
||||
MAKE_SOFT_DECISION();
|
||||
if(v > 0) {
|
||||
if(Demod.posCount < 12) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
Demod.posCount = 0;
|
||||
Demod.len = 0;
|
||||
Demod.metricN = 0;
|
||||
Demod.metric = 0;
|
||||
}
|
||||
} else {
|
||||
if(Demod.posCount > 100) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
}
|
||||
Demod.posCount++;
|
||||
break;
|
||||
|
||||
case DEMOD_AWAITING_START_BIT:
|
||||
MAKE_SOFT_DECISION();
|
||||
if(v > 0) {
|
||||
if(Demod.posCount > 10) {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
} else {
|
||||
Demod.bitCount = 0;
|
||||
Demod.posCount = 1;
|
||||
Demod.thisBit = v;
|
||||
Demod.shiftReg = 0;
|
||||
Demod.state = DEMOD_RECEIVING_DATA;
|
||||
}
|
||||
break;
|
||||
|
||||
case DEMOD_RECEIVING_DATA:
|
||||
MAKE_SOFT_DECISION();
|
||||
if(Demod.posCount == 0) {
|
||||
Demod.thisBit = v;
|
||||
Demod.posCount = 1;
|
||||
} else {
|
||||
Demod.thisBit += v;
|
||||
|
||||
if(Demod.thisBit > 0) {
|
||||
Demod.metric += Demod.thisBit;
|
||||
} else {
|
||||
Demod.metric -= Demod.thisBit;
|
||||
}
|
||||
(Demod.metricN)++;
|
||||
|
||||
Demod.shiftReg >>= 1;
|
||||
if(Demod.thisBit > 0) {
|
||||
Demod.shiftReg |= 0x200;
|
||||
}
|
||||
|
||||
Demod.bitCount++;
|
||||
if(Demod.bitCount == 10) {
|
||||
WORD s = Demod.shiftReg;
|
||||
if((s & 0x200) && !(s & 0x001)) {
|
||||
BYTE b = (s >> 1);
|
||||
Demod.output[Demod.len] = b;
|
||||
Demod.len++;
|
||||
Demod.state = DEMOD_AWAITING_START_BIT;
|
||||
} else if(s == 0x000) {
|
||||
// This is EOF
|
||||
return TRUE;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
} else {
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
}
|
||||
Demod.posCount = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void GetSamplesFor14443Demod(BOOL weTx, int n)
|
||||
{
|
||||
int max = 0;
|
||||
BOOL gotFrame = FALSE;
|
||||
|
||||
//# define DMA_BUFFER_SIZE 8
|
||||
SBYTE *dmaBuf;
|
||||
|
||||
int lastRxCounter;
|
||||
SBYTE *upTo;
|
||||
|
||||
int ci, cq;
|
||||
|
||||
int samples = 0;
|
||||
|
||||
// Clear out the state of the "UART" that receives from the tag.
|
||||
memset(BigBuf, 0x44, 400);
|
||||
Demod.output = (BYTE *)BigBuf;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
|
||||
// And the UART that receives from the reader
|
||||
Uart.output = (((BYTE *)BigBuf) + 1024);
|
||||
Uart.byteCntMax = 100;
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
|
||||
// Setup for the DMA.
|
||||
dmaBuf = (SBYTE *)(BigBuf + 32);
|
||||
upTo = dmaBuf;
|
||||
lastRxCounter = DMA_BUFFER_SIZE;
|
||||
FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);
|
||||
|
||||
// And put the FPGA in the appropriate mode
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
|
||||
(weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
|
||||
|
||||
for(;;) {
|
||||
int behindBy = lastRxCounter - PDC_RX_COUNTER(SSC_BASE);
|
||||
if(behindBy > max) max = behindBy;
|
||||
|
||||
LED_D_ON();
|
||||
while(((lastRxCounter-PDC_RX_COUNTER(SSC_BASE)) & (DMA_BUFFER_SIZE-1))
|
||||
> 2)
|
||||
{
|
||||
ci = upTo[0];
|
||||
cq = upTo[1];
|
||||
upTo += 2;
|
||||
if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
|
||||
upTo -= DMA_BUFFER_SIZE;
|
||||
PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;
|
||||
PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;
|
||||
}
|
||||
lastRxCounter -= 2;
|
||||
if(lastRxCounter <= 0) {
|
||||
lastRxCounter += DMA_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
samples += 2;
|
||||
|
||||
Handle14443UartBit(1);
|
||||
Handle14443UartBit(1);
|
||||
|
||||
if(Handle14443SamplesDemod(ci, cq)) {
|
||||
gotFrame = 1;
|
||||
}
|
||||
}
|
||||
LED_D_OFF();
|
||||
|
||||
if(samples > 2000) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;
|
||||
DbpIntegers(max, gotFrame, -1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read the tag's response. We just receive a stream of slightly-processed
|
||||
// samples from the FPGA, which we will later do some signal processing on,
|
||||
// to get the bits.
|
||||
//-----------------------------------------------------------------------------
|
||||
/*static void GetSamplesFor14443(BOOL weTx, int n)
|
||||
{
|
||||
BYTE *dest = (BYTE *)BigBuf;
|
||||
int c;
|
||||
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
|
||||
(weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));
|
||||
|
||||
c = 0;
|
||||
for(;;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0x43;
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
SBYTE b;
|
||||
b = (SBYTE)SSC_RECEIVE_HOLDING;
|
||||
|
||||
dest[c++] = (BYTE)b;
|
||||
|
||||
if(c >= n) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Transmit the command (to the tag) that was placed in ToSend[].
|
||||
//-----------------------------------------------------------------------------
|
||||
static void TransmitFor14443(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
FpgaSetupSsc();
|
||||
|
||||
while(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0xff;
|
||||
}
|
||||
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
|
||||
|
||||
for(c = 0; c < 10;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = 0xff;
|
||||
c++;
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
volatile DWORD r = SSC_RECEIVE_HOLDING;
|
||||
(void)r;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
|
||||
c = 0;
|
||||
for(;;) {
|
||||
if(SSC_STATUS & (SSC_STATUS_TX_READY)) {
|
||||
SSC_TRANSMIT_HOLDING = ToSend[c];
|
||||
c++;
|
||||
if(c >= ToSendMax) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(SSC_STATUS & (SSC_STATUS_RX_READY)) {
|
||||
volatile DWORD r = SSC_RECEIVE_HOLDING;
|
||||
(void)r;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Code a layer 2 command (string of octets, including CRC) into ToSend[],
|
||||
// so that it is ready to transmit to the tag using TransmitFor14443().
|
||||
//-----------------------------------------------------------------------------
|
||||
void CodeIso14443bAsReader(const BYTE *cmd, int len)
|
||||
{
|
||||
int i, j;
|
||||
BYTE b;
|
||||
|
||||
ToSendReset();
|
||||
|
||||
// Establish initial reference level
|
||||
for(i = 0; i < 40; i++) {
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
// Send SOF
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
// Stop bits/EGT
|
||||
ToSendStuffBit(1);
|
||||
ToSendStuffBit(1);
|
||||
// Start bit
|
||||
ToSendStuffBit(0);
|
||||
// Data bits
|
||||
b = cmd[i];
|
||||
for(j = 0; j < 8; j++) {
|
||||
if(b & 1) {
|
||||
ToSendStuffBit(1);
|
||||
} else {
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
// Send EOF
|
||||
ToSendStuffBit(1);
|
||||
for(i = 0; i < 10; i++) {
|
||||
ToSendStuffBit(0);
|
||||
}
|
||||
for(i = 0; i < 8; i++) {
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
// And then a little more, to make sure that the last character makes
|
||||
// it out before we switch to rx mode.
|
||||
for(i = 0; i < 24; i++) {
|
||||
ToSendStuffBit(1);
|
||||
}
|
||||
|
||||
// Convert from last character reference to length
|
||||
ToSendMax++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read an ISO 14443 tag. We send it some set of commands, and record the
|
||||
// responses.
|
||||
//-----------------------------------------------------------------------------
|
||||
void AcquireRawAdcSamplesIso14443(DWORD parameter)
|
||||
{
|
||||
// BYTE cmd1[] = { 0x05, 0x00, 0x00, 0x71, 0xff };
|
||||
BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };
|
||||
|
||||
// Make sure that we start from off, since the tags are stateful;
|
||||
// confusing things will happen if we don't reset them between reads.
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(200);
|
||||
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
|
||||
// Now give it time to spin up.
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);
|
||||
SpinDelay(200);
|
||||
|
||||
CodeIso14443bAsReader(cmd1, sizeof(cmd1));
|
||||
TransmitFor14443();
|
||||
LED_A_ON();
|
||||
GetSamplesFor14443Demod(TRUE, 2000);
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Finally, the `sniffer' combines elements from both the reader and
|
||||
// simulated tag, to show both sides of the conversation.
|
||||
//=============================================================================
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Record the sequence of commands sent by the reader to the tag, with
|
||||
// triggering so that we start recording at the point that the tag is moved
|
||||
// near the reader.
|
||||
//-----------------------------------------------------------------------------
|
||||
void SnoopIso14443(void)
|
||||
{
|
||||
// We won't start recording the frames that we acquire until we trigger;
|
||||
// a good trigger condition to get started is probably when we see a
|
||||
// response from the tag.
|
||||
BOOL triggered = FALSE;
|
||||
|
||||
// The command (reader -> tag) that we're working on receiving.
|
||||
BYTE *receivedCmd = (((BYTE *)BigBuf) + 1024);
|
||||
// The response (tag -> reader) that we're working on receiving.
|
||||
BYTE *receivedResponse = (((BYTE *)BigBuf) + 1536);
|
||||
|
||||
// As we receive stuff, we copy it from receivedCmd or receivedResponse
|
||||
// into trace, along with its length and other annotations.
|
||||
BYTE *trace = (BYTE *)BigBuf;
|
||||
int traceLen = 0;
|
||||
|
||||
// The DMA buffer, used to stream samples from the FPGA.
|
||||
//# define DMA_BUFFER_SIZE 256
|
||||
SBYTE *dmaBuf = ((SBYTE *)BigBuf) + 2048;
|
||||
int lastRxCounter;
|
||||
SBYTE *upTo;
|
||||
int ci, cq;
|
||||
int maxBehindBy = 0;
|
||||
|
||||
// Count of samples received so far, so that we can include timing
|
||||
// information in the trace buffer.
|
||||
int samples = 0;
|
||||
|
||||
memset(trace, 0x44, 1000);
|
||||
|
||||
// Set up the demodulator for tag -> reader responses.
|
||||
Demod.output = receivedResponse;
|
||||
Demod.len = 0;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
|
||||
// And the reader -> tag commands
|
||||
memset(&Uart, 0, sizeof(Uart));
|
||||
Uart.output = receivedCmd;
|
||||
Uart.byteCntMax = 100;
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
|
||||
// And put the FPGA in the appropriate mode
|
||||
FpgaWriteConfWord(
|
||||
FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |
|
||||
FPGA_HF_READER_RX_XCORR_SNOOP);
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
|
||||
// Setup for the DMA.
|
||||
FpgaSetupSsc();
|
||||
upTo = dmaBuf;
|
||||
lastRxCounter = DMA_BUFFER_SIZE;
|
||||
FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// And now we loop, receiving samples.
|
||||
for(;;) {
|
||||
int behindBy = (lastRxCounter - PDC_RX_COUNTER(SSC_BASE)) &
|
||||
(DMA_BUFFER_SIZE-1);
|
||||
if(behindBy > maxBehindBy) {
|
||||
maxBehindBy = behindBy;
|
||||
if(behindBy > 100) {
|
||||
DbpString("blew circular buffer!");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if(behindBy < 2) continue;
|
||||
|
||||
ci = upTo[0];
|
||||
cq = upTo[1];
|
||||
upTo += 2;
|
||||
lastRxCounter -= 2;
|
||||
if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
|
||||
upTo -= DMA_BUFFER_SIZE;
|
||||
lastRxCounter += DMA_BUFFER_SIZE;
|
||||
PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;
|
||||
PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
samples += 2;
|
||||
|
||||
#define HANDLE_BIT_IF_BODY \
|
||||
if(triggered) { \
|
||||
trace[traceLen++] = ((samples >> 0) & 0xff); \
|
||||
trace[traceLen++] = ((samples >> 8) & 0xff); \
|
||||
trace[traceLen++] = ((samples >> 16) & 0xff); \
|
||||
trace[traceLen++] = ((samples >> 24) & 0xff); \
|
||||
trace[traceLen++] = 0; \
|
||||
trace[traceLen++] = 0; \
|
||||
trace[traceLen++] = 0; \
|
||||
trace[traceLen++] = 0; \
|
||||
trace[traceLen++] = Uart.byteCnt; \
|
||||
memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \
|
||||
traceLen += Uart.byteCnt; \
|
||||
if(traceLen > 1000) break; \
|
||||
} \
|
||||
/* And ready to receive another command. */ \
|
||||
memset(&Uart, 0, sizeof(Uart)); \
|
||||
Uart.output = receivedCmd; \
|
||||
Uart.byteCntMax = 100; \
|
||||
Uart.state = STATE_UNSYNCD; \
|
||||
/* And also reset the demod code, which might have been */ \
|
||||
/* false-triggered by the commands from the reader. */ \
|
||||
memset(&Demod, 0, sizeof(Demod)); \
|
||||
Demod.output = receivedResponse; \
|
||||
Demod.state = DEMOD_UNSYNCD; \
|
||||
|
||||
if(Handle14443UartBit(ci & 1)) {
|
||||
HANDLE_BIT_IF_BODY
|
||||
}
|
||||
if(Handle14443UartBit(cq & 1)) {
|
||||
HANDLE_BIT_IF_BODY
|
||||
}
|
||||
|
||||
if(Handle14443SamplesDemod(ci, cq)) {
|
||||
// timestamp, as a count of samples
|
||||
trace[traceLen++] = ((samples >> 0) & 0xff);
|
||||
trace[traceLen++] = ((samples >> 8) & 0xff);
|
||||
trace[traceLen++] = ((samples >> 16) & 0xff);
|
||||
trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);
|
||||
// correlation metric (~signal strength estimate)
|
||||
if(Demod.metricN != 0) {
|
||||
Demod.metric /= Demod.metricN;
|
||||
}
|
||||
trace[traceLen++] = ((Demod.metric >> 0) & 0xff);
|
||||
trace[traceLen++] = ((Demod.metric >> 8) & 0xff);
|
||||
trace[traceLen++] = ((Demod.metric >> 16) & 0xff);
|
||||
trace[traceLen++] = ((Demod.metric >> 24) & 0xff);
|
||||
// length
|
||||
trace[traceLen++] = Demod.len;
|
||||
memcpy(trace+traceLen, receivedResponse, Demod.len);
|
||||
traceLen += Demod.len;
|
||||
if(traceLen > 1000) break;
|
||||
|
||||
triggered = TRUE;
|
||||
LED_A_OFF();
|
||||
LED_B_ON();
|
||||
|
||||
// And ready to receive another response.
|
||||
memset(&Demod, 0, sizeof(Demod));
|
||||
Demod.output = receivedResponse;
|
||||
Demod.state = DEMOD_UNSYNCD;
|
||||
}
|
||||
|
||||
if(BUTTON_PRESS()) {
|
||||
DbpString("cancelled");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
DbpString("in done pt");
|
||||
|
||||
DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);
|
||||
DbpIntegers(Uart.byteCntMax, traceLen, 0x23);
|
||||
|
||||
done:
|
||||
PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;
|
||||
LED_A_OFF();
|
||||
LED_B_OFF();
|
||||
}
|
1815
armsrc/iso14443a.c
Normal file
1815
armsrc/iso14443a.c
Normal file
File diff suppressed because it is too large
Load diff
1226
armsrc/iso15693.c
Normal file
1226
armsrc/iso15693.c
Normal file
File diff suppressed because it is too large
Load diff
11
armsrc/ldscript
Normal file
11
armsrc/ldscript
Normal file
|
@ -0,0 +1,11 @@
|
|||
SECTIONS
|
||||
{
|
||||
. = 0x00010000;
|
||||
.text : { obj/start.o(.text) *(.text) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = 0x00200000;
|
||||
.data : { *(.data) }
|
||||
__bss_start__ = .;
|
||||
.bss : { *(.bss) }
|
||||
__bss_end__ = .;
|
||||
}
|
11
armsrc/ldscript-fpga
Normal file
11
armsrc/ldscript-fpga
Normal file
|
@ -0,0 +1,11 @@
|
|||
SECTIONS
|
||||
{
|
||||
. = 0x00002000;
|
||||
.text : { obj/fpgaimg.o(.text) *(.text) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = 0x00200000;
|
||||
.data : { *(.data) }
|
||||
__bss_start__ = .;
|
||||
.bss : { *(.bss) }
|
||||
__bss_end__ = .;
|
||||
}
|
12
armsrc/start.c
Normal file
12
armsrc/start.c
Normal file
|
@ -0,0 +1,12 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Just vector to AppMain(). This is in its own file so that I can place it
|
||||
// with the linker script.
|
||||
// Jonathan Westhues, Mar 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <proxmark3.h>
|
||||
#include "apps.h"
|
||||
|
||||
void Vector(void)
|
||||
{
|
||||
AppMain();
|
||||
}
|
53
armsrc/util.c
Normal file
53
armsrc/util.c
Normal file
|
@ -0,0 +1,53 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Utility functions used in many places, not specific to any piece of code.
|
||||
// Jonathan Westhues, Sept 2005
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <proxmark3.h>
|
||||
#include "apps.h"
|
||||
|
||||
void *memcpy(void *dest, const void *src, int len)
|
||||
{
|
||||
BYTE *d = dest;
|
||||
const BYTE *s = src;
|
||||
while((len--) > 0) {
|
||||
*d = *s;
|
||||
d++;
|
||||
s++;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *dest, int c, int len)
|
||||
{
|
||||
BYTE *d = dest;
|
||||
while((len--) > 0) {
|
||||
*d = c;
|
||||
d++;
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
int memcmp(const void *av, const void *bv, int len)
|
||||
{
|
||||
const BYTE *a = av;
|
||||
const BYTE *b = bv;
|
||||
|
||||
while((len--) > 0) {
|
||||
if(*a != *b) {
|
||||
return *a - *b;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strlen(char *str)
|
||||
{
|
||||
int l = 0;
|
||||
while(*str) {
|
||||
l++;
|
||||
str++;
|
||||
}
|
||||
return l;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue