mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-05 20:51:18 -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
281
LICENSE.txt
Normal file
281
LICENSE.txt
Normal file
|
@ -0,0 +1,281 @@
|
|||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
3
LOG.txt
Normal file
3
LOG.txt
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
MAY 2008: Added ISO14443 type A support, Gerhard de Koning Gans
|
||||
|
28
README-gj.txt
Normal file
28
README-gj.txt
Normal file
|
@ -0,0 +1,28 @@
|
|||
Modifications to 20081211 release by d18c7db on proxmark.org
|
||||
|
||||
This compiles fine under the pre-built windows compile environment ProxSpace
|
||||
|
||||
I make no apologies for the utterly cr@p coding. It's rubbish, you've been warned.
|
||||
|
||||
Changes made to armsrc and winsrc, no changed to fpga code. Works fine with the bootloader and fpga images that you will build using the 20081211 release.
|
||||
|
||||
|
||||
Extra functionality includes:
|
||||
|
||||
ISO1443a support
|
||||
================
|
||||
|
||||
i) Support for cascade 2 select (used for UID's longer than 4 bytes)
|
||||
ii) Hard-coded (some) responses in for DESfire
|
||||
|
||||
|
||||
ISO15563 support
|
||||
================
|
||||
|
||||
i) demodulation all moved onto the arm
|
||||
ii) Addition of a command, hi15reader (a reader simulator)
|
||||
iii) Addition of a command, hi15sim (a tag simulator) - not working too well
|
||||
|
||||
|
||||
|
||||
greg.jones@digitalassurance.com
|
156
README.txt
Normal file
156
README.txt
Normal file
|
@ -0,0 +1,156 @@
|
|||
INTRO:
|
||||
|
||||
This file contains enough software, logic (for the FPGA), and design
|
||||
documentation for the hardware that you could, at least in theory,
|
||||
do something useful with a proxmark3. It has commands to:
|
||||
|
||||
* read any kind of 125 kHz unidirectional tag
|
||||
* simulate any kind of 125 kHz unidirectional tag
|
||||
|
||||
(This is enough to perform all of the silly cloning attacks, like the
|
||||
ones that I did at the Capitol in Sacramento, or anything involving
|
||||
a Verichip. From a technical standpoint, these are not that exciting,
|
||||
although the `software radio' architecture of the proxmark3 makes it
|
||||
easy and fun to support new formats.)
|
||||
|
||||
As a bonus, I include some code to use the 13.56 MHz hardware, so you can:
|
||||
|
||||
* do anything that a (medium-range) ISO 15693 reader could
|
||||
* read an ISO 14443 tag, if you know the higher-layer protocol
|
||||
* pretend to be an ISO 14443 tag, if you know the higher-layer protocol
|
||||
* snoop on an ISO 14443 transaction
|
||||
|
||||
I am not actively developing any of this. I have other projects that
|
||||
seem to be more useful.
|
||||
|
||||
USING THE PACKAGE:
|
||||
|
||||
The software tools required to build include:
|
||||
|
||||
* cygwin or other unix-like tools for Windows
|
||||
* the Microsoft Visual C++ compiler (I use Version 6)
|
||||
* arm-elf-gcc; I use WinterMute's build, from http://www.devkitpro.org/
|
||||
* Xilinx's WebPack tools
|
||||
* Modelsim (for test only)
|
||||
* perl
|
||||
|
||||
It is not necessary to build the FPGA image yourself; a pre-compiled
|
||||
image is provided, as armsrc/fpgaimg.c. This is a generated file,
|
||||
though, and you can rebuild it by running fpga/go.bat.
|
||||
|
||||
Documentation is minimal, but see the doc/ directory for what exists. A
|
||||
previous familiarity with the ARM, with digital signal processing,
|
||||
and with embedded programming in general is assumed.
|
||||
|
||||
The device is used through a specialized command line interface; for
|
||||
example, to clone a Verichip, you might type:
|
||||
|
||||
loread ; this reads the tag, and stores the
|
||||
; raw samples in memory on the ARM
|
||||
|
||||
losamples ; then we download the samples to
|
||||
; the PC
|
||||
|
||||
vchdemod clone ; demodulate the ID, and then put it
|
||||
; back in a format that we can replay
|
||||
|
||||
losim ; and then replay it
|
||||
|
||||
To read an ISO 15693 tag, you might type:
|
||||
|
||||
hiread ; read the tag; this involves sending a
|
||||
; particular command, and then getting
|
||||
; the response (which is stored as raw
|
||||
; samples in memory on the ARM)
|
||||
|
||||
hisamples ; then download those samples to the PC
|
||||
|
||||
hi15demod ; and demod them to bits (and check the
|
||||
; CRC etc. at the same time)
|
||||
|
||||
Notice that in both cases the signal processing mostly happened on the PC
|
||||
side; that is of course not practical for a real reader, but it is easier
|
||||
to initially write your code and debug on the PC side than on the ARM. As
|
||||
long as you use integer math (and I do), it's trivial to port it over
|
||||
when you're done.
|
||||
|
||||
The USB driver and bootloader are documented (and available separately
|
||||
for download, if you wish to use them in another project) at
|
||||
|
||||
http://cq.cx/trivia.pl
|
||||
|
||||
|
||||
OBTAINING HARDWARE:
|
||||
|
||||
Most of the ultra-low-volume contract assemblers that have sprung up
|
||||
(Screaming Circuits, the various cheap Asian suppliers, etc.) could put
|
||||
something like this together with a reasonable yield. A run of around
|
||||
a dozen units is probably cost-effective. The BOM includes (possibly-
|
||||
outdated) component pricing, and everything is available from Digikey
|
||||
and the usual distributors.
|
||||
|
||||
If you've never assembled a modern circuit board by hand, then this is
|
||||
not a good place to start. Some of the components (e.g. the crystals)
|
||||
must not be assembled with a soldering iron, and require hot air.
|
||||
|
||||
The schematics are included; the component values given are not
|
||||
necessarily correct for all situations, but it should be possible to do
|
||||
nearly anything you would want with appropriate population options.
|
||||
|
||||
The printed circuit board artwork is also available, as Gerbers and an
|
||||
Excellon drill file.
|
||||
|
||||
|
||||
FUTURE PLANS, ENHANCEMENTS THAT YOU COULD MAKE:
|
||||
|
||||
At some point I should write software involving a proper real-time
|
||||
operating system for the ARM. I would then provide interrupt-driven
|
||||
drivers for many of the peripherals that are polled now (the USB,
|
||||
the data stream from the FPGA), which would make it easier to develop
|
||||
complex applications.
|
||||
|
||||
It would not be all that hard to implement the ISO 15693 reader properly
|
||||
(with anticollision, all the commands supported, and so on)--the signal
|
||||
processing is already written, so it is all straightforward applications
|
||||
work.
|
||||
|
||||
I have basic support for ISO 14443 as well: a sniffer, a simulated
|
||||
tag, and a reader. It won't do anything useful unless you fill in the
|
||||
high-layer protocol.
|
||||
|
||||
Nicer (i.e., closer-to-optimal) implementations of all kinds of signal
|
||||
processing would be useful as well.
|
||||
|
||||
A practical implementation of the learning-the-tag's-ID-from-what-the-
|
||||
reader-broadcasts-during-anticollision attacks would be relatively
|
||||
straightforward. This would involve some signal processing on the FPGA,
|
||||
but not much else after that.
|
||||
|
||||
It would be neat to write a driver that could stream samples from the A/Ds
|
||||
over USB to the PC, using the full available bandwidth of USB. I am not
|
||||
yet sure what that would be good for, but surely something. This would
|
||||
require a kernel-mode driver under Windows, though, which is more work.
|
||||
|
||||
|
||||
LICENSING:
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Jonathan Westhues
|
||||
user jwesthues, at host cq.cx
|
||||
|
||||
May 2007, Cambridge MA
|
||||
|
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;
|
||||
}
|
58
bootrom/Makefile
Normal file
58
bootrom/Makefile
Normal file
|
@ -0,0 +1,58 @@
|
|||
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
|
||||
|
||||
CFLAGS = -g -c $(INCLUDE) -Wall
|
||||
|
||||
OBJJTAG = $(OBJDIR)/bootrom.o $(OBJDIR)/ram-reset.o $(OBJDIR)/usb.o
|
||||
|
||||
OBJFLASH = $(OBJDIR)/flash-reset.o $(OBJDIR)/fromflash.o
|
||||
|
||||
all: bootrom.s19
|
||||
|
||||
bootrom.s19: $(OBJDIR)/bootrom.s19 $(OBJDIR)/bootrom-forjtag.s19
|
||||
@echo bootrom.s19
|
||||
@perl ..\tools\merge-srec.pl $(OBJDIR)\bootrom.s19 $(OBJDIR)\bootrom-forjtag.s19 > $(OBJDIR)\bootrom-merged.s19
|
||||
@perl ..\tools\srecswap.pl $(OBJDIR)\bootrom-forjtag.s19 > $(OBJDIR)\bootrom-forjtag-swapped.s19
|
||||
|
||||
$(OBJDIR)/bootrom.s19: $(OBJFLASH)
|
||||
@echo obj/bootrom.s19
|
||||
@$(LD) -g -Tldscript-flash --oformat elf32-littlearm -o $(OBJDIR)/bootrom.elf $(OBJFLASH)
|
||||
@$(OBJCOPY) -Osrec --srec-forceS3 $(OBJDIR)/bootrom.elf $(OBJDIR)/bootrom.s19
|
||||
|
||||
$(OBJDIR)/bootrom-forjtag.s19: $(OBJJTAG)
|
||||
@echo obj/bootrom-forjtag.s19
|
||||
@$(LD) -g -Tldscript-ram-jtag --oformat elf32-littlearm -o $(OBJDIR)/bootrom-forjtag.elf $(OBJJTAG)
|
||||
@$(OBJCOPY) -Osrec --srec-forceS3 $(OBJDIR)/bootrom-forjtag.elf $(OBJDIR)/bootrom-forjtag.s19
|
||||
|
||||
$(OBJDIR)/bootrom.o: bootrom.c $(INCLUDES)
|
||||
@echo $(@B).c
|
||||
@$(CC) $(CFLAGS) -mthumb -mthumb-interwork bootrom.c -o $(OBJDIR)/bootrom.o
|
||||
|
||||
$(OBJDIR)/fromflash.o: fromflash.c $(INCLUDES)
|
||||
@echo $(@B).c
|
||||
@$(CC) $(CFLAGS) -mthumb -mthumb-interwork fromflash.c -o $(OBJDIR)/fromflash.o
|
||||
|
||||
$(OBJDIR)/usb.o: ../common/usb.c $(INCLUDES)
|
||||
@echo $(@B).c
|
||||
@$(CC) $(CFLAGS) -mthumb -mthumb-interwork ../common/usb.c -o $(OBJDIR)/usb.o
|
||||
|
||||
$(OBJDIR)/ram-reset.o: ram-reset.s
|
||||
@echo $(@B).s
|
||||
@$(CC) $(CFLAGS) -mthumb-interwork -o $(OBJDIR)/ram-reset.o ram-reset.s
|
||||
|
||||
$(OBJDIR)/flash-reset.o: flash-reset.s
|
||||
@echo $(@B).s
|
||||
@$(CC) $(CFLAGS) -mthumb-interwork -o $(OBJDIR)/flash-reset.o flash-reset.s
|
||||
|
||||
clean:
|
||||
del /q obj\*.o
|
||||
del /q obj\*.elf
|
||||
del /q obj\*.s19
|
190
bootrom/bootrom.c
Normal file
190
bootrom/bootrom.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include <proxmark3.h>
|
||||
|
||||
static void ConfigClocks(void)
|
||||
{
|
||||
// we are using a 16 MHz crystal as the basis for everything
|
||||
// slow clock runs at 32Khz typical regardless of crystal
|
||||
|
||||
// enable system clock and USB clock
|
||||
PMC_SYS_CLK_ENABLE = PMC_SYS_CLK_PROCESSOR_CLK | PMC_SYS_CLK_UDP_CLK;
|
||||
|
||||
// enable the clock to the following peripherals
|
||||
PMC_PERIPHERAL_CLK_ENABLE =
|
||||
(1<<PERIPH_PIOA) |
|
||||
(1<<PERIPH_ADC) |
|
||||
(1<<PERIPH_SPI) |
|
||||
(1<<PERIPH_SSC) |
|
||||
(1<<PERIPH_PWMC) |
|
||||
(1<<PERIPH_UDP);
|
||||
|
||||
// worst case scenario, with 16Mhz xtal startup delay is 14.5ms
|
||||
// with a slow clock running at it worst case (max) frequency of 42khz
|
||||
// max startup delay = (14.5ms*42k)/8 = 76 = 0x4C round up to 0x50
|
||||
|
||||
// enable main oscillator and set startup delay
|
||||
PMC_MAIN_OSCILLATOR = PMC_MAIN_OSCILLATOR_ENABLE |
|
||||
PMC_MAIN_OSCILLATOR_STARTUP_DELAY(0x50);
|
||||
|
||||
// wait for main oscillator to stabilize
|
||||
while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_STABILIZED) )
|
||||
;
|
||||
|
||||
// minimum PLL clock frequency is 80 MHz in range 00 (96 here so okay)
|
||||
// frequency is crystal * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz
|
||||
PMC_PLL = PMC_PLL_DIVISOR(2) | PMC_PLL_COUNT_BEFORE_LOCK(0x50) |
|
||||
PMC_PLL_FREQUENCY_RANGE(0) | PMC_PLL_MULTIPLIER(12) |
|
||||
PMC_PLL_USB_DIVISOR(1);
|
||||
|
||||
// wait for PLL to lock
|
||||
while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_PLL_LOCK) )
|
||||
;
|
||||
|
||||
// we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz
|
||||
// as per datasheet, this register must be programmed in two operations
|
||||
// when changing to PLL, program the prescaler first then the source
|
||||
PMC_MASTER_CLK = PMC_CLK_PRESCALE_DIV_2;
|
||||
|
||||
// wait for main clock ready signal
|
||||
while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_MCK_READY) )
|
||||
;
|
||||
|
||||
// set the source to PLL
|
||||
PMC_MASTER_CLK = PMC_CLK_SELECTION_PLL_CLOCK | PMC_CLK_PRESCALE_DIV_2;
|
||||
|
||||
// wait for main clock ready signal
|
||||
while ( !(PMC_INTERRUPT_STATUS & PMC_MAIN_OSCILLATOR_MCK_READY) )
|
||||
;
|
||||
}
|
||||
|
||||
static void Fatal(void)
|
||||
{
|
||||
for(;;);
|
||||
}
|
||||
|
||||
void UsbPacketReceived(BYTE *packet, int len)
|
||||
{
|
||||
int i;
|
||||
UsbCommand *c = (UsbCommand *)packet;
|
||||
volatile DWORD *p;
|
||||
|
||||
if(len != sizeof(*c)) {
|
||||
Fatal();
|
||||
}
|
||||
|
||||
switch(c->cmd) {
|
||||
case CMD_DEVICE_INFO:
|
||||
break;
|
||||
|
||||
case CMD_SETUP_WRITE:
|
||||
p = (volatile DWORD *)0;
|
||||
for(i = 0; i < 12; i++) {
|
||||
p[i+c->ext1] = c->d.asDwords[i];
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_FINISH_WRITE:
|
||||
p = (volatile DWORD *)0;
|
||||
for(i = 0; i < 4; i++) {
|
||||
p[i+60] = c->d.asDwords[i];
|
||||
}
|
||||
|
||||
MC_FLASH_COMMAND = MC_FLASH_COMMAND_KEY |
|
||||
MC_FLASH_COMMAND_PAGEN(c->ext1/FLASH_PAGE_SIZE_BYTES) |
|
||||
FCMD_WRITE_PAGE;
|
||||
while(!(MC_FLASH_STATUS & MC_FLASH_STATUS_READY))
|
||||
;
|
||||
break;
|
||||
|
||||
case CMD_HARDWARE_RESET:
|
||||
break;
|
||||
|
||||
default:
|
||||
Fatal();
|
||||
break;
|
||||
}
|
||||
|
||||
c->cmd = CMD_ACK;
|
||||
UsbSendPacket(packet, len);
|
||||
}
|
||||
|
||||
void BootROM(void)
|
||||
{
|
||||
//------------
|
||||
// First set up all the I/O pins; GPIOs configured directly, other ones
|
||||
// just need to be assigned to the appropriate peripheral.
|
||||
|
||||
// Kill all the pullups, especially the one on USB D+; leave them for
|
||||
// the unused pins, though.
|
||||
PIO_NO_PULL_UP_ENABLE = (1 << GPIO_USB_PU) |
|
||||
(1 << GPIO_LED_A) |
|
||||
(1 << GPIO_LED_B) |
|
||||
(1 << GPIO_LED_C) |
|
||||
(1 << GPIO_LED_D) |
|
||||
(1 << GPIO_FPGA_DIN) |
|
||||
(1 << GPIO_FPGA_DOUT) |
|
||||
(1 << GPIO_FPGA_CCLK) |
|
||||
(1 << GPIO_FPGA_NINIT) |
|
||||
(1 << GPIO_FPGA_NPROGRAM) |
|
||||
(1 << GPIO_FPGA_DONE) |
|
||||
(1 << GPIO_MUXSEL_HIPKD) |
|
||||
(1 << GPIO_MUXSEL_HIRAW) |
|
||||
(1 << GPIO_MUXSEL_LOPKD) |
|
||||
(1 << GPIO_MUXSEL_LORAW) |
|
||||
(1 << GPIO_RELAY) |
|
||||
(1 << GPIO_NVDD_ON);
|
||||
// (and add GPIO_FPGA_ON)
|
||||
// These pins are outputs
|
||||
PIO_OUTPUT_ENABLE = (1 << GPIO_LED_A) |
|
||||
(1 << GPIO_LED_B) |
|
||||
(1 << GPIO_LED_C) |
|
||||
(1 << GPIO_LED_D) |
|
||||
(1 << GPIO_RELAY) |
|
||||
(1 << GPIO_NVDD_ON);
|
||||
// PIO controls the following pins
|
||||
PIO_ENABLE = (1 << GPIO_USB_PU) |
|
||||
(1 << GPIO_LED_A) |
|
||||
(1 << GPIO_LED_B) |
|
||||
(1 << GPIO_LED_C) |
|
||||
(1 << GPIO_LED_D);
|
||||
|
||||
USB_D_PLUS_PULLUP_OFF();
|
||||
LED_D_OFF();
|
||||
LED_C_ON();
|
||||
LED_B_OFF();
|
||||
LED_A_OFF();
|
||||
|
||||
// if 512K FLASH part - TODO make some defines :)
|
||||
if ((DBGU_CIDR | 0xf00) == 0xa00) {
|
||||
MC_FLASH_MODE0 = MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
|
||||
MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
|
||||
MC_FLASH_MODE1 = MC_FLASH_MODE_FLASH_WAIT_STATES(1) |
|
||||
MC_FLASH_MODE_MASTER_CLK_IN_MHZ(0x48);
|
||||
} else {
|
||||
MC_FLASH_MODE0 = MC_FLASH_MODE_FLASH_WAIT_STATES(0) |
|
||||
MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
|
||||
}
|
||||
|
||||
// Initialize all system clocks
|
||||
ConfigClocks();
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
if(BUTTON_PRESS()) {
|
||||
UsbStart();
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
WDT_HIT();
|
||||
|
||||
UsbPoll(TRUE);
|
||||
|
||||
if(!BUTTON_PRESS()) {
|
||||
USB_D_PLUS_PULLUP_OFF();
|
||||
LED_B_ON();
|
||||
|
||||
// jump to RAM address 0x10000 (LSBit set for thumb mode)
|
||||
asm("ldr r3, = 0x10001\n");
|
||||
asm("bx r3\n");
|
||||
}
|
||||
}
|
||||
}
|
38
bootrom/flash-reset.s
Normal file
38
bootrom/flash-reset.s
Normal file
|
@ -0,0 +1,38 @@
|
|||
.extern CopyBootToRAM
|
||||
|
||||
.text
|
||||
.code 32
|
||||
.align 0
|
||||
|
||||
.global start
|
||||
start:
|
||||
b Reset
|
||||
b UndefinedInstruction
|
||||
b SoftwareInterrupt
|
||||
b PrefetchAbort
|
||||
b DataAbort
|
||||
b Reserved
|
||||
b Irq
|
||||
b Fiq
|
||||
|
||||
Reset:
|
||||
ldr sp, = 0x0020FFF8 @ initialize stack pointer to top of RAM
|
||||
bl CopyBootToRAM @ copy bootloader to RAM (in case the
|
||||
@ user re-flashes the bootloader)
|
||||
ldr r3, = 0x00200000 @ start address of RAM bootloader
|
||||
bx r3 @ jump to it
|
||||
|
||||
Fiq:
|
||||
b Fiq
|
||||
UndefinedInstruction:
|
||||
b UndefinedInstruction
|
||||
SoftwareInterrupt:
|
||||
b SoftwareInterrupt
|
||||
PrefetchAbort:
|
||||
b PrefetchAbort
|
||||
DataAbort:
|
||||
b DataAbort
|
||||
Reserved:
|
||||
b Reserved
|
||||
Irq:
|
||||
b Irq
|
11
bootrom/fromflash.c
Normal file
11
bootrom/fromflash.c
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include <proxmark3.h>
|
||||
|
||||
void CopyBootToRAM(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
volatile DWORD *s = (volatile DWORD *)0x200;
|
||||
volatile DWORD *d = (volatile DWORD *)0x200000;
|
||||
|
||||
for(i = 0; i < 1024; i++) *d++ = *s++;
|
||||
}
|
11
bootrom/ldscript-flash
Normal file
11
bootrom/ldscript-flash
Normal file
|
@ -0,0 +1,11 @@
|
|||
SECTIONS
|
||||
{
|
||||
. = 0x00000000;
|
||||
.text : { obj/flash-reset.o(.text) *(.text) }
|
||||
.rodata : { *(.rodata) }
|
||||
. = 0x00200000;
|
||||
.data : { *(.data) }
|
||||
__bss_start__ = .;
|
||||
.bss : { *(.bss) }
|
||||
__bss_end__ = .;
|
||||
}
|
10
bootrom/ldscript-ram-jtag
Normal file
10
bootrom/ldscript-ram-jtag
Normal file
|
@ -0,0 +1,10 @@
|
|||
SECTIONS
|
||||
{
|
||||
. = 0x00200000;
|
||||
.text : { obj/ram-reset.o(.text) *(.text) }
|
||||
.rodata : { *(.rodata) }
|
||||
.data : { *(.data) }
|
||||
__bss_start__ = .;
|
||||
.bss : { *(.bss) }
|
||||
__bss_end__ = .;
|
||||
}
|
10
bootrom/ram-reset.s
Normal file
10
bootrom/ram-reset.s
Normal file
|
@ -0,0 +1,10 @@
|
|||
.extern BootROM
|
||||
|
||||
.text
|
||||
.code 32
|
||||
.align 0
|
||||
|
||||
.global start
|
||||
start:
|
||||
ldr sp, = 0x0020FFF8
|
||||
bl BootROM
|
5
cockpit/0setpath.bat
Normal file
5
cockpit/0setpath.bat
Normal file
|
@ -0,0 +1,5 @@
|
|||
@echo off
|
||||
set PATH=..\..\devkitARM\bin;..\..\devkitWIN\bin;%PATH%
|
||||
set INCLUDE=..\..\devkitWIN\include
|
||||
set LIB=..\..\devkitWIN\lib
|
||||
cmd.exe
|
5
cockpit/1makearm.bat
Normal file
5
cockpit/1makearm.bat
Normal file
|
@ -0,0 +1,5 @@
|
|||
@echo off
|
||||
cd ..\armsrc
|
||||
rem nmake clean
|
||||
nmake
|
||||
cd ..\cockpit
|
5
cockpit/2makeboot.bat
Normal file
5
cockpit/2makeboot.bat
Normal file
|
@ -0,0 +1,5 @@
|
|||
@echo off
|
||||
cd ..\bootrom
|
||||
rem nmake clean
|
||||
nmake
|
||||
cd ..\cockpit
|
5
cockpit/3makewin.bat
Normal file
5
cockpit/3makewin.bat
Normal file
|
@ -0,0 +1,5 @@
|
|||
@echo off
|
||||
cd ..\winsrc
|
||||
rem nmake clean
|
||||
nmake
|
||||
cd ..\cockpit
|
3
cockpit/4flashos.bat
Normal file
3
cockpit/4flashos.bat
Normal file
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
..\winsrc\prox.exe load ..\armsrc\obj\osimage.s19
|
||||
..\winsrc\prox.exe load ..\armsrc\obj\osimage.s19
|
3
cockpit/5makeall.bat
Normal file
3
cockpit/5makeall.bat
Normal file
|
@ -0,0 +1,3 @@
|
|||
call 1makearm.bat
|
||||
call 2makeboot.bat
|
||||
call 3makewin.bat
|
3
cockpit/prox.bat
Normal file
3
cockpit/prox.bat
Normal file
|
@ -0,0 +1,3 @@
|
|||
@echo off
|
||||
cd ..\winsrc
|
||||
call prox gui
|
35
common/iso14443_crc.c
Normal file
35
common/iso14443_crc.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Routines to compute the CRCs (two different flavours, just for confusion)
|
||||
// required for ISO 14443, swiped directly from the spec.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define CRC_14443_A 0x6363 /* ITU-V.41 */
|
||||
#define CRC_14443_B 0xFFFF /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
|
||||
|
||||
static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc)
|
||||
{
|
||||
ch = (ch ^ (unsigned char) ((*lpwCrc) & 0x00FF));
|
||||
ch = (ch ^ (ch << 4));
|
||||
*lpwCrc = (*lpwCrc >> 8) ^ ((unsigned short) ch << 8) ^
|
||||
((unsigned short) ch << 3) ^ ((unsigned short) ch >> 4);
|
||||
return (*lpwCrc);
|
||||
}
|
||||
|
||||
static void ComputeCrc14443(int CrcType, BYTE *Data, int Length,
|
||||
BYTE *TransmitFirst, BYTE *TransmitSecond)
|
||||
{
|
||||
unsigned char chBlock;
|
||||
unsigned short wCrc=CrcType;
|
||||
|
||||
do {
|
||||
chBlock = *Data++;
|
||||
UpdateCrc14443(chBlock, &wCrc);
|
||||
} while (--Length);
|
||||
|
||||
if (CrcType == CRC_14443_B)
|
||||
wCrc = ~wCrc; /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
|
||||
|
||||
*TransmitFirst = (BYTE) (wCrc & 0xFF);
|
||||
*TransmitSecond = (BYTE) ((wCrc >> 8) & 0xFF);
|
||||
return;
|
||||
}
|
472
common/usb.c
Normal file
472
common/usb.c
Normal file
|
@ -0,0 +1,472 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// My USB driver. This has to be common, because it exists in both the
|
||||
// bootrom and the application.
|
||||
// Jonathan Westhues, split Aug 14 2005
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <proxmark3.h>
|
||||
|
||||
#define min(a, b) (((a) > (b)) ? (b) : (a))
|
||||
|
||||
#define USB_REPORT_PACKET_SIZE 64
|
||||
|
||||
typedef struct PACKED {
|
||||
BYTE bmRequestType;
|
||||
BYTE bRequest;
|
||||
WORD wValue;
|
||||
WORD wIndex;
|
||||
WORD wLength;
|
||||
} UsbSetupData;
|
||||
|
||||
#define USB_REQUEST_GET_STATUS 0
|
||||
#define USB_REQUEST_CLEAR_FEATURE 1
|
||||
#define USB_REQUEST_SET_FEATURE 3
|
||||
#define USB_REQUEST_SET_ADDRESS 5
|
||||
#define USB_REQUEST_GET_DESCRIPTOR 6
|
||||
#define USB_REQUEST_SET_DESCRIPTOR 7
|
||||
#define USB_REQUEST_GET_CONFIGURATION 8
|
||||
#define USB_REQUEST_SET_CONFIGURATION 9
|
||||
#define USB_REQUEST_GET_INTERFACE 10
|
||||
#define USB_REQUEST_SET_INTERFACE 11
|
||||
#define USB_REQUEST_SYNC_FRAME 12
|
||||
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE 1
|
||||
#define USB_DESCRIPTOR_TYPE_CONFIGURATION 2
|
||||
#define USB_DESCRIPTOR_TYPE_STRING 3
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE 4
|
||||
#define USB_DESCRIPTOR_TYPE_ENDPOINT 5
|
||||
#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 6
|
||||
#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONF 7
|
||||
#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 8
|
||||
#define USB_DESCRIPTOR_TYPE_HID 0x21
|
||||
#define USB_DESCRIPTOR_TYPE_HID_REPORT 0x22
|
||||
|
||||
#define USB_DEVICE_CLASS_HID 0x03
|
||||
|
||||
static const BYTE HidReportDescriptor[] = {
|
||||
0x06,0xA0,0xFF, // Usage Page (vendor defined) FFA0
|
||||
0x09,0x01, // Usage (vendor defined)
|
||||
0xA1,0x01, // Collection (Application)
|
||||
0x09,0x02, // Usage (vendor defined)
|
||||
0xA1,0x00, // Collection (Physical)
|
||||
0x06,0xA1,0xFF, // Usage Page (vendor defined)
|
||||
|
||||
//The,input report
|
||||
0x09,0x03, // usage - vendor defined
|
||||
0x09,0x04, // usage - vendor defined
|
||||
0x15,0x80, // Logical Minimum (-128)
|
||||
0x25,0x7F, // Logical Maximum (127)
|
||||
0x35,0x00, // Physical Minimum (0)
|
||||
0x45,0xFF, // Physical Maximum (255)
|
||||
0x75,0x08, // Report Size (8) (bits)
|
||||
0x95,0x40, // Report Count (64) (fields)
|
||||
0x81,0x02, // Input (Data,Variable,Absolute)
|
||||
|
||||
//The,output report
|
||||
0x09,0x05, // usage - vendor defined
|
||||
0x09,0x06, // usage - vendor defined
|
||||
0x15,0x80, // Logical Minimum (-128)
|
||||
0x25,0x7F, // Logical Maximum (127)
|
||||
0x35,0x00, // Physical Minimum (0)
|
||||
0x45,0xFF, // Physical Maximum (255)
|
||||
0x75,0x08, // Report Size (8) (bits)
|
||||
0x95,0x40, // Report Count (64) (fields)
|
||||
0x91,0x02, // Output (Data,Variable,Absolute)
|
||||
|
||||
0xC0, // End Collection
|
||||
|
||||
0xC0, // End Collection
|
||||
};
|
||||
|
||||
static const BYTE DeviceDescriptor[] = {
|
||||
0x12, // Descriptor length (18 bytes)
|
||||
0x01, // Descriptor type (Device)
|
||||
0x10,0x01, // Complies with USB Spec. Release (0110h = release 1.10)
|
||||
0x00, // Class code (0)
|
||||
0x00, // Subclass code (0)
|
||||
0x00, // Protocol (No specific protocol)
|
||||
0x08, // Maximum packet size for Endpoint 0 (8 bytes)
|
||||
0xc4,0x9a, // Vendor ID (random numbers)
|
||||
0x8f,0x4b, // Product ID (random numbers)
|
||||
0x01,0x00, // Device release number (0001)
|
||||
0x01, // Manufacturer string descriptor index
|
||||
0x02, // Product string descriptor index
|
||||
0x00, // Serial Number string descriptor index (None)
|
||||
0x01, // Number of possible configurations (1)
|
||||
};
|
||||
|
||||
static const BYTE ConfigurationDescriptor[] = {
|
||||
0x09, // Descriptor length (9 bytes)
|
||||
0x02, // Descriptor type (Configuration)
|
||||
0x29,0x00, // Total data length (41 bytes)
|
||||
0x01, // Interface supported (1)
|
||||
0x01, // Configuration value (1)
|
||||
0x00, // Index of string descriptor (None)
|
||||
0x80, // Configuration (Bus powered)
|
||||
250, // Maximum power consumption (500mA)
|
||||
|
||||
//interface
|
||||
0x09, // Descriptor length (9 bytes)
|
||||
0x04, // Descriptor type (Interface)
|
||||
0x00, // Number of interface (0)
|
||||
0x00, // Alternate setting (0)
|
||||
0x02, // Number of interface endpoint (2)
|
||||
0x03, // Class code (HID)
|
||||
0x00, // Subclass code ()
|
||||
0x00, // Protocol code ()
|
||||
0x00, // Index of string()
|
||||
|
||||
// class
|
||||
0x09, // Descriptor length (9 bytes)
|
||||
0x21, // Descriptor type (HID)
|
||||
0x00,0x01, // HID class release number (1.00)
|
||||
0x00, // Localized country code (None)
|
||||
0x01, // # of HID class dscrptr to follow (1)
|
||||
0x22, // Report descriptor type (HID)
|
||||
// Total length of report descriptor
|
||||
sizeof(HidReportDescriptor),0x00,
|
||||
|
||||
// endpoint 1
|
||||
0x07, // Descriptor length (7 bytes)
|
||||
0x05, // Descriptor type (Endpoint)
|
||||
0x01, // Encoded address (Respond to OUT)
|
||||
0x03, // Endpoint attribute (Interrupt transfer)
|
||||
0x08,0x00, // Maximum packet size (8 bytes)
|
||||
0x01, // Polling interval (1 ms)
|
||||
|
||||
// endpoint 2
|
||||
0x07, // Descriptor length (7 bytes)
|
||||
0x05, // Descriptor type (Endpoint)
|
||||
0x82, // Encoded address (Respond to IN)
|
||||
0x03, // Endpoint attribute (Interrupt transfer)
|
||||
0x08,0x00, // Maximum packet size (8 bytes)
|
||||
0x01, // Polling interval (1 ms)
|
||||
};
|
||||
|
||||
static const BYTE StringDescriptor0[] = {
|
||||
0x04, // Length
|
||||
0x03, // Type is string
|
||||
0x09, // English
|
||||
0x04, // US
|
||||
};
|
||||
|
||||
static const BYTE StringDescriptor1[] = {
|
||||
24, // Length
|
||||
0x03, // Type is string
|
||||
'J', 0x00,
|
||||
'.', 0x00,
|
||||
' ', 0x00,
|
||||
'W', 0x00,
|
||||
'e', 0x00,
|
||||
's', 0x00,
|
||||
't', 0x00,
|
||||
'h', 0x00,
|
||||
'u', 0x00,
|
||||
'e', 0x00,
|
||||
's', 0x00,
|
||||
};
|
||||
|
||||
static const BYTE StringDescriptor2[] = {
|
||||
54, // Length
|
||||
0x03, // Type is string
|
||||
'P', 0x00,
|
||||
'r', 0x00,
|
||||
'o', 0x00,
|
||||
'x', 0x00,
|
||||
'M', 0x00,
|
||||
'a', 0x00,
|
||||
'r', 0x00,
|
||||
'k', 0x00,
|
||||
'-', 0x00,
|
||||
'3', 0x00,
|
||||
' ', 0x00,
|
||||
'R', 0x00,
|
||||
'F', 0x00,
|
||||
'I', 0x00,
|
||||
'D', 0x00,
|
||||
' ', 0x00,
|
||||
'I', 0x00,
|
||||
'n', 0x00,
|
||||
's', 0x00,
|
||||
't', 0x00,
|
||||
'r', 0x00,
|
||||
'u', 0x00,
|
||||
'm', 0x00,
|
||||
'e', 0x00,
|
||||
'n', 0x00,
|
||||
't', 0x00,
|
||||
};
|
||||
|
||||
static const BYTE * const StringDescriptors[] = {
|
||||
StringDescriptor0,
|
||||
StringDescriptor1,
|
||||
StringDescriptor2,
|
||||
};
|
||||
|
||||
|
||||
static BYTE UsbBuffer[64];
|
||||
static int UsbSoFarCount;
|
||||
|
||||
static BYTE CurrentConfiguration;
|
||||
|
||||
static void UsbSendEp0(const BYTE *data, int len)
|
||||
{
|
||||
int thisTime, i;
|
||||
|
||||
do {
|
||||
thisTime = min(len, 8);
|
||||
len -= thisTime;
|
||||
|
||||
for(i = 0; i < thisTime; i++) {
|
||||
UDP_ENDPOINT_FIFO(0) = *data;
|
||||
data++;
|
||||
}
|
||||
|
||||
if(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED) {
|
||||
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;
|
||||
while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)
|
||||
;
|
||||
}
|
||||
|
||||
UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;
|
||||
|
||||
do {
|
||||
if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {
|
||||
// This means that the host is trying to write to us, so
|
||||
// abandon our write to them.
|
||||
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;
|
||||
return;
|
||||
}
|
||||
} while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED));
|
||||
} while(len > 0);
|
||||
|
||||
if(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED) {
|
||||
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;
|
||||
while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void UsbSendZeroLength(void)
|
||||
{
|
||||
UDP_ENDPOINT_CSR(0) |= UDP_CSR_TX_PACKET;
|
||||
|
||||
while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED))
|
||||
;
|
||||
|
||||
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_TX_PACKET_ACKED;
|
||||
|
||||
while(UDP_ENDPOINT_CSR(0) & UDP_CSR_TX_PACKET_ACKED)
|
||||
;
|
||||
}
|
||||
|
||||
static void HandleRxdSetupData(void)
|
||||
{
|
||||
int i;
|
||||
UsbSetupData usd;
|
||||
|
||||
for(i = 0; i < sizeof(usd); i++) {
|
||||
((BYTE *)&usd)[i] = UDP_ENDPOINT_FIFO(0);
|
||||
}
|
||||
|
||||
if(usd.bmRequestType & 0x80) {
|
||||
UDP_ENDPOINT_CSR(0) |= UDP_CSR_CONTROL_DATA_DIR;
|
||||
while(!(UDP_ENDPOINT_CSR(0) & UDP_CSR_CONTROL_DATA_DIR))
|
||||
;
|
||||
}
|
||||
|
||||
UDP_ENDPOINT_CSR(0) &= ~UDP_CSR_RX_HAVE_READ_SETUP_DATA;
|
||||
while(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA)
|
||||
;
|
||||
|
||||
switch(usd.bRequest) {
|
||||
case USB_REQUEST_GET_DESCRIPTOR:
|
||||
if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_DEVICE) {
|
||||
UsbSendEp0((BYTE *)&DeviceDescriptor,
|
||||
min(sizeof(DeviceDescriptor), usd.wLength));
|
||||
} else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
|
||||
UsbSendEp0((BYTE *)&ConfigurationDescriptor,
|
||||
min(sizeof(ConfigurationDescriptor), usd.wLength));
|
||||
} else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_STRING) {
|
||||
const BYTE *s = StringDescriptors[usd.wValue & 0xff];
|
||||
UsbSendEp0(s, min(s[0], usd.wLength));
|
||||
} else if((usd.wValue >> 8) == USB_DESCRIPTOR_TYPE_HID_REPORT) {
|
||||
UsbSendEp0((BYTE *)&HidReportDescriptor,
|
||||
min(sizeof(HidReportDescriptor), usd.wLength));
|
||||
} else {
|
||||
*((DWORD *)0x00200000) = usd.wValue;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQUEST_SET_ADDRESS:
|
||||
UsbSendZeroLength();
|
||||
UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED | usd.wValue ;
|
||||
if(usd.wValue != 0) {
|
||||
UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;
|
||||
} else {
|
||||
UDP_GLOBAL_STATE = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_CONFIGURATION:
|
||||
UsbSendEp0(&CurrentConfiguration, sizeof(CurrentConfiguration));
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_STATUS: {
|
||||
if(usd.bmRequestType & 0x80) {
|
||||
WORD w = 0;
|
||||
UsbSendEp0((BYTE *)&w, sizeof(w));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case USB_REQUEST_SET_CONFIGURATION:
|
||||
CurrentConfiguration = usd.wValue;
|
||||
if(CurrentConfiguration) {
|
||||
UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_CONFIGURED;
|
||||
UDP_ENDPOINT_CSR(1) = UDP_CSR_ENABLE_EP |
|
||||
UDP_CSR_EPTYPE_INTERRUPT_OUT;
|
||||
UDP_ENDPOINT_CSR(2) = UDP_CSR_ENABLE_EP |
|
||||
UDP_CSR_EPTYPE_INTERRUPT_IN;
|
||||
} else {
|
||||
UDP_GLOBAL_STATE = UDP_GLOBAL_STATE_ADDRESSED;
|
||||
UDP_ENDPOINT_CSR(1) = 0;
|
||||
UDP_ENDPOINT_CSR(2) = 0;
|
||||
}
|
||||
UsbSendZeroLength();
|
||||
break;
|
||||
|
||||
case USB_REQUEST_GET_INTERFACE: {
|
||||
BYTE b = 0;
|
||||
UsbSendEp0(&b, sizeof(b));
|
||||
break;
|
||||
}
|
||||
|
||||
case USB_REQUEST_SET_INTERFACE:
|
||||
UsbSendZeroLength();
|
||||
break;
|
||||
|
||||
case USB_REQUEST_CLEAR_FEATURE:
|
||||
case USB_REQUEST_SET_FEATURE:
|
||||
case USB_REQUEST_SET_DESCRIPTOR:
|
||||
case USB_REQUEST_SYNC_FRAME:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UsbSendPacket(BYTE *packet, int len)
|
||||
{
|
||||
int i, thisTime;
|
||||
|
||||
while(len > 0) {
|
||||
thisTime = min(len, 8);
|
||||
|
||||
for(i = 0; i < thisTime; i++) {
|
||||
UDP_ENDPOINT_FIFO(2) = packet[i];
|
||||
}
|
||||
UDP_ENDPOINT_CSR(2) |= UDP_CSR_TX_PACKET;
|
||||
|
||||
while(!(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED))
|
||||
;
|
||||
UDP_ENDPOINT_CSR(2) &= ~UDP_CSR_TX_PACKET_ACKED;
|
||||
|
||||
while(UDP_ENDPOINT_CSR(2) & UDP_CSR_TX_PACKET_ACKED)
|
||||
;
|
||||
|
||||
len -= thisTime;
|
||||
packet += thisTime;
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleRxdData(void)
|
||||
{
|
||||
int i, len;
|
||||
|
||||
if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0) {
|
||||
len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);
|
||||
UsbSoFarCount++;
|
||||
}
|
||||
|
||||
UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_0;
|
||||
while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_0)
|
||||
;
|
||||
|
||||
if(UsbSoFarCount >= 64) {
|
||||
UsbPacketReceived(UsbBuffer, UsbSoFarCount);
|
||||
UsbSoFarCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1) {
|
||||
len = UDP_CSR_BYTES_RECEIVED(UDP_ENDPOINT_CSR(1));
|
||||
|
||||
for(i = 0; i < len; i++) {
|
||||
UsbBuffer[UsbSoFarCount] = UDP_ENDPOINT_FIFO(1);
|
||||
UsbSoFarCount++;
|
||||
}
|
||||
|
||||
UDP_ENDPOINT_CSR(1) &= ~UDP_CSR_RX_PACKET_RECEIVED_BANK_1;
|
||||
while(UDP_ENDPOINT_CSR(1) & UDP_CSR_RX_PACKET_RECEIVED_BANK_1)
|
||||
;
|
||||
|
||||
if(UsbSoFarCount >= 64) {
|
||||
UsbPacketReceived(UsbBuffer, UsbSoFarCount);
|
||||
UsbSoFarCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UsbStart(void)
|
||||
{
|
||||
volatile int i;
|
||||
|
||||
UsbSoFarCount = 0;
|
||||
|
||||
USB_D_PLUS_PULLUP_OFF();
|
||||
|
||||
for(i = 0; i < 1000000; i++)
|
||||
;
|
||||
|
||||
USB_D_PLUS_PULLUP_ON();
|
||||
|
||||
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {
|
||||
UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL UsbPoll(BOOL blinkLeds)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_END_OF_BUS_RESET) {
|
||||
UDP_INTERRUPT_CLEAR = UDP_INTERRUPT_END_OF_BUS_RESET;
|
||||
|
||||
// following a reset we should be ready to receive a setup packet
|
||||
UDP_RESET_ENDPOINT = 0xf;
|
||||
UDP_RESET_ENDPOINT = 0;
|
||||
|
||||
UDP_FUNCTION_ADDR = UDP_FUNCTION_ADDR_ENABLED;
|
||||
|
||||
UDP_ENDPOINT_CSR(0) = UDP_CSR_EPTYPE_CONTROL | UDP_CSR_ENABLE_EP;
|
||||
|
||||
CurrentConfiguration = 0;
|
||||
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(0)) {
|
||||
if(UDP_ENDPOINT_CSR(0) & UDP_CSR_RX_HAVE_READ_SETUP_DATA) {
|
||||
HandleRxdSetupData();
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if(UDP_INTERRUPT_STATUS & UDP_INTERRUPT_ENDPOINT(1)) {
|
||||
HandleRxdData();
|
||||
ret = TRUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
155
doc/CHANGES.TXT
Normal file
155
doc/CHANGES.TXT
Normal file
|
@ -0,0 +1,155 @@
|
|||
################
|
||||
## 2009/03/28 ##
|
||||
################
|
||||
winsrc/command.cpp
|
||||
Added two new LF commands for tag exploration :
|
||||
|
||||
- askdemod: takes 2 arguments, one is the clock rate, one is the modulation
|
||||
convention (high mod is 1 or high mod is zero)
|
||||
|
||||
This command demodulates the stream into a binary stream into
|
||||
the trace buffer (0's and 1's)
|
||||
|
||||
- mandemod: manchester decoding of a bitstream: takes a binary stream from
|
||||
the trace buffer (see askdemod) and attempts to do manchester decoding
|
||||
to it. One argument: clock rate. Outputs the bitstream to the scrollback buffer.
|
||||
|
||||
Those two helped me to validate that the unknown tag I had was indeed an EM4100 type of tag
|
||||
|
||||
|
||||
################
|
||||
## 2008/12/11 ##
|
||||
################
|
||||
bootrom/bootrom.c
|
||||
Significant changes to bootloader. Use of Chip ID register to detect if running on a SAM7S512 then configure FLASH
|
||||
waitstates as per SummoningDark's suggestion for a SAM7S512 or SAM7S256.
|
||||
Deleted idle loops waiting blindly for clocks to settle and now using status registers to detect when clocks are stable.
|
||||
|
||||
*************************
|
||||
* IMPORTANT INFORMATION *
|
||||
**************************************************************************************************************************
|
||||
* With this boot code, the device can now only be flashed if button is held down after power on or a software reset.
|
||||
* The flash procedure is this:
|
||||
* Hold down button. Either plug in USB or software reset it. _While_holding_down_button_ (red and yellow LEDs are lit) you can
|
||||
* issue one or more of the "prox bootrom <file>" "prox fpga <file>" "prox load <file>", be sure to hold button down for the
|
||||
* entire duration of the flash process. Only release the button when flashing is complete and you want to let the board boot.
|
||||
* This process may be less convenient but it's safer and avoids "unintentional" flashing of the board.
|
||||
**************************************************************************************************************************
|
||||
LED boot sequence now changed, C (red) lights up when boot code jumps from flash to RAM boot code, A (yellow) lights up after
|
||||
clocks have been initialized, B (green) lights up when jumping from boot code to main code, then D (red led away from the others)
|
||||
lights up while code is being downloaded to FPGA, then all leds turn off and board is ready for action.
|
||||
|
||||
With these changes the board now boots and is ready to use in about 3 seconds. Also since the USB bus is not initialized
|
||||
twice (once during boot, then again when the main code runs) unless the button is held down at boot, this seems to avoid
|
||||
the double USB connect and "USB device not recognized" when device is connected to the USB bus or software reset.
|
||||
|
||||
################
|
||||
## 2008/12/06 ##
|
||||
################
|
||||
armsrc/fpga.c
|
||||
Implemented function SetupSpi() to initialize the Serial Peripheral Interface (SPI) in preparation to adding an LCD to the board.
|
||||
Changed FpgaWriteConfWord() to use the SPI communication now instead of bit banging the serial data to the FPGA.
|
||||
|
||||
fpga/fpga.v
|
||||
The FPGA config word serializer required non standard SPI communication (ie for shifting in a 8 bit word, it required a 9th clock
|
||||
cycle with NCS high to load the word from the shift register to the conf register). This was OK for manually bitbanging it but not
|
||||
suitable for using SPI comms. The serializer was fixed to load the conf word from the shift register on a NCS lo-hi transition and
|
||||
not require additional clocking.
|
||||
|
||||
armsrc/fpgaimg.c
|
||||
Recompiled FPGA code after changes above.
|
||||
|
||||
armsrc/LCD.c
|
||||
LCD driver for PCF8833 based LCDs like those found on Nokia models 2600,2650,3100,3120,5140,6030,6100,6610,7210,7250 maybe
|
||||
others. These color LCDs have a resolution of 132x132 and a serial interface. They are very cheap like even down to $2/pc
|
||||
This LCD driver is a straight rip of that found at http://www.sparkfun.com/datasheets/LCD/Jimbo-Nokia-SAM7-Example.zip with
|
||||
very small changes, mainly to integrate it and make it compile with our codebase. Also comented out the circle subroutines
|
||||
to keep the code to integer math only.
|
||||
|
||||
armsrc/fonts.c
|
||||
Font definition for LCD driver
|
||||
|
||||
armsrc/appmain.c
|
||||
Fixed a small bug in CmdHIDdemodFSK (added case 4) which prevented reading some tags. 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.
|
||||
|
||||
################
|
||||
## 2008/11/27 ##
|
||||
################
|
||||
armsrc/appmain.c
|
||||
Implemented an HID tag FSK demodulator (CmdHIDdemodFSK) to obtain the tag ID code from the raw sampled waveform.
|
||||
Implemented CmdHIDsimTAG which takes a 44bit HID tag ID as a hex number then creates the waveform and simulates the tag
|
||||
|
||||
winsrc/command.cpp
|
||||
Added command "hidfskdemod" that calls CmdHIDdemodFSK, the ARM FSK demodulator for HID tags.
|
||||
|
||||
include/usb-cmd.h
|
||||
New defines CMD_HID_DEMOD_FSK and CMD_HID_SIM_TAG
|
||||
|
||||
2008/11/25
|
||||
common/iso14443_crc.c
|
||||
Moved CRC calculation code into this file as it's common to both ARM and Windows side. This file is now included as needed.
|
||||
|
||||
################
|
||||
## 2008/11/21 ##
|
||||
################
|
||||
armsrc/Makefile
|
||||
Changes to split up the compilation of the ARM and produce separate S files for the FPGA code and the ARM code.
|
||||
|
||||
armsrc/appmain.c
|
||||
Replaced some of the hex value params in FpgaWriteConfWord with more explanatory defines.
|
||||
Changes to the Tune command as it assumes wrong HF capacitor value (130pF) and produces wrong voltage readings.
|
||||
Combined some of the integer arithmetic statements to improve accuracy slightly, since the voltage divider ratio is not an integer.
|
||||
Voltage divider resistor network is 10M/240k = ratio of 41.6666
|
||||
|
||||
Originally the calculation was rounding the ratio down to 41
|
||||
3300 (mV) * 41 * sample_value / 1024
|
||||
New calculation without rounding error is
|
||||
3300 (mV) * 41.66666 * sample_value / 1024 => 137500 * sample_value / 1024
|
||||
|
||||
New define BUTTON_PRESS() returns status of button
|
||||
|
||||
armsrc/fpga.c
|
||||
The current board can only take a X2S30 as there is no larger FPGA in PQFP100 package and
|
||||
the smaller X2S15 FPGA can't fit the current code. The X2S30 FPGA config is fixed at 336,768 bits
|
||||
The FPGA code base address and length is hard coded to occupy FLASH region 0x2000 - 0xC470.
|
||||
|
||||
armsrc/ldscript-fpga
|
||||
New file to place the FPGA code at FLASH address 0x2000
|
||||
|
||||
bootrom/Makefile
|
||||
Slight changes, commented out the generation of byteswapped S file, the other S files are generated in the same section of the makefile now.
|
||||
|
||||
bootrom/bootrom.c
|
||||
Changed some thumb code with a one line ARM code which is clearer and more explicit. Processor runs in ARM mode at reset anyway.
|
||||
Changed jump to RAM address, used to jump to 0x2000 (now FPGA area), now jumps to 0x10000.
|
||||
|
||||
bootrom/flash-reset.s
|
||||
Changed name of CMain to CopyBootToRAM. Streamlined reset code, fixed up stack pointer initialization.
|
||||
|
||||
bootrom/fromflash.c
|
||||
Removed the whole section of initializing clocks, this is redundant as it's being done once we jump to boot code in RAM
|
||||
All fromflash.c does now is copy the boot code to ram and jumps to it.
|
||||
|
||||
bootrom/ram-reset.s
|
||||
Fixed up stack pointer initialization that caused crash when using "loread"
|
||||
|
||||
include/at91sam7s128.h
|
||||
New defines for debug register, lets you identify what processor flavour the code runs on, RAM and FLASH sizes, etc.
|
||||
|
||||
include/proxmark3.h
|
||||
New useful defines for relay and button
|
||||
|
||||
winsrc/Makefile
|
||||
Added new define /D_CRT_SECURE_NO_WARNINGS to elliminate a _whole bunch_ of bogus compilation warnings
|
||||
|
||||
winsrc/command.cpp
|
||||
Changed CmdLosamples to take a numeric argument (number of samples x4 to retrieve from buffer)
|
||||
New command Quit to exit the program from the GUI command prompt.
|
||||
|
||||
winsrc/gui.cpp
|
||||
Fixup compilation warnings.
|
||||
|
||||
winsrc/prox.cpp
|
||||
Tidy up printing to stdout, flashing progress now updates on the same line instead of scrolling up.
|
||||
New command line parameter to load FPGA image to FLASH.
|
39
doc/README.TXT
Normal file
39
doc/README.TXT
Normal file
|
@ -0,0 +1,39 @@
|
|||
This is a bare minimum compile environment for the proxmark3 sources.
|
||||
|
||||
CONTENTS
|
||||
|
||||
This bundle contains the ARM cross compiler in devkitARM and a _tiny_ subset
|
||||
of the Visual C++ 2008 Express Edition in devkitWIN which is the bare minimum
|
||||
required for compilation of this current source.
|
||||
|
||||
If you plan on further source code development you are strongly encouraged
|
||||
to download the full Visual C++ 2008 available for free download from
|
||||
http://www.microsoft.com/express/download/
|
||||
|
||||
CAVEATS
|
||||
|
||||
There is no provision in this environment for compiling the FPGA source. To
|
||||
do that you need to download the free (registration required) ISE WebPack
|
||||
from Xilinx at http://www.xilinx.com/ise/logic_design_prod/webpack.htm
|
||||
Be warned, the pack is huge, 2Gb download and >4Gb installed.
|
||||
|
||||
USAGE
|
||||
|
||||
First of all run the .msi file in devkitWIN\vcredist_x86 to install the VC++
|
||||
redistributables, without these, nmake, cl and link won't run.
|
||||
|
||||
Get a command prompts in the cockpit directory and pretty much run the batch
|
||||
files in the order they appear:
|
||||
|
||||
0setpath.bat - sets the environment vars for the compile environment
|
||||
1makearm.bat - compiles the files in armsrc, output files in armsrc\obj
|
||||
2makeboot.bat - compiles the files in bootrom, output files in bootrom\obj
|
||||
3makewin.bat - compiles the files in winsrc, output files in winsrc\obj
|
||||
4flashos.bat - attempts to upload the OS image to the proxmark3 board
|
||||
|
||||
ACKNOWLEDGMENTS
|
||||
|
||||
Thanks to J Westhues for the original proxmark, Roel and the proxmark.org
|
||||
community. This pack may contain F/OSS or free but copyrighted software
|
||||
from Xilinx, Microsoft and others. All trademarks are the property of
|
||||
their respective owners. All rights reserved.
|
BIN
doc/component-placement.bmp
Normal file
BIN
doc/component-placement.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
doc/proxmark3.pdf
Normal file
BIN
doc/proxmark3.pdf
Normal file
Binary file not shown.
BIN
doc/proxmark3.xls
Normal file
BIN
doc/proxmark3.xls
Normal file
Binary file not shown.
BIN
doc/schematics.pdf
Normal file
BIN
doc/schematics.pdf
Normal file
Binary file not shown.
276
doc/system.txt
Normal file
276
doc/system.txt
Normal file
|
@ -0,0 +1,276 @@
|
|||
|
||||
This is outdated.
|
||||
|
||||
---
|
||||
|
||||
INTRODUCTION TO THE proxmark3
|
||||
=============================
|
||||
|
||||
The proxmark3 device is designed to manipulate RFID tags in a number of
|
||||
different ways. For example, a proxmark3 can:
|
||||
|
||||
* read a low-frequency (~100 kHz) or high-frequency (13.56 MHz) tag,
|
||||
including the ISO-standard tags; standards that require
|
||||
bidirectional communication between the reader and the tag are
|
||||
not a problem
|
||||
|
||||
* emulate a low- or high-frequency tag, in a way very similar to the
|
||||
way that a real tag behaves (e.g., it derives its timing from the
|
||||
incident carrier)
|
||||
|
||||
* eavesdrop on the signals exchanged between another reader and tag
|
||||
|
||||
* measure the resonant frequency of an antenna, to a certain extent
|
||||
(this is a convenience when building a test setup for the previous
|
||||
three functions)
|
||||
|
||||
The proxmark3 may be thought of as a direct-sampling software radio.
|
||||
There is some complication, though, because of the usual dynamic range
|
||||
issue in dealing with signals in RFID systems (large signal due to
|
||||
the reader, small signal due to the tag). Some analog processing is
|
||||
therefore used to fix this before the signal is digitized. (Although,
|
||||
it is possible to digitize the signal from the antenna directly, with
|
||||
appropriate population options. It is just not usually a good idea.)
|
||||
|
||||
SYSTEM ARCHITECTURE
|
||||
===================
|
||||
|
||||
The ANTENNA sends and receives signals over the air. It is external to
|
||||
the board; it connects through SV2. Separate pins on the connector are
|
||||
used for the low- and high-frequency antennas, and the analog receive
|
||||
paths are separate. The antennas are inductive loops, which are resonated
|
||||
by on-board capacitors.
|
||||
|
||||
On the transmit side, the antennas are excited by large numbers of
|
||||
paralleled bus driver buffers. By tri-stating some of the buffers, it
|
||||
is possible to vary the transmit strength. This may be used to generate
|
||||
a modulated carrier. The buffers are driven by signals from the FPGA,
|
||||
as are the output enables. The antennas are excited as series circuits,
|
||||
which permits a large input power for a relatively small input voltage.
|
||||
|
||||
By driving all of the buffers low, it is possible to make the antenna
|
||||
look to the receive path like a parallel LC circuit; this provides a
|
||||
high-voltage output signal. This is typically what will be done when we
|
||||
are not actively transmitting a carrier (i.e., behaving as a reader).
|
||||
|
||||
On the receive side, there are two possibilities, which are selected by
|
||||
RLY1. A mechanical relay is used, because the signal from the antenna is
|
||||
likely to be more positive or negative than the highest or lowest supply
|
||||
voltages on-board. In the usual case (PEAK-DETECTED mode), the received
|
||||
signal is peak-detected by an analog circuit, then filtered slightly,
|
||||
and then digitized by the ADC. This is the case for both the low- and
|
||||
high-frequency paths, although the details of the circuits for the
|
||||
two cases are somewhat different. This receive path would typically
|
||||
be selected when the device is behaving as a reader, or when it is
|
||||
eavesdropping at close range.
|
||||
|
||||
It is also possible to digitize the signal from the antenna directly (RAW
|
||||
mode), after passing it through a gain stage. This is more likely to be
|
||||
useful in reading signals at long range, but the available dynamic range
|
||||
will be poor, since it is limited by the 8-bit A/D. These modes would be
|
||||
very appropriate, for example, for the heavily-discussed attacks in which
|
||||
a tag's ID is learned from the data broadcast by a reader performing an
|
||||
anticollision loop, because there is no dynamic range problem there. It
|
||||
would also be possible to program the proxmark3 to receive broadcast AM
|
||||
radio, with certain changes in component values.
|
||||
|
||||
In either case, an analog signal is digitized by the ADC (IC8), and
|
||||
from there goes in to the FPGA (IC1). The FPGA is big enough that it
|
||||
can perform DSP operations itself. For some high-frequency standards,
|
||||
the subcarriers are fast enough that it would be inconvenient to do all
|
||||
the math on a general-purpose CPU. The FPGA can therefore correlate for
|
||||
the desired signal itself, and simply report the total to the ARM. For
|
||||
low-frequency tags, it probably makes sense just to pass data straight
|
||||
through to the ARM.
|
||||
|
||||
The FPGA communicates with the ARM through either its SPI port (the ARM
|
||||
is the master) or its generic synchronous serial port (again, the ARM
|
||||
is the master). The ARM connects to the outside world over USB.
|
||||
|
||||
DETAILS: POWER DISTRIBUTION
|
||||
===========================
|
||||
|
||||
I make a half-hearted attempt to meet the USB power specs; this adds a
|
||||
bit of complexity. I have not made measurements to determine how close
|
||||
I come to succeeding, but I think that the suspend current might turn
|
||||
out to be a pain.
|
||||
|
||||
The +3V3 rail is always powered, whenever we are plugged in to USB. This
|
||||
is generated by an LDO, which burns a quiescent current of 150 uA
|
||||
(typical) already. The only thing powered from the +3V3 rail is the ARM,
|
||||
which can presumably do smart power control when we are in suspend.
|
||||
|
||||
The ARM generates two signals to switch power to the rest of the board:
|
||||
FPGA_ON, and NVDD_ON. When NVDD_ON goes low, the Vdd rail comes up to
|
||||
about five volts (the filtered-but-unregulated USB voltage). This powers
|
||||
most of the analog circuitry, including the ADC and all of the opamps
|
||||
and comparators in the receive path, and the coil drivers as well. Vdd
|
||||
also feeds the +3V3-FPGA and +2v5 regulators, which power only the
|
||||
FPGA. These regulators are enabled by FPGA_ON, so the FPGA is powered
|
||||
only when NVDD_ON is asserted low, and FPGA_ON is asserted high.
|
||||
|
||||
DETAILS: FPGA
|
||||
=============
|
||||
|
||||
The FPGA is a Spartan-II. This is a little bit old, but it is widely
|
||||
available, inexpensive, and five-volt tolerant. For development, the FPGA
|
||||
is configured over JTAG (SV5). In operation, the FPGA is configured in
|
||||
slave serial mode by the ARM, from a bitstream stored in the ARM's flash.
|
||||
|
||||
Power to the FPGA is managed by regulators IC13 and IC12, both of which
|
||||
have shutdown. These generate the FPGA's VCCO (+3v3) and VCCINT (+2v5)
|
||||
supplies. I am a little bit worried about the power-on surge, since we
|
||||
run off USB. At the very minimum, the FPGA should not get power until
|
||||
we have enumerated and requested the full 500 mA available from USB. The
|
||||
large electrolytic capacitors C37 and C38 will presumably help with this.
|
||||
|
||||
The logic is written in Verilog, of course for webpack. I have structured
|
||||
the FPGA in terms of `major modes:' the FPGA's `major mode' determines
|
||||
which of several modules is connected to the FPGA's I/O pins. A separate
|
||||
module is used for each of the FPGA's function; for example, there is
|
||||
now a module to read a 125 kHz tag, simulate a 125 kHz tag, transmit to
|
||||
an ISO 15693 tag, and receive from an ISO 15693 tag.
|
||||
|
||||
DETAILS: ANALOG RECEIVE PATH
|
||||
============================
|
||||
|
||||
For `slow' signals, I use an MCP6294 opamp. This has a GBW of 10 MHz,
|
||||
which is more than enough for the low-frequency stuff, and enough for
|
||||
all of the subcarrier frequencies that I know of at high frequency. In
|
||||
practice, the `slow' signals are all the signals following the peak
|
||||
detector. These signals are usually centred around the generated
|
||||
voltage Vmid.
|
||||
|
||||
For `fast' signals, I use an AD8052. This is a very fast voltage-feedback
|
||||
amplifier (~100 MHz GBW). I use it immediately after the antenna for
|
||||
both the low- and high-frequency cases, as a sort of an ugly LNA. It is
|
||||
not optimal, but it certainly made the design easy.
|
||||
|
||||
An ordinary CD4066 is used to multiplex the four possible signals
|
||||
(low/high frequency paths, RAW/PEAK-DETECTED). There is a potential
|
||||
problem at startup, when the ARM is in reset; there are pull-ups on the
|
||||
lines that control the mux, so all of the switches turn on. This shorts
|
||||
the four opamp outputs together through the on-resistance of the switch.
|
||||
All four outputs float to the same DC voltage with no signal, however,
|
||||
and the on-resistance of the switches is fairly large, so I don't think
|
||||
that will be a problem in practice.
|
||||
|
||||
Comparators are used to generate clock signals when the device is
|
||||
emulating a tag. These clock signals are generated from the signal on the
|
||||
antenna, and therefore from the signal transmitted by the reader. This
|
||||
allows us to clock ourselves off the reader, just like a real tag would.
|
||||
These signals go in to the FPGA. There is a potential problem when the
|
||||
FPGA is powered down; these outputs might go high and try to power the
|
||||
FPGA through the protection diodes. My present solution to this is a
|
||||
couple of resistors, which is not very elegeant.
|
||||
|
||||
The high-frequency peak-detected receive path contains population options
|
||||
for many features that I do not currently use. A lot of these are just
|
||||
me guessing that if I provide options for different series and shunt
|
||||
passives, perhaps it will come in handy in some way. The Zener diodes D10
|
||||
and D11 are optional, but may protect the front end from an overvoltage
|
||||
(which will fry the peak detector diodes) when the `simulated tag'
|
||||
is read by a powerful reader.
|
||||
|
||||
DETAILS: ANALOG TRANSMIT PATH
|
||||
=============================
|
||||
|
||||
The coil drivers are just ACT244 bus buffers. I parallel eight of them
|
||||
for each antenna (eight for the high-frequency antenna, eight for the
|
||||
low-frequency antenna). This should easily provide a hundred milliamps
|
||||
coil drive or so, which is more than enough for anything that I imagine
|
||||
doing with the device. The drivers hit the coil with a square wave
|
||||
voltage, however, which means that it is only the bandpass filter effect
|
||||
of a resonant antenna that suppresses the odd harmonics. In practice it
|
||||
would probably take heroic efforts (high antenna Q) to meet the FCC/CE
|
||||
harmonic specs; and in practice no one cares.
|
||||
|
||||
The tx strength, given good antenna tuning, is determined by the series
|
||||
resistors. Choose the ratios to stay within the rated current of the
|
||||
buffers, and to achieve the desired power ratios by enabling or disabling
|
||||
nOEs for the desired modulation index. It is useful to populate one of the
|
||||
resistors as a high value (~10k) for the simulated tag modes; this allows
|
||||
us to look at the incident carrier without loading the reader very much.
|
||||
|
||||
DETAILS: ARM
|
||||
============
|
||||
|
||||
Atmel makes a number of pin-compatible ARMs, with slightly different
|
||||
peripherals, and different amounts of flash and RAM. It is necessary
|
||||
to choose a device with enough flash not just for the ARM's program,
|
||||
but also for the FPGA image (which is loaded by the ARM).
|
||||
|
||||
The ARM is responsible for programming the FPGA. It also supplies a
|
||||
clock to the FPGA (although the FPGA clock can also run off the 13.56
|
||||
MHz clock not used for anything else, which is obviously asynchronous
|
||||
to anything in the ARM).
|
||||
|
||||
It is necessary to use JTAG to bring the ARM for the first time; at
|
||||
that point you can load a bootrom, and subsequently load new software
|
||||
over USB. It might be possible to use the ARM's pre-loaded bootloader
|
||||
(see datasheet) instead of JTAG, but I wanted the JTAG anyways for
|
||||
debugging, so I did not bother. I used a Wiggler clone, with Macraigor's
|
||||
OCD Commander. More expensive tools would work as well.
|
||||
|
||||
USB SOFTWARE
|
||||
============
|
||||
|
||||
At present I enumerate as an HID device. This saves me writing a driver,
|
||||
but it forces me to do interrupt transfers for everything. This limits
|
||||
speed and is not very elegant. A real USB driver would be nice, maybe
|
||||
even one that could do stuff like going isochronous to stream samples
|
||||
from the A/D for processing on the PC.
|
||||
|
||||
PRETENDING TO BE A TAG
|
||||
======================
|
||||
|
||||
It is not possible, with the given topology, to open-circuit the antenna
|
||||
entirely and still look at the signal received on it. The simulated tag
|
||||
modes must therefore switch between slight loading and heavy loading,
|
||||
not open- and short-circuts across the antenna, evening though they do
|
||||
not depend upon the incident carrier for power (just timing information).
|
||||
|
||||
RECEIVING SIGNAL STRAIGHT FROM THE ANTENNAS
|
||||
===========================================
|
||||
|
||||
There is a path straight from the antenna to the A/D, bypassing the peak
|
||||
detector assembly. This goes through a gain stage (just a fast voltage
|
||||
feedback opamp), and from there straight in to the mux.
|
||||
|
||||
It is necessary to energize the relay to connect these paths. If the
|
||||
coil is driven (as if to excite and read a tag) while these paths are
|
||||
connected, then damage will probably result. Most likely the opamp
|
||||
will fry.
|
||||
|
||||
READING A TAG
|
||||
=============
|
||||
|
||||
The tag is excited by a carrier transmitted by the reader. This is
|
||||
generated by IC9 and IC10, using some combination of buffers. The transmit
|
||||
power is determined by selecting the right combination of PWR_OEx pins;
|
||||
drive more of them low for more power. This can be used to modulate the
|
||||
transmitted signal, and thus send information to the tag.
|
||||
|
||||
The received signal from the antenna is first peak-detected, and then
|
||||
high-pass filtered to reject the unmodulated carrier. The signal is
|
||||
amplified a bit, and goes in to the A/D mux from there. The A/D is
|
||||
controlled by the FPGA. For 13.56 MHz tags, it is easiest to do everything
|
||||
synchronous to the 13.56 MHz carrier.
|
||||
|
||||
INTERFACE FROM THE ARM TO THE FPGA
|
||||
==================================
|
||||
|
||||
The FPGA and the ARM can communicate in two main ways: using the ARM's
|
||||
general-purpose synchronous serial port (the SSP), or using the ARM's
|
||||
SPI port. The SPI port is used to configure the FPGA. The ARM writes a
|
||||
configuration word to the FPGA, which determines what operation will
|
||||
be performed (e.g. read 13.56 MHz vs. read 125 kHz vs. read 134 kHz
|
||||
vs...). The SPI is used exclusively for configuration.
|
||||
|
||||
The SSP is used for actual data sent over the air. The ARM's SSP can
|
||||
work in slave mode, which means that we can send the data using clocks
|
||||
generated by the FPGA (either from the PCK0 clock, which the ARM itself
|
||||
supplies, or from the 13.56 MHz clock, which is certainly not going to
|
||||
be synchronous to anything in the ARM), which saves synchronizing logic
|
||||
in the FPGA. The SSP is bi-directional and full-duplex.
|
||||
|
239
fpga/fpga.mpf
Normal file
239
fpga/fpga.mpf
Normal file
|
@ -0,0 +1,239 @@
|
|||
;
|
||||
; Copyright Model Technology, a Mentor Graphics
|
||||
; Corporation company 2003, - All rights reserved.
|
||||
;
|
||||
[Library]
|
||||
std = $MODEL_TECH/../std
|
||||
ieee = $MODEL_TECH/../ieee
|
||||
verilog = $MODEL_TECH/../verilog
|
||||
vital2000 = $MODEL_TECH/../vital2000
|
||||
std_developerskit = $MODEL_TECH/../std_developerskit
|
||||
synopsys = $MODEL_TECH/../synopsys
|
||||
modelsim_lib = $MODEL_TECH/../modelsim_lib
|
||||
|
||||
|
||||
; VHDL Section
|
||||
unisim = $MODEL_TECH/../xilinx/vhdl/unisim
|
||||
simprim = $MODEL_TECH/../xilinx/vhdl/simprim
|
||||
xilinxcorelib = $MODEL_TECH/../xilinx/vhdl/xilinxcorelib
|
||||
aim = $MODEL_TECH/../xilinx/vhdl/aim
|
||||
pls = $MODEL_TECH/../xilinx/vhdl/pls
|
||||
cpld = $MODEL_TECH/../xilinx/vhdl/cpld
|
||||
|
||||
; Verilog Section
|
||||
unisims_ver = $MODEL_TECH/../xilinx/verilog/unisims_ver
|
||||
uni9000_ver = $MODEL_TECH/../xilinx/verilog/uni9000_ver
|
||||
simprims_ver = $MODEL_TECH/../xilinx/verilog/simprims_ver
|
||||
xilinxcorelib_ver = $MODEL_TECH/../xilinx/verilog/xilinxcorelib_ver
|
||||
aim_ver = $MODEL_TECH/../xilinx/verilog/aim_ver
|
||||
cpld_ver = $MODEL_TECH/../xilinx/verilog/cpld_ver
|
||||
|
||||
work = work
|
||||
[vcom]
|
||||
; Turn on VHDL-1993 as the default. Normally is off.
|
||||
VHDL93 = 1
|
||||
|
||||
; Show source line containing error. Default is off.
|
||||
; Show_source = 1
|
||||
|
||||
; Turn off unbound-component warnings. Default is on.
|
||||
; Show_Warning1 = 0
|
||||
|
||||
; Turn off process-without-a-wait-statement warnings. Default is on.
|
||||
; Show_Warning2 = 0
|
||||
|
||||
; Turn off null-range warnings. Default is on.
|
||||
; Show_Warning3 = 0
|
||||
|
||||
; Turn off no-space-in-time-literal warnings. Default is on.
|
||||
; Show_Warning4 = 0
|
||||
|
||||
; Turn off multiple-drivers-on-unresolved-signal warnings. Default is on.
|
||||
; Show_Warning5 = 0
|
||||
|
||||
; Turn off optimization for IEEE std_logic_1164 package. Default is on.
|
||||
; Optimize_1164 = 0
|
||||
|
||||
; Turn on resolving of ambiguous function overloading in favor of the
|
||||
; "explicit" function declaration (not the one automatically created by
|
||||
; the compiler for each type declaration). Default is off.
|
||||
Explicit = 1
|
||||
|
||||
; Turn off VITAL compliance checking. Default is checking on.
|
||||
; NoVitalCheck = 1
|
||||
|
||||
; Ignore VITAL compliance checking errors. Default is to not ignore.
|
||||
; IgnoreVitalErrors = 1
|
||||
|
||||
; Turn off VITAL compliance checking warnings. Default is to show warnings.
|
||||
; Show_VitalChecksWarnings = false
|
||||
|
||||
; Turn off "loading..." messages. Default is messages on.
|
||||
; Quiet = 1
|
||||
|
||||
; Turn on some limited synthesis rule compliance checking. Checks only:
|
||||
; -- signals used (read) by a process must be in the sensitivity list
|
||||
; CheckSynthesis = 1
|
||||
|
||||
[vlog]
|
||||
|
||||
; Turn off "loading..." messages. Default is messages on.
|
||||
; Quiet = 1
|
||||
|
||||
; Turn on Verilog hazard checking (order-dependent accessing of global vars).
|
||||
; Default is off.
|
||||
; Hazard = 1
|
||||
|
||||
; Turn on converting regular Verilog identifiers to uppercase. Allows case
|
||||
; insensitivity for module names. Default is no conversion.
|
||||
; UpCase = 1
|
||||
|
||||
; Turns on incremental compilation of modules
|
||||
; Incremental = 1
|
||||
|
||||
[vsim]
|
||||
; Simulator resolution
|
||||
; Set to fs, ps, ns, us, ms, or sec with optional prefix of 1, 10, or 100.
|
||||
Resolution = ps
|
||||
|
||||
; User time unit for run commands
|
||||
; Set to default, fs, ps, ns, us, ms, or sec. The default is to use the
|
||||
; unit specified for Resolution. For example, if Resolution is 100ps,
|
||||
; then UserTimeUnit defaults to ps.
|
||||
UserTimeUnit = default
|
||||
|
||||
; Default run length
|
||||
RunLength = 100
|
||||
|
||||
; Maximum iterations that can be run without advancing simulation time
|
||||
IterationLimit = 5000
|
||||
|
||||
; Directive to license manager:
|
||||
; vhdl Immediately reserve a VHDL license
|
||||
; vlog Immediately reserve a Verilog license
|
||||
; plus Immediately reserve a VHDL and Verilog license
|
||||
; nomgc Do not look for Mentor Graphics Licenses
|
||||
; nomti Do not look for Model Technology Licenses
|
||||
; noqueue Do not wait in the license queue when a license isn't available
|
||||
; License = plus
|
||||
|
||||
; Stop the simulator after an assertion message
|
||||
; 0 = Note 1 = Warning 2 = Error 3 = Failure 4 = Fatal
|
||||
BreakOnAssertion = 3
|
||||
|
||||
; Assertion Message Format
|
||||
; %S - Severity Level
|
||||
; %R - Report Message
|
||||
; %T - Time of assertion
|
||||
; %D - Delta
|
||||
; %I - Instance or Region pathname (if available)
|
||||
; %% - print '%' character
|
||||
; AssertionFormat = "** %S: %R\n Timf: %T Iteration: %D%I\n"
|
||||
|
||||
; Assertion File - alternate file for storing assertion messages
|
||||
; AssertFile = assert.log
|
||||
|
||||
; Default radix for all windows and commands...
|
||||
; Set to symbolic, ascii, binary, octal, decimal, hex, unsigned
|
||||
DefaultRadix = symbolic
|
||||
|
||||
; VSIM Startup command
|
||||
; Startup = do startup.do
|
||||
|
||||
; File for saving command transcript
|
||||
TranscriptFile = transcript
|
||||
|
||||
; File for saving command history
|
||||
;CommandHistory = cmdhist.log
|
||||
|
||||
; Specify whether paths in simulator commands should be described
|
||||
; in VHDL or Verilog format. For VHDL, PathSeparator = /
|
||||
; for Verilog, PathSeparator = .
|
||||
PathSeparator = /
|
||||
|
||||
; Specify the dataset separator for fully rooted contexts.
|
||||
; The default is ':'. For example, sim:/top
|
||||
; Must not be the same character as PathSeparator.
|
||||
DatasetSeparator = :
|
||||
|
||||
; Disable assertion messages
|
||||
; IgnoreNote = 1
|
||||
; IgnoreWarning = 1
|
||||
; IgnoreError = 1
|
||||
; IgnoreFailure = 1
|
||||
|
||||
; Default force kind. May be freeze, drive, or deposit
|
||||
; or in other terms, fixed, wired or charged.
|
||||
; DefaultForceKind = freeze
|
||||
|
||||
; If zero, open files when elaborated
|
||||
; else open files on first read or write
|
||||
; DelayFileOpen = 0
|
||||
|
||||
; Control VHDL files opened for write
|
||||
; 0 = Buffered, 1 = Unbuffered
|
||||
UnbufferedOutput = 0
|
||||
|
||||
; Control number of VHDL files open concurrently
|
||||
; This number should always be less then the
|
||||
; current ulimit setting for max file descriptors
|
||||
; 0 = unlimited
|
||||
ConcurrentFileLimit = 40
|
||||
|
||||
; This controls the number of hierarchical regions displayed as
|
||||
; part of a signal name shown in the waveform window. The default
|
||||
; value or a value of zero tells VSIM to display the full name.
|
||||
; WaveSignalNameWidth = 0
|
||||
|
||||
; Turn off warnings from the std_logic_arith, std_logic_unsigned
|
||||
; and std_logic_signed packages.
|
||||
; StdArithNoWarnings = 1
|
||||
|
||||
; Turn off warnings from the IEEE numeric_std and numeric_bit
|
||||
; packages.
|
||||
; NumericStdNoWarnings = 1
|
||||
|
||||
; Control the format of a generate statement label. Don't quote it.
|
||||
; GenerateFormat = %s__%d
|
||||
|
||||
; Specify whether checkpoint files should be compressed.
|
||||
; The default is to be compressed.
|
||||
; CheckpointCompressMode = 0
|
||||
|
||||
; List of dynamically loaded objects for Verilog PLI applications
|
||||
; Veriuser = veriuser.sl
|
||||
|
||||
[lmc]
|
||||
[Project]
|
||||
Project_Version = 5
|
||||
Project_DefaultLib = work
|
||||
Project_SortMethod = unused
|
||||
Project_Files_Count = 13
|
||||
Project_File_0 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/fpga_tb.v
|
||||
Project_File_P_0 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1179836462 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 2 dont_compile 0
|
||||
Project_File_1 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/hi_simulate.v
|
||||
Project_File_P_1 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225963633 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 compile_to work vlog_upper 0 vlog_options {} compile_order 6 dont_compile 0
|
||||
Project_File_2 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/testbed_hi_simulate.v
|
||||
Project_File_P_2 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225964050 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 compile_to work vlog_upper 0 vlog_options {} compile_order 12 dont_compile 0
|
||||
Project_File_3 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/fpga.v
|
||||
Project_File_P_3 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1207888760 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 1 dont_compile 0
|
||||
Project_File_4 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/hi_read_tx.v
|
||||
Project_File_P_4 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225960972 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 5 dont_compile 0
|
||||
Project_File_5 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/testbed_hi_read_tx.v
|
||||
Project_File_P_5 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225962515 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 11 dont_compile 0
|
||||
Project_File_6 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/hi_iso14443a.v
|
||||
Project_File_P_6 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1207889732 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 3 dont_compile 0
|
||||
Project_File_7 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/lo_simulate.v
|
||||
Project_File_P_7 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1179836462 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 8 dont_compile 0
|
||||
Project_File_8 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/lo_read.v
|
||||
Project_File_P_8 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225797126 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 7 dont_compile 0
|
||||
Project_File_9 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/util.v
|
||||
Project_File_P_9 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1179836462 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 0 dont_compile 0
|
||||
Project_File_10 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/testbed_lo_read.v
|
||||
Project_File_P_10 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225960239 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 9 dont_compile 0
|
||||
Project_File_11 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/testbed_lo_simulate.v
|
||||
Project_File_P_11 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1225960231 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 10 dont_compile 0
|
||||
Project_File_12 = G:/RFID/Hardware/Proxmark3/Sources/prox_work/fpga/hi_read_rx_xcorr.v
|
||||
Project_File_P_12 = vlog_protect 0 file_type Verilog group_id 0 vlog_1995compat 0 vlog_nodebug 0 folder {Top Level} vlog_noload 0 last_compile 1179836462 vlog_disableopt 0 vlog_hazard 0 vlog_showsource 0 ood 0 vlog_options {} vlog_upper 0 compile_to work compile_order 4 dont_compile 0
|
||||
Project_Sim_Count = 0
|
||||
Project_Folder_Count = 0
|
41
fpga/fpga.ucf
Normal file
41
fpga/fpga.ucf
Normal file
|
@ -0,0 +1,41 @@
|
|||
# See the schematic for the pin assignment.
|
||||
|
||||
NET "adc_d<0>" LOC = "P62" ;
|
||||
NET "adc_d<1>" LOC = "P60" ;
|
||||
NET "adc_d<2>" LOC = "P58" ;
|
||||
NET "adc_d<3>" LOC = "P57" ;
|
||||
NET "adc_d<4>" LOC = "P56" ;
|
||||
NET "adc_d<5>" LOC = "P55" ;
|
||||
NET "adc_d<6>" LOC = "P54" ;
|
||||
NET "adc_d<7>" LOC = "P53" ;
|
||||
#NET "cross_hi" LOC = "P88" ;
|
||||
#NET "miso" LOC = "P40" ;
|
||||
#PACE: Start of Constraints generated by PACE
|
||||
|
||||
#PACE: Start of PACE I/O Pin Assignments
|
||||
NET "adc_clk" LOC = "P46" ;
|
||||
NET "adc_noe" LOC = "P47" ;
|
||||
NET "ck_1356meg" LOC = "P91" ;
|
||||
NET "ck_1356megb" LOC = "P93" ;
|
||||
NET "cross_lo" LOC = "P87" ;
|
||||
NET "dbg" LOC = "P22" ;
|
||||
NET "mosi" LOC = "P43" ;
|
||||
NET "ncs" LOC = "P44" ;
|
||||
NET "pck0" LOC = "P36" ;
|
||||
NET "pwr_hi" LOC = "P80" ;
|
||||
NET "pwr_lo" LOC = "P81" ;
|
||||
NET "pwr_oe1" LOC = "P82" ;
|
||||
NET "pwr_oe2" LOC = "P83" ;
|
||||
NET "pwr_oe3" LOC = "P84" ;
|
||||
NET "pwr_oe4" LOC = "P86" ;
|
||||
NET "spck" LOC = "P39" ;
|
||||
NET "ssp_clk" LOC = "P71" ;
|
||||
NET "ssp_din" LOC = "P32" ;
|
||||
NET "ssp_dout" LOC = "P34" ;
|
||||
NET "ssp_frame" LOC = "P31" ;
|
||||
|
||||
#PACE: Start of PACE Area Constraints
|
||||
|
||||
#PACE: Start of PACE Prohibit Constraints
|
||||
|
||||
#PACE: End of Constraints generated by PACE
|
190
fpga/fpga.v
Normal file
190
fpga/fpga.v
Normal file
|
@ -0,0 +1,190 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// The FPGA is responsible for interfacing between the A/D, the coil drivers,
|
||||
// and the ARM. In the low-frequency modes it passes the data straight
|
||||
// through, so that the ARM gets raw A/D samples over the SSP. In the high-
|
||||
// frequency modes, the FPGA might perform some demodulation first, to
|
||||
// reduce the amount of data that we must send to the ARM.
|
||||
//
|
||||
// I am not really an FPGA/ASIC designer, so I am sure that a lot of this
|
||||
// could be improved.
|
||||
//
|
||||
// Jonathan Westhues, March 2006
|
||||
// Added ISO14443-A support by Gerhard de Koning Gans, April 2008
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
`include "lo_read.v"
|
||||
`include "lo_simulate.v"
|
||||
`include "hi_read_tx.v"
|
||||
`include "hi_read_rx_xcorr.v"
|
||||
`include "hi_simulate.v"
|
||||
`include "hi_iso14443a.v"
|
||||
`include "util.v"
|
||||
|
||||
module fpga(
|
||||
spck, miso, mosi, ncs,
|
||||
pck0i, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk, adc_noe,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg
|
||||
);
|
||||
input spck, mosi, ncs;
|
||||
output miso;
|
||||
input pck0i, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk, adc_noe;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
|
||||
IBUFG #(.IOSTANDARD("DEFAULT") ) pck0b(
|
||||
.O(pck0),
|
||||
.I(pck0i)
|
||||
);
|
||||
//assign pck0 = pck0i;
|
||||
//-----------------------------------------------------------------------------
|
||||
// The SPI receiver. This sets up the configuration word, which the rest of
|
||||
// the logic looks at to determine how to connect the A/D and the coil
|
||||
// drivers (i.e., which section gets it). Also assign some symbolic names
|
||||
// to the configuration bits, for use below.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
reg [7:0] conf_word_shift;
|
||||
reg [7:0] conf_word;
|
||||
|
||||
// We switch modes between transmitting to the 13.56 MHz tag and receiving
|
||||
// from it, which means that we must make sure that we can do so without
|
||||
// glitching, or else we will glitch the transmitted carrier.
|
||||
always @(posedge ncs)
|
||||
begin
|
||||
conf_word <= conf_word_shift;
|
||||
end
|
||||
|
||||
always @(posedge spck)
|
||||
begin
|
||||
if(~ncs)
|
||||
begin
|
||||
conf_word_shift[7:1] <= conf_word_shift[6:0];
|
||||
conf_word_shift[0] <= mosi;
|
||||
end
|
||||
end
|
||||
|
||||
wire [2:0] major_mode;
|
||||
assign major_mode = conf_word[7:5];
|
||||
|
||||
// For the low-frequency configuration:
|
||||
wire lo_is_125khz;
|
||||
assign lo_is_125khz = conf_word[3];
|
||||
|
||||
// For the high-frequency transmit configuration: modulation depth, either
|
||||
// 100% (just quite driving antenna, steady LOW), or shallower (tri-state
|
||||
// some fraction of the buffers)
|
||||
wire hi_read_tx_shallow_modulation;
|
||||
assign hi_read_tx_shallow_modulation = conf_word[0];
|
||||
|
||||
// For the high-frequency receive correlator: frequency against which to
|
||||
// correlate.
|
||||
wire hi_read_rx_xcorr_848;
|
||||
assign hi_read_rx_xcorr_848 = conf_word[0];
|
||||
// and whether to drive the coil (reader) or just short it (snooper)
|
||||
wire hi_read_rx_xcorr_snoop;
|
||||
assign hi_read_rx_xcorr_snoop = conf_word[1];
|
||||
|
||||
// For the high-frequency simulated tag: what kind of modulation to use.
|
||||
wire [2:0] hi_simulate_mod_type;
|
||||
assign hi_simulate_mod_type = conf_word[2:0];
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// And then we instantiate the modules corresponding to each of the FPGA's
|
||||
// major modes, and use muxes to connect the outputs of the active mode to
|
||||
// the output pins.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
lo_read lr(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
lr_pwr_lo, lr_pwr_hi, lr_pwr_oe1, lr_pwr_oe2, lr_pwr_oe3, lr_pwr_oe4,
|
||||
adc_d, lr_adc_clk,
|
||||
lr_ssp_frame, lr_ssp_din, ssp_dout, lr_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
lr_dbg,
|
||||
lo_is_125khz
|
||||
);
|
||||
|
||||
lo_simulate ls(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ls_pwr_lo, ls_pwr_hi, ls_pwr_oe1, ls_pwr_oe2, ls_pwr_oe3, ls_pwr_oe4,
|
||||
adc_d, ls_adc_clk,
|
||||
ls_ssp_frame, ls_ssp_din, ssp_dout, ls_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
ls_dbg
|
||||
);
|
||||
|
||||
hi_read_tx ht(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
ht_pwr_lo, ht_pwr_hi, ht_pwr_oe1, ht_pwr_oe2, ht_pwr_oe3, ht_pwr_oe4,
|
||||
adc_d, ht_adc_clk,
|
||||
ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
ht_dbg,
|
||||
hi_read_tx_shallow_modulation
|
||||
);
|
||||
|
||||
hi_read_rx_xcorr hrxc(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
hrxc_pwr_lo, hrxc_pwr_hi, hrxc_pwr_oe1, hrxc_pwr_oe2, hrxc_pwr_oe3, hrxc_pwr_oe4,
|
||||
adc_d, hrxc_adc_clk,
|
||||
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hrxc_dbg,
|
||||
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop
|
||||
);
|
||||
|
||||
hi_simulate hs(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4,
|
||||
adc_d, hs_adc_clk,
|
||||
hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hs_dbg,
|
||||
hi_simulate_mod_type
|
||||
);
|
||||
|
||||
hi_iso14443a hisn(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
hisn_pwr_lo, hisn_pwr_hi, hisn_pwr_oe1, hisn_pwr_oe2, hisn_pwr_oe3, hisn_pwr_oe4,
|
||||
adc_d, hisn_adc_clk,
|
||||
hisn_ssp_frame, hisn_ssp_din, ssp_dout, hisn_ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
hisn_dbg,
|
||||
hi_simulate_mod_type
|
||||
);
|
||||
|
||||
// Major modes:
|
||||
// 000 -- LF reader (generic)
|
||||
// 001 -- LF simulated tag (generic)
|
||||
// 010 -- HF reader, transmitting to tag; modulation depth selectable
|
||||
// 011 -- HF reader, receiving from tag, correlating as it goes; frequency selectable
|
||||
// 100 -- HF simulated tag
|
||||
// 101 -- HF ISO14443-A
|
||||
// 110 -- unused
|
||||
// 111 -- everything off
|
||||
|
||||
mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, ls_ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, ls_ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, 1'b0, 1'b0);
|
||||
mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, ls_ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, ls_pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, ls_pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, ls_pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, ls_pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, ls_pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, 1'b0, 1'b0);
|
||||
mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, ls_pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, 1'b0, 1'b0);
|
||||
mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, ls_adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, 1'b0, 1'b0);
|
||||
mux8 mux_dbg (major_mode, dbg, lr_dbg, ls_dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, 1'b0, 1'b0);
|
||||
|
||||
// In all modes, let the ADC's outputs be enabled.
|
||||
assign adc_noe = 1'b0;
|
||||
|
||||
endmodule
|
38
fpga/go.bat
Normal file
38
fpga/go.bat
Normal file
|
@ -0,0 +1,38 @@
|
|||
@echo off
|
||||
|
||||
rmdir/s/q xst
|
||||
|
||||
del fpga.ngc
|
||||
xst -ifn xst.scr
|
||||
if errorlevel 0 goto ok1
|
||||
goto done
|
||||
:ok1
|
||||
|
||||
del fpga.ngd
|
||||
ngdbuild -aul -p xc2s30-6vq100 -nt timestamp -uc fpga.ucf fpga.ngc fpga.ngd
|
||||
if errorlevel 0 goto ok2
|
||||
goto done
|
||||
:ok2
|
||||
|
||||
del fpga.ncd
|
||||
map -p xc2s30-6vq100 fpga.ngd
|
||||
if errorlevel 0 goto ok3
|
||||
goto done
|
||||
:ok3
|
||||
|
||||
del fpga-placed.ncd
|
||||
par fpga.ncd fpga-placed.ncd
|
||||
if errorlevel 0 goto ok4
|
||||
goto done
|
||||
:ok4
|
||||
|
||||
del fpga.bit fpga.drc fpga.rbt
|
||||
bitgen -b fpga-placed.ncd fpga.bit
|
||||
if errorlevel 0 goto ok5
|
||||
goto done
|
||||
:ok5
|
||||
|
||||
echo okay
|
||||
perl ..\tools\rbt2c.pl fpga.rbt > ..\armsrc\fpgaimg.c
|
||||
|
||||
:done
|
360
fpga/hi_iso14443a.v
Normal file
360
fpga/hi_iso14443a.v
Normal file
|
@ -0,0 +1,360 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// ISO14443-A support for the Proxmark III
|
||||
// Gerhard de Koning Gans, April 2008
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_iso14443a(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
mod_type
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input [2:0] mod_type;
|
||||
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
reg fc_div_2;
|
||||
always @(posedge ck_1356meg)
|
||||
fc_div_2 = ~fc_div_2;
|
||||
|
||||
wire adc_clk;
|
||||
assign adc_clk = ck_1356meg;
|
||||
|
||||
reg after_hysteresis, after_hysteresis_prev1, after_hysteresis_prev2, after_hysteresis_prev3;
|
||||
reg [11:0] has_been_low_for;
|
||||
reg [8:0] saw_deep_modulation;
|
||||
reg [2:0] deep_counter;
|
||||
reg deep_modulation;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(& adc_d[7:6]) after_hysteresis <= 1'b1;
|
||||
else if(~(| adc_d[7:4])) after_hysteresis <= 1'b0;
|
||||
|
||||
if(~(| adc_d[7:0]))
|
||||
begin
|
||||
if(deep_counter == 3'd7)
|
||||
begin
|
||||
deep_modulation <= 1'b1;
|
||||
saw_deep_modulation <= 8'd0;
|
||||
end
|
||||
else
|
||||
deep_counter <= deep_counter + 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
deep_counter <= 3'd0;
|
||||
if(saw_deep_modulation == 8'd255)
|
||||
deep_modulation <= 1'b0;
|
||||
else
|
||||
saw_deep_modulation <= saw_deep_modulation + 1;
|
||||
end
|
||||
|
||||
if(after_hysteresis)
|
||||
begin
|
||||
has_been_low_for <= 7'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(has_been_low_for == 12'd4095)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
after_hysteresis <= 1'b1;
|
||||
end
|
||||
else
|
||||
has_been_low_for <= has_been_low_for + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Report every 4 subcarrier cycles
|
||||
// 64 periods of carrier frequency => 6-bit counter [negedge_cnt]
|
||||
reg [5:0] negedge_cnt;
|
||||
reg bit1, bit2, bit3;
|
||||
reg [3:0] count_ones;
|
||||
reg [3:0] count_zeros;
|
||||
wire [7:0] avg;
|
||||
reg [7:0] lavg;
|
||||
reg signed [12:0] step1;
|
||||
reg signed [12:0] step2;
|
||||
reg [7:0] stepsize;
|
||||
reg curbit;
|
||||
reg [12:0] average;
|
||||
wire signed [9:0] dif;
|
||||
|
||||
// A register to send the results to the arm
|
||||
reg signed [7:0] to_arm;
|
||||
|
||||
assign avg[7:0] = average[11:4];
|
||||
assign dif = lavg - avg;
|
||||
|
||||
reg bit_to_arm;
|
||||
reg fdt_indicator, fdt_elapsed;
|
||||
reg [10:0] fdt_counter;
|
||||
reg [47:0] mod_sig_buf;
|
||||
wire mod_sig_buf_empty;
|
||||
reg [5:0] mod_sig_ptr;
|
||||
reg [3:0] mod_sig_flip;
|
||||
reg mod_sig, mod_sig_coil;
|
||||
reg temp_buffer_reset;
|
||||
reg sendbit;
|
||||
|
||||
assign mod_sig_buf_empty = ~(|mod_sig_buf[47:0]);
|
||||
reg [2:0] ssp_frame_counter;
|
||||
|
||||
// ADC data appears on the rising edge, so sample it on the falling edge
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
|
||||
// last bit = 0 then fdt = 1172, in case of 0x26 (7-bit command, LSB first!)
|
||||
// last bit = 1 then fdt = 1236, in case of 0x52 (7-bit command, LSB first!)
|
||||
if(fdt_counter == 11'd740) fdt_indicator = 1'b1;
|
||||
|
||||
if(fdt_counter == 11'd1148)
|
||||
begin
|
||||
if(fdt_elapsed)
|
||||
begin
|
||||
if(negedge_cnt[3:0] == mod_sig_flip[3:0]) mod_sig_coil <= mod_sig;
|
||||
end
|
||||
else
|
||||
begin
|
||||
mod_sig_flip[3:0] <= negedge_cnt[3:0];
|
||||
mod_sig_coil <= mod_sig;
|
||||
fdt_elapsed = 1'b1;
|
||||
fdt_indicator = 1'b0;
|
||||
|
||||
if(~(| mod_sig_ptr[5:0])) mod_sig_ptr <= 6'b001001;
|
||||
else temp_buffer_reset = 1'b1; // fix position of the buffer pointer
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
fdt_counter <= fdt_counter + 1;
|
||||
end
|
||||
|
||||
if(& negedge_cnt[3:0])
|
||||
begin
|
||||
// When there is a dip in the signal and not in reader mode
|
||||
if(~after_hysteresis && mod_sig_buf_empty && ~((mod_type == 3'b100) || (mod_type == 3'b011) || (mod_type == 3'b010))) // last condition to prevent reset
|
||||
begin
|
||||
fdt_counter <= 11'd0;
|
||||
fdt_elapsed = 1'b0;
|
||||
fdt_indicator = 1'b0;
|
||||
temp_buffer_reset = 1'b0;
|
||||
mod_sig_ptr <= 6'b000000;
|
||||
end
|
||||
|
||||
lavg <= avg;
|
||||
|
||||
if(stepsize<16) stepsize = 8'd16;
|
||||
|
||||
if(dif>0)
|
||||
begin
|
||||
step1 = dif*3;
|
||||
step2 = stepsize*2; // 3:2
|
||||
if(step1>step2)
|
||||
begin
|
||||
curbit = 1'b0;
|
||||
stepsize = dif;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
step1 = dif*3;
|
||||
step1 = -step1;
|
||||
step2 = stepsize*2;
|
||||
if(step1>step2)
|
||||
begin
|
||||
curbit = 1'b1;
|
||||
stepsize = -dif;
|
||||
end
|
||||
end
|
||||
|
||||
if(curbit)
|
||||
begin
|
||||
count_zeros <= 4'd0;
|
||||
if(& count_ones[3:2])
|
||||
begin
|
||||
curbit = 1'b0; // suppressed signal
|
||||
stepsize = 8'd24; // just a fine number
|
||||
end
|
||||
else
|
||||
begin
|
||||
count_ones <= count_ones + 1;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
count_ones <= 4'd0;
|
||||
if(& count_zeros[3:0])
|
||||
begin
|
||||
stepsize = 8'd24;
|
||||
end
|
||||
else
|
||||
begin
|
||||
count_zeros <= count_zeros + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// What do we communicate to the ARM
|
||||
if(mod_type == 3'b001) sendbit = after_hysteresis;
|
||||
else if(mod_type == 3'b010)
|
||||
begin
|
||||
if(fdt_counter > 11'd772) sendbit = mod_sig_coil;
|
||||
else sendbit = fdt_indicator;
|
||||
end
|
||||
else if(mod_type == 3'b011) sendbit = curbit;
|
||||
else sendbit = 1'b0;
|
||||
|
||||
end
|
||||
|
||||
if(~(| negedge_cnt[3:0])) average <= adc_d;
|
||||
else average <= average + adc_d;
|
||||
|
||||
if(negedge_cnt == 7'd63)
|
||||
begin
|
||||
if(deep_modulation)
|
||||
begin
|
||||
to_arm <= {after_hysteresis_prev1,after_hysteresis_prev2,after_hysteresis_prev3,after_hysteresis,1'b0,1'b0,1'b0,1'b0};
|
||||
end
|
||||
else
|
||||
begin
|
||||
to_arm <= {after_hysteresis_prev1,after_hysteresis_prev2,after_hysteresis_prev3,after_hysteresis,bit1,bit2,bit3,curbit};
|
||||
end
|
||||
|
||||
negedge_cnt <= 0;
|
||||
|
||||
end
|
||||
else
|
||||
begin
|
||||
negedge_cnt <= negedge_cnt + 1;
|
||||
end
|
||||
|
||||
if(negedge_cnt == 6'd15)
|
||||
begin
|
||||
after_hysteresis_prev1 <= after_hysteresis;
|
||||
bit1 <= curbit;
|
||||
end
|
||||
if(negedge_cnt == 6'd31)
|
||||
begin
|
||||
after_hysteresis_prev2 <= after_hysteresis;
|
||||
bit2 <= curbit;
|
||||
end
|
||||
if(negedge_cnt == 6'd47)
|
||||
begin
|
||||
after_hysteresis_prev3 <= after_hysteresis;
|
||||
bit3 <= curbit;
|
||||
end
|
||||
|
||||
|
||||
if(mod_type != 3'b000)
|
||||
begin
|
||||
if(negedge_cnt[3:0] == 4'b1000)
|
||||
begin
|
||||
// The modulation signal of the tag
|
||||
mod_sig_buf[47:0] <= {mod_sig_buf[46:1], ssp_dout, 1'b0};
|
||||
if((ssp_dout || (| mod_sig_ptr[5:0])) && ~fdt_elapsed)
|
||||
if(mod_sig_ptr == 6'b101110)
|
||||
begin
|
||||
mod_sig_ptr <= 6'b000000;
|
||||
end
|
||||
else mod_sig_ptr <= mod_sig_ptr + 1;
|
||||
else if(fdt_elapsed && ~temp_buffer_reset)
|
||||
begin
|
||||
if(ssp_dout) temp_buffer_reset = 1'b1;
|
||||
if(mod_sig_ptr == 6'b000010) mod_sig_ptr <= 6'b001001;
|
||||
else mod_sig_ptr <= mod_sig_ptr - 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// side effect: when ptr = 1 it will cancel the first 1 of every block of ones
|
||||
if(~mod_sig_buf[mod_sig_ptr-1] && ~mod_sig_buf[mod_sig_ptr+1]) mod_sig = 1'b0;
|
||||
else mod_sig = mod_sig_buf[mod_sig_ptr] & fdt_elapsed; // & fdt_elapsed was for direct relay to oe4
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// SSP Clock and data
|
||||
if(mod_type == 3'b000)
|
||||
begin
|
||||
if(negedge_cnt[2:0] == 3'b100)
|
||||
ssp_clk <= 1'b0;
|
||||
|
||||
if(negedge_cnt[2:0] == 3'b000)
|
||||
begin
|
||||
ssp_clk <= 1'b1;
|
||||
// Don't shift if we just loaded new data, obviously.
|
||||
if(negedge_cnt != 7'd0)
|
||||
begin
|
||||
to_arm[7:1] <= to_arm[6:0];
|
||||
end
|
||||
end
|
||||
|
||||
if(negedge_cnt[5:4] == 2'b00)
|
||||
ssp_frame = 1'b1;
|
||||
else
|
||||
ssp_frame = 1'b0;
|
||||
|
||||
bit_to_arm = to_arm[7];
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(negedge_cnt[3:0] == 4'b1000) ssp_clk <= 1'b0;
|
||||
|
||||
if(negedge_cnt[3:0] == 4'b0111)
|
||||
begin
|
||||
if(ssp_frame_counter == 3'd7) ssp_frame_counter <= 3'd0;
|
||||
else ssp_frame_counter <= ssp_frame_counter + 1;
|
||||
end
|
||||
|
||||
if(negedge_cnt[3:0] == 4'b0000)
|
||||
begin
|
||||
ssp_clk <= 1'b1;
|
||||
end
|
||||
|
||||
ssp_frame = (ssp_frame_counter == 3'd7);
|
||||
|
||||
bit_to_arm = sendbit;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
assign ssp_din = bit_to_arm;
|
||||
|
||||
// Modulating carrier frequency is fc/16
|
||||
wire modulating_carrier;
|
||||
assign modulating_carrier = (mod_sig_coil & negedge_cnt[3] & (mod_type == 3'b010));
|
||||
assign pwr_hi = (ck_1356megb & (((mod_type == 3'b100) & ~mod_sig_coil) || (mod_type == 3'b011)));
|
||||
|
||||
// This one is all LF, so doesn't matter
|
||||
//assign pwr_oe2 = modulating_carrier;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// Toggle only one of these, since we are already producing much deeper
|
||||
// modulation than a real tag would.
|
||||
//assign pwr_oe1 = modulating_carrier;
|
||||
assign pwr_oe1 = 1'b0;
|
||||
assign pwr_oe4 = modulating_carrier;
|
||||
//assign pwr_oe4 = 1'b0;
|
||||
|
||||
// This one is always on, so that we can watch the carrier.
|
||||
//assign pwr_oe3 = modulating_carrier;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
||||
|
||||
assign dbg = negedge_cnt[3];
|
||||
|
||||
// Unused.
|
||||
assign pwr_lo = 1'b0;
|
||||
|
||||
endmodule
|
165
fpga/hi_read_rx_xcorr.v
Normal file
165
fpga/hi_read_rx_xcorr.v
Normal file
|
@ -0,0 +1,165 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_read_rx_xcorr(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
xcorr_is_848, snoop
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input xcorr_is_848, snoop;
|
||||
|
||||
// Carrier is steady on through this, unless we're snooping.
|
||||
assign pwr_hi = ck_1356megb & (~snoop);
|
||||
assign pwr_oe1 = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe4 = 1'b0;
|
||||
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
reg fc_div_2;
|
||||
always @(posedge ck_1356meg)
|
||||
fc_div_2 = ~fc_div_2;
|
||||
|
||||
reg adc_clk;
|
||||
|
||||
always @(xcorr_is_848 or fc_div_2 or ck_1356meg)
|
||||
if(xcorr_is_848)
|
||||
// The subcarrier frequency is fc/16; we will sample at fc, so that
|
||||
// means the subcarrier is 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 ...
|
||||
adc_clk <= ck_1356meg;
|
||||
else
|
||||
// The subcarrier frequency is fc/32; we will sample at fc/2, and
|
||||
// the subcarrier will look identical.
|
||||
adc_clk <= fc_div_2;
|
||||
|
||||
// When we're a reader, we just need to do the BPSK demod; but when we're an
|
||||
// eavesdropper, we also need to pick out the commands sent by the reader,
|
||||
// using AM. Do this the same way that we do it for the simulated tag.
|
||||
reg after_hysteresis, after_hysteresis_prev;
|
||||
reg [11:0] has_been_low_for;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(& adc_d[7:0]) after_hysteresis <= 1'b1;
|
||||
else if(~(| adc_d[7:0])) after_hysteresis <= 1'b0;
|
||||
|
||||
if(after_hysteresis)
|
||||
begin
|
||||
has_been_low_for <= 7'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(has_been_low_for == 12'd4095)
|
||||
begin
|
||||
has_been_low_for <= 12'd0;
|
||||
after_hysteresis <= 1'b1;
|
||||
end
|
||||
else
|
||||
has_been_low_for <= has_been_low_for + 1;
|
||||
end
|
||||
end
|
||||
|
||||
// Let us report a correlation every 4 subcarrier cycles, or 4*16 samples,
|
||||
// so we need a 6-bit counter.
|
||||
reg [5:0] corr_i_cnt;
|
||||
reg [5:0] corr_q_cnt;
|
||||
// And a couple of registers in which to accumulate the correlations.
|
||||
reg signed [15:0] corr_i_accum;
|
||||
reg signed [15:0] corr_q_accum;
|
||||
reg signed [7:0] corr_i_out;
|
||||
reg signed [7:0] corr_q_out;
|
||||
|
||||
// ADC data appears on the rising edge, so sample it on the falling edge
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
// These are the correlators: we correlate against in-phase and quadrature
|
||||
// versions of our reference signal, and keep the (signed) result to
|
||||
// send out later over the SSP.
|
||||
if(corr_i_cnt == 7'd63)
|
||||
begin
|
||||
if(snoop)
|
||||
begin
|
||||
corr_i_out <= {corr_i_accum[12:6], after_hysteresis_prev};
|
||||
corr_q_out <= {corr_q_accum[12:6], after_hysteresis};
|
||||
end
|
||||
else
|
||||
begin
|
||||
// Only correlations need to be delivered.
|
||||
corr_i_out <= corr_i_accum[13:6];
|
||||
corr_q_out <= corr_q_accum[13:6];
|
||||
end
|
||||
|
||||
corr_i_accum <= adc_d;
|
||||
corr_q_accum <= adc_d;
|
||||
corr_q_cnt <= 4;
|
||||
corr_i_cnt <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(corr_i_cnt[3])
|
||||
corr_i_accum <= corr_i_accum - adc_d;
|
||||
else
|
||||
corr_i_accum <= corr_i_accum + adc_d;
|
||||
|
||||
if(corr_q_cnt[3])
|
||||
corr_q_accum <= corr_q_accum - adc_d;
|
||||
else
|
||||
corr_q_accum <= corr_q_accum + adc_d;
|
||||
|
||||
corr_i_cnt <= corr_i_cnt + 1;
|
||||
corr_q_cnt <= corr_q_cnt + 1;
|
||||
end
|
||||
|
||||
// The logic in hi_simulate.v reports 4 samples per bit. We report two
|
||||
// (I, Q) pairs per bit, so we should do 2 samples per pair.
|
||||
if(corr_i_cnt == 6'd31)
|
||||
after_hysteresis_prev <= after_hysteresis;
|
||||
|
||||
// Then the result from last time is serialized and send out to the ARM.
|
||||
// We get one report each cycle, and each report is 16 bits, so the
|
||||
// ssp_clk should be the adc_clk divided by 64/16 = 4.
|
||||
|
||||
if(corr_i_cnt[1:0] == 2'b10)
|
||||
ssp_clk <= 1'b0;
|
||||
|
||||
if(corr_i_cnt[1:0] == 2'b00)
|
||||
begin
|
||||
ssp_clk <= 1'b1;
|
||||
// Don't shift if we just loaded new data, obviously.
|
||||
if(corr_i_cnt != 7'd0)
|
||||
begin
|
||||
corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]};
|
||||
corr_q_out[7:1] <= corr_q_out[6:0];
|
||||
end
|
||||
end
|
||||
|
||||
if(corr_i_cnt[5:2] == 4'b000 || corr_i_cnt[5:2] == 4'b1000)
|
||||
ssp_frame = 1'b1;
|
||||
else
|
||||
ssp_frame = 1'b0;
|
||||
|
||||
end
|
||||
|
||||
assign ssp_din = corr_i_out[7];
|
||||
|
||||
assign dbg = corr_i_cnt[3];
|
||||
|
||||
// Unused.
|
||||
assign pwr_lo = 1'b0;
|
||||
|
||||
endmodule
|
76
fpga/hi_read_tx.v
Normal file
76
fpga/hi_read_tx.v
Normal file
|
@ -0,0 +1,76 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// The way that we connect things when transmitting a command to an ISO
|
||||
// 15693 tag, using 100% modulation only for now.
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_read_tx(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
shallow_modulation
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input shallow_modulation;
|
||||
|
||||
// The high-frequency stuff. For now, for testing, just bring out the carrier,
|
||||
// and allow the ARM to modulate it over the SSP.
|
||||
reg pwr_hi;
|
||||
reg pwr_oe1;
|
||||
reg pwr_oe2;
|
||||
reg pwr_oe3;
|
||||
reg pwr_oe4;
|
||||
always @(ck_1356megb or ssp_dout or shallow_modulation)
|
||||
begin
|
||||
if(shallow_modulation)
|
||||
begin
|
||||
pwr_hi <= ck_1356megb;
|
||||
pwr_oe1 <= ~ssp_dout;
|
||||
pwr_oe2 <= ~ssp_dout;
|
||||
pwr_oe3 <= ~ssp_dout;
|
||||
pwr_oe4 <= 1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
pwr_hi <= ck_1356megb & ssp_dout;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe2 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// Then just divide the 13.56 MHz clock down to produce appropriate clocks
|
||||
// for the synchronous serial port.
|
||||
|
||||
reg [6:0] hi_div_by_128;
|
||||
|
||||
always @(posedge ck_1356meg)
|
||||
hi_div_by_128 <= hi_div_by_128 + 1;
|
||||
|
||||
assign ssp_clk = hi_div_by_128[6];
|
||||
|
||||
reg [2:0] hi_byte_div;
|
||||
|
||||
always @(negedge ssp_clk)
|
||||
hi_byte_div <= hi_byte_div + 1;
|
||||
|
||||
assign ssp_frame = (hi_byte_div == 3'b000);
|
||||
|
||||
assign ssp_din = 1'b0;
|
||||
|
||||
assign pwr_lo = 1'b0;
|
||||
assign dbg = ssp_frame;
|
||||
|
||||
endmodule
|
106
fpga/hi_simulate.v
Normal file
106
fpga/hi_simulate.v
Normal file
|
@ -0,0 +1,106 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Pretend to be an ISO 14443 tag. We will do this by alternately short-
|
||||
// circuiting and open-circuiting the antenna coil, with the tri-state
|
||||
// pins.
|
||||
//
|
||||
// We communicate over the SSP, as a bitstream (i.e., might as well be
|
||||
// unframed, though we still generate the word sync signal). The output
|
||||
// (ARM -> FPGA) tells us whether to modulate or not. The input (FPGA
|
||||
// -> ARM) is us using the A/D as a fancy comparator; this is with
|
||||
// (software-added) hysteresis, to undo the high-pass filter.
|
||||
//
|
||||
// At this point only Type A is implemented. This means that we are using a
|
||||
// bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make
|
||||
// things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s)
|
||||
//
|
||||
// Jonathan Westhues, October 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_simulate(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
mod_type
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input [2:0] mod_type;
|
||||
|
||||
// Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can
|
||||
// always be low.
|
||||
assign pwr_hi = 1'b0;
|
||||
assign pwr_lo = 1'b0;
|
||||
|
||||
// The comparator with hysteresis on the output from the peak detector.
|
||||
reg after_hysteresis;
|
||||
assign adc_clk = ck_1356meg;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if(& adc_d[7:5]) after_hysteresis = 1'b1;
|
||||
else if(~(| adc_d[7:5])) after_hysteresis = 1'b0;
|
||||
end
|
||||
|
||||
// Divide 13.56 MHz by 32 to produce the SSP_CLK
|
||||
reg [4:0] ssp_clk_divider;
|
||||
always @(posedge adc_clk)
|
||||
ssp_clk_divider <= (ssp_clk_divider + 1);
|
||||
assign ssp_clk = ssp_clk_divider[4];
|
||||
|
||||
// Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
|
||||
// this is arbitrary, because it's just a bitstream.
|
||||
// One nasty issue, though: I can't make it work with both rx and tx at
|
||||
// once. The phase wrt ssp_clk must be changed. TODO to find out why
|
||||
// that is and make a better fix.
|
||||
reg [2:0] ssp_frame_divider_to_arm;
|
||||
always @(posedge ssp_clk)
|
||||
ssp_frame_divider_to_arm <= (ssp_frame_divider_to_arm + 1);
|
||||
reg [2:0] ssp_frame_divider_from_arm;
|
||||
always @(negedge ssp_clk)
|
||||
ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1);
|
||||
|
||||
reg ssp_frame;
|
||||
always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type)
|
||||
if(mod_type == 3'b000) // not modulating, so listening, to ARM
|
||||
ssp_frame = (ssp_frame_divider_to_arm == 3'b000);
|
||||
else
|
||||
ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
|
||||
|
||||
// Synchronize up the after-hysteresis signal, to produce DIN.
|
||||
reg ssp_din;
|
||||
always @(posedge ssp_clk)
|
||||
ssp_din = after_hysteresis;
|
||||
|
||||
// Modulating carrier frequency is fc/16, reuse ssp_clk divider for that
|
||||
reg modulating_carrier;
|
||||
always @(mod_type or ssp_clk or ssp_dout)
|
||||
if(mod_type == 3'b000)
|
||||
modulating_carrier <= 1'b0; // no modulation
|
||||
else if(mod_type == 3'b001)
|
||||
modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK
|
||||
else
|
||||
modulating_carrier <= 1'b0; // yet unused
|
||||
|
||||
// This one is all LF, so doesn't matter
|
||||
assign pwr_oe2 = modulating_carrier;
|
||||
|
||||
// Toggle only one of these, since we are already producing much deeper
|
||||
// modulation than a real tag would.
|
||||
assign pwr_oe1 = modulating_carrier;
|
||||
assign pwr_oe4 = modulating_carrier;
|
||||
|
||||
// This one is always on, so that we can watch the carrier.
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
||||
assign dbg = after_hysteresis;
|
||||
|
||||
endmodule
|
102
fpga/lo_read.v
Normal file
102
fpga/lo_read.v
Normal file
|
@ -0,0 +1,102 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// The way that we connect things in low-frequency read mode. In this case
|
||||
// we are generating the 134 kHz or 125 kHz carrier, and running the
|
||||
// unmodulated carrier at that frequency. The A/D samples at that same rate,
|
||||
// and the result is serialized.
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module lo_read(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
lo_is_125khz
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input lo_is_125khz;
|
||||
|
||||
// The low-frequency RFID stuff. This is relatively simple, because most
|
||||
// of the work happens on the ARM, and we just pass samples through. The
|
||||
// PCK0 must be divided down to generate the A/D clock, and from there by
|
||||
// a factor of 8 to generate the carrier (that we apply to the coil drivers).
|
||||
//
|
||||
// This is also where we decode the received synchronous serial port words,
|
||||
// to determine how to drive the output enables.
|
||||
|
||||
// PCK0 will run at (PLL clock) / 4, or 24 MHz. That means that we can do
|
||||
// 125 kHz by dividing by a further factor of (8*12*2), or ~134 kHz by
|
||||
// dividing by a factor of (8*11*2) (for 136 kHz, ~2% error, tolerable).
|
||||
|
||||
reg [3:0] pck_divider;
|
||||
reg clk_lo;
|
||||
|
||||
always @(posedge pck0)
|
||||
begin
|
||||
if(lo_is_125khz)
|
||||
begin
|
||||
if(pck_divider == 4'd11)
|
||||
begin
|
||||
pck_divider <= 4'd0;
|
||||
clk_lo = !clk_lo;
|
||||
end
|
||||
else
|
||||
pck_divider <= pck_divider + 1;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(pck_divider == 4'd10)
|
||||
begin
|
||||
pck_divider <= 4'd0;
|
||||
clk_lo = !clk_lo;
|
||||
end
|
||||
else
|
||||
pck_divider <= pck_divider + 1;
|
||||
end
|
||||
end
|
||||
|
||||
reg [2:0] carrier_divider_lo;
|
||||
|
||||
always @(posedge clk_lo)
|
||||
begin
|
||||
carrier_divider_lo <= carrier_divider_lo + 1;
|
||||
end
|
||||
|
||||
assign pwr_lo = carrier_divider_lo[2];
|
||||
|
||||
// This serializes the values returned from the A/D, and sends them out
|
||||
// over the SSP.
|
||||
|
||||
reg [7:0] to_arm_shiftreg;
|
||||
|
||||
always @(posedge clk_lo)
|
||||
begin
|
||||
if(carrier_divider_lo == 3'b000)
|
||||
to_arm_shiftreg <= adc_d;
|
||||
else
|
||||
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
|
||||
end
|
||||
|
||||
assign ssp_clk = clk_lo;
|
||||
assign ssp_frame = (carrier_divider_lo == 3'b001);
|
||||
assign ssp_din = to_arm_shiftreg[7];
|
||||
|
||||
// The ADC converts on the falling edge, and our serializer loads when
|
||||
// carrier_divider_lo == 3'b000.
|
||||
assign adc_clk = ~carrier_divider_lo[2];
|
||||
|
||||
assign pwr_hi = 1'b0;
|
||||
|
||||
assign dbg = adc_clk;
|
||||
|
||||
endmodule
|
37
fpga/lo_simulate.v
Normal file
37
fpga/lo_simulate.v
Normal file
|
@ -0,0 +1,37 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// The way that we connect things in low-frequency simulation mode. In this
|
||||
// case just pass everything through to the ARM, which can bit-bang this
|
||||
// (because it is so slow).
|
||||
//
|
||||
// Jonathan Westhues, April 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module lo_simulate(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
|
||||
// No logic, straight through.
|
||||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe1 = ssp_dout;
|
||||
assign pwr_oe2 = ssp_dout;
|
||||
assign pwr_oe4 = ssp_dout;
|
||||
assign ssp_clk = cross_lo;
|
||||
assign pwr_lo = 1'b0;
|
||||
assign adc_clk = 1'b0;
|
||||
assign pwr_hi = 1'b0;
|
||||
assign dbg = cross_lo;
|
||||
|
||||
endmodule
|
27
fpga/sim.tcl
Normal file
27
fpga/sim.tcl
Normal file
|
@ -0,0 +1,27 @@
|
|||
#------------------------------------------------------------------------------
|
||||
# Run the simulation testbench in ModelSim: recompile both Verilog source
|
||||
# files, then start the simulation, add a lot of signals to the waveform
|
||||
# viewer, and run. I should (TODO) fix the absolute paths at some point.
|
||||
#
|
||||
# Jonathan Westhues, Mar 2006
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
vlog -work work -O0 C:/depot/proximity/mark3/fpga/fpga.v
|
||||
vlog -work work -O0 C:/depot/proximity/mark3/fpga/fpga_tb.v
|
||||
|
||||
vsim work.fpga_tb
|
||||
|
||||
add wave sim:/fpga_tb/adc_clk
|
||||
add wave sim:/fpga_tb/adc_d
|
||||
add wave sim:/fpga_tb/pwr_lo
|
||||
add wave sim:/fpga_tb/ssp_clk
|
||||
add wave sim:/fpga_tb/ssp_frame
|
||||
add wave sim:/fpga_tb/ssp_din
|
||||
add wave sim:/fpga_tb/ssp_dout
|
||||
|
||||
add wave sim:/fpga_tb/dut/clk_lo
|
||||
add wave sim:/fpga_tb/dut/pck_divider
|
||||
add wave sim:/fpga_tb/dut/carrier_divider_lo
|
||||
add wave sim:/fpga_tb/dut/conf_word
|
||||
|
||||
run 30000
|
50
fpga/testbed_fpga.v
Normal file
50
fpga/testbed_fpga.v
Normal file
|
@ -0,0 +1,50 @@
|
|||
`include "fpga.v"
|
||||
|
||||
module testbed_fpga;
|
||||
reg spck, mosi, ncs;
|
||||
wire miso;
|
||||
reg pck0i, ck_1356meg, ck_1356megb;
|
||||
wire pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
reg [7:0] adc_d;
|
||||
wire adc_clk, adc_noe;
|
||||
reg ssp_dout;
|
||||
wire ssp_frame, ssp_din, ssp_clk;
|
||||
|
||||
fpga dut(
|
||||
spck, miso, mosi, ncs,
|
||||
pck0i, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk, adc_noe,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk
|
||||
);
|
||||
|
||||
integer i;
|
||||
|
||||
initial begin
|
||||
|
||||
// init inputs
|
||||
#5 ncs=1;
|
||||
#5 spck = 1;
|
||||
#5 mosi = 1;
|
||||
|
||||
#50 ncs=0;
|
||||
for (i = 0 ; i < 8 ; i = i + 1) begin
|
||||
#5 mosi = $random;
|
||||
#5 spck = 0;
|
||||
#5 spck = 1;
|
||||
end
|
||||
#5 ncs=1;
|
||||
|
||||
#50 ncs=0;
|
||||
for (i = 0 ; i < 8 ; i = i + 1) begin
|
||||
#5 mosi = $random;
|
||||
#5 spck = 0;
|
||||
#5 spck = 1;
|
||||
end
|
||||
#5 ncs=1;
|
||||
|
||||
#50 mosi=1;
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
109
fpga/testbed_hi_read_tx.v
Normal file
109
fpga/testbed_hi_read_tx.v
Normal file
|
@ -0,0 +1,109 @@
|
|||
`include "hi_read_tx.v"
|
||||
|
||||
/*
|
||||
pck0 - input main 24Mhz clock (PLL / 4)
|
||||
[7:0] adc_d - input data from A/D converter
|
||||
shallow_modulation - modulation type
|
||||
|
||||
pwr_lo - output to coil drivers (ssp_clk / 8)
|
||||
adc_clk - output A/D clock signal
|
||||
ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted)
|
||||
ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first)
|
||||
ssp_clk - output SSP clock signal
|
||||
|
||||
ck_1356meg - input unused
|
||||
ck_1356megb - input unused
|
||||
ssp_dout - input unused
|
||||
cross_hi - input unused
|
||||
cross_lo - input unused
|
||||
|
||||
pwr_hi - output unused, tied low
|
||||
pwr_oe1 - output unused, undefined
|
||||
pwr_oe2 - output unused, undefined
|
||||
pwr_oe3 - output unused, undefined
|
||||
pwr_oe4 - output unused, undefined
|
||||
dbg - output alias for adc_clk
|
||||
*/
|
||||
|
||||
module testbed_hi_read_tx;
|
||||
reg pck0;
|
||||
reg [7:0] adc_d;
|
||||
reg shallow_modulation;
|
||||
|
||||
wire pwr_lo;
|
||||
wire adc_clk;
|
||||
reg ck_1356meg;
|
||||
reg ck_1356megb;
|
||||
wire ssp_frame;
|
||||
wire ssp_din;
|
||||
wire ssp_clk;
|
||||
reg ssp_dout;
|
||||
wire pwr_hi;
|
||||
wire pwr_oe1;
|
||||
wire pwr_oe2;
|
||||
wire pwr_oe3;
|
||||
wire pwr_oe4;
|
||||
wire cross_lo;
|
||||
wire cross_hi;
|
||||
wire dbg;
|
||||
|
||||
hi_read_tx #(5,200) dut(
|
||||
.pck0(pck0),
|
||||
.ck_1356meg(ck_1356meg),
|
||||
.ck_1356megb(ck_1356megb),
|
||||
.pwr_lo(pwr_lo),
|
||||
.pwr_hi(pwr_hi),
|
||||
.pwr_oe1(pwr_oe1),
|
||||
.pwr_oe2(pwr_oe2),
|
||||
.pwr_oe3(pwr_oe3),
|
||||
.pwr_oe4(pwr_oe4),
|
||||
.adc_d(adc_d),
|
||||
.adc_clk(adc_clk),
|
||||
.ssp_frame(ssp_frame),
|
||||
.ssp_din(ssp_din),
|
||||
.ssp_dout(ssp_dout),
|
||||
.ssp_clk(ssp_clk),
|
||||
.cross_hi(cross_hi),
|
||||
.cross_lo(cross_lo),
|
||||
.dbg(dbg),
|
||||
.shallow_modulation(shallow_modulation)
|
||||
);
|
||||
|
||||
integer idx, i;
|
||||
|
||||
// main clock
|
||||
always #5 begin
|
||||
ck_1356megb = !ck_1356megb;
|
||||
ck_1356meg = ck_1356megb;
|
||||
end
|
||||
|
||||
//crank DUT
|
||||
task crank_dut;
|
||||
begin
|
||||
@(posedge ssp_clk) ;
|
||||
ssp_dout = $random;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
|
||||
// init inputs
|
||||
ck_1356megb = 0;
|
||||
adc_d = 0;
|
||||
ssp_dout=0;
|
||||
|
||||
// shallow modulation off
|
||||
shallow_modulation=0;
|
||||
for (i = 0 ; i < 16 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
|
||||
// shallow modulation on
|
||||
shallow_modulation=1;
|
||||
for (i = 0 ; i < 16 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
116
fpga/testbed_hi_simulate.v
Normal file
116
fpga/testbed_hi_simulate.v
Normal file
|
@ -0,0 +1,116 @@
|
|||
`include "hi_simulate.v"
|
||||
|
||||
/*
|
||||
pck0 - input main 24Mhz clock (PLL / 4)
|
||||
[7:0] adc_d - input data from A/D converter
|
||||
mod_type - modulation type
|
||||
|
||||
pwr_lo - output to coil drivers (ssp_clk / 8)
|
||||
adc_clk - output A/D clock signal
|
||||
ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted)
|
||||
ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first)
|
||||
ssp_clk - output SSP clock signal
|
||||
|
||||
ck_1356meg - input unused
|
||||
ck_1356megb - input unused
|
||||
ssp_dout - input unused
|
||||
cross_hi - input unused
|
||||
cross_lo - input unused
|
||||
|
||||
pwr_hi - output unused, tied low
|
||||
pwr_oe1 - output unused, undefined
|
||||
pwr_oe2 - output unused, undefined
|
||||
pwr_oe3 - output unused, undefined
|
||||
pwr_oe4 - output unused, undefined
|
||||
dbg - output alias for adc_clk
|
||||
*/
|
||||
|
||||
module testbed_hi_simulate;
|
||||
reg pck0;
|
||||
reg [7:0] adc_d;
|
||||
reg mod_type;
|
||||
|
||||
wire pwr_lo;
|
||||
wire adc_clk;
|
||||
reg ck_1356meg;
|
||||
reg ck_1356megb;
|
||||
wire ssp_frame;
|
||||
wire ssp_din;
|
||||
wire ssp_clk;
|
||||
reg ssp_dout;
|
||||
wire pwr_hi;
|
||||
wire pwr_oe1;
|
||||
wire pwr_oe2;
|
||||
wire pwr_oe3;
|
||||
wire pwr_oe4;
|
||||
wire cross_lo;
|
||||
wire cross_hi;
|
||||
wire dbg;
|
||||
|
||||
hi_simulate #(5,200) dut(
|
||||
.pck0(pck0),
|
||||
.ck_1356meg(ck_1356meg),
|
||||
.ck_1356megb(ck_1356megb),
|
||||
.pwr_lo(pwr_lo),
|
||||
.pwr_hi(pwr_hi),
|
||||
.pwr_oe1(pwr_oe1),
|
||||
.pwr_oe2(pwr_oe2),
|
||||
.pwr_oe3(pwr_oe3),
|
||||
.pwr_oe4(pwr_oe4),
|
||||
.adc_d(adc_d),
|
||||
.adc_clk(adc_clk),
|
||||
.ssp_frame(ssp_frame),
|
||||
.ssp_din(ssp_din),
|
||||
.ssp_dout(ssp_dout),
|
||||
.ssp_clk(ssp_clk),
|
||||
.cross_hi(cross_hi),
|
||||
.cross_lo(cross_lo),
|
||||
.dbg(dbg),
|
||||
.mod_type(mod_type)
|
||||
);
|
||||
|
||||
integer idx, i;
|
||||
|
||||
// main clock
|
||||
always #5 begin
|
||||
ck_1356megb = !ck_1356megb;
|
||||
ck_1356meg = ck_1356megb;
|
||||
end
|
||||
|
||||
always begin
|
||||
@(negedge adc_clk) ;
|
||||
adc_d = $random;
|
||||
end
|
||||
|
||||
//crank DUT
|
||||
task crank_dut;
|
||||
begin
|
||||
@(negedge ssp_clk) ;
|
||||
ssp_dout = $random;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
|
||||
// init inputs
|
||||
ck_1356megb = 0;
|
||||
// random values
|
||||
adc_d = 0;
|
||||
ssp_dout=1;
|
||||
|
||||
// shallow modulation off
|
||||
mod_type=0;
|
||||
for (i = 0 ; i < 16 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
|
||||
// shallow modulation on
|
||||
mod_type=1;
|
||||
for (i = 0 ; i < 16 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
||||
|
105
fpga/testbed_lo_read.v
Normal file
105
fpga/testbed_lo_read.v
Normal file
|
@ -0,0 +1,105 @@
|
|||
`include "lo_read.v"
|
||||
|
||||
/*
|
||||
pck0 - input main 24Mhz clock (PLL / 4)
|
||||
[7:0] adc_d - input data from A/D converter
|
||||
lo_is_125khz - input freq selector (1=125Khz, 0=136Khz)
|
||||
|
||||
pwr_lo - output to coil drivers (ssp_clk / 8)
|
||||
adc_clk - output A/D clock signal
|
||||
ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted)
|
||||
ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first)
|
||||
ssp_clk - output SSP clock signal 1Mhz/1.09Mhz (pck0 / 2*(11+lo_is_125khz) )
|
||||
|
||||
ck_1356meg - input unused
|
||||
ck_1356megb - input unused
|
||||
ssp_dout - input unused
|
||||
cross_hi - input unused
|
||||
cross_lo - input unused
|
||||
|
||||
pwr_hi - output unused, tied low
|
||||
pwr_oe1 - output unused, undefined
|
||||
pwr_oe2 - output unused, undefined
|
||||
pwr_oe3 - output unused, undefined
|
||||
pwr_oe4 - output unused, undefined
|
||||
dbg - output alias for adc_clk
|
||||
*/
|
||||
|
||||
module testbed_lo_read;
|
||||
reg pck0;
|
||||
reg [7:0] adc_d;
|
||||
reg lo_is_125khz;
|
||||
|
||||
wire pwr_lo;
|
||||
wire adc_clk;
|
||||
wire ck_1356meg;
|
||||
wire ck_1356megb;
|
||||
wire ssp_frame;
|
||||
wire ssp_din;
|
||||
wire ssp_clk;
|
||||
wire ssp_dout;
|
||||
wire pwr_hi;
|
||||
wire pwr_oe1;
|
||||
wire pwr_oe2;
|
||||
wire pwr_oe3;
|
||||
wire pwr_oe4;
|
||||
wire cross_lo;
|
||||
wire cross_hi;
|
||||
wire dbg;
|
||||
|
||||
lo_read #(5,200) dut(
|
||||
.pck0(pck0),
|
||||
.ck_1356meg(ck_1356meg),
|
||||
.ck_1356megb(ck_1356megb),
|
||||
.pwr_lo(pwr_lo),
|
||||
.pwr_hi(pwr_hi),
|
||||
.pwr_oe1(pwr_oe1),
|
||||
.pwr_oe2(pwr_oe2),
|
||||
.pwr_oe3(pwr_oe3),
|
||||
.pwr_oe4(pwr_oe4),
|
||||
.adc_d(adc_d),
|
||||
.adc_clk(adc_clk),
|
||||
.ssp_frame(ssp_frame),
|
||||
.ssp_din(ssp_din),
|
||||
.ssp_dout(ssp_dout),
|
||||
.ssp_clk(ssp_clk),
|
||||
.cross_hi(cross_hi),
|
||||
.cross_lo(cross_lo),
|
||||
.dbg(dbg),
|
||||
.lo_is_125khz(lo_is_125khz)
|
||||
);
|
||||
|
||||
integer idx, i;
|
||||
|
||||
// main clock
|
||||
always #5 pck0 = !pck0;
|
||||
|
||||
//new A/D value available from ADC on positive edge
|
||||
task crank_dut;
|
||||
begin
|
||||
@(posedge adc_clk) ;
|
||||
adc_d = $random;
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
|
||||
// init inputs
|
||||
pck0 = 0;
|
||||
adc_d = 0;
|
||||
|
||||
// simulate 4 A/D cycles at 134Khz
|
||||
lo_is_125khz=0;
|
||||
for (i = 0 ; i < 4 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
|
||||
// simulate 4 A/D cycles at 125Khz
|
||||
lo_is_125khz=1;
|
||||
for (i = 0 ; i < 4 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
101
fpga/testbed_lo_simulate.v
Normal file
101
fpga/testbed_lo_simulate.v
Normal file
|
@ -0,0 +1,101 @@
|
|||
`include "lo_simulate.v"
|
||||
|
||||
/*
|
||||
pck0 - input main 24Mhz clock (PLL / 4)
|
||||
[7:0] adc_d - input data from A/D converter
|
||||
|
||||
|
||||
pwr_lo - output to coil drivers (ssp_clk / 8)
|
||||
adc_clk - output A/D clock signal
|
||||
ssp_frame - output SSS frame indicator (goes high while the 8 bits are shifted)
|
||||
ssp_din - output SSP data to ARM (shifts 8 bit A/D value serially to ARM MSB first)
|
||||
ssp_clk - output SSP clock signal
|
||||
|
||||
ck_1356meg - input unused
|
||||
ck_1356megb - input unused
|
||||
ssp_dout - input unused
|
||||
cross_hi - input unused
|
||||
cross_lo - input unused
|
||||
|
||||
pwr_hi - output unused, tied low
|
||||
pwr_oe1 - output unused, undefined
|
||||
pwr_oe2 - output unused, undefined
|
||||
pwr_oe3 - output unused, undefined
|
||||
pwr_oe4 - output unused, undefined
|
||||
dbg - output alias for adc_clk
|
||||
*/
|
||||
|
||||
module testbed_lo_simulate;
|
||||
reg pck0;
|
||||
reg [7:0] adc_d;
|
||||
|
||||
|
||||
wire pwr_lo;
|
||||
wire adc_clk;
|
||||
wire ck_1356meg;
|
||||
wire ck_1356megb;
|
||||
wire ssp_frame;
|
||||
wire ssp_din;
|
||||
wire ssp_clk;
|
||||
reg ssp_dout;
|
||||
wire pwr_hi;
|
||||
wire pwr_oe1;
|
||||
wire pwr_oe2;
|
||||
wire pwr_oe3;
|
||||
wire pwr_oe4;
|
||||
reg cross_lo;
|
||||
wire cross_hi;
|
||||
wire dbg;
|
||||
|
||||
lo_simulate #(5,200) dut(
|
||||
.pck0(pck0),
|
||||
.ck_1356meg(ck_1356meg),
|
||||
.ck_1356megb(ck_1356megb),
|
||||
.pwr_lo(pwr_lo),
|
||||
.pwr_hi(pwr_hi),
|
||||
.pwr_oe1(pwr_oe1),
|
||||
.pwr_oe2(pwr_oe2),
|
||||
.pwr_oe3(pwr_oe3),
|
||||
.pwr_oe4(pwr_oe4),
|
||||
.adc_d(adc_d),
|
||||
.adc_clk(adc_clk),
|
||||
.ssp_frame(ssp_frame),
|
||||
.ssp_din(ssp_din),
|
||||
.ssp_dout(ssp_dout),
|
||||
.ssp_clk(ssp_clk),
|
||||
.cross_hi(cross_hi),
|
||||
.cross_lo(cross_lo),
|
||||
.dbg(dbg)
|
||||
);
|
||||
|
||||
|
||||
integer i, counter=0;
|
||||
|
||||
// main clock
|
||||
always #5 pck0 = !pck0;
|
||||
|
||||
//cross_lo is not really synced to pck0 but it's roughly pck0/192 (24Mhz/192=125Khz)
|
||||
task crank_dut;
|
||||
begin
|
||||
@(posedge pck0) ;
|
||||
counter = counter + 1;
|
||||
if (counter == 192) begin
|
||||
counter = 0;
|
||||
ssp_dout = $random;
|
||||
cross_lo = 1;
|
||||
end else begin
|
||||
cross_lo = 0;
|
||||
end
|
||||
|
||||
end
|
||||
endtask
|
||||
|
||||
initial begin
|
||||
pck0 = 0;
|
||||
for (i = 0 ; i < 4096 ; i = i + 1) begin
|
||||
crank_dut;
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule // main
|
27
fpga/util.v
Normal file
27
fpga/util.v
Normal file
|
@ -0,0 +1,27 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// General-purpose miscellany.
|
||||
//
|
||||
// Jonathan Westhues, April 2006.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module mux8(sel, y, x0, x1, x2, x3, x4, x5, x6, x7);
|
||||
input [2:0] sel;
|
||||
input x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
output y;
|
||||
reg y;
|
||||
|
||||
always @(x0 or x1 or x2 or x3 or x4 or x5 or x6 or x7 or sel)
|
||||
begin
|
||||
case (sel)
|
||||
3'b000: y = x0;
|
||||
3'b001: y = x1;
|
||||
3'b010: y = x2;
|
||||
3'b011: y = x3;
|
||||
3'b100: y = x4;
|
||||
3'b101: y = x5;
|
||||
3'b110: y = x6;
|
||||
3'b111: y = x7;
|
||||
endcase
|
||||
end
|
||||
|
||||
endmodule
|
1
fpga/xst.scr
Normal file
1
fpga/xst.scr
Normal file
|
@ -0,0 +1 @@
|
|||
run -ifn fpga.v -ifmt Verilog -ofn fpga.ngc -ofmt NGC -p xc2s30-6vq100 -opt_mode Speed -opt_level 1 -ent fpga
|
461
include/at91sam7s128.h
Normal file
461
include/at91sam7s128.h
Normal file
|
@ -0,0 +1,461 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Incomplete register definitions for the AT91SAM7S128 chip.
|
||||
// Jonathan Westhues, Jul 2005
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __AT91SAM7S128_H
|
||||
#define __AT91SAM7S128_H
|
||||
|
||||
#define REG(x) (*(volatile unsigned long *)(x))
|
||||
|
||||
//-------------
|
||||
// Peripheral IDs
|
||||
|
||||
#define PERIPH_AIC_FIQ 0
|
||||
#define PERIPH_SYSIRQ 1
|
||||
#define PERIPH_PIOA 2
|
||||
#define PERIPH_ADC 4
|
||||
#define PERIPH_SPI 5
|
||||
#define PERIPH_US0 6
|
||||
#define PERIPH_US1 7
|
||||
#define PERIPH_SSC 8
|
||||
#define PERIPH_TWI 9
|
||||
#define PERIPH_PWMC 10
|
||||
#define PERIPH_UDP 11
|
||||
#define PERIPH_TC0 12
|
||||
#define PERIPH_TC1 13
|
||||
#define PERIPH_TC2 14
|
||||
#define PERIPH_AIC_IRQ0 30
|
||||
#define PERIPH_AIC_IRQ1 31
|
||||
|
||||
//-------------
|
||||
// Reset Controller
|
||||
|
||||
#define RSTC_BASE (0xfffffd00)
|
||||
|
||||
#define RSTC_CONTROL REG(RSTC_BASE+0x00)
|
||||
|
||||
#define RST_CONTROL_KEY (0xa5<<24)
|
||||
#define RST_CONTROL_PROCESSOR_RESET (1<<0)
|
||||
|
||||
//-------------
|
||||
// PWM Controller
|
||||
|
||||
#define PWM_BASE (0xfffcc000)
|
||||
|
||||
#define PWM_MODE REG(PWM_BASE+0x00)
|
||||
#define PWM_ENABLE REG(PWM_BASE+0x04)
|
||||
#define PWM_DISABLE REG(PWM_BASE+0x08)
|
||||
#define PWM_STATUS REG(PWM_BASE+0x0c)
|
||||
#define PWM_INTERRUPT_ENABLE REG(PWM_BASE+0x10)
|
||||
#define PWM_INTERRUPT_DISABLE REG(PWM_BASE+0x14)
|
||||
#define PWM_INTERRUPT_MASK REG(PWM_BASE+0x18)
|
||||
#define PWM_INTERRUPT_STATUS REG(PWM_BASE+0x1c)
|
||||
#define PWM_CH_MODE(x) REG(PWM_BASE+0x200+((x)*0x20))
|
||||
#define PWM_CH_DUTY_CYCLE(x) REG(PWM_BASE+0x204+((x)*0x20))
|
||||
#define PWM_CH_PERIOD(x) REG(PWM_BASE+0x208+((x)*0x20))
|
||||
#define PWM_CH_COUNTER(x) REG(PWM_BASE+0x20c+((x)*0x20))
|
||||
#define PWM_CH_UPDATE(x) REG(PWM_BASE+0x210+((x)*0x20))
|
||||
|
||||
#define PWM_MODE_DIVA(x) ((x)<<0)
|
||||
#define PWM_MODE_PREA(x) ((x)<<8)
|
||||
#define PWM_MODE_DIVB(x) ((x)<<16)
|
||||
#define PWM_MODE_PREB(x) ((x)<<24)
|
||||
|
||||
#define PWM_CHANNEL(x) (1<<(x))
|
||||
|
||||
#define PWM_CH_MODE_PRESCALER(x) ((x)<<0)
|
||||
#define PWM_CH_MODE_PERIOD_CENTER_ALIGNED (1<<8)
|
||||
#define PWM_CH_MODE_POLARITY_STARTS_HIGH (1<<9)
|
||||
#define PWM_CH_MODE_UPDATE_UPDATES_PERIOD (1<<10)
|
||||
|
||||
//-------------
|
||||
// Debug Unit
|
||||
|
||||
#define DBG_BASE (0xfffff200)
|
||||
|
||||
#define DBGU_CR REG(DBG_BASE+0x0000)
|
||||
#define DBGU_MR REG(DBG_BASE+0x0004)
|
||||
#define DBGU_IER REG(DBG_BASE+0x0008)
|
||||
#define DBGU_IDR REG(DBG_BASE+0x000C)
|
||||
#define DBGU_IMR REG(DBG_BASE+0x0010)
|
||||
#define DBGU_SR REG(DBG_BASE+0x0014)
|
||||
#define DBGU_RHR REG(DBG_BASE+0x0018)
|
||||
#define DBGU_THR REG(DBG_BASE+0x001C)
|
||||
#define DBGU_BRGR REG(DBG_BASE+0x0020)
|
||||
#define DBGU_CIDR REG(DBG_BASE+0x0040)
|
||||
#define DBGU_EXID REG(DBG_BASE+0x0044)
|
||||
#define DBGU_FNR REG(DBG_BASE+0x0048)
|
||||
|
||||
//-------------
|
||||
// Embedded Flash Controller
|
||||
|
||||
#define MC_BASE (0xffffff00)
|
||||
|
||||
#define MC_FLASH_MODE0 REG(MC_BASE+0x60)
|
||||
#define MC_FLASH_COMMAND REG(MC_BASE+0x64)
|
||||
#define MC_FLASH_STATUS REG(MC_BASE+0x68)
|
||||
#define MC_FLASH_MODE1 REG(MC_BASE+0x70)
|
||||
|
||||
#define MC_FLASH_MODE_READY_INTERRUPT_ENABLE (1<<0)
|
||||
#define MC_FLASH_MODE_LOCK_INTERRUPT_ENABLE (1<<2)
|
||||
#define MC_FLASH_MODE_PROG_ERROR_INTERRUPT_ENABLE (1<<3)
|
||||
#define MC_FLASH_MODE_NO_ERASE_BEFORE_PROGRAMMING (1<<7)
|
||||
#define MC_FLASH_MODE_FLASH_WAIT_STATES(x) ((x)<<8)
|
||||
#define MC_FLASH_MODE_MASTER_CLK_IN_MHZ(x) ((x)<<16)
|
||||
|
||||
#define MC_FLASH_COMMAND_FCMD(x) ((x)<<0)
|
||||
#define MC_FLASH_COMMAND_PAGEN(x) ((x)<<8)
|
||||
#define MC_FLASH_COMMAND_KEY ((0x5a)<<24)
|
||||
|
||||
#define FCMD_NOP 0x0
|
||||
#define FCMD_WRITE_PAGE 0x1
|
||||
#define FCMD_SET_LOCK_BIT 0x2
|
||||
#define FCMD_WRITE_PAGE_LOCK 0x3
|
||||
#define FCMD_CLEAR_LOCK_BIT 0x4
|
||||
#define FCMD_ERASE_ALL 0x8
|
||||
#define FCMD_SET_GP_NVM_BIT 0xb
|
||||
#define FCMD_SET_SECURITY_BIT 0xf
|
||||
|
||||
#define MC_FLASH_STATUS_READY (1<<0)
|
||||
#define MC_FLASH_STATUS_LOCK_ERROR (1<<2)
|
||||
#define MC_FLASH_STATUS_PROGRAMMING_ERROR (1<<3)
|
||||
#define MC_FLASH_STATUS_SECURITY_BIT_ACTIVE (1<<4)
|
||||
#define MC_FLASH_STATUS_GP_NVM_ACTIVE_0 (1<<8)
|
||||
#define MC_FLASH_STATUS_GP_NVM_ACTIVE_1 (1<<9)
|
||||
#define MC_FLASH_STATUS_LOCK_ACTIVE(x) (1<<((x)+16))
|
||||
|
||||
#define FLASH_PAGE_SIZE_BYTES 256
|
||||
#define FLASH_PAGE_COUNT 512
|
||||
|
||||
//-------------
|
||||
// Watchdog Timer - 12 bit down counter, uses slow clock divided by 128 as source
|
||||
|
||||
#define WDT_BASE (0xfffffd40)
|
||||
|
||||
#define WDT_CONTROL REG(WDT_BASE+0x00)
|
||||
#define WDT_MODE REG(WDT_BASE+0x04)
|
||||
#define WDT_STATUS REG(WDT_BASE+0x08)
|
||||
|
||||
#define WDT_HIT() WDT_CONTROL = 0xa5000001
|
||||
|
||||
#define WDT_MODE_COUNT(x) ((x)<<0)
|
||||
#define WDT_MODE_INTERRUPT_ON_EVENT (1<<12)
|
||||
#define WDT_MODE_RESET_ON_EVENT_ENABLE (1<<13)
|
||||
#define WDT_MODE_RESET_ON_EVENT (1<<14)
|
||||
#define WDT_MODE_WATCHDOG_DELTA(x) ((x)<<16)
|
||||
#define WDT_MODE_HALT_IN_DEBUG_MODE (1<<28)
|
||||
#define WDT_MODE_HALT_IN_IDLE_MODE (1<<29)
|
||||
#define WDT_MODE_DISABLE (1<<15)
|
||||
|
||||
//-------------
|
||||
// Parallel Input/Output Controller
|
||||
|
||||
#define PIO_BASE (0xfffff400)
|
||||
|
||||
#define PIO_ENABLE REG(PIO_BASE+0x000)
|
||||
#define PIO_DISABLE REG(PIO_BASE+0x004)
|
||||
#define PIO_STATUS REG(PIO_BASE+0x008)
|
||||
#define PIO_OUTPUT_ENABLE REG(PIO_BASE+0x010)
|
||||
#define PIO_OUTPUT_DISABLE REG(PIO_BASE+0x014)
|
||||
#define PIO_OUTPUT_STATUS REG(PIO_BASE+0x018)
|
||||
#define PIO_GLITCH_ENABLE REG(PIO_BASE+0x020)
|
||||
#define PIO_GLITCH_DISABLE REG(PIO_BASE+0x024)
|
||||
#define PIO_GLITCH_STATUS REG(PIO_BASE+0x028)
|
||||
#define PIO_OUTPUT_DATA_SET REG(PIO_BASE+0x030)
|
||||
#define PIO_OUTPUT_DATA_CLEAR REG(PIO_BASE+0x034)
|
||||
#define PIO_OUTPUT_DATA_STATUS REG(PIO_BASE+0x038)
|
||||
#define PIO_PIN_DATA_STATUS REG(PIO_BASE+0x03c)
|
||||
#define PIO_OPEN_DRAIN_ENABLE REG(PIO_BASE+0x050)
|
||||
#define PIO_OPEN_DRAIN_DISABLE REG(PIO_BASE+0x054)
|
||||
#define PIO_OPEN_DRAIN_STATUS REG(PIO_BASE+0x058)
|
||||
#define PIO_NO_PULL_UP_ENABLE REG(PIO_BASE+0x060)
|
||||
#define PIO_NO_PULL_UP_DISABLE REG(PIO_BASE+0x064)
|
||||
#define PIO_NO_PULL_UP_STATUS REG(PIO_BASE+0x068)
|
||||
#define PIO_PERIPHERAL_A_SEL REG(PIO_BASE+0x070)
|
||||
#define PIO_PERIPHERAL_B_SEL REG(PIO_BASE+0x074)
|
||||
#define PIO_PERIPHERAL_WHICH REG(PIO_BASE+0x078)
|
||||
#define PIO_OUT_WRITE_ENABLE REG(PIO_BASE+0x0a0)
|
||||
#define PIO_OUT_WRITE_DISABLE REG(PIO_BASE+0x0a4)
|
||||
#define PIO_OUT_WRITE_STATUS REG(PIO_BASE+0x0a8)
|
||||
|
||||
//-------------
|
||||
// USB Device Port
|
||||
|
||||
#define UDP_BASE (0xfffb0000)
|
||||
|
||||
#define UDP_FRAME_NUMBER REG(UDP_BASE+0x0000)
|
||||
#define UDP_GLOBAL_STATE REG(UDP_BASE+0x0004)
|
||||
#define UDP_FUNCTION_ADDR REG(UDP_BASE+0x0008)
|
||||
#define UDP_INTERRUPT_ENABLE REG(UDP_BASE+0x0010)
|
||||
#define UDP_INTERRUPT_DISABLE REG(UDP_BASE+0x0014)
|
||||
#define UDP_INTERRUPT_MASK REG(UDP_BASE+0x0018)
|
||||
#define UDP_INTERRUPT_STATUS REG(UDP_BASE+0x001c)
|
||||
#define UDP_INTERRUPT_CLEAR REG(UDP_BASE+0x0020)
|
||||
#define UDP_RESET_ENDPOINT REG(UDP_BASE+0x0028)
|
||||
#define UDP_ENDPOINT_CSR(x) REG(UDP_BASE+0x0030+((x)*4))
|
||||
#define UDP_ENDPOINT_FIFO(x) REG(UDP_BASE+0x0050+((x)*4))
|
||||
#define UDP_TRANSCEIVER_CTRL REG(UDP_BASE+0x0074)
|
||||
|
||||
#define UDP_GLOBAL_STATE_ADDRESSED (1<<0)
|
||||
#define UDP_GLOBAL_STATE_CONFIGURED (1<<1)
|
||||
#define UDP_GLOBAL_STATE_SEND_RESUME_ENABLED (1<<2)
|
||||
#define UDP_GLOBAL_STATE_RESUME_RECEIVED (1<<3)
|
||||
#define UDP_GLOBAL_STATE_REMOTE_WAKE_UP_ENABLED (1<<4)
|
||||
|
||||
#define UDP_FUNCTION_ADDR_ENABLED (1<<8)
|
||||
|
||||
#define UDP_INTERRUPT_ENDPOINT(x) (1<<(x))
|
||||
#define UDP_INTERRUPT_SUSPEND (1<<8)
|
||||
#define UDP_INTERRUPT_RESUME (1<<9)
|
||||
#define UDP_INTERRUPT_EXTERNAL_RESUME (1<<10)
|
||||
#define UDP_INTERRUPT_SOF (1<<11)
|
||||
#define UDP_INTERRUPT_END_OF_BUS_RESET (1<<12)
|
||||
#define UDP_INTERRUPT_WAKEUP (1<<13)
|
||||
|
||||
#define UDP_RESET_ENDPOINT_NUMBER(x) (1<<(x))
|
||||
|
||||
#define UDP_CSR_TX_PACKET_ACKED (1<<0)
|
||||
#define UDP_CSR_RX_PACKET_RECEIVED_BANK_0 (1<<1)
|
||||
#define UDP_CSR_RX_HAVE_READ_SETUP_DATA (1<<2)
|
||||
#define UDP_CSR_STALL_SENT (1<<3)
|
||||
#define UDP_CSR_TX_PACKET (1<<4)
|
||||
#define UDP_CSR_FORCE_STALL (1<<5)
|
||||
#define UDP_CSR_RX_PACKET_RECEIVED_BANK_1 (1<<6)
|
||||
#define UDP_CSR_CONTROL_DATA_DIR (1<<7)
|
||||
#define UDP_CSR_EPTYPE_CONTROL (0<<8)
|
||||
#define UDP_CSR_EPTYPE_ISOCHRON_OUT (1<<8)
|
||||
#define UDP_CSR_EPTYPE_ISOCHRON_IN (5<<8)
|
||||
#define UDP_CSR_EPTYPE_BULK_OUT (2<<8)
|
||||
#define UDP_CSR_EPTYPE_BULK_IN (6<<8)
|
||||
#define UDP_CSR_EPTYPE_INTERRUPT_OUT (3<<8)
|
||||
#define UDP_CSR_EPTYPE_INTERRUPT_IN (7<<8)
|
||||
#define UDP_CSR_IS_DATA1 (1<<11)
|
||||
#define UDP_CSR_ENABLE_EP (1<<15)
|
||||
#define UDP_CSR_BYTES_RECEIVED(x) (((x) >> 16) & 0x7ff)
|
||||
|
||||
#define UDP_TRANSCEIVER_CTRL_DISABLE (1<<8)
|
||||
|
||||
//-------------
|
||||
// Power Management Controller
|
||||
|
||||
#define PMC_BASE (0xfffffc00)
|
||||
|
||||
#define PMC_SYS_CLK_ENABLE REG(PMC_BASE+0x0000)
|
||||
#define PMC_SYS_CLK_DISABLE REG(PMC_BASE+0x0004)
|
||||
#define PMC_SYS_CLK_STATUS REG(PMC_BASE+0x0008)
|
||||
#define PMC_PERIPHERAL_CLK_ENABLE REG(PMC_BASE+0x0010)
|
||||
#define PMC_PERIPHERAL_CLK_DISABLE REG(PMC_BASE+0x0014)
|
||||
#define PMC_PERIPHERAL_CLK_STATUS REG(PMC_BASE+0x0018)
|
||||
#define PMC_MAIN_OSCILLATOR REG(PMC_BASE+0x0020)
|
||||
#define PMC_MAIN_CLK_FREQUENCY REG(PMC_BASE+0x0024)
|
||||
#define PMC_PLL REG(PMC_BASE+0x002c)
|
||||
#define PMC_MASTER_CLK REG(PMC_BASE+0x0030)
|
||||
#define PMC_PROGRAMMABLE_CLK_0 REG(PMC_BASE+0x0040)
|
||||
#define PMC_PROGRAMMABLE_CLK_1 REG(PMC_BASE+0x0044)
|
||||
#define PMC_INTERRUPT_ENABLE REG(PMC_BASE+0x0060)
|
||||
#define PMC_INTERRUPT_DISABLE REG(PMC_BASE+0x0064)
|
||||
#define PMC_INTERRUPT_STATUS REG(PMC_BASE+0x0068)
|
||||
#define PMC_INTERRUPT_MASK REG(PMC_BASE+0x006c)
|
||||
|
||||
#define PMC_SYS_CLK_PROCESSOR_CLK (1<<0)
|
||||
#define PMC_SYS_CLK_UDP_CLK (1<<7)
|
||||
#define PMC_SYS_CLK_PROGRAMMABLE_CLK_0 (1<<8)
|
||||
#define PMC_SYS_CLK_PROGRAMMABLE_CLK_1 (1<<9)
|
||||
#define PMC_SYS_CLK_PROGRAMMABLE_CLK_2 (1<<10)
|
||||
|
||||
#define PMC_MAIN_OSCILLATOR_STABILIZED (1<<0)
|
||||
#define PMC_MAIN_OSCILLATOR_PLL_LOCK (1<<2)
|
||||
#define PMC_MAIN_OSCILLATOR_MCK_READY (1<<3)
|
||||
#define PMC_MAIN_OSCILLATOR_ENABLE (1<<0)
|
||||
#define PMC_MAIN_OSCILLATOR_BYPASS (1<<1)
|
||||
#define PMC_MAIN_OSCILLATOR_STARTUP_DELAY(x) ((x)<<8)
|
||||
|
||||
#define PMC_PLL_DIVISOR(x) (x)
|
||||
#define PMC_PLL_COUNT_BEFORE_LOCK(x) ((x)<<8)
|
||||
#define PMC_PLL_FREQUENCY_RANGE(x) ((x)<<14)
|
||||
#define PMC_PLL_MULTIPLIER(x) (((x)-1)<<16)
|
||||
#define PMC_PLL_USB_DIVISOR(x) ((x)<<28)
|
||||
|
||||
#define PMC_CLK_SELECTION_PLL_CLOCK (3<<0)
|
||||
#define PMC_CLK_SELECTION_MAIN_CLOCK (1<<0)
|
||||
#define PMC_CLK_SELECTION_SLOW_CLOCK (0<<0)
|
||||
#define PMC_CLK_PRESCALE_DIV_1 (0<<2)
|
||||
#define PMC_CLK_PRESCALE_DIV_2 (1<<2)
|
||||
#define PMC_CLK_PRESCALE_DIV_4 (2<<2)
|
||||
#define PMC_CLK_PRESCALE_DIV_8 (3<<2)
|
||||
#define PMC_CLK_PRESCALE_DIV_16 (4<<2)
|
||||
#define PMC_CLK_PRESCALE_DIV_32 (5<<2)
|
||||
#define PMC_CLK_PRESCALE_DIV_64 (6<<2)
|
||||
|
||||
//-------------
|
||||
// Serial Peripheral Interface (SPI)
|
||||
|
||||
#define SPI_BASE (0xfffe0000)
|
||||
|
||||
#define SPI_CONTROL REG(SPI_BASE+0x00)
|
||||
#define SPI_MODE REG(SPI_BASE+0x04)
|
||||
#define SPI_RX_DATA REG(SPI_BASE+0x08)
|
||||
#define SPI_TX_DATA REG(SPI_BASE+0x0c)
|
||||
#define SPI_STATUS REG(SPI_BASE+0x10)
|
||||
#define SPI_INTERRUPT_ENABLE REG(SPI_BASE+0x14)
|
||||
#define SPI_INTERRUPT_DISABLE REG(SPI_BASE+0x18)
|
||||
#define SPI_INTERRUPT_MASK REG(SPI_BASE+0x1c)
|
||||
#define SPI_FOR_CHIPSEL_0 REG(SPI_BASE+0x30)
|
||||
#define SPI_FOR_CHIPSEL_1 REG(SPI_BASE+0x34)
|
||||
#define SPI_FOR_CHIPSEL_2 REG(SPI_BASE+0x38)
|
||||
#define SPI_FOR_CHIPSEL_3 REG(SPI_BASE+0x3c)
|
||||
|
||||
#define SPI_CONTROL_ENABLE (1<<0)
|
||||
#define SPI_CONTROL_DISABLE (1<<1)
|
||||
#define SPI_CONTROL_RESET (1<<7)
|
||||
#define SPI_CONTROL_LAST_TRANSFER (1<<24)
|
||||
|
||||
#define SPI_MODE_MASTER (1<<0)
|
||||
#define SPI_MODE_VARIABLE_CHIPSEL (1<<1)
|
||||
#define SPI_MODE_CHIPSELS_DECODED (1<<2)
|
||||
#define SPI_MODE_USE_DIVIDED_CLOCK (1<<3)
|
||||
#define SPI_MODE_MODE_FAULT_DETECTION_OFF (1<<4)
|
||||
#define SPI_MODE_LOOPBACK (1<<7)
|
||||
#define SPI_MODE_CHIPSEL(x) ((x)<<16)
|
||||
#define SPI_MODE_DELAY_BETWEEN_CHIPSELS(x) ((x)<<24)
|
||||
|
||||
#define SPI_RX_DATA_CHIPSEL(x) (((x)>>16)&0xf)
|
||||
|
||||
#define SPI_TX_DATA_CHIPSEL(x) ((x)<<16)
|
||||
#define SPI_TX_DATA_LAST_TRANSFER (1<<24)
|
||||
|
||||
#define SPI_STATUS_RECEIVE_FULL (1<<0)
|
||||
#define SPI_STATUS_TRANSMIT_EMPTY (1<<1)
|
||||
#define SPI_STATUS_MODE_FAULT (1<<2)
|
||||
#define SPI_STATUS_OVERRUN (1<<3)
|
||||
#define SPI_STATUS_END_OF_RX_BUFFER (1<<4)
|
||||
#define SPI_STATUS_END_OF_TX_BUFFER (1<<5)
|
||||
#define SPI_STATUS_RX_BUFFER_FULL (1<<6)
|
||||
#define SPI_STATUS_TX_BUFFER_EMPTY (1<<7)
|
||||
#define SPI_STATUS_NSS_RISING_DETECTED (1<<8)
|
||||
#define SPI_STATUS_TX_EMPTY (1<<9)
|
||||
#define SPI_STATUS_SPI_ENABLED (1<<16)
|
||||
|
||||
#define SPI_FOR_CHIPSEL_INACTIVE_CLK_1 (1<<0)
|
||||
#define SPI_FOR_CHIPSEL_PHASE (1<<1)
|
||||
#define SPI_FOR_CHIPSEL_LEAVE_CHIPSEL_LOW (1<<3)
|
||||
#define SPI_FOR_CHIPSEL_BITS_IN_WORD(x) ((x)<<4)
|
||||
#define SPI_FOR_CHIPSEL_DIVISOR(x) ((x)<<8)
|
||||
#define SPI_FOR_CHIPSEL_DELAY_BEFORE_CLK(x) ((x)<<16)
|
||||
#define SPI_FOR_CHIPSEL_INTERWORD_DELAY(x) ((x)<<24)
|
||||
|
||||
//-------------
|
||||
// Analog to Digital Converter
|
||||
|
||||
#define ADC_BASE (0xfffd8000)
|
||||
|
||||
#define ADC_CONTROL REG(ADC_BASE+0x00)
|
||||
#define ADC_MODE REG(ADC_BASE+0x04)
|
||||
#define ADC_CHANNEL_ENABLE REG(ADC_BASE+0x10)
|
||||
#define ADC_CHANNEL_DISABLE REG(ADC_BASE+0x14)
|
||||
#define ADC_CHANNEL_STATUS REG(ADC_BASE+0x18)
|
||||
#define ADC_STATUS REG(ADC_BASE+0x1c)
|
||||
#define ADC_LAST_CONVERTED_DATA REG(ADC_BASE+0x20)
|
||||
#define ADC_INTERRUPT_ENABLE REG(ADC_BASE+0x24)
|
||||
#define ADC_INTERRUPT_DISABLE REG(ADC_BASE+0x28)
|
||||
#define ADC_INTERRUPT_MASK REG(ADC_BASE+0x2c)
|
||||
#define ADC_CHANNEL_DATA(x) REG(ADC_BASE+0x30+(4*(x)))
|
||||
|
||||
#define ADC_CONTROL_RESET (1<<0)
|
||||
#define ADC_CONTROL_START (1<<1)
|
||||
|
||||
#define ADC_MODE_HW_TRIGGERS_ENABLED (1<<0)
|
||||
#define ADC_MODE_8_BIT_RESOLUTION (1<<4)
|
||||
#define ADC_MODE_SLEEP (1<<5)
|
||||
#define ADC_MODE_PRESCALE(x) ((x)<<8)
|
||||
#define ADC_MODE_STARTUP_TIME(x) ((x)<<16)
|
||||
#define ADC_MODE_SAMPLE_HOLD_TIME(x) ((x)<<24)
|
||||
|
||||
#define ADC_CHANNEL(x) (1<<(x))
|
||||
|
||||
#define ADC_END_OF_CONVERSION(x) (1<<(x))
|
||||
#define ADC_OVERRUN_ERROR(x) (1<<(8+(x)))
|
||||
#define ADC_DATA_READY (1<<16)
|
||||
#define ADC_GENERAL_OVERRUN (1<<17)
|
||||
#define ADC_END_OF_RX_BUFFER (1<<18)
|
||||
#define ADC_RX_BUFFER_FULL (1<<19)
|
||||
|
||||
//-------------
|
||||
// Synchronous Serial Controller
|
||||
|
||||
#define SSC_BASE (0xfffd4000)
|
||||
|
||||
#define SSC_CONTROL REG(SSC_BASE+0x00)
|
||||
#define SSC_CLOCK_DIVISOR REG(SSC_BASE+0x04)
|
||||
#define SSC_RECEIVE_CLOCK_MODE REG(SSC_BASE+0x10)
|
||||
#define SSC_RECEIVE_FRAME_MODE REG(SSC_BASE+0x14)
|
||||
#define SSC_TRANSMIT_CLOCK_MODE REG(SSC_BASE+0x18)
|
||||
#define SSC_TRANSMIT_FRAME_MODE REG(SSC_BASE+0x1c)
|
||||
#define SSC_RECEIVE_HOLDING REG(SSC_BASE+0x20)
|
||||
#define SSC_TRANSMIT_HOLDING REG(SSC_BASE+0x24)
|
||||
#define SSC_RECEIVE_SYNC_HOLDING REG(SSC_BASE+0x30)
|
||||
#define SSC_TRANSMIT_SYNC_HOLDING REG(SSC_BASE+0x34)
|
||||
#define SSC_STATUS REG(SSC_BASE+0x40)
|
||||
#define SSC_INTERRUPT_ENABLE REG(SSC_BASE+0x44)
|
||||
#define SSC_INTERRUPT_DISABLE REG(SSC_BASE+0x48)
|
||||
#define SSC_INTERRUPT_MASK REG(SSC_BASE+0x4c)
|
||||
|
||||
#define SSC_CONTROL_RX_ENABLE (1<<0)
|
||||
#define SSC_CONTROL_RX_DISABLE (1<<1)
|
||||
#define SSC_CONTROL_TX_ENABLE (1<<8)
|
||||
#define SSC_CONTROL_TX_DISABLE (1<<9)
|
||||
#define SSC_CONTROL_RESET (1<<15)
|
||||
|
||||
#define SSC_CLOCK_MODE_SELECT(x) ((x)<<0)
|
||||
#define SSC_CLOCK_MODE_OUTPUT(x) ((x)<<2)
|
||||
#define SSC_CLOCK_MODE_INVERT (1<<5)
|
||||
#define SSC_CLOCK_MODE_START(x) ((x)<<8)
|
||||
#define SSC_CLOCK_MODE_START_DELAY(x) ((x)<<16)
|
||||
#define SSC_CLOCK_MODE_FRAME_PERIOD(x) ((x)<<24)
|
||||
|
||||
#define SSC_FRAME_MODE_BITS_IN_WORD(x) (((x)-1)<<0)
|
||||
#define SSC_FRAME_MODE_LOOPBACK (1<<5) // for RX
|
||||
#define SSC_FRAME_MODE_DEFAULT_IS_1 (1<<5) // for TX
|
||||
#define SSC_FRAME_MODE_MSB_FIRST (1<<7)
|
||||
#define SSC_FRAME_MODE_WORDS_PER_TRANSFER(x) ((x)<<8)
|
||||
#define SSC_FRAME_MODE_FRAME_SYNC_LEN(x) ((x)<<16)
|
||||
#define SSC_FRAME_MODE_FRAME_SYNC_TYPE(x) ((x)<<20)
|
||||
#define SSC_FRAME_MODE_SYNC_DATA_ENABLE (1<<23) // for TX only
|
||||
#define SSC_FRAME_MODE_NEGATIVE_EDGE (1<<24)
|
||||
|
||||
#define SSC_STATUS_TX_READY (1<<0)
|
||||
#define SSC_STATUS_TX_EMPTY (1<<1)
|
||||
#define SSC_STATUS_TX_ENDED (1<<2)
|
||||
#define SSC_STATUS_TX_BUF_EMPTY (1<<3)
|
||||
#define SSC_STATUS_RX_READY (1<<4)
|
||||
#define SSC_STATUS_RX_OVERRUN (1<<5)
|
||||
#define SSC_STATUS_RX_ENDED (1<<6)
|
||||
#define SSC_STATUS_RX_BUF_FULL (1<<7)
|
||||
#define SSC_STATUS_TX_SYNC_OCCURRED (1<<10)
|
||||
#define SSC_STATUS_RX_SYNC_OCCURRED (1<<11)
|
||||
#define SSC_STATUS_TX_ENABLED (1<<16)
|
||||
#define SSC_STATUS_RX_ENABLED (1<<17)
|
||||
|
||||
//-------------
|
||||
// Peripheral DMA Controller
|
||||
//
|
||||
// There is one set of registers for every peripheral that supports DMA.
|
||||
|
||||
#define PDC_RX_POINTER(x) REG((x)+0x100)
|
||||
#define PDC_RX_COUNTER(x) REG((x)+0x104)
|
||||
#define PDC_TX_POINTER(x) REG((x)+0x108)
|
||||
#define PDC_TX_COUNTER(x) REG((x)+0x10c)
|
||||
#define PDC_RX_NEXT_POINTER(x) REG((x)+0x110)
|
||||
#define PDC_RX_NEXT_COUNTER(x) REG((x)+0x114)
|
||||
#define PDC_TX_NEXT_POINTER(x) REG((x)+0x118)
|
||||
#define PDC_TX_NEXT_COUNTER(x) REG((x)+0x11c)
|
||||
#define PDC_CONTROL(x) REG((x)+0x120)
|
||||
#define PDC_STATUS(x) REG((x)+0x124)
|
||||
|
||||
#define PDC_RX_ENABLE (1<<0)
|
||||
#define PDC_RX_DISABLE (1<<1)
|
||||
#define PDC_TX_ENABLE (1<<8)
|
||||
#define PDC_TX_DISABLE (1<<9)
|
||||
|
||||
#endif
|
40
include/config_gpio.h
Normal file
40
include/config_gpio.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef __CONFIG_GPIO_H
|
||||
#define __CONFIG_GPIO_H
|
||||
|
||||
#define GPIO_LED_A 0
|
||||
#define GPIO_PA1 1
|
||||
#define GPIO_LED_D 2
|
||||
#define GPIO_NVDD_ON 3
|
||||
#define GPIO_FPGA_NINIT 4
|
||||
#define GPIO_PA5 5
|
||||
#define GPIO_PCK0 6
|
||||
#define GPIO_LRST 7
|
||||
#define GPIO_LED_B 8
|
||||
#define GPIO_LED_C 9
|
||||
#define GPIO_NCS2 10
|
||||
#define GPIO_NCS0 11
|
||||
#define GPIO_MISO 12
|
||||
#define GPIO_MOSI 13
|
||||
#define GPIO_SPCK 14
|
||||
#define GPIO_SSC_FRAME 15
|
||||
#define GPIO_SSC_CLK 16
|
||||
#define GPIO_SSC_DOUT 17
|
||||
#define GPIO_SSC_DIN 18
|
||||
#define GPIO_MUXSEL_HIPKD 19
|
||||
#define GPIO_MUXSEL_LOPKD 20
|
||||
#define GPIO_MUXSEL_HIRAW 21
|
||||
#define GPIO_MUXSEL_LORAW 22
|
||||
#define GPIO_BUTTON 23
|
||||
#define GPIO_USB_PU 24
|
||||
#define GPIO_RELAY 25
|
||||
#define GPIO_FPGA_ON 26
|
||||
#define GPIO_FPGA_DONE 27
|
||||
#define GPIO_FPGA_NPROGRAM 28
|
||||
#define GPIO_FPGA_CCLK 29
|
||||
#define GPIO_FPGA_DIN 30
|
||||
#define GPIO_FPGA_DOUT 31
|
||||
|
||||
#define ANIN_AMPL_LO 4
|
||||
#define ANIN_AMPL_HI 5
|
||||
|
||||
#endif
|
62
include/proxmark3.h
Normal file
62
include/proxmark3.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Definitions of interest to most of the software for this project.
|
||||
// Jonathan Westhues, Mar 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __PROXMARK3_H
|
||||
#define __PROXMARK3_H
|
||||
|
||||
// Might as well have the hardware-specific defines everywhere.
|
||||
#include <at91sam7s128.h>
|
||||
|
||||
#include <config_gpio.h>
|
||||
#define LOW(x) PIO_OUTPUT_DATA_CLEAR = (1 << (x))
|
||||
#define HIGH(x) PIO_OUTPUT_DATA_SET = (1 << (x))
|
||||
|
||||
#define SPI_FPGA_MODE 0
|
||||
#define SPI_LCD_MODE 1
|
||||
|
||||
typedef unsigned long DWORD;
|
||||
typedef signed long SDWORD;
|
||||
typedef unsigned long long QWORD;
|
||||
typedef int BOOL;
|
||||
typedef unsigned char BYTE;
|
||||
typedef signed char SBYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef signed short SWORD;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#include <usb_cmd.h>
|
||||
|
||||
#define PACKED __attribute__((__packed__))
|
||||
|
||||
#define USB_D_PLUS_PULLUP_ON() { \
|
||||
PIO_OUTPUT_DATA_SET = (1<<GPIO_USB_PU); \
|
||||
PIO_OUTPUT_ENABLE = (1<<GPIO_USB_PU); \
|
||||
}
|
||||
#define USB_D_PLUS_PULLUP_OFF() PIO_OUTPUT_DISABLE = (1<<GPIO_USB_PU)
|
||||
|
||||
#define LED_A_ON() PIO_OUTPUT_DATA_SET = (1<<GPIO_LED_A)
|
||||
#define LED_A_OFF() PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_LED_A)
|
||||
#define LED_B_ON() PIO_OUTPUT_DATA_SET = (1<<GPIO_LED_B)
|
||||
#define LED_B_OFF() PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_LED_B)
|
||||
#define LED_C_ON() PIO_OUTPUT_DATA_SET = (1<<GPIO_LED_C)
|
||||
#define LED_C_OFF() PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_LED_C)
|
||||
#define LED_D_ON() PIO_OUTPUT_DATA_SET = (1<<GPIO_LED_D)
|
||||
#define LED_D_OFF() PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_LED_D)
|
||||
#define RELAY_ON() PIO_OUTPUT_DATA_SET = (1<<GPIO_RELAY)
|
||||
#define RELAY_OFF() PIO_OUTPUT_DATA_CLEAR = (1<<GPIO_RELAY)
|
||||
#define BUTTON_PRESS() !(PIO_PIN_DATA_STATUS & (1<<GPIO_BUTTON))
|
||||
//--------------------------------
|
||||
// USB declarations
|
||||
|
||||
void UsbSendPacket(BYTE *packet, int len);
|
||||
BOOL UsbPoll(BOOL blinkLeds);
|
||||
void UsbStart(void);
|
||||
|
||||
// This function is provided by the apps/bootrom, and called from UsbPoll
|
||||
// if data are available.
|
||||
void UsbPacketReceived(BYTE *packet, int len);
|
||||
|
||||
#endif
|
71
include/usb_cmd.h
Normal file
71
include/usb_cmd.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Definitions for all the types of commands that may be sent over USB; our
|
||||
// own protocol.
|
||||
// Jonathan Westhues, Mar 2006
|
||||
// Edits by Gerhard de Koning Gans, Sep 2007
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __USB_CMD_H
|
||||
#define __USB_CMD_H
|
||||
|
||||
typedef struct {
|
||||
DWORD cmd;
|
||||
DWORD ext1;
|
||||
DWORD ext2;
|
||||
DWORD ext3;
|
||||
union {
|
||||
BYTE asBytes[48];
|
||||
DWORD asDwords[12];
|
||||
} d;
|
||||
} UsbCommand;
|
||||
|
||||
// For the bootloader
|
||||
#define CMD_DEVICE_INFO 0x0000
|
||||
#define CMD_SETUP_WRITE 0x0001
|
||||
#define CMD_FINISH_WRITE 0x0003
|
||||
#define CMD_HARDWARE_RESET 0x0004
|
||||
#define CMD_ACK 0x00ff
|
||||
|
||||
// For general mucking around
|
||||
#define CMD_DEBUG_PRINT_STRING 0x0100
|
||||
#define CMD_DEBUG_PRINT_INTEGERS 0x0101
|
||||
#define CMD_DEBUG_PRINT_BYTES 0x0102
|
||||
#define CMD_LCD_RESET 0x0103
|
||||
#define CMD_LCD 0x0104
|
||||
|
||||
// For low-frequency tags
|
||||
#define CMD_ACQUIRE_RAW_BITS_TI_TYPE 0x0200
|
||||
#define CMD_DOWNLOAD_RAW_BITS_TI_TYPE 0x0201
|
||||
#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0202
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0203
|
||||
#define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0204
|
||||
#define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0205
|
||||
#define CMD_DOWNLOADED_SIM_SAMPLES_125K 0x0206
|
||||
#define CMD_SIMULATE_TAG_125K 0x0207
|
||||
#define CMD_HID_DEMOD_FSK 0x0208 // ## New command: demodulate HID tag ID
|
||||
#define CMD_HID_SIM_TAG 0x0209 // ## New command: simulate HID tag by ID
|
||||
|
||||
// For the 13.56 MHz tags
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM 0x0302
|
||||
#define CMD_READER_ISO_15693 0x0310 // ## New command to act like a 15693 reader - greg
|
||||
#define CMD_SIMTAG_ISO_15693 0x0311 // ## New command to act like a 15693 reader - greg
|
||||
|
||||
#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380
|
||||
#define CMD_SIMULATE_TAG_ISO_14443 0x0381
|
||||
#define CMD_SNOOP_ISO_14443 0x0382
|
||||
#define CMD_SNOOP_ISO_14443a 0x0383 // ## New snoop command
|
||||
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384 // ## New command: Simulate tag 14443a
|
||||
#define CMD_READER_ISO_14443a 0x0385 // ## New command to act like a 14443a reader
|
||||
|
||||
#define CMD_SIMULATE_MIFARE_CARD 0x0386
|
||||
|
||||
// For measurements of the antenna tuning
|
||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||
#define CMD_MEASURED_ANTENNA_TUNING 0x0401
|
||||
|
||||
// For direct FPGA control
|
||||
#define CMD_FPGA_MAJOR_MODE_OFF 0x0500 // ## FPGA Control
|
||||
|
||||
#endif
|
29
linux/Makefile
Normal file
29
linux/Makefile
Normal file
|
@ -0,0 +1,29 @@
|
|||
LDFLAGS = -lusb -lreadline -lpthread -L/opt/local/lib
|
||||
CFLAGS = -I. -I/opt/local/include -Wall
|
||||
|
||||
CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall
|
||||
QTLDFLAGS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
|
||||
|
||||
ifneq ($(QTLDFLAGS),)
|
||||
QTGUI = proxgui.o proxguiqt.o proxguiqt.moc.o
|
||||
CFLAGS += -DHAVE_GUI
|
||||
MOC = $(shell type moc-qt4 >/dev/null 2>&1 && echo moc-qt4 || echo moc)
|
||||
LINK.o = $(LINK.cpp)
|
||||
else
|
||||
QTGUI = guidummy.o
|
||||
endif
|
||||
|
||||
all: proxmark3 snooper
|
||||
|
||||
proxmark3: LDFLAGS+=$(QTLDFLAGS)
|
||||
proxmark3: proxmark3.o gui.o command.o usb.o $(QTGUI)
|
||||
|
||||
snooper: snooper.o gui.o command.o usb.o guidummy.o
|
||||
|
||||
proxguiqt.moc.cpp: proxguiqt.h
|
||||
$(MOC) -o$@ $^
|
||||
|
||||
clean:
|
||||
rm -f proxmark3 snooper *.o *.moc.cpp
|
||||
|
||||
.PHONY: all clean
|
2
linux/command.c
Normal file
2
linux/command.c
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "translate.h"
|
||||
#include "../winsrc/command.cpp"
|
166
linux/flasher.c
Normal file
166
linux/flasher.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
#include <usb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "../winsrc/prox.h"
|
||||
#include "proxmark3.h"
|
||||
|
||||
static DWORD ExpectedAddr;
|
||||
static BYTE QueuedToSend[256];
|
||||
static BOOL AllWritten;
|
||||
|
||||
static void FlushPrevious(void)
|
||||
{
|
||||
UsbCommand c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
printf("expected = %08x flush, ", ExpectedAddr);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 240; i += 48) {
|
||||
c.cmd = CMD_SETUP_WRITE;
|
||||
memcpy(c.d.asBytes, QueuedToSend+i, 48);
|
||||
c.ext1 = (i/4);
|
||||
SendCommand(&c, TRUE);
|
||||
}
|
||||
|
||||
c.cmd = CMD_FINISH_WRITE;
|
||||
c.ext1 = (ExpectedAddr-1) & (~255);
|
||||
printf("c.ext1 = %08x\r", c.ext1);
|
||||
memcpy(c.d.asBytes, QueuedToSend+240, 16);
|
||||
SendCommand(&c, TRUE);
|
||||
|
||||
AllWritten = TRUE;
|
||||
}
|
||||
|
||||
static void GotByte(DWORD where, BYTE which)
|
||||
{
|
||||
AllWritten = FALSE;
|
||||
|
||||
if(where != ExpectedAddr) {
|
||||
printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr);
|
||||
exit(-1);
|
||||
}
|
||||
QueuedToSend[where & 255] = which;
|
||||
ExpectedAddr++;
|
||||
|
||||
if((where & 255) == 255) {
|
||||
// we have completed a full page
|
||||
FlushPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
static int HexVal(int c)
|
||||
{
|
||||
c = tolower(c);
|
||||
if(c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
} else if(c >= 'a' && c <= 'f') {
|
||||
return (c - 'a') + 10;
|
||||
} else {
|
||||
printf("bad hex digit '%c'\n", c);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static BYTE HexByte(char *s)
|
||||
{
|
||||
return (HexVal(s[0]) << 4) | HexVal(s[1]);
|
||||
}
|
||||
|
||||
static void LoadFlashFromSRecords(char *file, int addr)
|
||||
{
|
||||
ExpectedAddr = addr;
|
||||
|
||||
FILE *f = fopen(file, "r");
|
||||
if(!f) {
|
||||
printf("couldn't open file\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char line[512];
|
||||
while(fgets(line, sizeof(line), f)) {
|
||||
if(memcmp(line, "S3", 2)==0) {
|
||||
char *s = line + 2;
|
||||
int len = HexByte(s) - 5;
|
||||
s += 2;
|
||||
|
||||
char addrStr[9];
|
||||
memcpy(addrStr, s, 8);
|
||||
addrStr[8] = '\0';
|
||||
DWORD addr;
|
||||
sscanf(addrStr, "%x", &addr);
|
||||
s += 8;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < len; i++) {
|
||||
while((addr+i) > ExpectedAddr) {
|
||||
GotByte(ExpectedAddr, 0xff);
|
||||
}
|
||||
GotByte(addr+i, HexByte(s));
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!AllWritten) FlushPrevious();
|
||||
|
||||
fclose(f);
|
||||
printf("\ndone.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
unsigned int addr = 0;
|
||||
UsbCommand c;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr,"Usage: %s {bootrom|os|fpga} image.s19\n", argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1],"bootrom")) {
|
||||
addr = 0;
|
||||
} else if (!strcmp(argv[1],"os")) {
|
||||
addr = 0x10000;
|
||||
} else if (!strcmp(argv[1],"fpga")) {
|
||||
addr = 0x2000;
|
||||
} else {
|
||||
fprintf(stderr,"Unknown action '%s'!\n", argv[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
usb_init();
|
||||
|
||||
fprintf(stderr,"Waiting for Proxmark to appear on USB...\n");
|
||||
while(!(devh=OpenProxmark(0))) { sleep(1); }
|
||||
fprintf(stderr,"Found...\n");
|
||||
|
||||
fprintf(stderr,"Entering flash-mode...\n");
|
||||
bzero(&c, sizeof(c));
|
||||
c.cmd = CMD_START_FLASH;
|
||||
SendCommand(&c, FALSE);
|
||||
CloseProxmark();
|
||||
sleep(1);
|
||||
|
||||
fprintf(stderr,"Waiting for Proxmark to reappear on USB...\n");
|
||||
while(!(devh=OpenProxmark(0))) { sleep(1); }
|
||||
fprintf(stderr,"Found...\n");
|
||||
|
||||
LoadFlashFromSRecords(argv[2], addr);
|
||||
|
||||
bzero(&c, sizeof(c));
|
||||
c.cmd = CMD_HARDWARE_RESET;
|
||||
SendCommand(&c, FALSE);
|
||||
|
||||
CloseProxmark();
|
||||
|
||||
fprintf(stderr,"Have a nice day!\n");
|
||||
|
||||
return 0;
|
||||
}
|
54
linux/gui.c
Normal file
54
linux/gui.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "proxgui.h"
|
||||
#include "translate.h"
|
||||
#include "../winsrc/prox.h"
|
||||
|
||||
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
int GraphTraceLen;
|
||||
double CursorScaleFactor;
|
||||
int CommandFinished;
|
||||
|
||||
static char *logfilename = "proxmark3.log";
|
||||
|
||||
void PrintToScrollback(char *fmt, ...) {
|
||||
va_list argptr;
|
||||
static FILE *logfile = NULL;
|
||||
static int logging=1;
|
||||
|
||||
if (logging && !logfile) {
|
||||
logfile=fopen(logfilename, "a");
|
||||
if (!logfile) {
|
||||
fprintf(stderr, "Can't open logfile, logging disabled!\n");
|
||||
logging=0;
|
||||
}
|
||||
}
|
||||
|
||||
va_start(argptr, fmt);
|
||||
vprintf(fmt, argptr);
|
||||
printf("\n");
|
||||
if (logging && logfile) {
|
||||
#if 0
|
||||
char zeit[25];
|
||||
time_t jetzt_t;
|
||||
struct tm *jetzt;
|
||||
|
||||
jetzt_t = time(NULL);
|
||||
jetzt = localtime(&jetzt_t);
|
||||
strftime(zeit, 25, "%b %e %T", jetzt);
|
||||
|
||||
fprintf(logfile,"%s ", zeit);
|
||||
#endif
|
||||
vfprintf(logfile, fmt, argptr);
|
||||
fprintf(logfile,"\n");
|
||||
fflush(logfile);
|
||||
}
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void setlogfilename(char *fn)
|
||||
{
|
||||
logfilename = fn;
|
||||
}
|
17
linux/guidummy.c
Normal file
17
linux/guidummy.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <stdio.h>
|
||||
|
||||
void ShowGraphWindow(void)
|
||||
{
|
||||
static int warned = 0;
|
||||
|
||||
if (!warned) {
|
||||
printf("No GUI in this build!\n");
|
||||
warned = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void HideGraphWindow(void) {}
|
||||
void RepaintGraphWindow(void) {}
|
||||
void MainGraphics() {}
|
||||
void InitGraphics(int argc, char **argv) {}
|
||||
void ExitGraphics(void) {}
|
58
linux/proxgui.cpp
Normal file
58
linux/proxgui.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
#include "proxgui.h"
|
||||
#include "proxguiqt.h"
|
||||
|
||||
static ProxGuiQT *gui = NULL;
|
||||
|
||||
extern "C" void ShowGraphWindow(void)
|
||||
{
|
||||
if (!gui)
|
||||
return;
|
||||
|
||||
gui->ShowGraphWindow();
|
||||
}
|
||||
|
||||
extern "C" void HideGraphWindow(void)
|
||||
{
|
||||
if (!gui)
|
||||
return;
|
||||
|
||||
gui->HideGraphWindow();
|
||||
}
|
||||
|
||||
extern "C" void RepaintGraphWindow(void)
|
||||
{
|
||||
if (!gui)
|
||||
return;
|
||||
|
||||
gui->RepaintGraphWindow();
|
||||
}
|
||||
|
||||
extern "C" void MainGraphics(void)
|
||||
{
|
||||
if (!gui)
|
||||
return;
|
||||
|
||||
gui->MainLoop();
|
||||
}
|
||||
|
||||
extern "C" void InitGraphics(int argc, char **argv)
|
||||
{
|
||||
#ifdef Q_WS_X11
|
||||
bool useGUI = getenv("DISPLAY") != 0;
|
||||
#else
|
||||
bool useGUI = true;
|
||||
#endif
|
||||
if (!useGUI)
|
||||
return;
|
||||
|
||||
gui = new ProxGuiQT(argc, argv);
|
||||
}
|
||||
|
||||
extern "C" void ExitGraphics(void)
|
||||
{
|
||||
if (!gui)
|
||||
return;
|
||||
|
||||
delete gui;
|
||||
gui = NULL;
|
||||
}
|
20
linux/proxgui.h
Normal file
20
linux/proxgui.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ShowGraphWindow(void);
|
||||
void HideGraphWindow(void);
|
||||
void RepaintGraphWindow(void);
|
||||
void MainGraphics(void);
|
||||
void InitGraphics(int argc, char **argv);
|
||||
void ExitGraphics(void);
|
||||
|
||||
#define MAX_GRAPH_TRACE_LEN (1024*128)
|
||||
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
extern int GraphTraceLen;
|
||||
extern double CursorScaleFactor;
|
||||
extern int CommandFinished;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
309
linux/proxguiqt.cpp
Normal file
309
linux/proxguiqt.cpp
Normal file
|
@ -0,0 +1,309 @@
|
|||
#include <iostream>
|
||||
#include <QPainterPath>
|
||||
#include <QBrush>
|
||||
#include <QPen>
|
||||
#include <QTimer>
|
||||
#include <QCloseEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include "proxguiqt.h"
|
||||
#include "proxgui.h"
|
||||
|
||||
void ProxGuiQT::ShowGraphWindow(void)
|
||||
{
|
||||
emit ShowGraphWindowSignal();
|
||||
}
|
||||
|
||||
void ProxGuiQT::RepaintGraphWindow(void)
|
||||
{
|
||||
emit RepaintGraphWindowSignal();
|
||||
}
|
||||
|
||||
void ProxGuiQT::HideGraphWindow(void)
|
||||
{
|
||||
emit HideGraphWindowSignal();
|
||||
}
|
||||
|
||||
void ProxGuiQT::_ShowGraphWindow(void)
|
||||
{
|
||||
if(!plotapp)
|
||||
return;
|
||||
|
||||
if (!plotwidget)
|
||||
plotwidget = new ProxWidget();
|
||||
|
||||
plotwidget->show();
|
||||
}
|
||||
|
||||
void ProxGuiQT::_RepaintGraphWindow(void)
|
||||
{
|
||||
if (!plotapp || !plotwidget)
|
||||
return;
|
||||
|
||||
plotwidget->update();
|
||||
}
|
||||
|
||||
void ProxGuiQT::_HideGraphWindow(void)
|
||||
{
|
||||
if (!plotapp || !plotwidget)
|
||||
return;
|
||||
|
||||
plotwidget->hide();
|
||||
}
|
||||
|
||||
void ProxGuiQT::MainLoop()
|
||||
{
|
||||
plotapp = new QApplication(argc, argv);
|
||||
|
||||
connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow()));
|
||||
connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow()));
|
||||
connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow()));
|
||||
|
||||
plotapp->exec();
|
||||
}
|
||||
|
||||
ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL),
|
||||
argc(argc), argv(argv)
|
||||
{
|
||||
}
|
||||
|
||||
ProxGuiQT::~ProxGuiQT(void)
|
||||
{
|
||||
if (plotwidget) {
|
||||
delete plotwidget;
|
||||
plotwidget = NULL;
|
||||
}
|
||||
|
||||
if (plotapp) {
|
||||
plotapp->quit();
|
||||
delete plotapp;
|
||||
plotapp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ProxWidget::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QPainter painter(this);
|
||||
QPainterPath penPath, whitePath, greyPath, cursorAPath, cursorBPath;
|
||||
QRect r;
|
||||
QBrush brush(QColor(100, 255, 100));
|
||||
QPen pen(QColor(100, 255, 100));
|
||||
|
||||
painter.setFont(QFont("Arial", 10));
|
||||
|
||||
if(GraphStart < 0) {
|
||||
GraphStart = 0;
|
||||
}
|
||||
|
||||
r = rect();
|
||||
|
||||
painter.fillRect(r, QColor(0, 0, 0));
|
||||
|
||||
whitePath.moveTo(r.left() + 40, r.top());
|
||||
whitePath.lineTo(r.left() + 40, r.bottom());
|
||||
|
||||
int zeroHeight = r.top() + (r.bottom() - r.top()) / 2;
|
||||
|
||||
greyPath.moveTo(r.left(), zeroHeight);
|
||||
greyPath.lineTo(r.right(), zeroHeight);
|
||||
painter.setPen(QColor(100, 100, 100));
|
||||
painter.drawPath(greyPath);
|
||||
|
||||
int startMax =
|
||||
(GraphTraceLen - (int)((r.right() - r.left() - 40) / GraphPixelsPerPoint));
|
||||
if(startMax < 0) {
|
||||
startMax = 0;
|
||||
}
|
||||
if(GraphStart > startMax) {
|
||||
GraphStart = startMax;
|
||||
}
|
||||
|
||||
int absYMax = 1;
|
||||
|
||||
int i;
|
||||
for(i = GraphStart; ; i++) {
|
||||
if(i >= GraphTraceLen) {
|
||||
break;
|
||||
}
|
||||
if(fabs((double)GraphBuffer[i]) > absYMax) {
|
||||
absYMax = (int)fabs((double)GraphBuffer[i]);
|
||||
}
|
||||
int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);
|
||||
if(x > r.right()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
absYMax = (int)(absYMax*1.2 + 1);
|
||||
|
||||
// number of points that will be plotted
|
||||
int span = (int)((r.right() - r.left()) / GraphPixelsPerPoint);
|
||||
// one label every 100 pixels, let us say
|
||||
int labels = (r.right() - r.left() - 40) / 100;
|
||||
if(labels <= 0) labels = 1;
|
||||
int pointsPerLabel = span / labels;
|
||||
if(pointsPerLabel <= 0) pointsPerLabel = 1;
|
||||
|
||||
int yMin = INT_MAX;
|
||||
int yMax = INT_MIN;
|
||||
int yMean = 0;
|
||||
int n = 0;
|
||||
|
||||
for(i = GraphStart; ; i++) {
|
||||
if(i >= GraphTraceLen) {
|
||||
break;
|
||||
}
|
||||
int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);
|
||||
if(x > r.right() + GraphPixelsPerPoint) {
|
||||
break;
|
||||
}
|
||||
|
||||
int y = GraphBuffer[i];
|
||||
if(y < yMin) {
|
||||
yMin = y;
|
||||
}
|
||||
if(y > yMax) {
|
||||
yMax = y;
|
||||
}
|
||||
yMean += y;
|
||||
n++;
|
||||
|
||||
y = (y * (r.top() - r.bottom()) / (2*absYMax)) + zeroHeight;
|
||||
if(i == GraphStart) {
|
||||
penPath.moveTo(x, y);
|
||||
} else {
|
||||
penPath.lineTo(x, y);
|
||||
}
|
||||
|
||||
if(GraphPixelsPerPoint > 10) {
|
||||
QRect f(QPoint(x - 3, y - 3),QPoint(x + 3, y + 3));
|
||||
painter.fillRect(f, brush);
|
||||
}
|
||||
|
||||
if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {
|
||||
whitePath.moveTo(x, zeroHeight - 3);
|
||||
whitePath.lineTo(x, zeroHeight + 3);
|
||||
|
||||
char str[100];
|
||||
sprintf(str, "+%d", (i - GraphStart));
|
||||
|
||||
painter.setPen(QColor(255, 255, 255));
|
||||
QRect size;
|
||||
QFontMetrics metrics(painter.font());
|
||||
size = metrics.boundingRect(str);
|
||||
painter.drawText(x - (size.right() - size.left()), zeroHeight + 9, str);
|
||||
|
||||
penPath.moveTo(x,y);
|
||||
}
|
||||
|
||||
if(i == CursorAPos || i == CursorBPos) {
|
||||
QPainterPath *cursorPath;
|
||||
|
||||
if(i == CursorAPos) {
|
||||
cursorPath = &cursorAPath;
|
||||
} else {
|
||||
cursorPath = &cursorBPath;
|
||||
}
|
||||
cursorPath->moveTo(x, r.top());
|
||||
cursorPath->lineTo(x, r.bottom());
|
||||
penPath.moveTo(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
if(n != 0) {
|
||||
yMean /= n;
|
||||
}
|
||||
|
||||
painter.setPen(QColor(255, 255, 255));
|
||||
painter.drawPath(whitePath);
|
||||
painter.setPen(pen);
|
||||
painter.drawPath(penPath);
|
||||
painter.setPen(QColor(255, 255, 0));
|
||||
painter.drawPath(cursorAPath);
|
||||
painter.setPen(QColor(255, 0, 255));
|
||||
painter.drawPath(cursorBPath);
|
||||
|
||||
char str[100];
|
||||
sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f]",
|
||||
GraphStart, yMax, yMin, yMean, n, GraphTraceLen,
|
||||
CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor);
|
||||
|
||||
painter.setPen(QColor(255, 255, 255));
|
||||
painter.drawText(50, r.bottom() - 20, str);
|
||||
}
|
||||
|
||||
ProxWidget::ProxWidget(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1)
|
||||
{
|
||||
resize(600, 500);
|
||||
|
||||
QPalette palette(QColor(0,0,0,0));
|
||||
palette.setColor(QPalette::WindowText, QColor(255,255,255));
|
||||
palette.setColor(QPalette::Text, QColor(255,255,255));
|
||||
palette.setColor(QPalette::Button, QColor(100, 100, 100));
|
||||
setPalette(palette);
|
||||
setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void ProxWidget::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
event->ignore();
|
||||
this->hide();
|
||||
}
|
||||
|
||||
void ProxWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
int x = event->x();
|
||||
x -= 40;
|
||||
x = (int)(x / GraphPixelsPerPoint);
|
||||
x += GraphStart;
|
||||
if((event->buttons() & Qt::LeftButton)) {
|
||||
CursorAPos = x;
|
||||
} else if (event->buttons() & Qt::RightButton) {
|
||||
CursorBPos = x;
|
||||
}
|
||||
|
||||
|
||||
this->update();
|
||||
}
|
||||
|
||||
void ProxWidget::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
switch(event->key()) {
|
||||
case Qt::Key_Down:
|
||||
if(GraphPixelsPerPoint <= 50) {
|
||||
GraphPixelsPerPoint *= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
if(GraphPixelsPerPoint >= 0.02) {
|
||||
GraphPixelsPerPoint /= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Right:
|
||||
if(GraphPixelsPerPoint < 20) {
|
||||
GraphStart += (int)(20 / GraphPixelsPerPoint);
|
||||
} else {
|
||||
GraphStart++;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Left:
|
||||
if(GraphPixelsPerPoint < 20) {
|
||||
GraphStart -= (int)(20 / GraphPixelsPerPoint);
|
||||
} else {
|
||||
GraphStart--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
QWidget::keyPressEvent(event);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
this->update();
|
||||
}
|
56
linux/proxguiqt.h
Normal file
56
linux/proxguiqt.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include <QApplication>
|
||||
#include <QPushButton>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
|
||||
class ProxWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
private:
|
||||
int GraphStart;
|
||||
double GraphPixelsPerPoint;
|
||||
int CursorAPos;
|
||||
int CursorBPos;
|
||||
|
||||
public:
|
||||
ProxWidget(QWidget *parent = 0);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void mousePressEvent(QMouseEvent *event) { mouseMoveEvent(event); }
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
};
|
||||
|
||||
class ProxGuiQT : public QObject
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
private:
|
||||
QApplication *plotapp;
|
||||
ProxWidget *plotwidget;
|
||||
int argc;
|
||||
char **argv;
|
||||
void (*main_func)(void);
|
||||
|
||||
public:
|
||||
ProxGuiQT(int argc, char **argv);
|
||||
~ProxGuiQT(void);
|
||||
void ShowGraphWindow(void);
|
||||
void RepaintGraphWindow(void);
|
||||
void HideGraphWindow(void);
|
||||
void MainLoop(void);
|
||||
|
||||
private slots:
|
||||
void _ShowGraphWindow(void);
|
||||
void _RepaintGraphWindow(void);
|
||||
void _HideGraphWindow(void);
|
||||
|
||||
signals:
|
||||
void ShowGraphWindowSignal(void);
|
||||
void RepaintGraphWindowSignal(void);
|
||||
void HideGraphWindowSignal(void);
|
||||
};
|
91
linux/proxmark3.c
Normal file
91
linux/proxmark3.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
#include <usb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "../winsrc/prox.h"
|
||||
#include "proxmark3.h"
|
||||
#include "proxgui.h"
|
||||
|
||||
struct usb_receiver_arg {
|
||||
int run;
|
||||
};
|
||||
|
||||
static void *usb_receiver(void *targ) {
|
||||
struct usb_receiver_arg *arg = (struct usb_receiver_arg*)targ;
|
||||
UsbCommand cmdbuf;
|
||||
|
||||
while(arg->run) {
|
||||
if (ReceiveCommandP(&cmdbuf) > 0) {
|
||||
int i;
|
||||
|
||||
for (i=0; i<strlen(PROXPROMPT); i++)
|
||||
putchar(0x08);
|
||||
|
||||
UsbCommandReceived(&cmdbuf);
|
||||
printf(PROXPROMPT);
|
||||
fflush(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
static void *main_loop(void *targ)
|
||||
{
|
||||
char *cmd = NULL;
|
||||
|
||||
while(1) {
|
||||
struct usb_receiver_arg rarg;
|
||||
pthread_t reader_thread;
|
||||
|
||||
rarg.run=1;
|
||||
pthread_create(&reader_thread, NULL, &usb_receiver, &rarg);
|
||||
|
||||
cmd = readline(PROXPROMPT);
|
||||
rarg.run=0;
|
||||
pthread_join(reader_thread, NULL);
|
||||
|
||||
if (cmd) {
|
||||
if (cmd[0] != 0x00) {
|
||||
CommandReceived(cmd);
|
||||
add_history(cmd);
|
||||
}
|
||||
free(cmd);
|
||||
} else {
|
||||
printf("\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ExitGraphics();
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
pthread_t main_loop_t;
|
||||
usb_init();
|
||||
|
||||
if (!(devh = OpenProxmark(1))) {
|
||||
fprintf(stderr,"PROXMARK3: NOT FOUND!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_create(&main_loop_t, NULL, &main_loop, NULL);
|
||||
InitGraphics(argc, argv);
|
||||
|
||||
MainGraphics();
|
||||
|
||||
pthread_join(main_loop_t, NULL);
|
||||
|
||||
CloseProxmark();
|
||||
return 0;
|
||||
}
|
11
linux/proxmark3.h
Normal file
11
linux/proxmark3.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#define PROXPROMPT "proxmark3> "
|
||||
|
||||
extern usb_dev_handle *devh;
|
||||
extern unsigned char return_on_error;
|
||||
extern unsigned char error_occured;
|
||||
|
||||
int ReceiveCommandP(UsbCommand *c);
|
||||
usb_dev_handle* OpenProxmark(int);
|
||||
void CloseProxmark(void);
|
||||
|
||||
void setlogfilename(char *fn);
|
49
linux/snooper.c
Normal file
49
linux/snooper.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
#include <usb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "../winsrc/prox.h"
|
||||
#include "proxmark3.h"
|
||||
|
||||
#define HANDLE_ERROR if (error_occured) { \
|
||||
error_occured = 0;\
|
||||
break;\
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
usb_init();
|
||||
setlogfilename("snooper.log");
|
||||
|
||||
return_on_error = 1;
|
||||
|
||||
while(1) {
|
||||
while(!(devh=OpenProxmark(0))) { sleep(1); }
|
||||
|
||||
while(1) {
|
||||
UsbCommand cmdbuf;
|
||||
int i;
|
||||
|
||||
CommandReceived("hi14asnoop");
|
||||
HANDLE_ERROR
|
||||
|
||||
ReceiveCommand(&cmdbuf);
|
||||
HANDLE_ERROR
|
||||
for (i=0; i<5; i++) {
|
||||
ReceiveCommandP(&cmdbuf);
|
||||
}
|
||||
HANDLE_ERROR
|
||||
|
||||
CommandReceived("hi14alist");
|
||||
HANDLE_ERROR
|
||||
}
|
||||
}
|
||||
|
||||
CloseProxmark();
|
||||
return 0;
|
||||
}
|
9
linux/translate.h
Normal file
9
linux/translate.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#define BYTE unsigned char
|
||||
#define WORD unsigned short
|
||||
#define DWORD unsigned int
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#define BOOL int
|
||||
|
||||
#define max(a,b) (((a)>(b))?(a):(b))
|
||||
#define min(a,b) (((a)>(b))?(b):(a))
|
16
linux/unbind-proxmark
Executable file
16
linux/unbind-proxmark
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
for i in /sys/bus/usb/devices/*; do
|
||||
if grep "9ac4" "${i}/idVendor" >/dev/null 2>&1; then
|
||||
echo "Found Proxmark..."
|
||||
dev=`basename "${i}"`
|
||||
|
||||
for j in /sys/bus/usb/drivers/usbhid/*; do
|
||||
if basename "${j}"|grep "^${dev}" >/dev/null; then
|
||||
bound="`basename "${j}"`"
|
||||
echo "Unbinding ${bound}..."
|
||||
echo -n "${bound}" >/sys/bus/usb/drivers/usbhid/unbind
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
171
linux/usb.c
Normal file
171
linux/usb.c
Normal file
|
@ -0,0 +1,171 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <usb.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "translate.h"
|
||||
#include "../winsrc/prox.h"
|
||||
#include "proxmark3.h"
|
||||
|
||||
usb_dev_handle *devh = NULL;
|
||||
static unsigned int claimed_iface = 0;
|
||||
unsigned char return_on_error = 0;
|
||||
unsigned char error_occured = 0;
|
||||
|
||||
void SendCommand(UsbCommand *c, BOOL wantAck) {
|
||||
int ret;
|
||||
|
||||
#if 0
|
||||
printf("Sending %d bytes\n", sizeof(UsbCommand));
|
||||
#endif
|
||||
ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000);
|
||||
if (ret<0) {
|
||||
error_occured = 1;
|
||||
if (return_on_error)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "write failed: %s!\nTrying to reopen device...\n",
|
||||
usb_strerror());
|
||||
|
||||
if (devh) {
|
||||
usb_close(devh);
|
||||
devh = NULL;
|
||||
}
|
||||
while(!(devh=OpenProxmark(0))) { sleep(1); }
|
||||
printf(PROXPROMPT);
|
||||
fflush(NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(wantAck) {
|
||||
UsbCommand ack;
|
||||
ReceiveCommand(&ack);
|
||||
if(ack.cmd != CMD_ACK) {
|
||||
printf("bad ACK\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ReceiveCommandP(UsbCommand *c) {
|
||||
int ret;
|
||||
|
||||
bzero(c, sizeof(UsbCommand));
|
||||
ret = usb_bulk_read(devh, 0x82, (char*)c, sizeof(UsbCommand), 500);
|
||||
if (ret<0) {
|
||||
if (ret != -ETIMEDOUT) {
|
||||
error_occured = 1;
|
||||
if (return_on_error)
|
||||
return 0;
|
||||
|
||||
fprintf(stderr, "read failed: %s(%d)!\nTrying to reopen device...\n",
|
||||
usb_strerror(), ret);
|
||||
|
||||
if (devh) {
|
||||
usb_close(devh);
|
||||
devh = NULL;
|
||||
}
|
||||
while(!(devh=OpenProxmark(0))) { sleep(1); }
|
||||
printf(PROXPROMPT);
|
||||
fflush(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (ret && (ret < sizeof(UsbCommand))) {
|
||||
fprintf(stderr, "Read only %d instead of requested %d bytes!\n",
|
||||
ret, (int)sizeof(UsbCommand));
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Read %d bytes\n", ret);
|
||||
for (i = 0; i < ret; i++) {
|
||||
printf("0x%02X ", ((unsigned char*)c)[i]);
|
||||
if (!((i+1)%8))
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ReceiveCommand(UsbCommand *c) {
|
||||
while(ReceiveCommandP(c)<0) {}
|
||||
}
|
||||
|
||||
usb_dev_handle* findProxmark(int verbose, unsigned int *iface) {
|
||||
struct usb_bus *busses, *bus;
|
||||
usb_dev_handle *handle = NULL;
|
||||
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
busses = usb_get_busses();
|
||||
|
||||
for (bus = busses; bus; bus = bus->next) {
|
||||
struct usb_device *dev;
|
||||
|
||||
for (dev = bus->devices; dev; dev = dev->next) {
|
||||
struct usb_device_descriptor *desc = &(dev->descriptor);
|
||||
|
||||
if ((desc->idProduct == 0x4b8f) && (desc->idVendor == 0x9ac4)) {
|
||||
handle = usb_open(dev);
|
||||
if (!handle) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "open failed: %s!\n", usb_strerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*iface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
|
||||
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
usb_dev_handle* OpenProxmark(int verbose) {
|
||||
int ret;
|
||||
usb_dev_handle *handle = NULL;
|
||||
unsigned int iface;
|
||||
|
||||
#ifndef __APPLE__
|
||||
handle = findProxmark(verbose, &iface);
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
/* Whatever... */
|
||||
usb_reset(handle);
|
||||
#endif
|
||||
|
||||
handle = findProxmark(verbose, &iface);
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
ret = usb_claim_interface(handle, iface);
|
||||
if (ret<0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "claim failed: %s!\n", usb_strerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
claimed_iface = iface;
|
||||
devh = handle;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void CloseProxmark(void) {
|
||||
usb_release_interface(devh, claimed_iface);
|
||||
usb_close(devh);
|
||||
}
|
0
linux/windows.h
Normal file
0
linux/windows.h
Normal file
31
winsrc/Makefile
Normal file
31
winsrc/Makefile
Normal file
|
@ -0,0 +1,31 @@
|
|||
BASE_DEFS = /D_WIN32_WINNT=0x501 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x600 /DWIN32_LEAN_AND_MEAN /DWIN32 /D_MT /D_CRT_SECURE_NO_WARNINGS
|
||||
BASE_CFLAGS = /W3 /nologo
|
||||
|
||||
DEFINES = $(BASE_DEFS)
|
||||
CFLAGS = $(BASE_CFLAGS) /Zi /MT
|
||||
|
||||
OBJDIR = obj
|
||||
|
||||
OBJS = $(OBJDIR)\prox.obj \
|
||||
$(OBJDIR)\gui.obj \
|
||||
$(OBJDIR)\command.obj
|
||||
|
||||
LIBS = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib setupapi.lib
|
||||
|
||||
HEADERS = prox.h
|
||||
|
||||
all: $(OBJDIR)/prox.exe
|
||||
copy $(OBJDIR)\prox.exe .
|
||||
|
||||
clean:
|
||||
del /q obj\*.obj
|
||||
del /q obj\*.ilk
|
||||
del /q obj\*.exe
|
||||
del /q obj\*.pdb
|
||||
del /q *.pdb
|
||||
|
||||
$(OBJDIR)/prox.exe: $(OBJS)
|
||||
$(CC) $(DEFINES) $(CFLAGS) -Fe$(OBJDIR)/prox.exe $(OBJS) $(LIBS)
|
||||
|
||||
$(OBJS): $(@B).cpp $(HEADERS)
|
||||
$(CC) $(CFLAGS) $(DEFINES) -c -Fo$(OBJDIR)/$(@B).obj $(@B).cpp
|
1812
winsrc/command.cpp
Normal file
1812
winsrc/command.cpp
Normal file
File diff suppressed because it is too large
Load diff
510
winsrc/gui.cpp
Normal file
510
winsrc/gui.cpp
Normal file
|
@ -0,0 +1,510 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Routines for the user interface when doing interactive things with prox
|
||||
// cards; this is basically a command line thing, in one window, and then
|
||||
// another window to do the graphs.
|
||||
// Jonathan Westhues, Sept 2005
|
||||
//-----------------------------------------------------------------------------
|
||||
#include <windows.h>
|
||||
#include <limits.h>
|
||||
#include <commctrl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "prox.h"
|
||||
|
||||
#define oops() do { \
|
||||
char line[100]; \
|
||||
sprintf(line, "Internal error at line %d file '%s'", __LINE__, \
|
||||
__FILE__); \
|
||||
MessageBox(NULL, line, "Error", MB_ICONERROR); \
|
||||
exit(-1); \
|
||||
} while(0)
|
||||
|
||||
void dbp(char *str, ...)
|
||||
{
|
||||
va_list f;
|
||||
char buf[1024];
|
||||
va_start(f, str);
|
||||
vsprintf(buf, str, f);
|
||||
OutputDebugString(buf);
|
||||
OutputDebugString("\n");
|
||||
}
|
||||
|
||||
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
int GraphTraceLen;
|
||||
|
||||
HPEN GreyPen, GreenPen, WhitePen, YellowPen;
|
||||
HBRUSH GreenBrush, YellowBrush;
|
||||
|
||||
static int GraphStart = 0;
|
||||
static double GraphPixelsPerPoint = 1;
|
||||
|
||||
static int CursorAPos;
|
||||
static int CursorBPos;
|
||||
double CursorScaleFactor = 1.0;
|
||||
static HPEN CursorAPen;
|
||||
static HPEN CursorBPen;
|
||||
|
||||
static HWND CommandWindow;
|
||||
static HWND GraphWindow;
|
||||
static HWND ScrollbackEdit;
|
||||
static HWND CommandEdit;
|
||||
|
||||
#define COMMAND_HISTORY_MAX 16
|
||||
static char CommandHistory[COMMAND_HISTORY_MAX][256];
|
||||
static int CommandHistoryPos = -1;
|
||||
static int CommandHistoryNext;
|
||||
|
||||
static HFONT MyFixedFont;
|
||||
#define FixedFont(x) SendMessage((x), WM_SETFONT, (WPARAM)MyFixedFont, TRUE)
|
||||
|
||||
void ExecCmd(char *cmd)
|
||||
{
|
||||
|
||||
}
|
||||
int CommandFinished;
|
||||
|
||||
static void ResizeCommandWindow(void)
|
||||
{
|
||||
int w, h;
|
||||
RECT r;
|
||||
GetClientRect(CommandWindow, &r);
|
||||
w = r.right - r.left;
|
||||
h = r.bottom - r.top;
|
||||
MoveWindow(ScrollbackEdit, 10, 10, w - 20, h - 50, TRUE);
|
||||
MoveWindow(CommandEdit, 10, h - 29, w - 20, 22, TRUE);
|
||||
}
|
||||
|
||||
void RepaintGraphWindow(void)
|
||||
{
|
||||
InvalidateRect(GraphWindow, NULL, TRUE);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
CommandWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_DESTROY:
|
||||
case WM_QUIT:
|
||||
exit(0);
|
||||
return 0;
|
||||
|
||||
case WM_SIZE:
|
||||
ResizeCommandWindow();
|
||||
return 0;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
SetFocus(CommandEdit);
|
||||
break;
|
||||
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void PaintGraph(HDC hdc)
|
||||
{
|
||||
HBRUSH brush;
|
||||
HPEN pen;
|
||||
|
||||
brush = GreenBrush;
|
||||
pen = GreenPen;
|
||||
|
||||
if(GraphStart < 0) {
|
||||
GraphStart = 0;
|
||||
}
|
||||
|
||||
RECT r;
|
||||
GetClientRect(GraphWindow, &r);
|
||||
|
||||
SelectObject(hdc, WhitePen);
|
||||
|
||||
MoveToEx(hdc, r.left + 40, r.top, NULL);
|
||||
LineTo(hdc, r.left + 40, r.bottom);
|
||||
|
||||
int zeroHeight = r.top + (r.bottom - r.top) / 2;
|
||||
SelectObject(hdc, GreyPen);
|
||||
MoveToEx(hdc, r.left, zeroHeight, NULL);
|
||||
LineTo(hdc, r.right, zeroHeight);
|
||||
|
||||
int startMax =
|
||||
(GraphTraceLen - (int)((r.right - r.left - 40) / GraphPixelsPerPoint));
|
||||
if(startMax < 0) {
|
||||
startMax = 0;
|
||||
}
|
||||
if(GraphStart > startMax) {
|
||||
GraphStart = startMax;
|
||||
}
|
||||
|
||||
int absYMax = 1;
|
||||
|
||||
SelectObject(hdc, pen);
|
||||
|
||||
int i;
|
||||
for(i = GraphStart; ; i++) {
|
||||
if(i >= GraphTraceLen) {
|
||||
break;
|
||||
}
|
||||
if(fabs((double)GraphBuffer[i]) > absYMax) {
|
||||
absYMax = (int)fabs((double)GraphBuffer[i]);
|
||||
}
|
||||
int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);
|
||||
if(x > r.right) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
absYMax = (int)(absYMax*1.2 + 1);
|
||||
SelectObject(hdc, MyFixedFont);
|
||||
SetTextColor(hdc, RGB(255, 255, 255));
|
||||
SetBkColor(hdc, RGB(0, 0, 0));
|
||||
|
||||
// number of points that will be plotted
|
||||
int span = (int)((r.right - r.left) / GraphPixelsPerPoint);
|
||||
// one label every 100 pixels, let us say
|
||||
int labels = (r.right - r.left - 40) / 100;
|
||||
if(labels <= 0) labels = 1;
|
||||
int pointsPerLabel = span / labels;
|
||||
if(pointsPerLabel <= 0) pointsPerLabel = 1;
|
||||
|
||||
int yMin = INT_MAX;
|
||||
int yMax = INT_MIN;
|
||||
int yMean = 0;
|
||||
int n = 0;
|
||||
|
||||
for(i = GraphStart; ; i++) {
|
||||
if(i >= GraphTraceLen) {
|
||||
break;
|
||||
}
|
||||
int x = 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);
|
||||
if(x > r.right + GraphPixelsPerPoint) {
|
||||
break;
|
||||
}
|
||||
|
||||
int y = GraphBuffer[i];
|
||||
if(y < yMin) {
|
||||
yMin = y;
|
||||
}
|
||||
if(y > yMax) {
|
||||
yMax = y;
|
||||
}
|
||||
yMean += y;
|
||||
n++;
|
||||
|
||||
y = (y * (r.top - r.bottom) / (2*absYMax)) + zeroHeight;
|
||||
if(i == GraphStart) {
|
||||
MoveToEx(hdc, x, y, NULL);
|
||||
} else {
|
||||
LineTo(hdc, x, y);
|
||||
}
|
||||
|
||||
if(GraphPixelsPerPoint > 10) {
|
||||
RECT f;
|
||||
f.left = x - 3;
|
||||
f.top = y - 3;
|
||||
f.right = x + 3;
|
||||
f.bottom = y + 3;
|
||||
FillRect(hdc, &f, brush);
|
||||
}
|
||||
|
||||
if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {
|
||||
SelectObject(hdc, WhitePen);
|
||||
MoveToEx(hdc, x, zeroHeight - 3, NULL);
|
||||
LineTo(hdc, x, zeroHeight + 3);
|
||||
|
||||
char str[100];
|
||||
sprintf(str, "+%d", (i - GraphStart));
|
||||
SIZE size;
|
||||
GetTextExtentPoint32(hdc, str, strlen(str), &size);
|
||||
TextOut(hdc, x - size.cx, zeroHeight + 8, str, strlen(str));
|
||||
|
||||
SelectObject(hdc, pen);
|
||||
MoveToEx(hdc, x, y, NULL);
|
||||
}
|
||||
|
||||
if(i == CursorAPos || i == CursorBPos) {
|
||||
if(i == CursorAPos) {
|
||||
SelectObject(hdc, CursorAPen);
|
||||
} else {
|
||||
SelectObject(hdc, CursorBPen);
|
||||
}
|
||||
MoveToEx(hdc, x, r.top, NULL);
|
||||
LineTo(hdc, x, r.bottom);
|
||||
|
||||
SelectObject(hdc, pen);
|
||||
MoveToEx(hdc, x, y, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if(n != 0) {
|
||||
yMean /= n;
|
||||
}
|
||||
|
||||
char str[100];
|
||||
sprintf(str, "@%d max=%d min=%d mean=%d n=%d/%d dt=%d [%.3f]",
|
||||
GraphStart, yMax, yMin, yMean, n, GraphTraceLen,
|
||||
CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor);
|
||||
TextOut(hdc, 50, r.bottom - 20, str, strlen(str));
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK
|
||||
GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_DESTROY:
|
||||
case WM_QUIT:
|
||||
GraphWindow = NULL;
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
|
||||
case WM_SIZE:
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
|
||||
case WM_PAINT: {
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hwnd, &ps);
|
||||
if(GraphStart < 0) {
|
||||
GraphStart = 0;
|
||||
}
|
||||
// This draws the trace.
|
||||
PaintGraph(hdc);
|
||||
EndPaint(hwnd, &ps);
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
switch(wParam) {
|
||||
case VK_DOWN:
|
||||
if(GraphPixelsPerPoint <= 50) {
|
||||
GraphPixelsPerPoint *= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_UP:
|
||||
if(GraphPixelsPerPoint >= 0.02) {
|
||||
GraphPixelsPerPoint /= 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_RIGHT:
|
||||
if(GraphPixelsPerPoint < 20) {
|
||||
GraphStart += (int)(20 / GraphPixelsPerPoint);
|
||||
} else {
|
||||
GraphStart++;
|
||||
}
|
||||
break;
|
||||
|
||||
case VK_LEFT:
|
||||
if(GraphPixelsPerPoint < 20) {
|
||||
GraphStart -= (int)(20 / GraphPixelsPerPoint);
|
||||
} else {
|
||||
GraphStart--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto nopaint;
|
||||
}
|
||||
RepaintGraphWindow();
|
||||
nopaint:
|
||||
break;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN: {
|
||||
int x = LOWORD(lParam);
|
||||
x -= 40;
|
||||
x = (int)(x / GraphPixelsPerPoint);
|
||||
x += GraphStart;
|
||||
if(msg == WM_LBUTTONDOWN) {
|
||||
CursorAPos = x;
|
||||
} else {
|
||||
CursorBPos = x;
|
||||
}
|
||||
RepaintGraphWindow();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void PrintToScrollback(char *fmt, ...)
|
||||
{
|
||||
va_list f;
|
||||
char str[1024];
|
||||
strcpy(str, "\r\n");
|
||||
va_start(f, fmt);
|
||||
vsprintf(str+2, fmt, f);
|
||||
|
||||
static char TextBuf[1024*32];
|
||||
SendMessage(ScrollbackEdit, WM_GETTEXT, (WPARAM)sizeof(TextBuf),
|
||||
(LPARAM)TextBuf);
|
||||
|
||||
if(strlen(TextBuf) + strlen(str) + 1 <= sizeof(TextBuf)) {
|
||||
strcat(TextBuf, str);
|
||||
} else {
|
||||
lstrcpyn(TextBuf, str, sizeof(TextBuf));
|
||||
}
|
||||
|
||||
SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)TextBuf);
|
||||
SendMessage(ScrollbackEdit, EM_LINESCROLL, 0, (LPARAM)INT_MAX);
|
||||
}
|
||||
|
||||
void ShowGraphWindow(void)
|
||||
{
|
||||
if(GraphWindow) return;
|
||||
|
||||
GraphWindow = CreateWindowEx(0, "Graph", "graphed",
|
||||
WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |
|
||||
WS_SIZEBOX | WS_VISIBLE, 200, 150, 600, 500, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if(!GraphWindow) oops();
|
||||
}
|
||||
|
||||
void HideGraphWindow(void)
|
||||
{
|
||||
if(GraphWindow) {
|
||||
DestroyWindow(GraphWindow);
|
||||
GraphWindow = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void SetCommandEditTo(char *str)
|
||||
{
|
||||
SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)str);
|
||||
SendMessage(CommandEdit, EM_SETSEL, strlen(str), strlen(str));
|
||||
}
|
||||
|
||||
void ShowGui(void)
|
||||
{
|
||||
WNDCLASSEX wc;
|
||||
memset(&wc, 0, sizeof(wc));
|
||||
wc.cbSize = sizeof(wc);
|
||||
|
||||
wc.style = CS_BYTEALIGNCLIENT | CS_BYTEALIGNWINDOW | CS_OWNDC;
|
||||
wc.lpfnWndProc = (WNDPROC)CommandWindowProc;
|
||||
wc.hInstance = NULL;
|
||||
wc.hbrBackground = (HBRUSH)(COLOR_BTNSHADOW);
|
||||
wc.lpszClassName = "Command";
|
||||
wc.lpszMenuName = NULL;
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
|
||||
if(!RegisterClassEx(&wc)) oops();
|
||||
|
||||
wc.lpszClassName = "Graph";
|
||||
wc.lpfnWndProc = (WNDPROC)GraphWindowProc;
|
||||
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
|
||||
|
||||
if(!RegisterClassEx(&wc)) oops();
|
||||
|
||||
CommandWindow = CreateWindowEx(0, "Command", "prox",
|
||||
WS_OVERLAPPED | WS_BORDER | WS_MINIMIZEBOX | WS_SYSMENU |
|
||||
WS_SIZEBOX | WS_VISIBLE, 20, 20, 500, 400, NULL, NULL, NULL,
|
||||
NULL);
|
||||
if(!CommandWindow) oops();
|
||||
|
||||
ScrollbackEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
|
||||
WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | ES_MULTILINE |
|
||||
ES_AUTOVSCROLL | WS_VSCROLL, 0, 0, 0, 0, CommandWindow, NULL,
|
||||
NULL, NULL);
|
||||
|
||||
CommandEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "edit", "",
|
||||
WS_CHILD | WS_CLIPSIBLINGS | WS_TABSTOP | WS_VISIBLE |
|
||||
ES_AUTOHSCROLL, 0, 0, 0, 0, CommandWindow, NULL, NULL, NULL);
|
||||
|
||||
MyFixedFont = CreateFont(14, 0, 0, 0, FW_REGULAR, FALSE, FALSE, FALSE,
|
||||
ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||||
FF_DONTCARE, "Lucida Console");
|
||||
if(!MyFixedFont)
|
||||
MyFixedFont = (HFONT)GetStockObject(SYSTEM_FONT);
|
||||
|
||||
FixedFont(ScrollbackEdit);
|
||||
FixedFont(CommandEdit);
|
||||
|
||||
ResizeCommandWindow();
|
||||
SetFocus(CommandEdit);
|
||||
|
||||
PrintToScrollback(">> Started prox, built " __DATE__ " " __TIME__);
|
||||
PrintToScrollback(">> Connected to device");
|
||||
|
||||
GreyPen = CreatePen(PS_SOLID, 1, RGB(100, 100, 100));
|
||||
GreenPen = CreatePen(PS_SOLID, 1, RGB(100, 255, 100));
|
||||
YellowPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 0));
|
||||
GreenBrush = CreateSolidBrush(RGB(100, 255, 100));
|
||||
YellowBrush = CreateSolidBrush(RGB(255, 255, 0));
|
||||
WhitePen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255));
|
||||
|
||||
CursorAPen = CreatePen(PS_DASH, 1, RGB(255, 255, 0));
|
||||
CursorBPen = CreatePen(PS_DASH, 1, RGB(255, 0, 255));
|
||||
|
||||
MSG msg;
|
||||
for(;;) {
|
||||
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if(msg.message == WM_KEYDOWN && msg.wParam == VK_RETURN) {
|
||||
char got[1024];
|
||||
SendMessage(CommandEdit, WM_GETTEXT, (WPARAM)sizeof(got),
|
||||
(LPARAM)got);
|
||||
|
||||
if(strcmp(got, "cls")==0) {
|
||||
SendMessage(ScrollbackEdit, WM_SETTEXT, 0, (LPARAM)"");
|
||||
} else {
|
||||
CommandReceived(got);
|
||||
}
|
||||
SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");
|
||||
|
||||
// Insert it into the command history, unless it is
|
||||
// identical to the previous command in the history.
|
||||
int prev = CommandHistoryNext - 1;
|
||||
if(prev < 0) prev += COMMAND_HISTORY_MAX;
|
||||
if(strcmp(CommandHistory[prev], got) != 0) {
|
||||
strcpy(CommandHistory[CommandHistoryNext], got);
|
||||
CommandHistoryNext++;
|
||||
if(CommandHistoryNext == COMMAND_HISTORY_MAX) {
|
||||
CommandHistoryNext = 0;
|
||||
}
|
||||
}
|
||||
CommandHistoryPos = -1;
|
||||
} else if(msg.message == WM_KEYDOWN && msg.wParam == VK_UP &&
|
||||
msg.hwnd == CommandEdit)
|
||||
{
|
||||
if(CommandHistoryPos == -1) {
|
||||
CommandHistoryPos = CommandHistoryNext;
|
||||
}
|
||||
CommandHistoryPos--;
|
||||
if(CommandHistoryPos < 0) {
|
||||
CommandHistoryPos = COMMAND_HISTORY_MAX-1;
|
||||
}
|
||||
SetCommandEditTo(CommandHistory[CommandHistoryPos]);
|
||||
} else if(msg.message == WM_KEYDOWN && msg.wParam == VK_DOWN &&
|
||||
msg.hwnd == CommandEdit)
|
||||
{
|
||||
CommandHistoryPos++;
|
||||
if(CommandHistoryPos >= COMMAND_HISTORY_MAX) {
|
||||
CommandHistoryPos = 0;
|
||||
}
|
||||
SetCommandEditTo(CommandHistory[CommandHistoryPos]);
|
||||
} else if(msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE &&
|
||||
msg.hwnd == CommandEdit)
|
||||
{
|
||||
SendMessage(CommandEdit, WM_SETTEXT, 0, (LPARAM)"");
|
||||
} else {
|
||||
if(msg.message == WM_KEYDOWN) {
|
||||
CommandHistoryPos = -1;
|
||||
}
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
UsbCommand c;
|
||||
if(ReceiveCommandPoll(&c)) {
|
||||
UsbCommandReceived(&c);
|
||||
}
|
||||
|
||||
Sleep(10);
|
||||
}
|
||||
}
|
1787
winsrc/include/hidpi.h
Normal file
1787
winsrc/include/hidpi.h
Normal file
File diff suppressed because it is too large
Load diff
412
winsrc/include/hidsdi.h
Normal file
412
winsrc/include/hidsdi.h
Normal file
|
@ -0,0 +1,412 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) 1996 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
HIDSDI.H
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the PUBLIC definitions for the
|
||||
code that implements the HID dll.
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel & user mode
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#ifndef _HIDSDI_H
|
||||
#define _HIDSDI_H
|
||||
|
||||
#include <pshpack4.h>
|
||||
|
||||
//#include "wtypes.h"
|
||||
|
||||
//#include <windef.h>
|
||||
//#include <win32.h>
|
||||
//#include <basetyps.h>
|
||||
|
||||
typedef LONG NTSTATUS;
|
||||
#include "hidusage.h"
|
||||
#include "hidpi.h"
|
||||
|
||||
typedef struct _HIDD_CONFIGURATION {
|
||||
PVOID cookie;
|
||||
ULONG size;
|
||||
ULONG RingBufferSize;
|
||||
} HIDD_CONFIGURATION, *PHIDD_CONFIGURATION;
|
||||
|
||||
typedef struct _HIDD_ATTRIBUTES {
|
||||
ULONG Size; // = sizeof (struct _HIDD_ATTRIBUTES)
|
||||
|
||||
//
|
||||
// Vendor ids of this hid device
|
||||
//
|
||||
USHORT VendorID;
|
||||
USHORT ProductID;
|
||||
USHORT VersionNumber;
|
||||
|
||||
//
|
||||
// Additional fields will be added to the end of this structure.
|
||||
//
|
||||
} HIDD_ATTRIBUTES, *PHIDD_ATTRIBUTES;
|
||||
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetAttributes (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PHIDD_ATTRIBUTES Attributes
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Fill in the given HIDD_ATTRIBUTES structure with the attributes of the
|
||||
given hid device.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
void __stdcall
|
||||
HidD_GetHidGuid (
|
||||
OUT LPGUID HidGuid
|
||||
);
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetPreparsedData (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PHIDP_PREPARSED_DATA * PreparsedData
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Given a handle to a valid Hid Class Device Object, retrieve the preparsed
|
||||
data for the device. This routine will allocate the appropriately
|
||||
sized buffer to hold this preparsed data. It is up to client to call
|
||||
HidP_FreePreparsedData to free the memory allocated to this structure when
|
||||
it is no longer needed.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device that the client obtains using
|
||||
a call to CreateFile on a valid Hid device string name.
|
||||
The string name can be obtained using standard PnP calls.
|
||||
|
||||
PreparsedData An opaque data structure used by other functions in this
|
||||
library to retrieve information about a given device.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful.
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_FreePreparsedData (
|
||||
IN PHIDP_PREPARSED_DATA PreparsedData
|
||||
);
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_FlushQueue (
|
||||
IN HANDLE HidDeviceObject
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Flush the input queue for the given HID device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device that the client obtains using
|
||||
a call to CreateFile on a valid Hid device string name.
|
||||
The string name can be obtained using standard PnP calls.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetConfiguration (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Get the configuration information for this Hid device
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Configuration A configuration structure. HidD_GetConfiguration MUST
|
||||
be called before the configuration can be modified and
|
||||
set using HidD_SetConfiguration
|
||||
|
||||
ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this
|
||||
parameter, we can later increase the length of the
|
||||
configuration array and not break older apps.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_SetConfiguration (
|
||||
IN HANDLE HidDeviceObject,
|
||||
IN PHIDD_CONFIGURATION Configuration,
|
||||
IN ULONG ConfigurationLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Set the configuration information for this Hid device...
|
||||
|
||||
NOTE: HidD_GetConfiguration must be called to retrieve the current
|
||||
configuration information before this information can be modified
|
||||
and set.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Configuration A configuration structure. HidD_GetConfiguration MUST
|
||||
be called before the configuration can be modified and
|
||||
set using HidD_SetConfiguration
|
||||
|
||||
ConfigurationLength That is ``sizeof (HIDD_CONFIGURATION)''. Using this
|
||||
parameter, we can later increase the length of the
|
||||
configuration array and not break older apps.
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetFeature (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID ReportBuffer,
|
||||
IN ULONG ReportBufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Retrieve a feature report from a HID device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
ReportBuffer The buffer that the feature report should be placed
|
||||
into. The first byte of the buffer should be set to
|
||||
the report ID of the desired report
|
||||
|
||||
ReportBufferLength The size (in bytes) of ReportBuffer. This value
|
||||
should be greater than or equal to the
|
||||
FeatureReportByteLength field as specified in the
|
||||
HIDP_CAPS structure for the device
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_SetFeature (
|
||||
IN HANDLE HidDeviceObject,
|
||||
IN PVOID ReportBuffer,
|
||||
IN ULONG ReportBufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
Send a feature report to a HID device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
ReportBuffer The buffer of the feature report to send to the device
|
||||
|
||||
ReportBufferLength The size (in bytes) of ReportBuffer. This value
|
||||
should be greater than or equal to the
|
||||
FeatureReportByteLength field as specified in the
|
||||
HIDP_CAPS structure for the device
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetNumInputBuffers (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PULONG NumberBuffers
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function returns the number of input buffers used by the specified
|
||||
file handle to the Hid device. Each file object has a number of buffers
|
||||
associated with it to queue reports read from the device but which have
|
||||
not yet been read by the user-mode app with a handle to that device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
NumberBuffers Number of buffers currently being used for this file
|
||||
handle to the Hid device
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_SetNumInputBuffers (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT ULONG NumberBuffers
|
||||
);
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
This function sets the number of input buffers used by the specified
|
||||
file handle to the Hid device. Each file object has a number of buffers
|
||||
associated with it to queue reports read from the device but which have
|
||||
not yet been read by the user-mode app with a handle to that device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
NumberBuffers New number of buffers to use for this file handle to
|
||||
the Hid device
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetPhysicalDescriptor (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the raw physical descriptor for the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the physical
|
||||
descriptor if one exists for the specified device
|
||||
handle
|
||||
|
||||
BufferLength Length of buffer (in bytes)
|
||||
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetManufacturerString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the manufacturer string from the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the manufacturer
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetProductString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the product string from the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the product
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetIndexedString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
IN ULONG StringIndex,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves a string from the specified Hid device that is
|
||||
specified with a certain string index.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
StringIndex Index of the string to retrieve
|
||||
|
||||
Buffer Buffer which on return will contain the product
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
BOOLEAN __stdcall
|
||||
HidD_GetSerialNumberString (
|
||||
IN HANDLE HidDeviceObject,
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG BufferLength
|
||||
);
|
||||
/*++
|
||||
Routine Description:
|
||||
This function retrieves the serial number string from the specified
|
||||
Hid device.
|
||||
|
||||
Arguments:
|
||||
HidDeviceObject A handle to a Hid Device Object.
|
||||
|
||||
Buffer Buffer which on return will contain the serial number
|
||||
string returned from the device. This string is a
|
||||
wide-character string
|
||||
|
||||
BufferLength Length of Buffer (in bytes)
|
||||
|
||||
Return Value:
|
||||
TRUE if successful
|
||||
FALSE otherwise -- Use GetLastError() to get extended error information
|
||||
--*/
|
||||
|
||||
|
||||
#include <poppack.h>
|
||||
|
||||
#endif
|
263
winsrc/include/hidusage.h
Normal file
263
winsrc/include/hidusage.h
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) 1996, 1997 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
HIDUSAGE.H
|
||||
|
||||
Abstract:
|
||||
|
||||
Public Definitions of HID USAGES.
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel & user mode
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __HIDUSAGE_H__
|
||||
#define __HIDUSAGE_H__
|
||||
|
||||
//
|
||||
// Usage Pages
|
||||
//
|
||||
|
||||
typedef USHORT USAGE, *PUSAGE;
|
||||
|
||||
#define HID_USAGE_PAGE_GENERIC ((USAGE) 0x01)
|
||||
#define HID_USAGE_PAGE_SIMULATION ((USAGE) 0x02)
|
||||
#define HID_USAGE_PAGE_VR ((USAGE) 0x03)
|
||||
#define HID_USAGE_PAGE_SPORT ((USAGE) 0x04)
|
||||
#define HID_USAGE_PAGE_GAME ((USAGE) 0x05)
|
||||
#define HID_USAGE_PAGE_KEYBOARD ((USAGE) 0x07)
|
||||
#define HID_USAGE_PAGE_LED ((USAGE) 0x08)
|
||||
#define HID_USAGE_PAGE_BUTTON ((USAGE) 0x09)
|
||||
#define HID_USAGE_PAGE_ORDINAL ((USAGE) 0x0A)
|
||||
#define HID_USAGE_PAGE_TELEPHONY ((USAGE) 0x0B)
|
||||
#define HID_USAGE_PAGE_CONSUMER ((USAGE) 0x0C)
|
||||
#define HID_USAGE_PAGE_DIGITIZER ((USAGE) 0x0D)
|
||||
#define HID_USAGE_PAGE_UNICODE ((USAGE) 0x10)
|
||||
#define HID_USAGE_PAGE_ALPHANUMERIC ((USAGE) 0x14)
|
||||
|
||||
|
||||
//
|
||||
// Usages from Generic Desktop Page (0x01)
|
||||
//
|
||||
|
||||
#define HID_USAGE_GENERIC_POINTER ((USAGE) 0x01)
|
||||
#define HID_USAGE_GENERIC_MOUSE ((USAGE) 0x02)
|
||||
#define HID_USAGE_GENERIC_JOYSTICK ((USAGE) 0x04)
|
||||
#define HID_USAGE_GENERIC_GAMEPAD ((USAGE) 0x05)
|
||||
#define HID_USAGE_GENERIC_KEYBOARD ((USAGE) 0x06)
|
||||
#define HID_USAGE_GENERIC_KEYPAD ((USAGE) 0x07)
|
||||
#define HID_USAGE_GENERIC_SYSTEM_CTL ((USAGE) 0x80)
|
||||
|
||||
#define HID_USAGE_GENERIC_X ((USAGE) 0x30)
|
||||
#define HID_USAGE_GENERIC_Y ((USAGE) 0x31)
|
||||
#define HID_USAGE_GENERIC_Z ((USAGE) 0x32)
|
||||
#define HID_USAGE_GENERIC_RX ((USAGE) 0x33)
|
||||
#define HID_USAGE_GENERIC_RY ((USAGE) 0x34)
|
||||
#define HID_USAGE_GENERIC_RZ ((USAGE) 0x35)
|
||||
#define HID_USAGE_GENERIC_SLIDER ((USAGE) 0x36)
|
||||
#define HID_USAGE_GENERIC_DIAL ((USAGE) 0x37)
|
||||
#define HID_USAGE_GENERIC_WHEEL ((USAGE) 0x38)
|
||||
#define HID_USAGE_GENERIC_HATSWITCH ((USAGE) 0x39)
|
||||
#define HID_USAGE_GENERIC_COUNTED_BUFFER ((USAGE) 0x3A)
|
||||
#define HID_USAGE_GENERIC_BYTE_COUNT ((USAGE) 0x3B)
|
||||
#define HID_USAGE_GENERIC_MOTION_WAKEUP ((USAGE) 0x3C)
|
||||
#define HID_USAGE_GENERIC_VX ((USAGE) 0x40)
|
||||
#define HID_USAGE_GENERIC_VY ((USAGE) 0x41)
|
||||
#define HID_USAGE_GENERIC_VZ ((USAGE) 0x42)
|
||||
#define HID_USAGE_GENERIC_VBRX ((USAGE) 0x43)
|
||||
#define HID_USAGE_GENERIC_VBRY ((USAGE) 0x44)
|
||||
#define HID_USAGE_GENERIC_VBRZ ((USAGE) 0x45)
|
||||
#define HID_USAGE_GENERIC_VNO ((USAGE) 0x46)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_POWER ((USAGE) 0x81)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_SLEEP ((USAGE) 0x82)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_WAKE ((USAGE) 0x83)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_CONTEXT_MENU ((USAGE) 0x84)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MAIN_MENU ((USAGE) 0x85)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_APP_MENU ((USAGE) 0x86)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_HELP_MENU ((USAGE) 0x87)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_EXIT ((USAGE) 0x88)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_SELECT ((USAGE) 0x89)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_RIGHT ((USAGE) 0x8A)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_LEFT ((USAGE) 0x8B)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_UP ((USAGE) 0x8C)
|
||||
#define HID_USAGE_GENERIC_SYSCTL_MENU_DOWN ((USAGE) 0x8D)
|
||||
|
||||
//
|
||||
// Usages from Simulation Controls Page (0x02)
|
||||
//
|
||||
|
||||
#define HID_USAGE_SIMULATION_RUDDER ((USAGE) 0xBA)
|
||||
#define HID_USAGE_SIMULATION_THROTTLE ((USAGE) 0xBB)
|
||||
|
||||
//
|
||||
// Virtual Reality Controls Page (0x03)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Sport Controls Page (0x04)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Game Controls Page (0x05)
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Keyboard/Keypad Page (0x07)
|
||||
//
|
||||
|
||||
// Error "keys"
|
||||
#define HID_USAGE_KEYBOARD_NOEVENT ((USAGE) 0x00)
|
||||
#define HID_USAGE_KEYBOARD_ROLLOVER ((USAGE) 0x01)
|
||||
#define HID_USAGE_KEYBOARD_POSTFAIL ((USAGE) 0x02)
|
||||
#define HID_USAGE_KEYBOARD_UNDEFINED ((USAGE) 0x03)
|
||||
|
||||
// Letters
|
||||
#define HID_USAGE_KEYBOARD_aA ((USAGE) 0x04)
|
||||
#define HID_USAGE_KEYBOARD_zZ ((USAGE) 0x1D)
|
||||
// Numbers
|
||||
#define HID_USAGE_KEYBOARD_ONE ((USAGE) 0x1E)
|
||||
#define HID_USAGE_KEYBOARD_ZERO ((USAGE) 0x27)
|
||||
// Modifier Keys
|
||||
#define HID_USAGE_KEYBOARD_LCTRL ((USAGE) 0xE0)
|
||||
#define HID_USAGE_KEYBOARD_LSHFT ((USAGE) 0xE1)
|
||||
#define HID_USAGE_KEYBOARD_LALT ((USAGE) 0xE2)
|
||||
#define HID_USAGE_KEYBOARD_LGUI ((USAGE) 0xE3)
|
||||
#define HID_USAGE_KEYBOARD_RCTRL ((USAGE) 0xE4)
|
||||
#define HID_USAGE_KEYBOARD_RSHFT ((USAGE) 0xE5)
|
||||
#define HID_USAGE_KEYBOARD_RALT ((USAGE) 0xE6)
|
||||
#define HID_USAGE_KEYBOARD_RGUI ((USAGE) 0xE7)
|
||||
#define HID_USAGE_KEYBOARD_SCROLL_LOCK ((USAGE) 0x47)
|
||||
#define HID_USAGE_KEYBOARD_NUM_LOCK ((USAGE) 0x53)
|
||||
#define HID_USAGE_KEYBOARD_CAPS_LOCK ((USAGE) 0x39)
|
||||
// Funtion keys
|
||||
#define HID_USAGE_KEYBOARD_F1 ((USAGE) 0x3A)
|
||||
#define HID_USAGE_KEYBOARD_F12 ((USAGE) 0x45)
|
||||
|
||||
#define HID_USAGE_KEYBOARD_RETURN ((USAGE) 0x28)
|
||||
#define HID_USAGE_KEYBOARD_ESCAPE ((USAGE) 0x29)
|
||||
#define HID_USAGE_KEYBOARD_DELETE ((USAGE) 0x2A)
|
||||
|
||||
#define HID_USAGE_KEYBOARD_PRINT_SCREEN ((USAGE) 0x46)
|
||||
|
||||
// and hundreds more...
|
||||
|
||||
//
|
||||
// LED Page (0x08)
|
||||
//
|
||||
|
||||
#define HID_USAGE_LED_NUM_LOCK ((USAGE) 0x01)
|
||||
#define HID_USAGE_LED_CAPS_LOCK ((USAGE) 0x02)
|
||||
#define HID_USAGE_LED_SCROLL_LOCK ((USAGE) 0x03)
|
||||
#define HID_USAGE_LED_COMPOSE ((USAGE) 0x04)
|
||||
#define HID_USAGE_LED_KANA ((USAGE) 0x05)
|
||||
#define HID_USAGE_LED_POWER ((USAGE) 0x06)
|
||||
#define HID_USAGE_LED_SHIFT ((USAGE) 0x07)
|
||||
#define HID_USAGE_LED_DO_NOT_DISTURB ((USAGE) 0x08)
|
||||
#define HID_USAGE_LED_MUTE ((USAGE) 0x09)
|
||||
#define HID_USAGE_LED_TONE_ENABLE ((USAGE) 0x0A)
|
||||
#define HID_USAGE_LED_HIGH_CUT_FILTER ((USAGE) 0x0B)
|
||||
#define HID_USAGE_LED_LOW_CUT_FILTER ((USAGE) 0x0C)
|
||||
#define HID_USAGE_LED_EQUALIZER_ENABLE ((USAGE) 0x0D)
|
||||
#define HID_USAGE_LED_SOUND_FIELD_ON ((USAGE) 0x0E)
|
||||
#define HID_USAGE_LED_SURROUND_FIELD_ON ((USAGE) 0x0F)
|
||||
#define HID_USAGE_LED_REPEAT ((USAGE) 0x10)
|
||||
#define HID_USAGE_LED_STEREO ((USAGE) 0x11)
|
||||
#define HID_USAGE_LED_SAMPLING_RATE_DETECT ((USAGE) 0x12)
|
||||
#define HID_USAGE_LED_SPINNING ((USAGE) 0x13)
|
||||
#define HID_USAGE_LED_CAV ((USAGE) 0x14)
|
||||
#define HID_USAGE_LED_CLV ((USAGE) 0x15)
|
||||
#define HID_USAGE_LED_RECORDING_FORMAT_DET ((USAGE) 0x16)
|
||||
#define HID_USAGE_LED_OFF_HOOK ((USAGE) 0x17)
|
||||
#define HID_USAGE_LED_RING ((USAGE) 0x18)
|
||||
#define HID_USAGE_LED_MESSAGE_WAITING ((USAGE) 0x19)
|
||||
#define HID_USAGE_LED_DATA_MODE ((USAGE) 0x1A)
|
||||
#define HID_USAGE_LED_BATTERY_OPERATION ((USAGE) 0x1B)
|
||||
#define HID_USAGE_LED_BATTERY_OK ((USAGE) 0x1C)
|
||||
#define HID_USAGE_LED_BATTERY_LOW ((USAGE) 0x1D)
|
||||
#define HID_USAGE_LED_SPEAKER ((USAGE) 0x1E)
|
||||
#define HID_USAGE_LED_HEAD_SET ((USAGE) 0x1F)
|
||||
#define HID_USAGE_LED_HOLD ((USAGE) 0x20)
|
||||
#define HID_USAGE_LED_MICROPHONE ((USAGE) 0x21)
|
||||
#define HID_USAGE_LED_COVERAGE ((USAGE) 0x22)
|
||||
#define HID_USAGE_LED_NIGHT_MODE ((USAGE) 0x23)
|
||||
#define HID_USAGE_LED_SEND_CALLS ((USAGE) 0x24)
|
||||
#define HID_USAGE_LED_CALL_PICKUP ((USAGE) 0x25)
|
||||
#define HID_USAGE_LED_CONFERENCE ((USAGE) 0x26)
|
||||
#define HID_USAGE_LED_STAND_BY ((USAGE) 0x27)
|
||||
#define HID_USAGE_LED_CAMERA_ON ((USAGE) 0x28)
|
||||
#define HID_USAGE_LED_CAMERA_OFF ((USAGE) 0x29)
|
||||
#define HID_USAGE_LED_ON_LINE ((USAGE) 0x2A)
|
||||
#define HID_USAGE_LED_OFF_LINE ((USAGE) 0x2B)
|
||||
#define HID_USAGE_LED_BUSY ((USAGE) 0x2C)
|
||||
#define HID_USAGE_LED_READY ((USAGE) 0x2D)
|
||||
#define HID_USAGE_LED_PAPER_OUT ((USAGE) 0x2E)
|
||||
#define HID_USAGE_LED_PAPER_JAM ((USAGE) 0x2F)
|
||||
#define HID_USAGE_LED_REMOTE ((USAGE) 0x30)
|
||||
#define HID_USAGE_LED_FORWARD ((USAGE) 0x31)
|
||||
#define HID_USAGE_LED_REVERSE ((USAGE) 0x32)
|
||||
#define HID_USAGE_LED_STOP ((USAGE) 0x33)
|
||||
#define HID_USAGE_LED_REWIND ((USAGE) 0x34)
|
||||
#define HID_USAGE_LED_FAST_FORWARD ((USAGE) 0x35)
|
||||
#define HID_USAGE_LED_PLAY ((USAGE) 0x36)
|
||||
#define HID_USAGE_LED_PAUSE ((USAGE) 0x37)
|
||||
#define HID_USAGE_LED_RECORD ((USAGE) 0x38)
|
||||
#define HID_USAGE_LED_ERROR ((USAGE) 0x39)
|
||||
#define HID_USAGE_LED_SELECTED_INDICATOR ((USAGE) 0x3A)
|
||||
#define HID_USAGE_LED_IN_USE_INDICATOR ((USAGE) 0x3B)
|
||||
#define HID_USAGE_LED_MULTI_MODE_INDICATOR ((USAGE) 0x3C)
|
||||
#define HID_USAGE_LED_INDICATOR_ON ((USAGE) 0x3D)
|
||||
#define HID_USAGE_LED_INDICATOR_FLASH ((USAGE) 0x3E)
|
||||
#define HID_USAGE_LED_INDICATOR_SLOW_BLINK ((USAGE) 0x3F)
|
||||
#define HID_USAGE_LED_INDICATOR_FAST_BLINK ((USAGE) 0x40)
|
||||
#define HID_USAGE_LED_INDICATOR_OFF ((USAGE) 0x41)
|
||||
#define HID_USAGE_LED_FLASH_ON_TIME ((USAGE) 0x42)
|
||||
#define HID_USAGE_LED_SLOW_BLINK_ON_TIME ((USAGE) 0x43)
|
||||
#define HID_USAGE_LED_SLOW_BLINK_OFF_TIME ((USAGE) 0x44)
|
||||
#define HID_USAGE_LED_FAST_BLINK_ON_TIME ((USAGE) 0x45)
|
||||
#define HID_USAGE_LED_FAST_BLINK_OFF_TIME ((USAGE) 0x46)
|
||||
#define HID_USAGE_LED_INDICATOR_COLOR ((USAGE) 0x47)
|
||||
#define HID_USAGE_LED_RED ((USAGE) 0x48)
|
||||
#define HID_USAGE_LED_GREEN ((USAGE) 0x49)
|
||||
#define HID_USAGE_LED_AMBER ((USAGE) 0x4A)
|
||||
#define HID_USAGE_LED_GENERIC_INDICATOR ((USAGE) 0x3B)
|
||||
|
||||
//
|
||||
// Button Page (0x09)
|
||||
//
|
||||
// There is no need to label these usages.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Ordinal Page (0x0A)
|
||||
//
|
||||
// There is no need to label these usages.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Telephony Device Page (0x0B)
|
||||
//
|
||||
|
||||
#define HID_USAGE_TELEPHONY_PHONE ((USAGE) 0x01)
|
||||
#define HID_USAGE_TELEPHONY_ANSWERING_MACHINE ((USAGE) 0x02)
|
||||
#define HID_USAGE_TELEPHONY_MESSAGE_CONTROLS ((USAGE) 0x03)
|
||||
#define HID_USAGE_TELEPHONY_HANDSET ((USAGE) 0x04)
|
||||
#define HID_USAGE_TELEPHONY_HEADSET ((USAGE) 0x05)
|
||||
#define HID_USAGE_TELEPHONY_KEYPAD ((USAGE) 0x06)
|
||||
#define HID_USAGE_TELEPHONY_PROGRAMMABLE_BUTTON ((USAGE) 0x07)
|
||||
|
||||
//
|
||||
// and others...
|
||||
//
|
||||
|
||||
|
||||
#endif
|
379
winsrc/prox.cpp
Normal file
379
winsrc/prox.cpp
Normal file
|
@ -0,0 +1,379 @@
|
|||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
extern "C" {
|
||||
#include "include/hidsdi.h"
|
||||
#include "include/hidpi.h"
|
||||
}
|
||||
|
||||
#include "prox.h"
|
||||
|
||||
#define OUR_VID 0x9ac4
|
||||
#define OUR_PID 0x4b8f
|
||||
|
||||
HANDLE UsbHandle;
|
||||
|
||||
static void ShowError(void)
|
||||
{
|
||||
char buf[1024];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0,
|
||||
buf, sizeof(buf), NULL);
|
||||
printf("ERROR: %s", buf);
|
||||
}
|
||||
|
||||
static BOOL UsbConnect(void)
|
||||
{
|
||||
typedef void (__stdcall *GetGuidProc)(GUID *);
|
||||
typedef BOOLEAN (__stdcall *GetAttrProc)(HANDLE, HIDD_ATTRIBUTES *);
|
||||
typedef BOOLEAN (__stdcall *GetPreparsedProc)(HANDLE,
|
||||
PHIDP_PREPARSED_DATA *);
|
||||
typedef NTSTATUS (__stdcall *GetCapsProc)(PHIDP_PREPARSED_DATA, PHIDP_CAPS);
|
||||
GetGuidProc getGuid;
|
||||
GetAttrProc getAttr;
|
||||
GetPreparsedProc getPreparsed;
|
||||
GetCapsProc getCaps;
|
||||
|
||||
HMODULE h = LoadLibrary("hid.dll");
|
||||
getGuid = (GetGuidProc)GetProcAddress(h, "HidD_GetHidGuid");
|
||||
getAttr = (GetAttrProc)GetProcAddress(h, "HidD_GetAttributes");
|
||||
getPreparsed = (GetPreparsedProc)GetProcAddress(h, "HidD_GetPreparsedData");
|
||||
getCaps = (GetCapsProc)GetProcAddress(h, "HidP_GetCaps");
|
||||
|
||||
GUID hidGuid;
|
||||
getGuid(&hidGuid);
|
||||
|
||||
HDEVINFO devInfo;
|
||||
devInfo = SetupDiGetClassDevs(&hidGuid, NULL, NULL,
|
||||
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
|
||||
|
||||
SP_DEVICE_INTERFACE_DATA devInfoData;
|
||||
devInfoData.cbSize = sizeof(devInfoData);
|
||||
|
||||
int i;
|
||||
for(i = 0;; i++) {
|
||||
if(!SetupDiEnumDeviceInterfaces(devInfo, 0, &hidGuid, i, &devInfoData))
|
||||
{
|
||||
if(GetLastError() != ERROR_NO_MORE_ITEMS) {
|
||||
// printf("SetupDiEnumDeviceInterfaces failed\n");
|
||||
}
|
||||
// printf("done list\n");
|
||||
SetupDiDestroyDeviceInfoList(devInfo);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// printf("item %d:\n", i);
|
||||
|
||||
DWORD sizeReqd = 0;
|
||||
if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData,
|
||||
NULL, 0, &sizeReqd, NULL))
|
||||
{
|
||||
if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
// printf("SetupDiGetDeviceInterfaceDetail (0) failed\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
SP_DEVICE_INTERFACE_DETAIL_DATA *devInfoDetailData =
|
||||
(SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(sizeReqd);
|
||||
devInfoDetailData->cbSize = sizeof(*devInfoDetailData);
|
||||
|
||||
if(!SetupDiGetDeviceInterfaceDetail(devInfo, &devInfoData,
|
||||
devInfoDetailData, 87, NULL, NULL))
|
||||
{
|
||||
// printf("SetupDiGetDeviceInterfaceDetail (1) failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
char *path = devInfoDetailData->DevicePath;
|
||||
|
||||
UsbHandle = CreateFile(path, /*GENERIC_READ |*/ GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED, NULL);
|
||||
|
||||
if(UsbHandle == INVALID_HANDLE_VALUE) {
|
||||
ShowError();
|
||||
// printf("CreateFile failed: for '%s'\n", path);
|
||||
continue;
|
||||
}
|
||||
|
||||
HIDD_ATTRIBUTES attr;
|
||||
attr.Size = sizeof(attr);
|
||||
if(!getAttr(UsbHandle, &attr)) {
|
||||
ShowError();
|
||||
// printf("HidD_GetAttributes failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// printf("VID: %04x PID %04x\n", attr.VendorID, attr.ProductID);
|
||||
|
||||
if(attr.VendorID != OUR_VID || attr.ProductID != OUR_PID) {
|
||||
CloseHandle(UsbHandle);
|
||||
// printf(" nope, not us\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// printf ("got it!\n");
|
||||
CloseHandle(UsbHandle);
|
||||
|
||||
UsbHandle = CreateFile(path, GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_OVERLAPPED, NULL);
|
||||
|
||||
if(UsbHandle == INVALID_HANDLE_VALUE) {
|
||||
ShowError();
|
||||
// printf("Error, couldn't open our own handle as desired.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
PHIDP_PREPARSED_DATA pp;
|
||||
getPreparsed(UsbHandle, &pp);
|
||||
HIDP_CAPS caps;
|
||||
|
||||
if(getCaps(pp, &caps) != HIDP_STATUS_SUCCESS) {
|
||||
// printf("getcaps failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// printf("input/out report %d/%d\n", caps.InputReportByteLength,
|
||||
// caps.OutputReportByteLength);
|
||||
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL ReceiveCommandPoll(UsbCommand *c)
|
||||
{
|
||||
static BOOL ReadInProgress = FALSE;
|
||||
static OVERLAPPED Ov;
|
||||
static BYTE Buf[65];
|
||||
static DWORD HaveRead;
|
||||
|
||||
if(!ReadInProgress) {
|
||||
memset(&Ov, 0, sizeof(Ov));
|
||||
ReadFile(UsbHandle, Buf, 65, &HaveRead, &Ov);
|
||||
if(GetLastError() != ERROR_IO_PENDING) {
|
||||
ShowError();
|
||||
exit(-1);
|
||||
}
|
||||
ReadInProgress = TRUE;
|
||||
}
|
||||
|
||||
if(HasOverlappedIoCompleted(&Ov)) {
|
||||
ReadInProgress = FALSE;
|
||||
|
||||
if(!GetOverlappedResult(UsbHandle, &Ov, &HaveRead, FALSE)) {
|
||||
ShowError();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memcpy(c, Buf+1, 64);
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void ReceiveCommand(UsbCommand *c)
|
||||
{
|
||||
while(!ReceiveCommandPoll(c)) {
|
||||
Sleep(0);
|
||||
}
|
||||
}
|
||||
|
||||
void SendCommand(UsbCommand *c, BOOL wantAck)
|
||||
{
|
||||
BYTE buf[65];
|
||||
buf[0] = 0;
|
||||
memcpy(buf+1, c, 64);
|
||||
|
||||
DWORD written;
|
||||
OVERLAPPED ov;
|
||||
memset(&ov, 0, sizeof(ov));
|
||||
WriteFile(UsbHandle, buf, 65, &written, &ov);
|
||||
if(GetLastError() != ERROR_IO_PENDING) {
|
||||
ShowError();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while(!HasOverlappedIoCompleted(&ov)) {
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
if(!GetOverlappedResult(UsbHandle, &ov, &written, FALSE)) {
|
||||
ShowError();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if(wantAck) {
|
||||
UsbCommand ack;
|
||||
ReceiveCommand(&ack);
|
||||
if(ack.cmd != CMD_ACK) {
|
||||
printf("bad ACK\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD ExpectedAddr;
|
||||
static BYTE QueuedToSend[256];
|
||||
static BOOL AllWritten;
|
||||
|
||||
static void FlushPrevious(void)
|
||||
{
|
||||
UsbCommand c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
|
||||
printf("expected = %08x flush, ", ExpectedAddr);
|
||||
|
||||
int i;
|
||||
for(i = 0; i < 240; i += 48) {
|
||||
c.cmd = CMD_SETUP_WRITE;
|
||||
memcpy(c.d.asBytes, QueuedToSend+i, 48);
|
||||
c.ext1 = (i/4);
|
||||
SendCommand(&c, TRUE);
|
||||
}
|
||||
|
||||
c.cmd = CMD_FINISH_WRITE;
|
||||
c.ext1 = (ExpectedAddr-1) & (~255);
|
||||
printf("c.ext1 = %08x\r", c.ext1);
|
||||
memcpy(c.d.asBytes, QueuedToSend+240, 16);
|
||||
SendCommand(&c, TRUE);
|
||||
|
||||
AllWritten = TRUE;
|
||||
}
|
||||
|
||||
static void GotByte(DWORD where, BYTE which)
|
||||
{
|
||||
AllWritten = FALSE;
|
||||
|
||||
if(where != ExpectedAddr) {
|
||||
printf("bad: got at %08x, expected at %08x\n", where, ExpectedAddr);
|
||||
exit(-1);
|
||||
}
|
||||
QueuedToSend[where & 255] = which;
|
||||
ExpectedAddr++;
|
||||
|
||||
if((where & 255) == 255) {
|
||||
// we have completed a full page
|
||||
FlushPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
static int HexVal(int c)
|
||||
{
|
||||
c = tolower(c);
|
||||
if(c >= '0' && c <= '9') {
|
||||
return c - '0';
|
||||
} else if(c >= 'a' && c <= 'f') {
|
||||
return (c - 'a') + 10;
|
||||
} else {
|
||||
printf("bad hex digit '%c'\n", c);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
static BYTE HexByte(char *s)
|
||||
{
|
||||
return (HexVal(s[0]) << 4) | HexVal(s[1]);
|
||||
}
|
||||
|
||||
static void LoadFlashFromSRecords(char *file, int addr)
|
||||
{
|
||||
ExpectedAddr = addr;
|
||||
|
||||
FILE *f = fopen(file, "r");
|
||||
if(!f) {
|
||||
printf("couldn't open file\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
char line[512];
|
||||
while(fgets(line, sizeof(line), f)) {
|
||||
if(memcmp(line, "S3", 2)==0) {
|
||||
char *s = line + 2;
|
||||
int len = HexByte(s) - 5;
|
||||
s += 2;
|
||||
|
||||
char addrStr[9];
|
||||
memcpy(addrStr, s, 8);
|
||||
addrStr[8] = '\0';
|
||||
DWORD addr;
|
||||
sscanf(addrStr, "%x", &addr);
|
||||
s += 8;
|
||||
|
||||
int i;
|
||||
for(i = 0; i < len; i++) {
|
||||
while((addr+i) > ExpectedAddr) {
|
||||
GotByte(ExpectedAddr, 0xff);
|
||||
}
|
||||
GotByte(addr+i, HexByte(s));
|
||||
s += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!AllWritten) FlushPrevious();
|
||||
|
||||
fclose(f);
|
||||
printf("\ndone.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if(argc < 2) {
|
||||
printf("Usage: %s bootrom file.s19\n", argv[0]);
|
||||
printf(" %s load osimage.s19\n", argv[0]);
|
||||
printf(" %s fpga fpgaimg.s19\n", argv[0]);
|
||||
printf(" %s gui\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
if(UsbConnect()) {
|
||||
break;
|
||||
}
|
||||
if(i == 0) {
|
||||
printf("...no device connected, polling for it now\n");
|
||||
}
|
||||
if(i > 50000) {
|
||||
printf("Could not connect to USB device; exiting.\n");
|
||||
return -1;
|
||||
}
|
||||
i++;
|
||||
Sleep(5);
|
||||
}
|
||||
|
||||
if(strcmp(argv[1], "bootrom")==0 || strcmp(argv[1], "load")==0 || strcmp(argv[1], "fpga")==0) {
|
||||
if(argc != 3) {
|
||||
printf("Need filename.\n");
|
||||
return -1;
|
||||
}
|
||||
if(strcmp(argv[1], "bootrom")==0) {
|
||||
LoadFlashFromSRecords(argv[2], 0);
|
||||
} else if(strcmp(argv[1], "fpga")==0) {
|
||||
LoadFlashFromSRecords(argv[2], 0x2000);
|
||||
} else {
|
||||
LoadFlashFromSRecords(argv[2], 0x10000);
|
||||
}
|
||||
} else if(strcmp(argv[1], "gui")==0) {
|
||||
ShowGui();
|
||||
} else if(strcmp(argv[1], "cmd")==0) {
|
||||
if(argc != 3) {
|
||||
printf("Need command.\n");
|
||||
return -1;
|
||||
}
|
||||
ExecCmd(argv[2]);
|
||||
} else {
|
||||
printf("Command '%s' not recognized.\n", argv[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
32
winsrc/prox.h
Normal file
32
winsrc/prox.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef __PROX_H
|
||||
#define __PROX_H
|
||||
|
||||
#include "../include/usb_cmd.h"
|
||||
|
||||
// prox.cpp
|
||||
void ReceiveCommand(UsbCommand *c);
|
||||
BOOL ReceiveCommandPoll(UsbCommand *c);
|
||||
void SendCommand(UsbCommand *c, BOOL wantAck);
|
||||
|
||||
// gui.cpp
|
||||
void ShowGui(void);
|
||||
void HideGraphWindow(void);
|
||||
void ShowGraphWindow(void);
|
||||
void RepaintGraphWindow(void);
|
||||
void PrintToScrollback(char *fmt, ...);
|
||||
#define MAX_GRAPH_TRACE_LEN (1024*128)
|
||||
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
extern int GraphTraceLen;
|
||||
extern double CursorScaleFactor;
|
||||
extern int CommandFinished;
|
||||
|
||||
// command.cpp
|
||||
void CommandReceived(char *cmd);
|
||||
void UsbCommandReceived(UsbCommand *c);
|
||||
|
||||
// cmdline.cpp
|
||||
void ShowCommandline(void);
|
||||
void ExecCmd(char *cmd);
|
||||
//void PrintToScrollback(char *fmt, ...);
|
||||
|
||||
#endif
|
BIN
winsrc/vc90.pdb
Normal file
BIN
winsrc/vc90.pdb
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue