aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Foster <nick@nerdnetworks.org>2010-09-15 14:58:44 -0700
committerNick Foster <nick@nerdnetworks.org>2010-09-15 14:58:44 -0700
commited245848df8cc011ae8fe30833ecc28049139db5 (patch)
treeda03d37de541826df734e8ab87e0b6114595afc8
parent44ac4461407aae3e26b218a1ab1bd27f893c5e96 (diff)
parent72646d1960b0c979afec225e741d7d89a827c7d0 (diff)
downloaduhd-ed245848df8cc011ae8fe30833ecc28049139db5.tar.gz
uhd-ed245848df8cc011ae8fe30833ecc28049139db5.tar.bz2
uhd-ed245848df8cc011ae8fe30833ecc28049139db5.zip
Merge branch 'master' of ettus.sourcerepo.com:ettus/uhdpriv into usrp2p
Conflicts: host/lib/usrp/usrp2/CMakeLists.txt host/lib/usrp/usrp2/mboard_impl.cpp host/lib/usrp/usrp2/usrp2_regs.hpp
-rw-r--r--firmware/fx2/.gitignore30
-rw-r--r--firmware/fx2/AUTHORS0
-rw-r--r--firmware/fx2/COPYING674
-rw-r--r--firmware/fx2/ChangeLog0
-rw-r--r--firmware/fx2/Makefile.am22
-rw-r--r--firmware/fx2/Makefile.common122
-rw-r--r--firmware/fx2/NEWS0
-rw-r--r--firmware/fx2/README0
-rwxr-xr-xfirmware/fx2/bootstrap30
-rw-r--r--firmware/fx2/config/.gitignore15
-rw-r--r--firmware/fx2/config/Makefile.am49
-rw-r--r--firmware/fx2/config/gr_git.m458
-rw-r--r--firmware/fx2/config/gr_lib64.m485
-rw-r--r--firmware/fx2/config/gr_no_undefined.m444
-rw-r--r--firmware/fx2/config/gr_pwin32.m4149
-rw-r--r--firmware/fx2/config/gr_python.m4172
-rw-r--r--firmware/fx2/config/gr_scripting.m426
-rw-r--r--firmware/fx2/config/gr_standalone.m4116
-rw-r--r--firmware/fx2/config/grc_build.m4287
-rw-r--r--firmware/fx2/config/grc_fx2.m458
-rw-r--r--firmware/fx2/config/lf_cc.m441
-rw-r--r--firmware/fx2/config/lf_cxx.m467
-rw-r--r--firmware/fx2/config/lf_warnings.m4121
-rw-r--r--firmware/fx2/config/mkstemp.m489
-rw-r--r--firmware/fx2/config/onceonly.m463
-rw-r--r--firmware/fx2/config/pkg.m4201
-rw-r--r--firmware/fx2/config/usrp_sdcc.m475
-rw-r--r--firmware/fx2/configure.ac335
-rw-r--r--firmware/fx2/include/.gitignore25
-rw-r--r--firmware/fx2/include/Makefile.am61
-rw-r--r--firmware/fx2/include/delay.h38
-rw-r--r--firmware/fx2/include/fpga_regs0.h42
-rw-r--r--firmware/fx2/include/fpga_regs_common.h150
-rw-r--r--firmware/fx2/include/fpga_regs_common.v117
-rw-r--r--firmware/fx2/include/fpga_regs_standard.h300
-rw-r--r--firmware/fx2/include/fpga_regs_standard.v256
-rw-r--r--firmware/fx2/include/fx2regs.h716
-rw-r--r--firmware/fx2/include/fx2utils.h31
-rwxr-xr-xfirmware/fx2/include/generate_regs.py57
-rw-r--r--firmware/fx2/include/i2c.h32
-rw-r--r--firmware/fx2/include/isr.h172
-rw-r--r--firmware/fx2/include/syncdelay.h65
-rw-r--r--firmware/fx2/include/timer.h35
-rw-r--r--firmware/fx2/include/usb_common.h37
-rw-r--r--firmware/fx2/include/usb_descriptors.h40
-rw-r--r--firmware/fx2/include/usb_requests.h88
-rw-r--r--firmware/fx2/include/usrp_commands.h106
-rw-r--r--firmware/fx2/include/usrp_config.h44
-rw-r--r--firmware/fx2/include/usrp_i2c_addr.h78
-rw-r--r--firmware/fx2/include/usrp_ids.h68
-rw-r--r--firmware/fx2/include/usrp_interfaces.h47
-rw-r--r--firmware/fx2/include/usrp_spi_defs.h86
-rw-r--r--firmware/fx2/lib/.gitignore18
-rw-r--r--firmware/fx2/lib/Makefile.am79
-rw-r--r--firmware/fx2/lib/delay.c76
-rw-r--r--firmware/fx2/lib/fx2utils.c54
-rw-r--r--firmware/fx2/lib/i2c-compiler-bug.c129
-rw-r--r--firmware/fx2/lib/i2c.c123
-rw-r--r--firmware/fx2/lib/isr.c167
-rw-r--r--firmware/fx2/lib/timer.c49
-rw-r--r--firmware/fx2/lib/usb_common.c386
-rw-r--r--firmware/fx2/src/.gitignore17
-rw-r--r--firmware/fx2/src/Makefile.am22
-rw-r--r--firmware/fx2/src/common/.gitignore17
-rw-r--r--firmware/fx2/src/common/Makefile.am50
-rw-r--r--firmware/fx2/src/common/_startup.a5180
-rw-r--r--firmware/fx2/src/common/_startup.a51.brittle78
-rw-r--r--firmware/fx2/src/common/blink_leds.c36
-rwxr-xr-xfirmware/fx2/src/common/build_eeprom.py107
-rw-r--r--firmware/fx2/src/common/check_mdelay.c37
-rw-r--r--firmware/fx2/src/common/check_udelay.c37
-rwxr-xr-xfirmware/fx2/src/common/edit-gpif114
-rw-r--r--firmware/fx2/src/common/fpga.h31
-rw-r--r--firmware/fx2/src/common/fpga_load.c193
-rw-r--r--firmware/fx2/src/common/fpga_load.h28
-rwxr-xr-xfirmware/fx2/src/common/gpif.c292
-rwxr-xr-xfirmware/fx2/src/common/gpif.gpfbin0 -> 5281 bytes
-rw-r--r--firmware/fx2/src/common/init_gpif.c59
-rw-r--r--firmware/fx2/src/common/usrp_common.c109
-rw-r--r--firmware/fx2/src/common/usrp_globals.h32
-rw-r--r--firmware/fx2/src/common/vectors.a51180
-rw-r--r--firmware/fx2/src/usrp1/.gitignore20
-rw-r--r--firmware/fx2/src/usrp1/Makefile.am141
-rw-r--r--firmware/fx2/src/usrp1/_startup.a511
-rw-r--r--firmware/fx2/src/usrp1/blink_leds.c1
-rw-r--r--firmware/fx2/src/usrp1/board_specific.c113
-rw-r--r--firmware/fx2/src/usrp1/check_mdelay.c1
-rw-r--r--firmware/fx2/src/usrp1/check_udelay.c1
-rwxr-xr-xfirmware/fx2/src/usrp1/edit-gpif114
-rw-r--r--firmware/fx2/src/usrp1/eeprom_boot.a51573
-rw-r--r--firmware/fx2/src/usrp1/eeprom_init.c116
-rw-r--r--firmware/fx2/src/usrp1/eeprom_io.c65
-rw-r--r--firmware/fx2/src/usrp1/eeprom_io.h38
-rw-r--r--firmware/fx2/src/usrp1/fpga_load.c1
-rw-r--r--firmware/fx2/src/usrp1/fpga_rev2.c122
-rw-r--r--firmware/fx2/src/usrp1/fpga_rev2.h58
-rw-r--r--firmware/fx2/src/usrp1/gpif.c292
-rwxr-xr-xfirmware/fx2/src/usrp1/gpif.gpfbin0 -> 5341 bytes
-rw-r--r--firmware/fx2/src/usrp1/init_gpif.c1
-rw-r--r--firmware/fx2/src/usrp1/spi.c472
-rw-r--r--firmware/fx2/src/usrp1/spi.h50
-rw-r--r--firmware/fx2/src/usrp1/usb_descriptors.a51404
-rw-r--r--firmware/fx2/src/usrp1/usrp_common.c1
-rw-r--r--firmware/fx2/src/usrp1/usrp_common.h77
-rw-r--r--firmware/fx2/src/usrp1/usrp_main.c388
-rw-r--r--firmware/fx2/src/usrp1/usrp_rev2_regs.h163
-rw-r--r--firmware/fx2/src/usrp1/vectors.a511
-rw-r--r--fpga/usrp2/sdr_lib/dsp_core_rx.v35
-rw-r--r--fpga/usrp2/top/u2_rev3/u2_core_udp.v2
-rw-r--r--fpga/usrp2/top/u2_rev3/u2_rev3.v15
-rw-r--r--host/AUTHORS14
-rw-r--r--host/docs/CMakeLists.txt1
-rw-r--r--host/docs/build.rst8
-rw-r--r--host/docs/dboards.rst10
-rw-r--r--host/docs/index.rst1
-rw-r--r--host/docs/usrp1.rst115
-rw-r--r--host/docs/usrp2.rst24
-rw-r--r--host/examples/CMakeLists.txt10
-rw-r--r--host/examples/test_async_messages.cpp208
-rw-r--r--host/examples/test_pps_input.cpp86
-rw-r--r--host/examples/tx_waveforms.cpp19
-rw-r--r--host/include/uhd/transport/CMakeLists.txt4
-rw-r--r--host/include/uhd/transport/convert_types.hpp37
-rw-r--r--host/include/uhd/transport/convert_types.ipp43
-rw-r--r--host/include/uhd/transport/usb_control.hpp65
-rw-r--r--host/include/uhd/transport/usb_device_handle.hpp79
-rw-r--r--host/include/uhd/transport/usb_zero_copy.hpp62
-rw-r--r--host/include/uhd/usrp/subdev_spec.hpp9
-rw-r--r--host/lib/transport/CMakeLists.txt24
-rw-r--r--host/lib/transport/FindUSB1.cmake38
-rw-r--r--host/lib/transport/convert_types_impl.hpp122
-rwxr-xr-xhost/lib/transport/gen_convert_types.py107
-rw-r--r--host/lib/transport/libusb1_base.cpp126
-rw-r--r--host/lib/transport/libusb1_base.hpp94
-rw-r--r--host/lib/transport/libusb1_control.cpp95
-rw-r--r--host/lib/transport/libusb1_device_handle.cpp117
-rw-r--r--host/lib/transport/libusb1_zero_copy.cpp767
-rw-r--r--host/lib/usrp/CMakeLists.txt1
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp32
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp7
-rw-r--r--host/lib/usrp/dsp_utils.cpp30
-rw-r--r--host/lib/usrp/misc_utils.cpp13
-rw-r--r--host/lib/usrp/usrp1/CMakeLists.txt65
-rw-r--r--host/lib/usrp/usrp1/clock_ctrl.cpp60
-rw-r--r--host/lib/usrp/usrp1/clock_ctrl.hpp50
-rw-r--r--host/lib/usrp/usrp1/codec_ctrl.cpp429
-rw-r--r--host/lib/usrp/usrp1/codec_ctrl.hpp97
-rw-r--r--host/lib/usrp/usrp1/codec_impl.cpp157
-rw-r--r--host/lib/usrp/usrp1/dboard_iface.cpp371
-rw-r--r--host/lib/usrp/usrp1/dboard_impl.cpp217
-rw-r--r--host/lib/usrp/usrp1/dsp_impl.cpp205
-rw-r--r--host/lib/usrp/usrp1/io_impl.cpp326
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp382
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.cpp446
-rw-r--r--host/lib/usrp/usrp1/usrp1_ctrl.hpp163
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.cpp261
-rw-r--r--host/lib/usrp/usrp1/usrp1_iface.hpp100
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp236
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.hpp197
-rw-r--r--host/lib/usrp/usrp2/CMakeLists.txt65
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.cpp4
-rw-r--r--host/lib/usrp/usrp2/fw_common.h2
-rw-r--r--host/lib/usrp/usrp2/io_impl.cpp4
-rw-r--r--host/lib/usrp/usrp2/mboard_impl.cpp11
-rw-r--r--host/lib/usrp/usrp2/usrp2_regs.hpp1
-rw-r--r--host/test/convert_types_test.cpp219
-rw-r--r--host/utils/CMakeLists.txt8
-rw-r--r--host/utils/usrp1_init_eeprom.cpp69
-rw-r--r--host/utils/usrp1_serial_burner.cpp75
-rw-r--r--host/utils/usrp_burn_db_eeprom.cpp15
-rw-r--r--images/Makefile55
-rw-r--r--images/README5
172 files changed, 17955 insertions, 194 deletions
diff --git a/firmware/fx2/.gitignore b/firmware/fx2/.gitignore
new file mode 100644
index 000000000..affc0b779
--- /dev/null
+++ b/firmware/fx2/.gitignore
@@ -0,0 +1,30 @@
+/Makefile
+/Makefile.in
+/aclocal.m4
+/configure
+/config.h.in
+/stamp-h.in
+/libtool
+/config.log
+/config.h
+/config.cache
+/config.status
+/missing
+/stamp-h
+/stamp-h1
+/.la
+/.lo
+/.deps
+/.libs
+/*.la
+/*.lo
+/autom4te.cache
+/*.cache
+/missing
+/make.log
+/usrp.pc
+/INSTALL
+/config.guess
+/config.sub
+/install-sh
+/ltmain.sh
diff --git a/firmware/fx2/AUTHORS b/firmware/fx2/AUTHORS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/firmware/fx2/AUTHORS
diff --git a/firmware/fx2/COPYING b/firmware/fx2/COPYING
new file mode 100644
index 000000000..94a9ed024
--- /dev/null
+++ b/firmware/fx2/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/firmware/fx2/ChangeLog b/firmware/fx2/ChangeLog
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/firmware/fx2/ChangeLog
diff --git a/firmware/fx2/Makefile.am b/firmware/fx2/Makefile.am
new file mode 100644
index 000000000..9c0da3573
--- /dev/null
+++ b/firmware/fx2/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+SUBDIRS = include lib src
diff --git a/firmware/fx2/Makefile.common b/firmware/fx2/Makefile.common
new file mode 100644
index 000000000..fb83b9470
--- /dev/null
+++ b/firmware/fx2/Makefile.common
@@ -0,0 +1,122 @@
+# -*- Makefile -*-
+#
+# Copyright 2004,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+AM_CFLAGS = @autoconf_default_CFLAGS@ @lf_CFLAGS@
+AM_CXXFLAGS = @autoconf_default_CXXFLAGS@ @lf_CXXFLAGS@
+
+# Sets ABI version in SONAME and appends -LIBVER to filename
+LTVERSIONFLAGS = -version-info 0:0:0 -release $(LIBVER)
+
+# includes
+grincludedir = $(includedir)/gnuradio
+
+if PYTHON
+# swig includes
+swigincludedir = $(grincludedir)/swig
+
+# Install the gnuradio stuff in the appropriate subdirectory
+# This usually ends up at:
+# ${prefix}/lib/python${python_version}/site-packages/gnuradio
+
+grpythondir = $(pythondir)/gnuradio
+grpyexecdir = $(pyexecdir)/gnuradio
+
+# Install the non-gnuradio usrp stuff in the appropriate subdirectory
+# This usually ends up at:
+# ${prefix}/lib/python${python_version}/site-packages/usrpm
+
+usrppythondir = $(pythondir)/usrpm
+usrppyexecdir = $(pyexecdir)/usrpm
+endif
+
+# gcell includes
+gcellincludedir = $(includedir)/gcell
+gcellspuincludedir = $(includedir)/gcell/spu
+
+# Cell spu libs
+libspudir = $(libdir)spu
+
+# This used to be set in configure.ac but is now defined here for all
+# Makefiles when this fragment is included.
+STD_DEFINES_AND_INCLUDES = $(DEFINES) $(BOOST_CPPFLAGS) \
+ $(GNURADIO_INCLUDES) $(GRUEL_INCLUDES)
+
+# when including for compilation from pre-installed libraries and such,
+# need to make sure those are put last on the compile command
+WITH_INCLUDES = @with_INCLUDES@
+WITH_SWIG_INCLUDES = @with_SWIG_INCLUDES@
+
+# Where to find gnuradio include files in the current build tree
+# top_srcdir for original stuff, top_builddir for generated files
+GNURADIO_INCLUDES = @gnuradio_core_INCLUDES@
+
+# How to link in GNU Radio core library from inside the tree
+GNURADIO_CORE_LA = @gnuradio_core_LA@
+
+# How to link in the USRP library from inside the tree
+GRUEL_INCLUDES = @gruel_INCLUDES@
+GRUEL_LA = @gruel_LA@
+
+# How to link in the USRP library from inside the tree
+USRP_INCLUDES = @usrp_INCLUDES@
+USRP_LA = @usrp_LA@
+
+# How to link the gcell library from inside the tree (the PPU part)
+GCELL_INCLUDES = @gcell_INCLUDES@
+GCELL_LA = @gcell_LA@
+
+# How to link the gcell library from inside the tree (the SPU part)
+GCELL_SPU_INCLUDES = @gcell_spu_INCLUDES@
+GCELL_SPU_LA = @gcell_spu_LA@
+
+# libtool aware wrapper for ppu-embedspu
+GCELL_EMBEDSPU_LIBTOOL = @abs_top_srcdir@/gcell/lib/runtime/gcell-embedspu-libtool
+
+# Fix for BSD make not defining $(RM). We define it now in configure.ac
+# using AM_PATH_PROG, but now here have to add a -f to be like GNU make
+RM=$(RM_PROG) -f
+
+RUN_GUILE = GUILE_LOAD_PATH="@abs_top_srcdir@/gruel/src/scheme" @GUILE@ -e main -s
+
+# Base directory for example applications
+exampledir = $(datadir)/gnuradio/examples
+
+# Base directory for documentation (docdir undefined in autoconf < 1.60)
+docdir ?= $(datadir)/doc/$(PACKAGE)
+gr_docdir = $(docdir)-$(DOCVER)
+
+# System configuration files
+gr_prefsdir = $(GR_PREFSDIR)
+
+# Data directory for grc block wrappers
+grc_blocksdir = $(pkgdatadir)/grc/blocks
+
+# Other common defines; use "+=" to add to these
+STAMPS =
+MOSTLYCLEANFILES = $(BUILT_SOURCES) $(STAMPS) *.pyc *.pyo *~ *.tmp *.loT
+
+# Don't distribute the files defined in the variable 'no_dist_files'
+dist-hook:
+ @for file in $(no_dist_files); do \
+ echo $(RM) $(distdir)/$$file; \
+ $(RM) $(distdir)/$$file; \
+ done;
diff --git a/firmware/fx2/NEWS b/firmware/fx2/NEWS
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/firmware/fx2/NEWS
diff --git a/firmware/fx2/README b/firmware/fx2/README
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/firmware/fx2/README
diff --git a/firmware/fx2/bootstrap b/firmware/fx2/bootstrap
new file mode 100755
index 000000000..7daff90d1
--- /dev/null
+++ b/firmware/fx2/bootstrap
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# Copyright 2001,2005,2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+
+rm -fr config.cache autom4te*.cache
+
+aclocal -I config
+autoconf
+autoheader
+libtoolize --automake
+automake --add-missing -Wno-portability -Wno-override -Wnone
+#automake --add-missing -Wno-portability
diff --git a/firmware/fx2/config/.gitignore b/firmware/fx2/config/.gitignore
new file mode 100644
index 000000000..16f775e32
--- /dev/null
+++ b/firmware/fx2/config/.gitignore
@@ -0,0 +1,15 @@
+/*.cache
+/*.la
+/*.lo
+/*.pc
+/.deps
+/.la
+/.libs
+/.lo
+/Makefile
+/Makefile.in
+/libtool.m4
+/lt~obsolete.m4
+/ltsugar.m4
+/ltversion.m4
+/ltoptions.m4
diff --git a/firmware/fx2/config/Makefile.am b/firmware/fx2/config/Makefile.am
new file mode 100644
index 000000000..487ceed1b
--- /dev/null
+++ b/firmware/fx2/config/Makefile.am
@@ -0,0 +1,49 @@
+#
+# Copyright 2001,2006,2008,2009,2010 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+# Install m4 macros in this directory
+m4datadir = $(datadir)/aclocal
+
+# List your m4 macros here
+m4macros = \
+ grc_build.m4 \
+ grc_fx2.m4 \
+ gr_git.m4 \
+ gr_lib64.m4 \
+ gr_no_undefined.m4 \
+ gr_pwin32.m4 \
+ gr_python.m4 \
+ gr_require_mc4020.m4 \
+ gr_scripting.m4 \
+ gr_set_md_cpu.m4 \
+ gr_standalone.m4 \
+ lf_cc.m4 \
+ lf_cxx.m4 \
+ lf_warnings.m4 \
+ lf_x11.m4 \
+ mkstemp.m4 \
+ onceonly.m4 \
+ pkg.m4 \
+ usrp_sdcc.m4
+
+EXTRA_DIST = $(m4macros)
diff --git a/firmware/fx2/config/gr_git.m4 b/firmware/fx2/config/gr_git.m4
new file mode 100644
index 000000000..5e8aa663b
--- /dev/null
+++ b/firmware/fx2/config/gr_git.m4
@@ -0,0 +1,58 @@
+dnl Copyright 2009,2010 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+
+AC_DEFUN([GR_GIT],[
+ dnl Identify git binary
+ AC_PATH_PROG([GIT],[git])
+
+ dnl If it exists, get either 'git describe' or fallback to current commit
+ if test x$GIT != x ; then
+ AC_MSG_CHECKING([existence of git version control directory])
+ if test -d $srcdir/.git ; then
+ AC_MSG_RESULT([ok])
+ AC_MSG_CHECKING([git description of current commit])
+ if (cd $srcdir && $GIT describe >/dev/null 2>&1); then
+ GIT_DESCRIBE=`cd $srcdir && $GIT describe --abbrev=8 --long`
+ GIT_TAG=`echo $GIT_DESCRIBE | cut -f 1 -d '-'`
+ GIT_SEQNO=`echo $GIT_DESCRIBE | cut -f 2 -d '-'`
+ GIT_COMMIT=`echo $GIT_DESCRIBE | cut -f 3 -d '-' | cut -f 2- -d 'g'`
+ # Release candidate tags create an extra -rcX field
+ if test x`echo $GIT_DESCRIBE | cut -f 1- -d '-' --output-delimiter=' ' | wc -w` = x4; then
+ GIT_TAG=`echo $GIT_DESCRIBE | cut -f -2 -d '-'`
+ GIT_SEQNO=`echo $GIT_DESCRIBE | cut -f 3 -d '-'`
+ GIT_COMMIT=`echo $GIT_DESCRIBE | cut -f 4 -d '-' | cut -f 2- -d 'g'`
+ fi
+ AC_MSG_RESULT([$GIT_DESCRIBE])
+ else
+ AC_MSG_RESULT([unable to find, using current commit])
+ GIT_TAG=''
+ GIT_SEQNO=''
+ GIT_COMMIT=`cd $srcdir && $GIT describe --always --abbrev=8`
+ fi
+ else
+ AC_MSG_RESULT([not found])
+ fi
+
+ AC_SUBST([GIT_DESCRIBE])
+ AC_SUBST([GIT_TAG])
+ AC_SUBST([GIT_SEQNO])
+ AC_SUBST([GIT_COMMIT])
+ fi
+])
diff --git a/firmware/fx2/config/gr_lib64.m4 b/firmware/fx2/config/gr_lib64.m4
new file mode 100644
index 000000000..751f774b4
--- /dev/null
+++ b/firmware/fx2/config/gr_lib64.m4
@@ -0,0 +1,85 @@
+dnl
+dnl Copyright 2005,2008 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+dnl GR_LIB64()
+dnl
+dnl Checks to see if we're on a x86_64 or powerpc64 machine, and if so, determine
+dnl if libdir should end in "64" or not.
+dnl
+dnl Sets gr_libdir_suffix to "" or "64" and calls AC_SUBST(gr_libdir_suffix)
+dnl May append "64" to libdir.
+dnl
+dnl The current heuristic is:
+dnl if the host_cpu isn't x86_64 or powerpc64, then ""
+dnl if the host_os isn't linux, then ""
+dnl if we're cross-compiling, ask the linker, by way of the selected compiler
+dnl if we're x86_64 and there's a /lib64 and it's not a symlink, then "64", else ""
+dnl else ask the compiler
+dnl
+AC_DEFUN([GR_LIB64],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([AC_PROG_CXX])
+
+ AC_MSG_CHECKING([gr_libdir_suffix])
+ gr_libdir_suffix=""
+ AC_SUBST(gr_libdir_suffix)
+
+ case "$host_os" in
+ linux*) is_linux=yes ;;
+ *) is_linux=no ;;
+ esac
+
+ if test "$is_linux" = no || test "$host_cpu" != "x86_64" && test "$host_cpu" != "powerpc64"; then
+ gr_libdir_suffix=""
+ elif test "$cross_compiling" = yes; then
+ _GR_LIB64_ASK_COMPILER
+ elif test "$host_cpu" = "x86_64"; then
+ if test -d /lib64 && test ! -L /lib64; then
+ gr_libdir_suffix=64
+ fi
+ else
+ _GR_LIB64_ASK_COMPILER
+ fi
+ AC_MSG_RESULT([$gr_libdir_suffix])
+
+
+ AC_MSG_CHECKING([whether to append 64 to libdir])
+ t=${libdir##*/lib}
+ if test "$t" != 64 && test "$gr_libdir_suffix" = "64"; then
+ libdir=${libdir}64
+ AC_MSG_RESULT([yes. Setting libdir to $libdir])
+ else
+ AC_MSG_RESULT([no])
+ fi
+])
+
+dnl If we're using g++, extract the first SEARCH_DIR("...") entry from the linker script
+dnl and see if it contains a suffix after the final .../lib part of the path.
+dnl (This works because the linker script varies depending on whether we're generating
+dnl 32-bit or 64-bit executables)
+dnl
+AC_DEFUN([_GR_LIB64_ASK_COMPILER],[
+ if test "$ac_cv_cxx_compiler_gnu" = "yes";
+ then
+ gr_libdir_suffix=`$CXX -Wl,--verbose 2>/dev/null | sed -n -e '/SEARCH_DIR/{s/;.*$//; s,^.*/,,; s/".*$//; s/^lib//; p}'`
+ fi
+])
+
diff --git a/firmware/fx2/config/gr_no_undefined.m4 b/firmware/fx2/config/gr_no_undefined.m4
new file mode 100644
index 000000000..c8d745d5f
--- /dev/null
+++ b/firmware/fx2/config/gr_no_undefined.m4
@@ -0,0 +1,44 @@
+dnl
+dnl Copyright 2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+# GR_NO_UNDEFINED()
+#
+# Detemine whether we need to use the -no-undefined linker flag
+# when building shared libraries.
+# Sets NO_UNDEFINED to "" or "-no-undefined"
+#
+# As far as I can tell, we need -no-undefined only when building
+# windows DLLs. This occurs when using MinGW and Cygwin.
+#
+# For now, we stub this out.
+
+AC_DEFUN([GR_NO_UNDEFINED],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ no_undefined=""
+ case "${host_os}" in
+ *mingw* | *cygwin*)
+
+ # on MinGW/Cygwin extra LDFLAGS are required
+ no_undefined="-no-undefined"
+ ;;
+ esac
+ AC_SUBST(NO_UNDEFINED,[$no_undefined])
+])
diff --git a/firmware/fx2/config/gr_pwin32.m4 b/firmware/fx2/config/gr_pwin32.m4
new file mode 100644
index 000000000..495e9dd4d
--- /dev/null
+++ b/firmware/fx2/config/gr_pwin32.m4
@@ -0,0 +1,149 @@
+# Check for (mingw)win32 POSIX replacements. -*- Autoconf -*-
+
+# Copyright 2003,2004,2005 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+
+AC_DEFUN([GR_PWIN32],
+[
+AC_REQUIRE([AC_HEADER_TIME])
+AC_CHECK_HEADERS([sys/types.h fcntl.h io.h])
+AC_CHECK_HEADERS([windows.h])
+AC_CHECK_HEADERS([winioctl.h winbase.h], [], [], [
+ #if HAVE_WINDOWS_H
+ #include <windows.h>
+ #endif
+])
+
+AC_CHECK_FUNCS([getopt usleep gettimeofday nanosleep rand srand random srandom sleep sigaction])
+AC_CHECK_TYPES([struct timezone, struct timespec, ssize_t],[],[],[
+ #if HAVE_SYS_TYPES_H
+ # include <sys/types.h>
+ #endif
+ #if TIME_WITH_SYS_TIME
+ # include <sys/time.h>
+ # include <time.h>
+ #else
+ # if HAVE_SYS_TIME_H
+ # include <sys/time.h>
+ # else
+ # include <time.h>
+ # endif
+ #endif
+])
+
+dnl Checks for replacements
+AC_REPLACE_FUNCS([getopt usleep gettimeofday])
+
+
+AC_MSG_CHECKING(for Sleep)
+AC_TRY_LINK([ #include <windows.h>
+ #include <winbase.h>
+ ], [ Sleep(0); ],
+ [AC_DEFINE(HAVE_SSLEEP,1,[Define to 1 if you have win32 Sleep])
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no)
+ )
+
+dnl Under Win32, mkdir prototype in io.h has only one arg
+AC_MSG_CHECKING(whether mkdir accepts only one arg)
+AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>], [
+ mkdir("")
+ ], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ],
+ [ AC_MSG_RESULT(no)
+ ])
+
+AH_BOTTOM(
+[
+/* Define missing prototypes, implemented in replacement lib */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HAVE_GETOPT
+int getopt (int argc, char * const argv[], const char * optstring);
+extern char * optarg;
+extern int optind, opterr, optopt;
+#endif
+
+#ifndef HAVE_USLEEP
+int usleep(unsigned long usec); /* SUSv2 */
+#endif
+
+#ifndef HAVE_NANOSLEEP
+#ifndef HAVE_STRUCT_TIMESPEC
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h> /* need time_t */
+#endif
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+static inline int nanosleep(const struct timespec *req, struct timespec *rem) { return usleep(req->tv_sec*1000000+req->tv_nsec/1000); }
+#endif
+
+#if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP)
+#ifdef HAVE_WINBASE_H
+#include <windows.h>
+#include <winbase.h>
+#endif
+/* TODO: what about SleepEx? */
+static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; }
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifndef HAVE_STRUCT_TIMEZONE
+struct timezone {
+ int tz_minuteswest;
+ int tz_dsttime;
+};
+#endif
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+#endif
+
+#if !defined(HAVE_RANDOM) && defined(HAVE_RAND)
+#include <stdlib.h>
+static inline long int random (void) { return rand(); }
+#endif
+
+#if !defined(HAVE_SRANDOM) && defined(HAVE_SRAND)
+static inline void srandom (unsigned int seed) { srand(seed); }
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef size_t ssize_t;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+])
+
+
+])
diff --git a/firmware/fx2/config/gr_python.m4 b/firmware/fx2/config/gr_python.m4
new file mode 100644
index 000000000..43ccfc015
--- /dev/null
+++ b/firmware/fx2/config/gr_python.m4
@@ -0,0 +1,172 @@
+dnl
+dnl Copyright 2003,2004,2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+# PYTHON_DEVEL()
+#
+# Checks for Python and tries to get the include path to 'Python.h'.
+# It sets the $(PYTHON_CPPFLAGS), $(PYTHON_LDFLAGS) and $(pythondir) output variables,
+#
+AC_DEFUN([PYTHON_DEVEL],[
+ AC_REQUIRE([AM_PATH_PYTHON])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+
+ AC_ARG_WITH(pythondir,
+ AC_HELP_STRING([--with-pythondir=DIR],
+ [python installation directory (cross-compiling) [[default=$prefix/lib/python2.5/site-packages]]]),
+ [with_pythondir=${withval}],[with_pythondir=${prefix}/lib/python2.5/site-packages])
+
+ # if we're cross-compiling, asking the host python about any of
+ # this is completely useless...
+
+ if test x$cross_compiling != xno
+ then
+ pythondir=$with_pythondir
+ pyexecdir=$with_pythondir
+ AC_SUBST(PYTHON_CPPFLAGS)
+ AC_SUBST(PYTHON_LDFLAGS)
+ else
+
+ # For Fedora Core 5 and 6, see ticket:39 in Trac
+ if test -f '/etc/redhat-release'; then
+ if (echo $pyexecdir | grep -q lib64); then
+ pythondir="$pyexecdir"
+ fi
+ fi
+
+ # Check for Python include path
+ AC_MSG_CHECKING([for Python include path])
+ if test -z "$PYTHON" ; then
+ AC_MSG_ERROR([cannot find Python path])
+ fi
+
+ # ask distutils which include path we should use
+ python_cmd='
+import distutils.sysconfig
+import os
+path = distutils.sysconfig.get_python_inc(plat_specific=False)
+if os.sep == "\\":
+ path = path.replace("\\", "/")
+print path
+'
+ python_path=`$PYTHON -c "$python_cmd"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python include path])
+ fi
+
+ AC_SUBST(PYTHON_CPPFLAGS,[-I$python_path])
+
+ # Check for Python headers usability
+ python_save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
+ AC_CHECK_HEADERS([Python.h], [],
+ [AC_MSG_ERROR([cannot find usable Python headers])])
+ CPPFLAGS="$python_save_CPPFLAGS"
+
+ # Only set this on mingw and cygwin hosts, (only implemented
+ # for mingw host, for crosscompiling you need to trick this)
+
+ PYTHON_LDFLAGS=""
+ case $host_os in
+ *mingw* | *cygwin* )
+ AC_MSG_CHECKING([for Python LDFLAGS])
+
+ python_cmd='
+import distutils.sysconfig
+import os
+path = distutils.sysconfig.get_config_var("LIBPL")
+if path == None:
+ path = distutils.sysconfig.PREFIX + "/libs"
+if os.sep == "\\":
+ path = path.replace("\\", "/")
+print path
+'
+ python_stdlib_path=`$PYTHON -c "$python_cmd"`
+
+ python_version_nodot=`echo $PYTHON_VERSION | sed "s,\.,,"`
+ libpython_name="python$PYTHON_VERSION"
+
+ # Standard install of python for win32 has libpython24.a
+ # instead of libpython2.4.a so we check for the library
+ # without the dot in the version number.
+
+ python_stdlib_filename=`find $python_stdlib_path -type f -name libpython$python_version_nodot.* -print | sed "1q"`
+ if test -n "$python_stdlib_filename" ; then
+ libpython_name="python$python_version_nodot"
+ fi
+
+ PYTHON_LDFLAGS="-L$python_stdlib_path -l$libpython_name"
+ AC_MSG_RESULT($PYTHON_LDFLAGS)
+ # Replace all backslashes in PYTHON Paths with forward slashes
+ pythondir=`echo $pythondir |sed 's,\\\\,/,g'`
+ pkgpythondir=`echo $pkgpythondir |sed 's,\\\\,/,g'`
+ pyexecdir=`echo $pyexecdir |sed 's,\\\\,/,g'`
+ pkgpyexecdir=`echo $pkgpyexecdir |sed 's,\\\\,/,g'`
+ ;;
+ esac
+
+ case $host_os in
+ *mingw* )
+ # Python 2.5 requires ".pyd" instead of ".dll" for extensions
+ PYTHON_LDFLAGS="-shrext .pyd ${PYTHON_LDFLAGS}"
+ esac
+
+ AC_SUBST(PYTHON_LDFLAGS)
+ fi
+])
+
+# PYTHON_CHECK_MODULE
+#
+# Determines if a particular Python module can be imported
+#
+# $1 - module name
+# $2 - module description
+# $3 - action if found
+# $4 - action if not found
+# $5 - test command
+
+AC_DEFUN([PYTHON_CHECK_MODULE],[
+ AC_MSG_CHECKING([for $2])
+ dnl ########################################
+ dnl # import and test checking
+ dnl ########################################
+ if test "$5"; then
+ python_cmd='
+try:
+ import $1
+ assert $5
+except: exit(1)'
+ dnl ########################################
+ dnl # import checking only
+ dnl ########################################
+ else
+ python_cmd='
+try: import $1
+except: exit(1)'
+ fi
+ if ! $PYTHON -c "$python_cmd" 2> /dev/null; then
+ AC_MSG_RESULT([no])
+ $4
+ else
+ AC_MSG_RESULT([yes])
+ $3
+ fi
+])
diff --git a/firmware/fx2/config/gr_scripting.m4 b/firmware/fx2/config/gr_scripting.m4
new file mode 100644
index 000000000..2803e975f
--- /dev/null
+++ b/firmware/fx2/config/gr_scripting.m4
@@ -0,0 +1,26 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([GR_SCRIPTING],[
+ AC_REQUIRE([AC_PROG_LN_S])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_LIBTOOL])
+])
diff --git a/firmware/fx2/config/gr_standalone.m4 b/firmware/fx2/config/gr_standalone.m4
new file mode 100644
index 000000000..370f7fb03
--- /dev/null
+++ b/firmware/fx2/config/gr_standalone.m4
@@ -0,0 +1,116 @@
+dnl
+dnl Copyright 2008 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License along
+dnl with this program; if not, write to the Free Software Foundation, Inc.,
+dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+dnl
+
+dnl
+dnl GR_STANDALONE([package],[version])
+dnl
+dnl Handles the bulk of the configure.ac work for an out-of-tree build
+dnl
+dnl N.B., this is an m4_define because if it were an AC_DEFUN it would
+dnl get called too late to be useful.
+
+m4_define([GR_STANDALONE],
+[
+ AC_INIT([$1],[$2])
+ AC_PREREQ(2.57)
+ AC_CONFIG_SRCDIR([config/gr_standalone.m4])
+ AC_CONFIG_AUX_DIR([.])
+ AM_CONFIG_HEADER(config.h)
+
+ AC_CANONICAL_BUILD
+ AC_CANONICAL_HOST
+ AC_CANONICAL_TARGET
+
+ AM_INIT_AUTOMAKE
+
+ LF_CONFIGURE_CC
+ LF_CONFIGURE_CXX
+ GR_LIB64 dnl check for lib64 suffix after choosing compilers
+
+ dnl add ${prefix}/lib${gr_libdir_suffix}/pkgconfig to the head of the PKG_CONFIG_PATH
+ if test x${PKG_CONFIG_PATH} = x; then
+ PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig
+ else
+ PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig:${PKG_CONFIG_PATH}
+ fi
+ export PKG_CONFIG_PATH
+
+ LF_SET_WARNINGS
+ GR_SET_GPROF
+ GR_SET_PROF
+ AM_PROG_AS
+ AC_PROG_LN_S
+ AC_PROG_MAKE_SET
+ AC_PROG_INSTALL
+ AC_PATH_PROG([RM_PROG], [rm])
+
+ AC_LIBTOOL_WIN32_DLL
+ AC_ENABLE_SHARED dnl do build shared libraries
+ AC_DISABLE_STATIC dnl don't build static libraries
+ m4_ifdef([LT_INIT],[LT_INIT],[AC_PROG_LIBTOOL])
+ dnl GR_FORTRAN
+
+ GR_NO_UNDEFINED dnl do we need the -no-undefined linker flag
+ GR_SCRIPTING dnl Locate python, SWIG, etc
+
+ AC_ARG_WITH([python],
+ AC_HELP_STRING([--with-python], [Should we use python? [[default=yes]]]),
+ [case "$with_python" in
+ (no | yes) ;;
+ (*) AC_MSG_ERROR([Invalid argument ($with_python) to --with-python]) ;;
+ esac],
+ [with_python=yes])
+
+ AM_CONDITIONAL([USE_PYTHON], [test "$with_python" = yes])
+
+
+ dnl Set the c++ compiler that we use for the build system when cross compiling
+ if test "x$CXX_FOR_BUILD" = x
+ then
+ CXX_FOR_BUILD=${CXX}
+ fi
+ AC_SUBST(CXX_FOR_BUILD)
+
+ dnl Checks for header files.
+ AC_HEADER_STDC
+
+ dnl Checks for typedefs, structures, and compiler characteristics.
+ AC_C_CONST
+ AC_C_INLINE
+ AC_TYPE_SIZE_T
+ AC_HEADER_TIME
+ AC_C_BIGENDIAN
+
+ dnl Check for Mingw support
+ GR_PWIN32
+
+ AC_CHECK_PROG([XMLTO],[xmlto],[yes],[])
+ AM_CONDITIONAL([HAS_XMLTO], [test x$XMLTO = xyes])
+
+ dnl Define where to look for cppunit includes and libs
+ dnl sets CPPUNIT_CFLAGS and CPPUNIT_LIBS
+ dnl Try using pkg-config first, then fall back to cppunit-config.
+ PKG_CHECK_EXISTS(cppunit,
+ [PKG_CHECK_MODULES(CPPUNIT, cppunit >= 1.9.14)],
+ [AM_PATH_CPPUNIT([1.9.14],[],
+ [AC_MSG_ERROR([GNU Radio requires cppunit. Stop])])])
+
+ PKG_CHECK_MODULES(GNURADIO_CORE, gnuradio-core >= 3)
+])
diff --git a/firmware/fx2/config/grc_build.m4 b/firmware/fx2/config/grc_build.m4
new file mode 100644
index 000000000..77b59db6b
--- /dev/null
+++ b/firmware/fx2/config/grc_build.m4
@@ -0,0 +1,287 @@
+dnl Copyright 2006,2008,2009 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+dnl Create --enable-foo argument for named component, create variables as needed
+dnl $1 is component name
+AC_DEFUN([GRC_ENABLE], [
+ _GRC_ENABLE($1,m4_bpatsubst($1,-,_))
+])
+dnl $2 is the '_'d component name
+dnl on exit variable enable_$2 will be set to [yes|no];
+dnl passed will be [yes|no] (same as enable_$2)
+
+AC_DEFUN([_GRC_ENABLE],[
+ passed=yes
+ AC_ARG_ENABLE([$1],
+ AC_HELP_STRING([--enable-$1],
+ [Stop if $1 fails configuration]),
+ [],[
+ [enable_]$2=$enable_all_components
+ if test x$enable_all_components = xno; then
+ passed=no
+ fi
+ ])
+])
+dnl Component specific configuration
+dnl The order of the GR_ macros determines the order of compilation
+dnl For -any- checks on $enable_all_components
+dnl use the following guildlines:
+dnl yes : --enable-all-components was specified, so error out if any
+dnl components do not pass configuration checks.
+dnl no : --disable-all-components was specified, so try to build the
+dnl --enable'd components, and error out if any do not pass
+dnl configuration checks.
+dnl "" : this option was not specified on the command line; try to
+dnl build all components that are not --with'd, but don't
+dnl error out if any component does not pass configuration checks.
+dnl
+dnl For each --enable-foo component, if that flag is not specified on
+dnl the command line, the related variable $enable_foo will be set to
+dnl $enable_all_components .
+
+dnl Create --with-foo argument for named compoment, create variables as needed
+dnl $1 is component name
+dnl $2 is what to do on success
+dnl $3 is the PKG_CONFIG name; if not given, then $1
+AC_DEFUN([GRC_WITH], [
+ if test [x]$3 = x; then
+ pc_comp_name="$1"
+ else
+ pc_comp_name="$3"
+ fi
+ _GRC_WITH($1,[$2],${pc_comp_name},m4_bpatsubst($1,-,_))
+])
+dnl $3 is the pkg-config component name
+dnl $4 is the '_'d component name
+dnl on exit variable passed will be [yes|no|with]:
+dnl yes: if --enable-$1 and/or --enable-all-components was specified,
+dnl but --with was not;
+dnl with: if --with-$1 was specified, and passed checks;
+dnl no: all other conditions
+AC_DEFUN([_GRC_WITH],[
+ AC_ARG_WITH([$1],
+ AC_HELP_STRING([--with-$1@<:@=PATH@:>@],
+ [Use package $1 if installed in PATH (if specified) or PKG_CONFIG_PATH (if PATH not specified); stop if $1 not found]),
+ [if test "x$withval" != "xyes"; then
+ [with_]$4[_val]=$withval
+ [with_]$4=yes
+ fi],
+ [])
+ if test x$[with_]$4 = xyes; then
+ if test x$[enable_]$4 = xyes; then
+ AC_MSG_ERROR([Component $1: Cannot use both --enable and --with])
+ else
+ _GRC_WITH_PKG_CONFIG_CHECK($1,$3,$4)
+ ifelse([$2], , :, [$2])
+ fi
+ fi
+])
+
+dnl Use 'pkgconfig' to check for a package
+dnl $1 is the --with component name
+dnl $2 is the pkg-config component name, if provided; otherwise use $1 for this
+dnl on success, resulting INCLUDES, INCLUDEDIR, LA, and LIBDIRPATH variables
+dnl will be set; on failure, will exit with an error.
+AC_DEFUN([GRC_WITH_PKG_CONFIG_CHECK], [
+ if test [x]$2 = x; then
+ pc_comp_name="$1"
+ else
+ pc_comp_name="$2"
+ fi
+ _GRC_WITH_PKG_CONFIG_CHECK($1,${pc_comp_name},m4_bpatsubst($1,-,_))
+])
+dnl $2 is the pkg-config component name
+dnl $3 is the '_'d component name
+AC_DEFUN([_GRC_WITH_PKG_CONFIG_CHECK],[
+ dnl save PKG_CONFIG_PATH, restore at the end
+ s_PKG_CONFIG_PATH=$PKG_CONFIG_PATH
+
+ dnl create the PKG_CONFIG_PATH, via this component arg, if provided;
+ dnl else use the environment PKG_CONFIG_PATH
+ l_PKG_CONFIG_PATH=$[with_]$3[_val]
+ if test "x$l_PKG_CONFIG_PATH" != "x"; then
+ export PKG_CONFIG_PATH=$l_PKG_CONFIG_PATH
+
+ dnl verify that the file exists; if not, no point in continuing
+ if ! test -r ${l_PKG_CONFIG_PATH}/$2[.pc]; then
+ AC_MSG_ERROR([Component $1: PKGCONFIG cannot find info for $2, with provided PKG_CONFIG_PATH = @<:@ $l_PKG_CONFIG_PATH @:>@ .])
+ fi
+ fi
+
+ dnl do the check; error out if not found
+ PKG_CHECK_EXISTS($2, [passed=with; check1=yes], [
+ check1=no
+ dnl pkg-config returned an error; this might be that the .pc
+ dnl file was not valid, or the Requires: were not met.
+ dnl If the arg was provided and the input PKG_CONFIG_PATH , then try
+ dnl again appending the whole PKG_CONFIG_PATH.
+ if test "x$l_PKG_CONFIG_PATH" != "x"; then
+ if test "x$s_PKG_CONFIG_PATH" != "x"; then
+ export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:${s_PKG_CONFIG_PATH}
+ PKG_CHECK_EXISTS($2, passed=with, passed=no)
+ fi
+ fi
+ if test $passed != with; then
+ AC_MSG_ERROR([Component $1: PKGCONFIG cannot find info for $2, with PKG_CONFIG_PATH = @<:@ $PKG_CONFIG_PATH @:>@ .])
+ fi
+ dnl pkg-config Requires are now met; save the new PKG_CONFIG_PATH
+ s_PKG_CONFIG_PATH=$PKG_CONFIG_PATH
+ ])
+
+ dnl if PKG_CHECK_EXISTS returned, then this component's .pc file was
+ dnl found in the provided 'arg' PKG_CONFIG_PATH;
+ dnl retrieve various parameters
+ $3[_INCLUDES]=`$PKG_CONFIG --cflags-only-I $2`
+ $3[_LA]=`$PKG_CONFIG --libs $2`
+ $3[_INCLUDEDIR]=`$PKG_CONFIG --variable=includedir $2`
+
+ if test x$check1 = xyes; then
+ dnl prepend the args PKG_CONFIG_PATH to the saved one, if the
+ dnl saved version was not empty
+ if test "x$s_PKG_CONFIG_PATH" != "x"; then
+ export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:${s_PKG_CONFIG_PATH}
+ fi
+ fi
+])
+
+dnl Check the $prefix versus the --with libdirpath for this component
+dnl $1 is the prefix
+dnl $2 is the --with component name
+dnl $3 is the --with component library path
+AC_DEFUN([GRC_PREFIX_LDFLAGS],[
+ $2[_LIBDIRPATH]=$3
+ dnl create LDFLAGS for this --with, if different from the provided $prefix
+ if test [x]$1[/lib] != [x]$3; then
+ $2[_LDFLAG]=[-L]$3
+ else
+ $2[_LDFLAG]=
+ fi
+])
+
+dnl Check to make sure this dependency is fulfilled for this component
+dnl $1 is the component's name
+dnl $2 is the component dependency name
+dnl On input and exit, $passed will be:
+dnl with : if --with passed muster
+dnl yes : if --enable passed muster
+dnl no : otherwise
+dnl If trying --with, will error-out if any dependency was not --with'd
+AC_DEFUN([GRC_CHECK_DEPENDENCY],[
+dnl f0=[enable_]m4_bpatsubst($1,-,_)
+dnl f1=[$enable_]m4_bpatsubst($1,-,_)
+dnl echo
+dnl echo "$1 : Checking Dependency $2"
+dnl echo "$1 : enable_all_components is '$enable_all_components'"
+dnl echo "$1 : $f0 is '$f1'"
+dnl echo "$1 : passed is '$passed'"
+dnl echo
+ if test $passed != no; then
+ if test $passed = yes; then
+ dnl make sure this dependency was not skipped
+ if test [x$]m4_bpatsubst($2,-,_)[_skipped] = xyes; then
+ AC_MSG_RESULT([Component $1 requires $2, which is not being built or specified via pre-installed files.])
+ passed=no
+ fi
+ else
+ dnl make sure this dependency was --with'd only; not --enable'd
+ if test [x$]m4_bpatsubst($2,-,_)[_with] = xno; then
+ AC_MSG_ERROR([Component $1 requires $2 to be included as --with-$2@<:@=arg@:>@])
+ fi
+ fi
+ fi
+])
+
+dnl Check to make sure GUILE is available
+dnl $1 is the component name
+AC_DEFUN([GRC_CHECK_GUILE],[
+ if test x"$GUILE" = x; then
+ AC_MSG_RESULT([Component $1 requires guile, which was not found.])
+ passed=no
+ fi
+])
+
+dnl Add the specified "with" list; clear the provided variable
+dnl $1 is the component name
+dnl $2 is the path list name suffix
+dnl $3 is the separator (for paths, ":"; for includes " ")
+AC_DEFUN([GRC_ADD_TO_LIST],[
+ if test "x${$1[_]$2}" != "x"; then
+ if test "x$[with_]$2" = "x"; then
+ [with_]$2="${$1[_]$2}"
+ else
+ [with_]$2="${$1[_]$2}"$3"$[with_]$2"
+ fi
+ $1[_]$2=
+ fi
+])
+
+dnl Conditionally build named component.
+dnl $1 is component name
+dnl $2 is executed if configuration passes and build is desired
+AC_DEFUN([GRC_BUILD_CONDITIONAL],[
+ _GRC_BUILD_CONDITIONAL($1, $2, m4_bpatsubst($1,-,_))
+])
+dnl $3=m4_bpatsubst($1,-,_)
+dnl Use $passed=no to indicate configuration failure;
+dnl Use $passed=with to indicate the use of pre-installed libraries and headers;
+dnl Any other value of $passed, including blank, assumes success;
+dnl Defines $3_with=[yes|no] depending on if $passed=with or not (respectively)
+dnl Defines $3_skipped=[yes|no] depending on if $passed=no or not (respectively)
+AC_DEFUN([_GRC_BUILD_CONDITIONAL],[
+ $3[_with]=no
+ if test $passed = no; then
+ if test x$[enable_]$3 = xyes; then
+ AC_MSG_ERROR([Component $1 has errors; stopping.])
+ else
+ AC_MSG_RESULT([Not building component $1.])
+ fi
+ else
+ if test $passed = with; then
+ with_dirs="$with_dirs $1"
+ GRC_ADD_TO_LIST($3, INCLUDES, " ")
+ GRC_ADD_TO_LIST($3, SWIG_INCLUDES, " ")
+ GRC_ADD_TO_LIST($3, PYDIRPATH, ":")
+ GRC_ADD_TO_LIST($3, SWIGDIRPATH, ":")
+ GRC_ADD_TO_LIST($3, LIBDIRPATH, ":")
+ AC_MSG_RESULT([Component $1 will be included from a pre-installed library and includes.])
+ $3[_with]=yes
+ else
+ $3[_LDFLAG]=
+ if test x$[enable_]$3 != xno; then
+ ifelse([$2], , :, [$2])
+ build_dirs="$build_dirs $1"
+ AC_MSG_RESULT([Component $1 passed configuration checks; building.])
+ else
+ passed=no
+ AC_MSG_RESULT([Component $1 passed configuration checks; but not building.])
+ fi
+ fi
+ fi
+ if test $passed = no; then
+ skipped_dirs="$skipped_dirs $1"
+ $3[_skipped]=yes
+ else
+ $3[_skipped]=no
+ fi
+ AC_SUBST($3[_INCLUDES])
+ AC_SUBST($3[_LA])
+ AC_SUBST($3[_INCLUDEDIR])
+ AC_SUBST($3[_LIBDIRPATH])
+ AC_SUBST($3[_LDFLAG])
+])
diff --git a/firmware/fx2/config/grc_fx2.m4 b/firmware/fx2/config/grc_fx2.m4
new file mode 100644
index 000000000..00a41c973
--- /dev/null
+++ b/firmware/fx2/config/grc_fx2.m4
@@ -0,0 +1,58 @@
+dnl Copyright 2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+AC_DEFUN([GRC_FX2],[
+ GRC_ENABLE(usrp)
+
+ GRC_WITH(usrp)
+
+ dnl If execution gets to here, $passed will be:
+ dnl with : if the --with code didn't error out
+ dnl yes : if the --enable code passed muster and all dependencies are met
+ dnl no : otherwise
+ if test $passed = yes; then
+ dnl gnulib.
+ dnl FIXME: this needs to fail gracefully and continue, not implemented yet
+ UTILS_FUNC_MKSTEMP
+
+ dnl These checks don't fail
+ AC_C_BIGENDIAN
+ AC_CHECK_HEADERS([byteswap.h linux/compiler.h])
+ AC_CHECK_FUNCS([getrusage sched_setscheduler pthread_setschedparam])
+ AC_CHECK_FUNCS([sigaction snprintf])
+
+ dnl Make sure SDCC >= 2.4.0 is available.
+ USRP_SDCC([2.4.0],[],[passed=no;AC_MSG_RESULT([Unable to find firmware compiler SDCC.])])
+ fi
+ if test $passed != with; then
+ dnl how and where to find INCLUDES and LA
+ usrp_INCLUDES=" \
+ -I\${abs_top_srcdir}/include"
+ fi
+
+ AC_CONFIG_FILES([ \
+ include/Makefile \
+ lib/Makefile \
+ src/Makefile \
+ src/common/Makefile \
+ src/usrp1/Makefile \
+ ])
+
+ GRC_BUILD_CONDITIONAL(usrp)
+])
diff --git a/firmware/fx2/config/lf_cc.m4 b/firmware/fx2/config/lf_cc.m4
new file mode 100644
index 000000000..b75e1a4c5
--- /dev/null
+++ b/firmware/fx2/config/lf_cc.m4
@@ -0,0 +1,41 @@
+dnl Autoconf support for C++
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# -------------------------------------------------------------------------
+# Use this macro to configure your C compiler
+# When called the macro does the following things:
+# 1. It finds an appropriate C compiler.
+# If you passed the flag --with-cc=foo then it uses that
+# particular compiler
+# 2. Check whether the compiler works.
+# 3. Checks whether the compiler accepts the -g
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CONFIGURE_CC],[
+ dnl Sing the song
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_CPP])dnl
+ AC_REQUIRE([AC_AIX])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+])
+
diff --git a/firmware/fx2/config/lf_cxx.m4 b/firmware/fx2/config/lf_cxx.m4
new file mode 100644
index 000000000..dfc6bfbfe
--- /dev/null
+++ b/firmware/fx2/config/lf_cxx.m4
@@ -0,0 +1,67 @@
+dnl Autoconf support for C++
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# -----------------------------------------------------------------
+# This macro should be called to configure your C++ compiler.
+# When called, the macro does the following things:
+# 1. It finds an appropriate C++ compiler
+# If you passed the flag --with-cxx=foo, then it uses that
+# particular compiler
+# 2. Checks whether the compiler accepts the -g
+# ------------------------------------------------------------------
+
+AC_DEFUN([LF_CONFIGURE_CXX],[
+ AC_REQUIRE([AC_PROG_CXX])dnl
+ AC_REQUIRE([AC_PROG_CXXCPP])dnl
+ LF_CXX_PORTABILITY
+])
+
+# -----------------------------------------------------------------------
+# This macro tests the C++ compiler for various portability problem.
+# -----------------------------------------------------------------------
+
+
+AC_DEFUN([LF_CXX_PORTABILITY],[
+
+ dnl
+ dnl Check for common C++ portability problems
+ dnl
+
+ dnl AC_LANG_PUSH
+ dnl AC_LANG_CPLUSPLUS
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+
+
+ dnl Test whether C++ has std::isnan
+ AC_MSG_CHECKING(whether C++ has std::isnan)
+ AC_TRY_COMPILE([#include <cmath>], [
+ std::isnan(0);
+], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(CXX_HAS_STD_ISNAN,[],[Define if has std::isnan]) ],
+ [ AC_MSG_RESULT(no) ])
+
+ dnl Done with the portability checks
+ dnl AC_LANG_POP([C++])
+ AC_LANG_RESTORE
+])
+
diff --git a/firmware/fx2/config/lf_warnings.m4 b/firmware/fx2/config/lf_warnings.m4
new file mode 100644
index 000000000..d40c77f14
--- /dev/null
+++ b/firmware/fx2/config/lf_warnings.m4
@@ -0,0 +1,121 @@
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl Copyright (C) 2009 Free Software Foundation, Inc.
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# --------------------------------------------------------------------------
+# Check whether the C++ compiler accepts a certain flag
+# If it does it adds the flag to lf_CXXFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_CXX_FLAG],[
+ echo 'void f(){}' > conftest.cc
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CXX accepts $i])
+ if test -z "`${CXX} $i -c conftest.cc 2>&1`"
+ then
+ lf_CXXFLAGS="${lf_CXXFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.cc conftest.o
+ AC_SUBST(lf_CXXFLAGS)
+])
+
+# --------------------------------------------------------------------------
+# Check whether the C compiler accepts a certain flag
+# If it does it adds the flag to lf_CFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_CC_FLAG],[
+ echo 'void f(){}' > conftest.c
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CC accepts $i])
+ if test -z "`${CC} $i -c conftest.c 2>&1`"
+ then
+ lf_CFLAGS="${lf_CFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.c conftest.o
+ AC_SUBST(lf_CFLAGS)
+])
+
+# --------------------------------------------------------------------------
+# Check whether the Fortran compiler accepts a certain flag
+# If it does it adds the flag to lf_FFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_F77_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_F77_FLAG],[
+ cat << EOF > conftest.f
+c....:++++++++++++++++++++++++
+ PROGRAM MAIN
+ PRINT*,'Hello World!'
+ END
+EOF
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $F77 accepts $i])
+ if test -z "`${F77} $i -c conftest.f 2>&1`"
+ then
+ lf_FFLAGS="${lf_FFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.f conftest.o
+ AC_SUBST(lf_FFLAGS)
+])
+
+# ----------------------------------------------------------------------
+# Enable compiler warnings.
+# Call this command AFTER you have configured ALL your compilers.
+# ----------------------------------------------------------------------
+
+AC_DEFUN([LF_SET_WARNINGS],[
+ dnl Warnings for the two main compilers
+ dnl add -Wextra when you're got time to fix a bunch of them ;-)
+ cc_warning_flags="-Wall -Werror-implicit-function-declaration"
+ cxx_warning_flags="-Wall -Woverloaded-virtual"
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_warning_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_warning_flags)
+ fi
+])
diff --git a/firmware/fx2/config/mkstemp.m4 b/firmware/fx2/config/mkstemp.m4
new file mode 100644
index 000000000..4af0f0a9b
--- /dev/null
+++ b/firmware/fx2/config/mkstemp.m4
@@ -0,0 +1,89 @@
+#serial 4
+
+# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a
+# silly limit that it can create no more than 26 files from a given template.
+# Other systems lack mkstemp altogether.
+# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create
+# only 32 files per process.
+# On systems like the above, arrange to use the replacement function.
+AC_DEFUN([UTILS_FUNC_MKSTEMP],
+[dnl
+ AC_REPLACE_FUNCS(mkstemp)
+ if test $ac_cv_func_mkstemp = no; then
+ utils_cv_func_mkstemp_limitations=yes
+ else
+ AC_CACHE_CHECK([for mkstemp limitations],
+ utils_cv_func_mkstemp_limitations,
+ [
+ AC_TRY_RUN([
+# include <stdlib.h>
+ int main ()
+ {
+ int i;
+ for (i = 0; i < 70; i++)
+ {
+ char template[] = "conftestXXXXXX";
+ int fd = mkstemp (template);
+ if (fd == -1)
+ exit (1);
+ close (fd);
+ }
+ exit (0);
+ }
+ ],
+ utils_cv_func_mkstemp_limitations=no,
+ utils_cv_func_mkstemp_limitations=yes,
+ utils_cv_func_mkstemp_limitations=yes
+ )
+ ]
+ )
+ fi
+
+ if test $utils_cv_func_mkstemp_limitations = yes; then
+ AC_LIBOBJ(mkstemp)
+ AC_LIBOBJ(tempname)
+ AC_DEFINE(mkstemp, rpl_mkstemp,
+ [Define to rpl_mkstemp if the replacement function should be used.])
+ gl_PREREQ_MKSTEMP
+ jm_PREREQ_TEMPNAME
+ fi
+])
+
+# Prerequisites of lib/mkstemp.c.
+AC_DEFUN([gl_PREREQ_MKSTEMP],
+[
+ AH_BOTTOM(
+ [
+ #ifndef HAVE_MKSTEMP
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ int rpl_mkstemp (char *templ);
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif
+ ])
+])
+
+# Prerequisites of lib/tempname.c.
+AC_DEFUN([jm_PREREQ_TEMPNAME],
+[
+ AC_REQUIRE([AC_HEADER_STAT])
+ AC_CHECK_HEADERS_ONCE(fcntl.h sys/time.h unistd.h)
+ AC_CHECK_HEADERS(stdint.h)
+ AC_CHECK_FUNCS(__secure_getenv gettimeofday lstat)
+ AC_CHECK_DECLS_ONCE(getenv)
+ # AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])
+
+ dnl Under Win32, mkdir prototype in io.h has only one arg
+ AC_MSG_CHECKING(whether mkdir accepts only one arg)
+ AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>], [
+ mkdir("")
+ ], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ],
+ [ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/firmware/fx2/config/onceonly.m4 b/firmware/fx2/config/onceonly.m4
new file mode 100644
index 000000000..f6fec37cb
--- /dev/null
+++ b/firmware/fx2/config/onceonly.m4
@@ -0,0 +1,63 @@
+# onceonly.m4 serial 3
+dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl This file defines some "once only" variants of standard autoconf macros.
+dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS
+dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS
+dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS
+dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC
+dnl The advantage is that the check for each of the headers/functions/decls
+dnl will be put only once into the 'configure' file. It keeps the size of
+dnl the 'configure' file down, and avoids redundant output when 'configure'
+dnl is run.
+dnl The drawback is that the checks cannot be conditionalized. If you write
+dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi
+dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to
+dnl empty, and the check will be inserted before the body of the AC_DEFUNed
+dnl function.
+
+dnl Autoconf version 2.57 or newer is recommended.
+AC_PREREQ(2.54)
+
+# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of
+# AC_CHECK_HEADERS(HEADER1 HEADER2 ...).
+AC_DEFUN([AC_CHECK_HEADERS_ONCE], [
+ :
+ AC_FOREACH([gl_HEADER_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(defn([gl_HEADER_NAME]),
+ [-./], [___])), [
+ AC_CHECK_HEADERS(gl_HEADER_NAME)
+ ])
+ AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
+ [-./], [___])))
+ ])
+])
+
+# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of
+# AC_CHECK_FUNCS(FUNC1 FUNC2 ...).
+AC_DEFUN([AC_CHECK_FUNCS_ONCE], [
+ :
+ AC_FOREACH([gl_FUNC_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]), [
+ AC_CHECK_FUNCS(defn([gl_FUNC_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]))
+ ])
+])
+
+# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of
+# AC_CHECK_DECLS(DECL1, DECL2, ...).
+AC_DEFUN([AC_CHECK_DECLS_ONCE], [
+ :
+ AC_FOREACH([gl_DECL_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_DECL_]defn([gl_DECL_NAME]), [
+ AC_CHECK_DECLS(defn([gl_DECL_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_DECL_]defn([gl_DECL_NAME]))
+ ])
+])
diff --git a/firmware/fx2/config/pkg.m4 b/firmware/fx2/config/pkg.m4
new file mode 100644
index 000000000..2d4d96109
--- /dev/null
+++ b/firmware/fx2/config/pkg.m4
@@ -0,0 +1,201 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+# Copyright © 2008 Free Software Foundation, Inc.
+#
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.18])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+# E.g.,
+# PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+# defines:
+#
+# GSTUFF_LIBS
+# GSTUFF_CFLAGS
+# GSTUFF_INCLUDEDIR
+# GSTUFF_CPPFLAGS # the -I, -D and -U's out of CFLAGS
+#
+# see pkg-config man page also defines GSTUFF_PKG_ERRORS on error
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],[
+AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_INCLUDEDIR], [includedir for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+
+if test x$cross_compiling = xyes
+then
+ dnl _PKG_CONFIG([$1][_LIBS], [libs-only-l --static], [$2])
+ _PKG_CONFIG([$1][_LIBS], [libs --static], [$2])
+ dnl prune out any -L/lib or -L/usr/lib since they're pointing to the wrong filesystem root
+ _pkg_tmp=
+ for flag in [$]pkg_cv_[$1][_LIBS]; do
+ case $flag in
+ (-L/lib* | -L/usr/lib* ) ;; # ignore
+ (*) _pkg_tmp="$_pkg_tmp $flag" ;;
+ esac
+ done
+ pkg_cv_[$1][_LIBS]="$_pkg_tmp"
+else
+ _PKG_CONFIG([$1][_LIBS], [libs --static], [$2])
+fi
+
+_PKG_CONFIG([$1][_INCLUDEDIR], [variable=includedir], [$2])
+
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ $1[]_INCLUDEDIR=$pkg_cv_[]$1[]_INCLUDEDIR
+
+ $1[]_CPPFLAGS=""
+ for flag in $$1[]_CFLAGS; do
+ case $flag in
+ -I* | -D* | -U*) $1[]_CPPFLAGS="$$1[]_CPPFLAGS $flag" ;;
+ esac
+ done
+ pkg_cv_[]$1[]_CPPFLAGS=$$1[]_CPPFLAGS
+ AC_SUBST($1[]_CPPFLAGS)
+
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/firmware/fx2/config/usrp_sdcc.m4 b/firmware/fx2/config/usrp_sdcc.m4
new file mode 100644
index 000000000..86f6429e5
--- /dev/null
+++ b/firmware/fx2/config/usrp_sdcc.m4
@@ -0,0 +1,75 @@
+# Check for sdcc support. -*- Autoconf -*-
+
+# Copyright 2004 Free Software Foundation, Inc.
+
+# 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 3, 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 Street, Boston, MA
+# 02110-1301, USA.
+
+AC_DEFUN([USRP_SDCC],
+[
+ sdccok=yes
+ AC_CHECK_PROG(XCC, sdcc, sdcc -mmcs51 --no-xinit-opt,no)
+ AC_CHECK_PROG(XAS, asx8051, asx8051 -plosgff,no)
+
+ if test "$XCC" = "no" -o "$XAS" = "no" ; then
+ AC_MSG_RESULT([USRP requires sdcc. sdcc not found. See http://sdcc.sf.net])
+ sdccok=no
+ else
+ sdcc_version_min=$1
+
+ sdcc_version=`sdcc --version 2>&1 | \
+ sed 's/\(SDCC.* \)\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\)\( .*$\)/\2/'`
+
+ AC_MSG_CHECKING([sdcc_version "$sdcc_version"])
+
+ sdcc_major_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdcc_minor_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdcc_micro_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ sdcc_major_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdcc_minor_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdcc_micro_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ sdcc_version_proper=`expr \
+ "$sdcc_major_version" \> "$sdcc_major_min" \| \
+ "$sdcc_major_version" \= "$sdcc_major_min" \& \
+ "$sdcc_minor_version" \> "$sdcc_minor_min" \| \
+ "$sdcc_major_version" \= "$sdcc_major_min" \& \
+ "$sdcc_minor_version" \= "$sdcc_minor_min" \& \
+ "$sdcc_micro_version" \>= "$sdcc_micro_min" `
+
+ if test "$sdcc_version_proper" = "1" ; then
+ AC_MSG_RESULT([$sdcc_major_version.$sdcc_minor_version.$sdcc_micro_version])
+ else
+ sdccok=no
+ AC_MSG_RESULT([USRP requires sdcc >= $sdcc_version_min. sdcc not found. See http://sdcc.sf.net])
+ fi
+
+ AC_SUBST(XCC)
+ AC_SUBST(XAS)
+ fi
+
+ if test $sdccok = yes; then
+ ifelse([$2], , :, [$2])
+ else
+ ifelse([$3], , :, [$3])
+ fi
+])
diff --git a/firmware/fx2/configure.ac b/firmware/fx2/configure.ac
new file mode 100644
index 000000000..a4fa59c2e
--- /dev/null
+++ b/firmware/fx2/configure.ac
@@ -0,0 +1,335 @@
+dnl Copyright 2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+AC_INIT
+AC_PREREQ(2.57)
+AM_CONFIG_HEADER(config.h)
+
+AC_CANONICAL_BUILD
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+dnl ustar required to have pathnames > 99 chars
+_AM_SET_OPTION([tar-ustar])
+AM_INIT_AUTOMAKE(gnuradio,$RELEASE)
+
+DEFINES=""
+AC_SUBST(DEFINES)
+
+dnl Remember if the user explicity set CFLAGS
+if test -n "${CFLAGS}"; then
+ user_set_cflags=yes
+fi
+dnl Remember if the user explicity set CXXFLAGS
+if test -n "${CXXFLAGS}"; then
+ user_set_cxxflags=yes
+fi
+
+
+LF_CONFIGURE_CC
+LF_CONFIGURE_CXX
+GR_LIB64 dnl check for lib64 suffix after choosing compilers
+
+
+dnl The three macros above are known to override CFLAGS if the user
+dnl didn't specify them. Though I'm sure somebody thought this was
+dnl a good idea, it makes it hard to use other than -g -O2 when compiling
+dnl selected files. Thus we "undo" the damage here...
+dnl
+dnl If the user specified CFLAGS, we use them.
+dnl See Makefile.common for the rest of the magic.
+if test "$user_set_cflags" != yes; then
+ autoconf_default_CFLAGS="$CFLAGS"
+ CFLAGS=""
+fi
+AC_SUBST(autoconf_default_CFLAGS)
+
+
+dnl The three macros above are known to override CXXFLAGS if the user
+dnl didn't specify them. Though I'm sure somebody thought this was
+dnl a good idea, it makes it hard to use other than -g -O2 when compiling
+dnl selected files. Thus we "undo" the damage here...
+dnl
+dnl If the user specified CXXFLAGS, we use them. Otherwise when compiling
+dnl the output of swig use use -O1 if we're using g++.
+dnl See Makefile.common for the rest of the magic.
+if test "$user_set_cxxflags" != yes; then
+ autoconf_default_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS=""
+ if test "$GXX" = yes; then
+ case "$host_cpu" in
+ powerpc*)
+ dnl "-O1" is broken on the PPC for some reason
+ dnl (at least as of g++ 4.1.1)
+ swig_CXXFLAGS="-g1 -O2 -Wno-strict-aliasing -Wno-parentheses"
+ ;;
+ *)
+ swig_CXXFLAGS="-g -O1 -Wno-strict-aliasing -Wno-parentheses"
+ ;;
+ esac
+ fi
+fi
+AC_SUBST(autoconf_default_CXXFLAGS)
+AC_SUBST(swig_CXXFLAGS)
+
+dnl add ${prefix}/lib${gr_libdir_suffix}/pkgconfig to the head of the PKG_CONFIG_PATH
+if test x${PKG_CONFIG_PATH} = x; then
+ PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig
+else
+ PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig:${PKG_CONFIG_PATH}
+fi
+export PKG_CONFIG_PATH
+
+LF_SET_WARNINGS
+AM_PROG_AS
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+
+# AC_PROG_MKDIR_P
+# is a backport of autoconf-2.60's AC_PROG_MKDIR_P.
+# Remove this macro when we can assume autoconf >= 2.60.
+m4_ifdef([AC_PROG_MKDIR_P], [], [
+ AC_DEFUN([AC_PROG_MKDIR_P],
+ [AC_REQUIRE([AM_PROG_MKDIR_P])dnl defined by automake
+ MKDIR_P='$(mkdir_p)'
+ AC_SUBST([MKDIR_P])])
+])
+AC_PROG_MKDIR_P
+
+AC_PATH_PROG([RM_PROG], [rm])
+
+AC_LIBTOOL_WIN32_DLL
+dnl AC_DISABLE_SHARED dnl don't build shared libraries
+AC_ENABLE_SHARED dnl do build shared libraries
+AC_DISABLE_STATIC dnl don't build static libraries
+m4_ifdef([LT_INIT],[LT_INIT],[AC_PROG_LIBTOOL])
+dnl GR_FORTRAN
+
+GR_NO_UNDEFINED dnl do we need the -no-undefined linker flag
+GR_SCRIPTING
+
+
+AM_CONDITIONAL([PYTHON], [test x$enable_python = xyes])
+
+dnl Checks for libraries.
+AC_CHECK_LIB(socket,socket)
+
+dnl Set the c++ compiler that we use for the build system when cross compiling
+if test x$CXX_FOR_BUILD = x
+then
+ if test x$cross_compiling = xno; then
+ CXX_FOR_BUILD=${CXX}
+ else
+ CXX_FOR_BUILD=g++
+ fi
+fi
+AC_SUBST(CXX_FOR_BUILD)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h limits.h strings.h time.h sys/ioctl.h sys/time.h unistd.h)
+AC_CHECK_HEADERS(linux/ppdev.h dev/ppbus/ppi.h sys/mman.h sys/select.h sys/types.h)
+AC_CHECK_HEADERS(sys/resource.h stdint.h sched.h signal.h sys/syscall.h malloc.h)
+AC_CHECK_HEADERS(windows.h)
+AC_CHECK_HEADERS(vec_types.h)
+AC_CHECK_HEADERS(netdb.h netinet/in.h arpa/inet.h sys/types.h sys/socket.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+AC_C_BIGENDIAN([GR_ARCH_BIGENDIAN=1],[GR_ARCH_BIGENDIAN=0])
+AC_SUBST(GR_ARCH_BIGENDIAN)
+AC_STRUCT_TM
+
+dnl Checks for library functions.
+AC_FUNC_ALLOCA
+AC_FUNC_SETVBUF_REVERSED
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([mmap select socket strcspn strerror strspn getpagesize sysconf])
+AC_CHECK_FUNCS([snprintf gettimeofday nanosleep sched_setscheduler])
+AC_CHECK_FUNCS([modf sqrt sigaction sigprocmask pthread_sigmask])
+AC_CHECK_FUNCS([sched_setaffinity])
+
+AC_CHECK_LIB(m, sincos, [AC_DEFINE([HAVE_SINCOS],[1],[Define to 1 if your system has `sincos'.])])
+AC_CHECK_LIB(m, sincosf,[AC_DEFINE([HAVE_SINCOSF],[1],[Define to 1 if your system has `sincosf'.])])
+AC_CHECK_LIB(m, sinf, [AC_DEFINE([HAVE_SINF],[1],[Define to 1 if your system has `sinf'.])])
+AC_CHECK_LIB(m, cosf, [AC_DEFINE([HAVE_COSF],[1],[Define to 1 if your system has `cosf'.])])
+AC_CHECK_LIB(m, trunc, [AC_DEFINE([HAVE_TRUNC],[1],[Define to 1 if your system has `trunc'.])])
+AC_CHECK_LIB(m, exp10, [AC_DEFINE([HAVE_EXP10],[1],[Define to 1 if your system has 'exp10'.])])
+AC_CHECK_LIB(m, log2, [AC_DEFINE([HAVE_LOG2],[1],[Define to 1 if your system has 'log2'.])])
+#AC_FUNC_MKTIME
+
+AH_BOTTOM([
+#ifndef HAVE_TRUNC
+#include <math.h>
+inline static double trunc(double x)
+{
+ return x >= 0 ? floor(x) : ceil(x);
+}
+#endif
+
+#ifndef HAVE_EXP10
+#include <math.h>
+inline static double exp10(double x)
+{
+ return pow(10.0, x);
+}
+#endif
+
+#ifdef HAVE_WINDOWS_H
+#define NOMINMAX
+#endif
+])
+
+dnl Do we have "dot", part of the graphviz package from AT&T?
+dnl Doxgen will use it to draw pretty diagrams ;-)
+AC_CHECK_PROG(HAVE_DOT, [dot],[YES],[NO])
+
+PKG_CHECK_MODULES(FFTW3F, fftw3f >= 3.0)
+AC_SUBST(FFTW3F_LIBS)
+
+dnl Define where to look for cppunit includes and libs
+dnl sets CPPUNIT_CFLAGS and CPPUNIT_LIBS
+dnl Try using pkg-config first, then fall back to cppunit-config.
+PKG_CHECK_EXISTS(cppunit,
+ [PKG_CHECK_MODULES(CPPUNIT, cppunit >= 1.9.14)],
+ [AM_PATH_CPPUNIT([1.9.14],[],
+ [AC_MSG_ERROR([GNU Radio requires cppunit. Stop])])])
+
+CPPUNIT_INCLUDES=$CPPUNIT_CFLAGS
+AC_SUBST(CPPUNIT_INCLUDES)
+
+dnl see if GUILE is installed
+AC_PATH_PROG(GUILE,guile)
+
+
+BUILD_DATE=`date -R -u`
+AC_SUBST(BUILD_DATE)
+
+dnl SYSCONFDIR substitution
+if test "${sysconfdir}" == "\${prefix}/etc" ; then
+ if test "${prefix}" == "NONE" ; then
+ SYSCONFDIR=["$ac_default_prefix/etc"]
+ else
+ SYSCONFDIR=["${prefix}/etc"]
+ fi
+else
+ SYSCONFDIR=[${sysconfdir}]
+fi
+AC_SUBST(SYSCONFDIR)
+
+dnl System configuration files
+GR_PREFSDIR=[$SYSCONFDIR/${PACKAGE}/conf.d]
+AC_SUBST(GR_PREFSDIR)
+
+dnl Component specific configuration
+dnl The order of the GR_ macros determines the order of compilation
+dnl For -any- checks on $enable_all_components
+dnl use the following guidelines:
+dnl yes : --enable-all-components was specified, so error out if any
+dnl components do not pass configuration checks.
+dnl no : --disable-all-components was specified, so try to build the
+dnl --enable'd components, and error out if any do not pass
+dnl configuration checks.
+dnl "" : this option was not specified on the command line; try to
+dnl build all components that are not --with'd, but don't
+dnl error out if any component does not pass configuration checks.
+dnl
+dnl For each --enable-foo component, if that flag is not specified on
+dnl the command line, the related variable $enable_foo will be set to
+dnl $enable_all_components .
+
+AC_ARG_ENABLE(
+ [all-components],
+ [ --enable-all-components Build all configurable components (default), or stop on failed dependencies]
+)
+
+build_dirs="config"
+GRC_FX2
+
+# Each component is now either to be built, was skipped, will be
+# included from pre-installed libraries and includes, or failed
+# dependencies.
+AC_SUBST([build_dirs], [$build_dirs])
+AC_SUBST([skipped_dirs], [$skipped_dirs])
+AC_SUBST([with_dirs], [$with_dirs])
+
+# fix for older autotools that don't define these by default
+AC_SUBST(abs_top_srcdir)
+AC_SUBST(abs_top_builddir)
+AC_SUBST(MKDIR_P)
+
+# 'with' variables - the pre-installed libraries, includes, and paths
+# - must always come last in the lists, so they require special
+# treatment.
+AC_SUBST(with_INCLUDES)
+AC_SUBST(with_PYDIRPATH)
+AC_SUBST(with_LIBDIRPATH)
+
+# Local files tweaked by AC
+AC_CONFIG_FILES([\
+ Makefile \
+ config/Makefile \
+])
+
+AC_OUTPUT
+
+echo
+echo "*********************************************************************"
+echo The following GNU Radio components have been successfully configured:
+echo
+for dir in $build_dirs
+do
+ echo $dir
+done
+echo
+echo You my now run the 'make' command to build these components.
+echo
+if test "$skipped_dirs" != ""; then
+ echo "*********************************************************************"
+ echo The following components were skipped either because you asked not
+ echo to build them or they didn\'t pass configuration checks:
+ echo
+ for dir in $skipped_dirs
+ do
+ echo $dir
+ done
+ echo
+ echo These components will not be built.
+ echo
+fi
+if test "$with_dirs" != ""; then
+ echo "*********************************************************************"
+ echo The following components will be included from pre-installed
+ echo libraries and includes:
+ echo
+ for dir in $with_dirs
+ do
+ echo $dir
+ done
+ echo
+ echo These components will not be built.
+ echo
+fi
+
+echo Configured GNU Radio release $RELEASE for build.
diff --git a/firmware/fx2/include/.gitignore b/firmware/fx2/include/.gitignore
new file mode 100644
index 000000000..75bb241c8
--- /dev/null
+++ b/firmware/fx2/include/.gitignore
@@ -0,0 +1,25 @@
+/Makefile
+/Makefile.in
+/aclocal.m4
+/configure
+/config.h.in
+/stamp-h.in
+/libtool
+/config.log
+/config.h
+/config.cache
+/config.status
+/missing
+/stamp-h
+/stamp-h1
+/.la
+/.lo
+/.deps
+/.libs
+/*.la
+/*.lo
+/autom4te.cache
+/*.cache
+/missing
+/make.log
+/usrp.pc
diff --git a/firmware/fx2/include/Makefile.am b/firmware/fx2/include/Makefile.am
new file mode 100644
index 000000000..e17726c07
--- /dev/null
+++ b/firmware/fx2/include/Makefile.am
@@ -0,0 +1,61 @@
+#
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+usrpincludedir = $(includedir)/usrp
+
+usrpinclude_HEADERS = \
+ usrp_i2c_addr.h \
+ usrp_spi_defs.h \
+ fpga_regs_common.h \
+ fpga_regs_standard.h
+
+
+noinst_HEADERS = \
+ delay.h \
+ fpga_regs_common.v \
+ fpga_regs_standard.v \
+ fpga_regs0.h \
+ fx2regs.h \
+ fx2utils.h \
+ i2c.h \
+ isr.h \
+ syncdelay.h \
+ timer.h \
+ usb_common.h \
+ usb_descriptors.h \
+ usb_requests.h \
+ usrp_commands.h \
+ usrp_config.h \
+ usrp_ids.h \
+ usrp_interfaces.h
+
+
+CODE_GENERATOR = \
+ generate_regs.py
+
+EXTRA_DIST = \
+ $(CODE_GENERATOR)
+
+fpga_regs_common.v: fpga_regs_common.h generate_regs.py
+ PYTHONPATH=$(top_srcdir)/usrp/firmware/include $(PYTHON) $(srcdir)/generate_regs.py $(srcdir)/fpga_regs_common.h $@
+
+fpga_regs_standard.v: fpga_regs_standard.h generate_regs.py
+ PYTHONPATH=$(top_srcdir)/usrp/firmware/include $(PYTHON) $(srcdir)/generate_regs.py $(srcdir)/fpga_regs_standard.h $@
diff --git a/firmware/fx2/include/delay.h b/firmware/fx2/include/delay.h
new file mode 100644
index 000000000..f5df779e1
--- /dev/null
+++ b/firmware/fx2/include/delay.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _DELAY_H_
+#define _DELAY_H_
+
+/*
+ * delay for approximately usecs microseconds
+ * Note limit of 255 usecs.
+ */
+void udelay (unsigned char usecs);
+
+/*
+ * delay for approximately msecs milliseconds
+ */
+void mdelay (unsigned short msecs);
+
+
+#endif /* _DELAY_H_ */
diff --git a/firmware/fx2/include/fpga_regs0.h b/firmware/fx2/include/fpga_regs0.h
new file mode 100644
index 000000000..883798301
--- /dev/null
+++ b/firmware/fx2/include/fpga_regs0.h
@@ -0,0 +1,42 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _FPGA_REGS0_H_
+#define _FPGA_REGS0_H_
+
+#define FR_RX_FREQ_0 0
+#define FR_RX_FREQ_1 1
+#define FR_RX_FREQ_2 2
+#define FR_RX_FREQ_3 3
+#define FR_TX_FREQ_0 4
+#define FR_TX_FREQ_1 5
+#define FR_TX_FREQ_2 6
+#define FR_TX_FREQ_3 7
+#define FR_COMBO 8
+
+
+#define FR_ADC_CLK_DIV 128 // pseudo regs mapped to FR_COMBO by f/w
+#define FR_EXT_CLK_DIV 129
+#define FR_INTERP 130
+#define FR_DECIM 131
+
+#endif
diff --git a/firmware/fx2/include/fpga_regs_common.h b/firmware/fx2/include/fpga_regs_common.h
new file mode 100644
index 000000000..b4a496af7
--- /dev/null
+++ b/firmware/fx2/include/fpga_regs_common.h
@@ -0,0 +1,150 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_FPGA_REGS_COMMON_H
+#define INCLUDED_FPGA_REGS_COMMON_H
+
+// This file defines registers common to all FPGA configurations.
+// Registers 0 to 31 are reserved for use in this file.
+
+
+// The FPGA needs to know the rate that samples are coming from and
+// going to the A/D's and D/A's. div = 128e6 / sample_rate
+
+#define FR_TX_SAMPLE_RATE_DIV 0
+#define FR_RX_SAMPLE_RATE_DIV 1
+
+// 2 and 3 are defined in the ATR section
+
+#define FR_MASTER_CTRL 4 // master enable and reset controls
+# define bmFR_MC_ENABLE_TX (1 << 0)
+# define bmFR_MC_ENABLE_RX (1 << 1)
+# define bmFR_MC_RESET_TX (1 << 2)
+# define bmFR_MC_RESET_RX (1 << 3)
+
+// i/o direction registers for pins that go to daughterboards.
+// Setting the bit makes it an output from the FPGA to the d'board.
+// top 16 is mask, low 16 is value
+
+#define FR_OE_0 5 // slot 0
+#define FR_OE_1 6
+#define FR_OE_2 7
+#define FR_OE_3 8
+
+// i/o registers for pins that go to daughterboards.
+// top 16 is a mask, low 16 is value
+
+#define FR_IO_0 9 // slot 0
+#define FR_IO_1 10
+#define FR_IO_2 11
+#define FR_IO_3 12
+
+#define FR_MODE 13
+# define bmFR_MODE_NORMAL 0
+# define bmFR_MODE_LOOPBACK (1 << 0) // enable digital loopback
+# define bmFR_MODE_RX_COUNTING (1 << 1) // Rx is counting
+# define bmFR_MODE_RX_COUNTING_32BIT (1 << 2) // Rx is counting with a 32 bit counter
+ // low and high 16 bits are multiplexed across channel I and Q
+
+
+// If the corresponding bit is set, internal FPGA debug circuitry
+// controls the i/o pins for the associated bank of daughterboard
+// i/o pins. Typically used for debugging FPGA designs.
+
+#define FR_DEBUG_EN 14
+# define bmFR_DEBUG_EN_TX_A (1 << 0) // debug controls TX_A i/o
+# define bmFR_DEBUG_EN_RX_A (1 << 1) // debug controls RX_A i/o
+# define bmFR_DEBUG_EN_TX_B (1 << 2) // debug controls TX_B i/o
+# define bmFR_DEBUG_EN_RX_B (1 << 3) // debug controls RX_B i/o
+
+
+// If the corresponding bit is set, enable the automatic DC
+// offset correction control loop.
+//
+// The 4 low bits are significant:
+//
+// ADC0 = (1 << 0)
+// ADC1 = (1 << 1)
+// ADC2 = (1 << 2)
+// ADC3 = (1 << 3)
+//
+// This control loop works if the attached daugherboard blocks DC.
+// Currently all daughterboards do block DC. This includes:
+// basic rx, dbs_rx, tv_rx, flex_xxx_rx.
+
+#define FR_DC_OFFSET_CL_EN 15 // DC Offset Control Loop Enable
+
+
+// offset corrections for ADC's and DAC's (2's complement)
+
+#define FR_ADC_OFFSET_0 16
+#define FR_ADC_OFFSET_1 17
+#define FR_ADC_OFFSET_2 18
+#define FR_ADC_OFFSET_3 19
+
+
+// ------------------------------------------------------------------------
+// Automatic Transmit/Receive switching
+//
+// If automatic transmit/receive (ATR) switching is enabled in the
+// FR_ATR_CTL register, the presence or absence of data in the FPGA
+// transmit fifo selects between two sets of values for each of the 4
+// banks of daughterboard i/o pins.
+//
+// Each daughterboard slot has 3 16-bit registers associated with it:
+// FR_ATR_MASK_*, FR_ATR_TXVAL_* and FR_ATR_RXVAL_*
+//
+// FR_ATR_MASK_{0,1,2,3}:
+//
+// These registers determine which of the daugherboard i/o pins are
+// affected by ATR switching. If a bit in the mask is set, the
+// corresponding i/o bit is controlled by ATR, else it's output
+// value comes from the normal i/o pin output register:
+// FR_IO_{0,1,2,3}.
+//
+// FR_ATR_TXVAL_{0,1,2,3}:
+// FR_ATR_RXVAL_{0,1,2,3}:
+//
+// If the Tx fifo contains data, then the bits from TXVAL that are
+// selected by MASK are output. Otherwise, the bits from RXVAL that
+// are selected by MASK are output.
+
+#define FR_ATR_MASK_0 20 // slot 0
+#define FR_ATR_TXVAL_0 21
+#define FR_ATR_RXVAL_0 22
+
+#define FR_ATR_MASK_1 23 // slot 1
+#define FR_ATR_TXVAL_1 24
+#define FR_ATR_RXVAL_1 25
+
+#define FR_ATR_MASK_2 26 // slot 2
+#define FR_ATR_TXVAL_2 27
+#define FR_ATR_RXVAL_2 28
+
+#define FR_ATR_MASK_3 29 // slot 3
+#define FR_ATR_TXVAL_3 30
+#define FR_ATR_RXVAL_3 31
+
+// Clock ticks to delay rising and falling edge of T/R signal
+#define FR_ATR_TX_DELAY 2
+#define FR_ATR_RX_DELAY 3
+
+#endif /* INCLUDED_FPGA_REGS_COMMON_H */
diff --git a/firmware/fx2/include/fpga_regs_common.v b/firmware/fx2/include/fpga_regs_common.v
new file mode 100644
index 000000000..8035d8565
--- /dev/null
+++ b/firmware/fx2/include/fpga_regs_common.v
@@ -0,0 +1,117 @@
+//
+// This file is machine generated from ./fpga_regs_common.h
+// Do not edit by hand; your edits will be overwritten.
+//
+
+// This file defines registers common to all FPGA configurations.
+// Registers 0 to 31 are reserved for use in this file.
+
+
+// The FPGA needs to know the rate that samples are coming from and
+// going to the A/D's and D/A's. div = 128e6 / sample_rate
+
+`define FR_TX_SAMPLE_RATE_DIV 7'd0
+`define FR_RX_SAMPLE_RATE_DIV 7'd1
+
+// 2 and 3 are defined in the ATR section
+
+`define FR_MASTER_CTRL 7'd4 // master enable and reset controls
+
+// i/o direction registers for pins that go to daughterboards.
+// Setting the bit makes it an output from the FPGA to the d'board.
+// top 16 is mask, low 16 is value
+
+`define FR_OE_0 7'd5 // slot 0
+`define FR_OE_1 7'd6
+`define FR_OE_2 7'd7
+`define FR_OE_3 7'd8
+
+// i/o registers for pins that go to daughterboards.
+// top 16 is a mask, low 16 is value
+
+`define FR_IO_0 7'd9 // slot 0
+`define FR_IO_1 7'd10
+`define FR_IO_2 7'd11
+`define FR_IO_3 7'd12
+
+`define FR_MODE 7'd13
+
+
+// If the corresponding bit is set, internal FPGA debug circuitry
+// controls the i/o pins for the associated bank of daughterboard
+// i/o pins. Typically used for debugging FPGA designs.
+
+`define FR_DEBUG_EN 7'd14
+
+
+// If the corresponding bit is set, enable the automatic DC
+// offset correction control loop.
+//
+// The 4 low bits are significant:
+//
+// ADC0 = (1 << 0)
+// ADC1 = (1 << 1)
+// ADC2 = (1 << 2)
+// ADC3 = (1 << 3)
+//
+// This control loop works if the attached daugherboard blocks DC.
+// Currently all daughterboards do block DC. This includes:
+// basic rx, dbs_rx, tv_rx, flex_xxx_rx.
+
+`define FR_DC_OFFSET_CL_EN 7'd15 // DC Offset Control Loop Enable
+
+
+// offset corrections for ADC's and DAC's (2's complement)
+
+`define FR_ADC_OFFSET_0 7'd16
+`define FR_ADC_OFFSET_1 7'd17
+`define FR_ADC_OFFSET_2 7'd18
+`define FR_ADC_OFFSET_3 7'd19
+
+
+// ------------------------------------------------------------------------
+// Automatic Transmit/Receive switching
+//
+// If automatic transmit/receive (ATR) switching is enabled in the
+// FR_ATR_CTL register, the presence or absence of data in the FPGA
+// transmit fifo selects between two sets of values for each of the 4
+// banks of daughterboard i/o pins.
+//
+// Each daughterboard slot has 3 16-bit registers associated with it:
+// FR_ATR_MASK_*, FR_ATR_TXVAL_* and FR_ATR_RXVAL_*
+//
+// FR_ATR_MASK_{0,1,2,3}:
+//
+// These registers determine which of the daugherboard i/o pins are
+// affected by ATR switching. If a bit in the mask is set, the
+// corresponding i/o bit is controlled by ATR, else it's output
+// value comes from the normal i/o pin output register:
+// FR_IO_{0,1,2,3}.
+//
+// FR_ATR_TXVAL_{0,1,2,3}:
+// FR_ATR_RXVAL_{0,1,2,3}:
+//
+// If the Tx fifo contains data, then the bits from TXVAL that are
+// selected by MASK are output. Otherwise, the bits from RXVAL that
+// are selected by MASK are output.
+
+`define FR_ATR_MASK_0 7'd20 // slot 0
+`define FR_ATR_TXVAL_0 7'd21
+`define FR_ATR_RXVAL_0 7'd22
+
+`define FR_ATR_MASK_1 7'd23 // slot 1
+`define FR_ATR_TXVAL_1 7'd24
+`define FR_ATR_RXVAL_1 7'd25
+
+`define FR_ATR_MASK_2 7'd26 // slot 2
+`define FR_ATR_TXVAL_2 7'd27
+`define FR_ATR_RXVAL_2 7'd28
+
+`define FR_ATR_MASK_3 7'd29 // slot 3
+`define FR_ATR_TXVAL_3 7'd30
+`define FR_ATR_RXVAL_3 7'd31
+
+// Clock ticks to delay rising and falling edge of T/R signal
+`define FR_ATR_TX_DELAY 7'd2
+`define FR_ATR_RX_DELAY 7'd3
+
diff --git a/firmware/fx2/include/fpga_regs_standard.h b/firmware/fx2/include/fpga_regs_standard.h
new file mode 100644
index 000000000..7485e2bab
--- /dev/null
+++ b/firmware/fx2/include/fpga_regs_standard.h
@@ -0,0 +1,300 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2004,2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_FPGA_REGS_STANDARD_H
+#define INCLUDED_FPGA_REGS_STANDARD_H
+
+// Register numbers 0 to 31 are reserved for use in fpga_regs_common.h.
+// Registers 64 to 79 are available for custom FPGA builds.
+
+
+// DDC / DUC
+
+#define FR_INTERP_RATE 32 // [1,1024]
+#define FR_DECIM_RATE 33 // [1,256]
+
+// DDC center freq
+
+#define FR_RX_FREQ_0 34
+#define FR_RX_FREQ_1 35
+#define FR_RX_FREQ_2 36
+#define FR_RX_FREQ_3 37
+
+// See below for DDC Starting Phase
+
+// ------------------------------------------------------------------------
+// configure FPGA Rx mux
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------+-------+-------+-------+-------+-+-----+
+// | must be zero | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
+// +-----------------------+-------+-------+-------+-------+-+-----+
+//
+// There are a maximum of 4 digital downconverters in the the FPGA.
+// Each DDC has two 16-bit inputs, I and Q, and two 16-bit outputs, I & Q.
+//
+// DDC I inputs are specified by the two bit fields I3, I2, I1 & I0
+//
+// 0 = DDC input is from ADC 0
+// 1 = DDC input is from ADC 1
+// 2 = DDC input is from ADC 2
+// 3 = DDC input is from ADC 3
+//
+// If Z == 1, all DDC Q inputs are set to zero
+// If Z == 0, DDC Q inputs are specified by the two bit fields Q3, Q2, Q1 & Q0
+//
+// NCH specifies the number of complex channels that are sent across
+// the USB. The legal values are 1, 2 or 4, corresponding to 2, 4 or
+// 8 16-bit values.
+
+#define FR_RX_MUX 38
+
+// ------------------------------------------------------------------------
+// configure FPGA Tx Mux.
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------+-------+-------+-------+-------+-+-----+
+// | | DAC3 | DAC2 | DAC1 | DAC0 |0| NCH |
+// +-----------------------------------------------+-------+-+-----+
+//
+// NCH specifies the number of complex channels that are sent across
+// the USB. The legal values are 1 or 2, corresponding to 2 or 4
+// 16-bit values.
+//
+// There are two interpolators with complex inputs and outputs.
+// There are four DACs. (We use the DUC in each AD9862.)
+//
+// Each 4-bit DACx field specifies the source for the DAC and
+// whether or not that DAC is enabled. Each subfield is coded
+// like this:
+//
+// 3 2 1 0
+// +-+-----+
+// |E| N |
+// +-+-----+
+//
+// Where E is set if the DAC is enabled, and N specifies which
+// interpolator output is connected to this DAC.
+//
+// N which interp output
+// --- -------------------
+// 0 chan 0 I
+// 1 chan 0 Q
+// 2 chan 1 I
+// 3 chan 1 Q
+
+#define FR_TX_MUX 39
+
+// ------------------------------------------------------------------------
+// REFCLK control
+//
+// Control whether a reference clock is sent to the daughterboards,
+// and what frequency. The refclk is sent on d'board i/o pin 0.
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------------------------------+-+------------+
+// | Reserved (Must be zero) |E| DIVISOR |
+// +-----------------------------------------------+-+------------+
+
+//
+// Bit 7 -- 1 turns on refclk, 0 allows IO use
+// Bits 6:0 Divider value
+
+#define FR_TX_A_REFCLK 40
+#define FR_RX_A_REFCLK 41
+#define FR_TX_B_REFCLK 42
+#define FR_RX_B_REFCLK 43
+
+# define bmFR_REFCLK_EN 0x80
+# define bmFR_REFCLK_DIVISOR_MASK 0x7f
+
+// ------------------------------------------------------------------------
+// DDC Starting Phase
+
+#define FR_RX_PHASE_0 44
+#define FR_RX_PHASE_1 45
+#define FR_RX_PHASE_2 46
+#define FR_RX_PHASE_3 47
+
+// ------------------------------------------------------------------------
+// Tx data format control register
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-------------------------------------------------------+-------+
+// | Reserved (Must be zero) | FMT |
+// +-------------------------------------------------------+-------+
+//
+// FMT values:
+
+#define FR_TX_FORMAT 48
+# define bmFR_TX_FORMAT_16_IQ 0 // 16-bit I, 16-bit Q
+
+// ------------------------------------------------------------------------
+// Rx data format control register
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------------------------+-+-+---------+-------+
+// | Reserved (Must be zero) |B|Q| WIDTH | SHIFT |
+// +-----------------------------------------+-+-+---------+-------+
+//
+// FMT values:
+
+#define FR_RX_FORMAT 49
+
+# define bmFR_RX_FORMAT_SHIFT_MASK (0x0f << 0) // arithmetic right shift [0, 15]
+# define bmFR_RX_FORMAT_SHIFT_SHIFT 0
+# define bmFR_RX_FORMAT_WIDTH_MASK (0x1f << 4) // data width in bits [1, 16] (not all valid)
+# define bmFR_RX_FORMAT_WIDTH_SHIFT 4
+# define bmFR_RX_FORMAT_WANT_Q (0x1 << 9) // deliver both I & Q, else just I
+# define bmFR_RX_FORMAT_BYPASS_HB (0x1 << 10) // bypass half-band filter
+
+// The valid combinations currently are:
+//
+// B Q WIDTH SHIFT
+// 0 1 16 0
+// 0 1 8 8
+
+
+// Possible future values of WIDTH = {4, 2, 1}
+// 12 takes a bit more work, since we need to know packet alignment.
+
+// ------------------------------------------------------------------------
+// FIXME register numbers 50 to 63 are available
+
+// ------------------------------------------------------------------------
+// Registers 64 to 95 are reserved for user custom FPGA builds.
+// The standard USRP software will not touch these.
+
+#define FR_USER_0 64
+#define FR_USER_1 65
+#define FR_USER_2 66
+#define FR_USER_3 67
+#define FR_USER_4 68
+#define FR_USER_5 69
+#define FR_USER_6 70
+#define FR_USER_7 71
+#define FR_USER_8 72
+#define FR_USER_9 73
+#define FR_USER_10 74
+#define FR_USER_11 75
+#define FR_USER_12 76
+#define FR_USER_13 77
+#define FR_USER_14 78
+#define FR_USER_15 79
+#define FR_USER_16 80
+#define FR_USER_17 81
+#define FR_USER_18 82
+#define FR_USER_19 83
+#define FR_USER_20 84
+#define FR_USER_21 85
+#define FR_USER_22 86
+#define FR_USER_23 87
+#define FR_USER_24 88
+#define FR_USER_25 89
+#define FR_USER_26 90
+#define FR_USER_27 91
+#define FR_USER_28 92
+#define FR_USER_29 93
+#define FR_USER_30 94
+#define FR_USER_31 95
+
+//Registers needed for multi usrp master/slave configuration
+//
+//Rx Master/slave control register (FR_RX_MASTER_SLAVE = FR_USER_0)
+//
+#define FR_RX_MASTER_SLAVE 64
+#define bitnoFR_RX_SYNC 0
+#define bitnoFR_RX_SYNC_MASTER 1
+#define bitnoFR_RX_SYNC_SLAVE 2
+# define bmFR_RX_SYNC (1 <<bitnoFR_RX_SYNC) //1 If this is a master "sync now" and send sync to slave.
+ // If this is a slave "sync now" (testing purpose only)
+ // Sync is allmost the same as reset (clear all counters and buffers)
+ // except that the io outputs and settings don't get reset (otherwise it couldn't send the sync to the slave)
+ //0 Normal operation
+
+# define bmFR_RX_SYNC_MASTER (1 <<bitnoFR_RX_SYNC_MASTER) //1 This is a rx sync master, output sync_rx on rx_a_io[15]
+ //0 This is not a rx sync master
+# define bmFR_RX_SYNC_SLAVE (1 <<bitnoFR_RX_SYNC_SLAVE) //1 This is a rx sync slave, follow sync_rx on rx_a_io[bitnoFR_RX_SYNC_INPUT_IOPIN]
+ //0 This is not an rx sync slave.
+
+//Caution The master settings will output values on the io lines.
+//They inheritely enable these lines as output. If you have a daughtercard which uses these lines also as output then you will burn your usrp and daughtercard.
+//If you set the slave bits then your usrp won't do anything if you don't connect a master.
+// Rx Master/slave control register
+//
+// The way this is supposed to be used is connecting a (short) 16pin flatcable from an rx daughterboard in RXA master io_rx[8..15] to slave io_rx[8..15] on RXA of slave usrp
+// This can be done with basic_rx boards or dbsrx boards
+//dbsrx: connect master-J25 to slave-J25
+//basic rx: connect J25 to slave-J25
+//CAUTION: pay attention to the lineup of your connector.
+//The red line (pin1) should be at the same side of the daughterboards on master and slave.
+//If you turnaround the cable on one end you will burn your usrp.
+
+//You cannot use a 16pin flatcable if you are using FLEX400 or FLEX2400 daughterboards, since these use a lot of the io pins.
+//You can still link them but you must use only a 2pin or 1pin cable
+//You can also use a 2-wire link. put a 2pin header on io[15],gnd of the master RXA daughterboard and connect it to io15,gnd of the slave RXA db.
+//You can use a cable like the ones found with the leds on the mainbord of a PC.
+//Make sure you don't twist the cable, otherwise you connect the sync output to ground.
+//To be save you could also just use a single wire from master io[15] to slave io[15], but this is not optimal for signal integrity.
+
+
+// Since rx_io[0] can normally be used as a refclk and is not exported on all daughterboards this line
+// still has the refclk function if you use the master/slave setup (it is not touched by the master/slave settings).
+// The master/slave circuitry will only use io pin 15 and does not touch any of the other io pins.
+#define bitnoFR_RX_SYNC_INPUT_IOPIN 15
+#define bmFR_RX_SYNC_INPUT_IOPIN (1<<bitnoFR_RX_SYNC_INPUT_IOPIN)
+//TODO the output pin is still hardcoded in the verilog code, make it listen to the following define
+#define bitnoFR_RX_SYNC_OUTPUT_IOPIN 15
+#define bmFR_RX_SYNC_OUTPUT_IOPIN (1<<bitnoFR_RX_SYNC_OUTPUT_IOPIN)
+// =======================================================================
+// READBACK Registers
+// =======================================================================
+
+#define FR_RB_IO_RX_A_IO_TX_A 1 // read back a-side i/o pins
+#define FR_RB_IO_RX_B_IO_TX_B 2 // read back b-side i/o pins
+
+// ------------------------------------------------------------------------
+// FPGA Capability register
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------------------------------+-+-----+-+-----+
+// | Reserved (Must be zero) |T|NDUC |R|NDDC |
+// +-----------------------------------------------+-+-----+-+-----+
+//
+// Bottom 4-bits are Rx capabilities
+// Next 4-bits are Tx capabilities
+
+#define FR_RB_CAPS 3
+# define bmFR_RB_CAPS_NDDC_MASK (0x7 << 0) // # of digital down converters 0,1,2,4
+# define bmFR_RB_CAPS_NDDC_SHIFT 0
+# define bmFR_RB_CAPS_RX_HAS_HALFBAND (0x1 << 3)
+# define bmFR_RB_CAPS_NDUC_MASK (0x7 << 4) // # of digital up converters 0,1,2
+# define bmFR_RB_CAPS_NDUC_SHIFT 4
+# define bmFR_RB_CAPS_TX_HAS_HALFBAND (0x1 << 7)
+
+
+#endif /* INCLUDED_FPGA_REGS_STANDARD_H */
diff --git a/firmware/fx2/include/fpga_regs_standard.v b/firmware/fx2/include/fpga_regs_standard.v
new file mode 100644
index 000000000..d09aa6116
--- /dev/null
+++ b/firmware/fx2/include/fpga_regs_standard.v
@@ -0,0 +1,256 @@
+//
+// This file is machine generated from ./fpga_regs_standard.h
+// Do not edit by hand; your edits will be overwritten.
+//
+
+// Register numbers 0 to 31 are reserved for use in fpga_regs_common.h.
+// Registers 64 to 79 are available for custom FPGA builds.
+
+
+// DDC / DUC
+
+`define FR_INTERP_RATE 7'd32 // [1,1024]
+`define FR_DECIM_RATE 7'd33 // [1,256]
+
+// DDC center freq
+
+`define FR_RX_FREQ_0 7'd34
+`define FR_RX_FREQ_1 7'd35
+`define FR_RX_FREQ_2 7'd36
+`define FR_RX_FREQ_3 7'd37
+
+// See below for DDC Starting Phase
+
+// ------------------------------------------------------------------------
+// configure FPGA Rx mux
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------+-------+-------+-------+-------+-+-----+
+// | must be zero | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
+// +-----------------------+-------+-------+-------+-------+-+-----+
+//
+// There are a maximum of 4 digital downconverters in the the FPGA.
+// Each DDC has two 16-bit inputs, I and Q, and two 16-bit outputs, I & Q.
+//
+// DDC I inputs are specified by the two bit fields I3, I2, I1 & I0
+//
+// 0 = DDC input is from ADC 0
+// 1 = DDC input is from ADC 1
+// 2 = DDC input is from ADC 2
+// 3 = DDC input is from ADC 3
+//
+// If Z == 1, all DDC Q inputs are set to zero
+// If Z == 0, DDC Q inputs are specified by the two bit fields Q3, Q2, Q1 & Q0
+//
+// NCH specifies the number of complex channels that are sent across
+// the USB. The legal values are 1, 2 or 4, corresponding to 2, 4 or
+// 8 16-bit values.
+
+`define FR_RX_MUX 7'd38
+
+// ------------------------------------------------------------------------
+// configure FPGA Tx Mux.
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------+-------+-------+-------+-------+-+-----+
+// | | DAC3 | DAC2 | DAC1 | DAC0 |0| NCH |
+// +-----------------------------------------------+-------+-+-----+
+//
+// NCH specifies the number of complex channels that are sent across
+// the USB. The legal values are 1 or 2, corresponding to 2 or 4
+// 16-bit values.
+//
+// There are two interpolators with complex inputs and outputs.
+// There are four DACs. (We use the DUC in each AD9862.)
+//
+// Each 4-bit DACx field specifies the source for the DAC and
+// whether or not that DAC is enabled. Each subfield is coded
+// like this:
+//
+// 3 2 1 0
+// +-+-----+
+// |E| N |
+// +-+-----+
+//
+// Where E is set if the DAC is enabled, and N specifies which
+// interpolator output is connected to this DAC.
+//
+// N which interp output
+// --- -------------------
+// 0 chan 0 I
+// 1 chan 0 Q
+// 2 chan 1 I
+// 3 chan 1 Q
+
+`define FR_TX_MUX 7'd39
+
+// ------------------------------------------------------------------------
+// REFCLK control
+//
+// Control whether a reference clock is sent to the daughterboards,
+// and what frequency. The refclk is sent on d'board i/o pin 0.
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------------------------------+-+------------+
+// | Reserved (Must be zero) |E| DIVISOR |
+// +-----------------------------------------------+-+------------+
+
+//
+// Bit 7 -- 1 turns on refclk, 0 allows IO use
+// Bits 6:0 Divider value
+
+`define FR_TX_A_REFCLK 7'd40
+`define FR_RX_A_REFCLK 7'd41
+`define FR_TX_B_REFCLK 7'd42
+`define FR_RX_B_REFCLK 7'd43
+
+
+// ------------------------------------------------------------------------
+// DDC Starting Phase
+
+`define FR_RX_PHASE_0 7'd44
+`define FR_RX_PHASE_1 7'd45
+`define FR_RX_PHASE_2 7'd46
+`define FR_RX_PHASE_3 7'd47
+
+// ------------------------------------------------------------------------
+// Tx data format control register
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-------------------------------------------------------+-------+
+// | Reserved (Must be zero) | FMT |
+// +-------------------------------------------------------+-------+
+//
+// FMT values:
+
+`define FR_TX_FORMAT 7'd48
+
+// ------------------------------------------------------------------------
+// Rx data format control register
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------------------------+-+-+---------+-------+
+// | Reserved (Must be zero) |B|Q| WIDTH | SHIFT |
+// +-----------------------------------------+-+-+---------+-------+
+//
+// FMT values:
+
+`define FR_RX_FORMAT 7'd49
+
+
+// The valid combinations currently are:
+//
+// B Q WIDTH SHIFT
+// 0 1 16 0
+// 0 1 8 8
+
+
+// Possible future values of WIDTH = {4, 2, 1}
+// 12 takes a bit more work, since we need to know packet alignment.
+
+// ------------------------------------------------------------------------
+// FIXME register numbers 50 to 63 are available
+
+// ------------------------------------------------------------------------
+// Registers 64 to 95 are reserved for user custom FPGA builds.
+// The standard USRP software will not touch these.
+
+`define FR_USER_0 7'd64
+`define FR_USER_1 7'd65
+`define FR_USER_2 7'd66
+`define FR_USER_3 7'd67
+`define FR_USER_4 7'd68
+`define FR_USER_5 7'd69
+`define FR_USER_6 7'd70
+`define FR_USER_7 7'd71
+`define FR_USER_8 7'd72
+`define FR_USER_9 7'd73
+`define FR_USER_10 7'd74
+`define FR_USER_11 7'd75
+`define FR_USER_12 7'd76
+`define FR_USER_13 7'd77
+`define FR_USER_14 7'd78
+`define FR_USER_15 7'd79
+`define FR_USER_16 7'd80
+`define FR_USER_17 7'd81
+`define FR_USER_18 7'd82
+`define FR_USER_19 7'd83
+`define FR_USER_20 7'd84
+`define FR_USER_21 7'd85
+`define FR_USER_22 7'd86
+`define FR_USER_23 7'd87
+`define FR_USER_24 7'd88
+`define FR_USER_25 7'd89
+`define FR_USER_26 7'd90
+`define FR_USER_27 7'd91
+`define FR_USER_28 7'd92
+`define FR_USER_29 7'd93
+`define FR_USER_30 7'd94
+`define FR_USER_31 7'd95
+
+//Registers needed for multi usrp master/slave configuration
+//
+//Rx Master/slave control register (FR_RX_MASTER_SLAVE = FR_USER_0)
+//
+`define FR_RX_MASTER_SLAVE 7'd64
+`define bitnoFR_RX_SYNC 0
+`define bitnoFR_RX_SYNC_MASTER 1
+`define bitnoFR_RX_SYNC_SLAVE 2
+
+
+//Caution The master settings will output values on the io lines.
+//They inheritely enable these lines as output. If you have a daughtercard which uses these lines also as output then you will burn your usrp and daughtercard.
+//If you set the slave bits then your usrp won't do anything if you don't connect a master.
+// Rx Master/slave control register
+//
+// The way this is supposed to be used is connecting a (short) 16pin flatcable from an rx daughterboard in RXA master io_rx[8..15] to slave io_rx[8..15] on RXA of slave usrp
+// This can be done with basic_rx boards or dbsrx boards
+//dbsrx: connect master-J25 to slave-J25
+//basic rx: connect J25 to slave-J25
+//CAUTION: pay attention to the lineup of your connector.
+//The red line (pin1) should be at the same side of the daughterboards on master and slave.
+//If you turnaround the cable on one end you will burn your usrp.
+
+//You cannot use a 16pin flatcable if you are using FLEX400 or FLEX2400 daughterboards, since these use a lot of the io pins.
+//You can still link them but you must use only a 2pin or 1pin cable
+//You can also use a 2-wire link. put a 2pin header on io[15],gnd of the master RXA daughterboard and connect it to io15,gnd of the slave RXA db.
+//You can use a cable like the ones found with the leds on the mainbord of a PC.
+//Make sure you don't twist the cable, otherwise you connect the sync output to ground.
+//To be save you could also just use a single wire from master io[15] to slave io[15], but this is not optimal for signal integrity.
+
+
+// Since rx_io[0] can normally be used as a refclk and is not exported on all daughterboards this line
+// still has the refclk function if you use the master/slave setup (it is not touched by the master/slave settings).
+// The master/slave circuitry will only use io pin 15 and does not touch any of the other io pins.
+`define bitnoFR_RX_SYNC_INPUT_IOPIN 15
+`define bmFR_RX_SYNC_INPUT_IOPIN (1<<bitnoFR_RX_SYNC_INPUT_IOPIN)
+//TODO the output pin is still hardcoded in the verilog code, make it listen to the following define
+`define bitnoFR_RX_SYNC_OUTPUT_IOPIN 15
+`define bmFR_RX_SYNC_OUTPUT_IOPIN (1<<bitnoFR_RX_SYNC_OUTPUT_IOPIN)
+// =======================================================================
+// READBACK Registers
+// =======================================================================
+
+`define FR_RB_IO_RX_A_IO_TX_A 7'd1 // read back a-side i/o pins
+`define FR_RB_IO_RX_B_IO_TX_B 7'd2 // read back b-side i/o pins
+
+// ------------------------------------------------------------------------
+// FPGA Capability register
+//
+// 3 2 1
+// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+// +-----------------------------------------------+-+-----+-+-----+
+// | Reserved (Must be zero) |T|NDUC |R|NDDC |
+// +-----------------------------------------------+-+-----+-+-----+
+//
+// Bottom 4-bits are Rx capabilities
+// Next 4-bits are Tx capabilities
+
+`define FR_RB_CAPS 7'd3
+
+
diff --git a/firmware/fx2/include/fx2regs.h b/firmware/fx2/include/fx2regs.h
new file mode 100644
index 000000000..2f210f567
--- /dev/null
+++ b/firmware/fx2/include/fx2regs.h
@@ -0,0 +1,716 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+//-----------------------------------------------------------------------------
+// File: FX2regs.h
+// Contents: EZ-USB FX2 register declarations and bit mask definitions.
+//
+// $Archive: /USB/Target/Inc/fx2regs.h $
+// $Date$
+// $Revision$
+//
+//
+// Copyright (c) 2000 Cypress Semiconductor, All rights reserved
+//-----------------------------------------------------------------------------
+*/
+
+
+#ifndef FX2REGS_H /* Header Sentry */
+#define FX2REGS_H
+
+#define ALLOCATE_EXTERN // required for "right thing to happen" with fx2regs.h
+
+/*
+//-----------------------------------------------------------------------------
+// FX2 Related Register Assignments
+//-----------------------------------------------------------------------------
+
+// The Ez-USB FX2 registers are defined here. We use FX2regs.h for register
+// address allocation by using "#define ALLOCATE_EXTERN".
+// When using "#define ALLOCATE_EXTERN", you get (for instance):
+// xdata volatile BYTE OUT7BUF[64] _at_ 0x7B40;
+// Such lines are created from FX2.h by using the preprocessor.
+// Incidently, these lines will not generate any space in the resulting hex
+// file; they just bind the symbols to the addresses for compilation.
+// You just need to put "#define ALLOCATE_EXTERN" in your main program file;
+// i.e. fw.c or a stand-alone C source file.
+// Without "#define ALLOCATE_EXTERN", you just get the external reference:
+// extern xdata volatile BYTE OUT7BUF[64] ;// 0x7B40;
+// This uses the concatenation operator "##" to insert a comment "//"
+// to cut off the end of the line, "_at_ 0x7B40;", which is not wanted.
+*/
+
+
+#ifdef ALLOCATE_EXTERN
+#define EXTERN
+#define _AT_(a) at a
+#else
+#define EXTERN extern
+#define _AT_ ;/ ## /
+#endif
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+
+EXTERN xdata _AT_(0xE400) volatile BYTE GPIF_WAVE_DATA[128];
+EXTERN xdata _AT_(0xE480) volatile BYTE RES_WAVEDATA_END ;
+
+// General Configuration
+
+EXTERN xdata _AT_(0xE600) volatile BYTE CPUCS ; // Control & Status
+EXTERN xdata _AT_(0xE601) volatile BYTE IFCONFIG ; // Interface Configuration
+EXTERN xdata _AT_(0xE602) volatile BYTE PINFLAGSAB ; // FIFO FLAGA and FLAGB Assignments
+EXTERN xdata _AT_(0xE603) volatile BYTE PINFLAGSCD ; // FIFO FLAGC and FLAGD Assignments
+EXTERN xdata _AT_(0xE604) volatile BYTE FIFORESET ; // Restore FIFOS to default state
+EXTERN xdata _AT_(0xE605) volatile BYTE BREAKPT ; // Breakpoint
+EXTERN xdata _AT_(0xE606) volatile BYTE BPADDRH ; // Breakpoint Address H
+EXTERN xdata _AT_(0xE607) volatile BYTE BPADDRL ; // Breakpoint Address L
+EXTERN xdata _AT_(0xE608) volatile BYTE UART230 ; // 230 Kbaud clock for T0,T1,T2
+EXTERN xdata _AT_(0xE609) volatile BYTE FIFOPINPOLAR ; // FIFO polarities
+EXTERN xdata _AT_(0xE60A) volatile BYTE REVID ; // Chip Revision
+EXTERN xdata _AT_(0xE60B) volatile BYTE REVCTL ; // Chip Revision Control
+
+// Endpoint Configuration
+
+EXTERN xdata _AT_(0xE610) volatile BYTE EP1OUTCFG ; // Endpoint 1-OUT Configuration
+EXTERN xdata _AT_(0xE611) volatile BYTE EP1INCFG ; // Endpoint 1-IN Configuration
+EXTERN xdata _AT_(0xE612) volatile BYTE EP2CFG ; // Endpoint 2 Configuration
+EXTERN xdata _AT_(0xE613) volatile BYTE EP4CFG ; // Endpoint 4 Configuration
+EXTERN xdata _AT_(0xE614) volatile BYTE EP6CFG ; // Endpoint 6 Configuration
+EXTERN xdata _AT_(0xE615) volatile BYTE EP8CFG ; // Endpoint 8 Configuration
+EXTERN xdata _AT_(0xE618) volatile BYTE EP2FIFOCFG ; // Endpoint 2 FIFO configuration
+EXTERN xdata _AT_(0xE619) volatile BYTE EP4FIFOCFG ; // Endpoint 4 FIFO configuration
+EXTERN xdata _AT_(0xE61A) volatile BYTE EP6FIFOCFG ; // Endpoint 6 FIFO configuration
+EXTERN xdata _AT_(0xE61B) volatile BYTE EP8FIFOCFG ; // Endpoint 8 FIFO configuration
+EXTERN xdata _AT_(0xE620) volatile BYTE EP2AUTOINLENH ; // Endpoint 2 Packet Length H (IN only)
+EXTERN xdata _AT_(0xE621) volatile BYTE EP2AUTOINLENL ; // Endpoint 2 Packet Length L (IN only)
+EXTERN xdata _AT_(0xE622) volatile BYTE EP4AUTOINLENH ; // Endpoint 4 Packet Length H (IN only)
+EXTERN xdata _AT_(0xE623) volatile BYTE EP4AUTOINLENL ; // Endpoint 4 Packet Length L (IN only)
+EXTERN xdata _AT_(0xE624) volatile BYTE EP6AUTOINLENH ; // Endpoint 6 Packet Length H (IN only)
+EXTERN xdata _AT_(0xE625) volatile BYTE EP6AUTOINLENL ; // Endpoint 6 Packet Length L (IN only)
+EXTERN xdata _AT_(0xE626) volatile BYTE EP8AUTOINLENH ; // Endpoint 8 Packet Length H (IN only)
+EXTERN xdata _AT_(0xE627) volatile BYTE EP8AUTOINLENL ; // Endpoint 8 Packet Length L (IN only)
+EXTERN xdata _AT_(0xE630) volatile BYTE EP2FIFOPFH ; // EP2 Programmable Flag trigger H
+EXTERN xdata _AT_(0xE631) volatile BYTE EP2FIFOPFL ; // EP2 Programmable Flag trigger L
+EXTERN xdata _AT_(0xE632) volatile BYTE EP4FIFOPFH ; // EP4 Programmable Flag trigger H
+EXTERN xdata _AT_(0xE633) volatile BYTE EP4FIFOPFL ; // EP4 Programmable Flag trigger L
+EXTERN xdata _AT_(0xE634) volatile BYTE EP6FIFOPFH ; // EP6 Programmable Flag trigger H
+EXTERN xdata _AT_(0xE635) volatile BYTE EP6FIFOPFL ; // EP6 Programmable Flag trigger L
+EXTERN xdata _AT_(0xE636) volatile BYTE EP8FIFOPFH ; // EP8 Programmable Flag trigger H
+EXTERN xdata _AT_(0xE637) volatile BYTE EP8FIFOPFL ; // EP8 Programmable Flag trigger L
+EXTERN xdata _AT_(0xE640) volatile BYTE EP2ISOINPKTS ; // EP2 (if ISO) IN Packets per frame (1-3)
+EXTERN xdata _AT_(0xE641) volatile BYTE EP4ISOINPKTS ; // EP4 (if ISO) IN Packets per frame (1-3)
+EXTERN xdata _AT_(0xE642) volatile BYTE EP6ISOINPKTS ; // EP6 (if ISO) IN Packets per frame (1-3)
+EXTERN xdata _AT_(0xE643) volatile BYTE EP8ISOINPKTS ; // EP8 (if ISO) IN Packets per frame (1-3)
+EXTERN xdata _AT_(0xE648) volatile BYTE INPKTEND ; // Force IN Packet End
+EXTERN xdata _AT_(0xE649) volatile BYTE OUTPKTEND ; // Force OUT Packet End
+
+// Interrupts
+
+EXTERN xdata _AT_(0xE650) volatile BYTE EP2FIFOIE ; // Endpoint 2 Flag Interrupt Enable
+EXTERN xdata _AT_(0xE651) volatile BYTE EP2FIFOIRQ ; // Endpoint 2 Flag Interrupt Request
+EXTERN xdata _AT_(0xE652) volatile BYTE EP4FIFOIE ; // Endpoint 4 Flag Interrupt Enable
+EXTERN xdata _AT_(0xE653) volatile BYTE EP4FIFOIRQ ; // Endpoint 4 Flag Interrupt Request
+EXTERN xdata _AT_(0xE654) volatile BYTE EP6FIFOIE ; // Endpoint 6 Flag Interrupt Enable
+EXTERN xdata _AT_(0xE655) volatile BYTE EP6FIFOIRQ ; // Endpoint 6 Flag Interrupt Request
+EXTERN xdata _AT_(0xE656) volatile BYTE EP8FIFOIE ; // Endpoint 8 Flag Interrupt Enable
+EXTERN xdata _AT_(0xE657) volatile BYTE EP8FIFOIRQ ; // Endpoint 8 Flag Interrupt Request
+EXTERN xdata _AT_(0xE658) volatile BYTE IBNIE ; // IN-BULK-NAK Interrupt Enable
+EXTERN xdata _AT_(0xE659) volatile BYTE IBNIRQ ; // IN-BULK-NAK interrupt Request
+EXTERN xdata _AT_(0xE65A) volatile BYTE NAKIE ; // Endpoint Ping NAK interrupt Enable
+EXTERN xdata _AT_(0xE65B) volatile BYTE NAKIRQ ; // Endpoint Ping NAK interrupt Request
+EXTERN xdata _AT_(0xE65C) volatile BYTE USBIE ; // USB Int Enables
+EXTERN xdata _AT_(0xE65D) volatile BYTE USBIRQ ; // USB Interrupt Requests
+EXTERN xdata _AT_(0xE65E) volatile BYTE EPIE ; // Endpoint Interrupt Enables
+EXTERN xdata _AT_(0xE65F) volatile BYTE EPIRQ ; // Endpoint Interrupt Requests
+EXTERN xdata _AT_(0xE660) volatile BYTE GPIFIE ; // GPIF Interrupt Enable
+EXTERN xdata _AT_(0xE661) volatile BYTE GPIFIRQ ; // GPIF Interrupt Request
+EXTERN xdata _AT_(0xE662) volatile BYTE USBERRIE ; // USB Error Interrupt Enables
+EXTERN xdata _AT_(0xE663) volatile BYTE USBERRIRQ ; // USB Error Interrupt Requests
+EXTERN xdata _AT_(0xE664) volatile BYTE ERRCNTLIM ; // USB Error counter and limit
+EXTERN xdata _AT_(0xE665) volatile BYTE CLRERRCNT ; // Clear Error Counter EC[3..0]
+EXTERN xdata _AT_(0xE666) volatile BYTE INT2IVEC ; // Interupt 2 (USB) Autovector
+EXTERN xdata _AT_(0xE667) volatile BYTE INT4IVEC ; // Interupt 4 (FIFOS & GPIF) Autovector
+EXTERN xdata _AT_(0xE668) volatile BYTE INTSETUP ; // Interrupt 2&4 Setup
+
+// Input/Output
+
+EXTERN xdata _AT_(0xE670) volatile BYTE PORTACFG ; // I/O PORTA Alternate Configuration
+EXTERN xdata _AT_(0xE671) volatile BYTE PORTCCFG ; // I/O PORTC Alternate Configuration
+EXTERN xdata _AT_(0xE672) volatile BYTE PORTECFG ; // I/O PORTE Alternate Configuration
+EXTERN xdata _AT_(0xE678) volatile BYTE I2CS ; // Control & Status
+EXTERN xdata _AT_(0xE679) volatile BYTE I2DAT ; // Data
+EXTERN xdata _AT_(0xE67A) volatile BYTE I2CTL ; // I2C Control
+EXTERN xdata _AT_(0xE67B) volatile BYTE XAUTODAT1 ; // Autoptr1 MOVX access
+EXTERN xdata _AT_(0xE67C) volatile BYTE XAUTODAT2 ; // Autoptr2 MOVX access
+
+#define EXTAUTODAT1 XAUTODAT1
+#define EXTAUTODAT2 XAUTODAT2
+
+// USB Control
+
+EXTERN xdata _AT_(0xE680) volatile BYTE USBCS ; // USB Control & Status
+EXTERN xdata _AT_(0xE681) volatile BYTE SUSPEND ; // Put chip into suspend
+EXTERN xdata _AT_(0xE682) volatile BYTE WAKEUPCS ; // Wakeup source and polarity
+EXTERN xdata _AT_(0xE683) volatile BYTE TOGCTL ; // Toggle Control
+EXTERN xdata _AT_(0xE684) volatile BYTE USBFRAMEH ; // USB Frame count H
+EXTERN xdata _AT_(0xE685) volatile BYTE USBFRAMEL ; // USB Frame count L
+EXTERN xdata _AT_(0xE686) volatile BYTE MICROFRAME ; // Microframe count, 0-7
+EXTERN xdata _AT_(0xE687) volatile BYTE FNADDR ; // USB Function address
+
+// Endpoints
+
+EXTERN xdata _AT_(0xE68A) volatile BYTE EP0BCH ; // Endpoint 0 Byte Count H
+EXTERN xdata _AT_(0xE68B) volatile BYTE EP0BCL ; // Endpoint 0 Byte Count L
+EXTERN xdata _AT_(0xE68D) volatile BYTE EP1OUTBC ; // Endpoint 1 OUT Byte Count
+EXTERN xdata _AT_(0xE68F) volatile BYTE EP1INBC ; // Endpoint 1 IN Byte Count
+EXTERN xdata _AT_(0xE690) volatile BYTE EP2BCH ; // Endpoint 2 Byte Count H
+EXTERN xdata _AT_(0xE691) volatile BYTE EP2BCL ; // Endpoint 2 Byte Count L
+EXTERN xdata _AT_(0xE694) volatile BYTE EP4BCH ; // Endpoint 4 Byte Count H
+EXTERN xdata _AT_(0xE695) volatile BYTE EP4BCL ; // Endpoint 4 Byte Count L
+EXTERN xdata _AT_(0xE698) volatile BYTE EP6BCH ; // Endpoint 6 Byte Count H
+EXTERN xdata _AT_(0xE699) volatile BYTE EP6BCL ; // Endpoint 6 Byte Count L
+EXTERN xdata _AT_(0xE69C) volatile BYTE EP8BCH ; // Endpoint 8 Byte Count H
+EXTERN xdata _AT_(0xE69D) volatile BYTE EP8BCL ; // Endpoint 8 Byte Count L
+EXTERN xdata _AT_(0xE6A0) volatile BYTE EP0CS ; // Endpoint Control and Status
+EXTERN xdata _AT_(0xE6A1) volatile BYTE EP1OUTCS ; // Endpoint 1 OUT Control and Status
+EXTERN xdata _AT_(0xE6A2) volatile BYTE EP1INCS ; // Endpoint 1 IN Control and Status
+EXTERN xdata _AT_(0xE6A3) volatile BYTE EP2CS ; // Endpoint 2 Control and Status
+EXTERN xdata _AT_(0xE6A4) volatile BYTE EP4CS ; // Endpoint 4 Control and Status
+EXTERN xdata _AT_(0xE6A5) volatile BYTE EP6CS ; // Endpoint 6 Control and Status
+EXTERN xdata _AT_(0xE6A6) volatile BYTE EP8CS ; // Endpoint 8 Control and Status
+EXTERN xdata _AT_(0xE6A7) volatile BYTE EP2FIFOFLGS ; // Endpoint 2 Flags
+EXTERN xdata _AT_(0xE6A8) volatile BYTE EP4FIFOFLGS ; // Endpoint 4 Flags
+EXTERN xdata _AT_(0xE6A9) volatile BYTE EP6FIFOFLGS ; // Endpoint 6 Flags
+EXTERN xdata _AT_(0xE6AA) volatile BYTE EP8FIFOFLGS ; // Endpoint 8 Flags
+EXTERN xdata _AT_(0xE6AB) volatile BYTE EP2FIFOBCH ; // EP2 FIFO total byte count H
+EXTERN xdata _AT_(0xE6AC) volatile BYTE EP2FIFOBCL ; // EP2 FIFO total byte count L
+EXTERN xdata _AT_(0xE6AD) volatile BYTE EP4FIFOBCH ; // EP4 FIFO total byte count H
+EXTERN xdata _AT_(0xE6AE) volatile BYTE EP4FIFOBCL ; // EP4 FIFO total byte count L
+EXTERN xdata _AT_(0xE6AF) volatile BYTE EP6FIFOBCH ; // EP6 FIFO total byte count H
+EXTERN xdata _AT_(0xE6B0) volatile BYTE EP6FIFOBCL ; // EP6 FIFO total byte count L
+EXTERN xdata _AT_(0xE6B1) volatile BYTE EP8FIFOBCH ; // EP8 FIFO total byte count H
+EXTERN xdata _AT_(0xE6B2) volatile BYTE EP8FIFOBCL ; // EP8 FIFO total byte count L
+EXTERN xdata _AT_(0xE6B3) volatile BYTE SUDPTRH ; // Setup Data Pointer high address byte
+EXTERN xdata _AT_(0xE6B4) volatile BYTE SUDPTRL ; // Setup Data Pointer low address byte
+EXTERN xdata _AT_(0xE6B5) volatile BYTE SUDPTRCTL ; // Setup Data Pointer Auto Mode
+EXTERN xdata _AT_(0xE6B8) volatile BYTE SETUPDAT[8] ; // 8 bytes of SETUP data
+
+// GPIF
+
+EXTERN xdata _AT_(0xE6C0) volatile BYTE GPIFWFSELECT ; // Waveform Selector
+EXTERN xdata _AT_(0xE6C1) volatile BYTE GPIFIDLECS ; // GPIF Done, GPIF IDLE drive mode
+EXTERN xdata _AT_(0xE6C2) volatile BYTE GPIFIDLECTL ; // Inactive Bus, CTL states
+EXTERN xdata _AT_(0xE6C3) volatile BYTE GPIFCTLCFG ; // CTL OUT pin drive
+EXTERN xdata _AT_(0xE6C4) volatile BYTE GPIFADRH ; // GPIF Address H
+EXTERN xdata _AT_(0xE6C5) volatile BYTE GPIFADRL ; // GPIF Address L
+
+EXTERN xdata _AT_(0xE6CE) volatile BYTE GPIFTCB3 ; // GPIF Transaction Count Byte 3
+EXTERN xdata _AT_(0xE6CF) volatile BYTE GPIFTCB2 ; // GPIF Transaction Count Byte 2
+EXTERN xdata _AT_(0xE6D0) volatile BYTE GPIFTCB1 ; // GPIF Transaction Count Byte 1
+EXTERN xdata _AT_(0xE6D1) volatile BYTE GPIFTCB0 ; // GPIF Transaction Count Byte 0
+
+#define EP2GPIFTCH GPIFTCB1 // these are here for backwards compatibility
+#define EP2GPIFTCL GPIFTCB0 // before REVE silicon (ie. REVB and REVD)
+#define EP4GPIFTCH GPIFTCB1 // these are here for backwards compatibility
+#define EP4GPIFTCL GPIFTCB0 // before REVE silicon (ie. REVB and REVD)
+#define EP6GPIFTCH GPIFTCB1 // these are here for backwards compatibility
+#define EP6GPIFTCL GPIFTCB0 // before REVE silicon (ie. REVB and REVD)
+#define EP8GPIFTCH GPIFTCB1 // these are here for backwards compatibility
+#define EP8GPIFTCL GPIFTCB0 // before REVE silicon (ie. REVB and REVD)
+
+// EXTERN xdata volatile BYTE EP2GPIFTCH _AT_ 0xE6D0; // EP2 GPIF Transaction Count High
+// EXTERN xdata volatile BYTE EP2GPIFTCL _AT_ 0xE6D1; // EP2 GPIF Transaction Count Low
+EXTERN xdata _AT_(0xE6D2) volatile BYTE EP2GPIFFLGSEL ; // EP2 GPIF Flag select
+EXTERN xdata _AT_(0xE6D3) volatile BYTE EP2GPIFPFSTOP ; // Stop GPIF EP2 transaction on prog. flag
+EXTERN xdata _AT_(0xE6D4) volatile BYTE EP2GPIFTRIG ; // EP2 FIFO Trigger
+// EXTERN xdata volatile BYTE EP4GPIFTCH _AT_ 0xE6D8; // EP4 GPIF Transaction Count High
+// EXTERN xdata volatile BYTE EP4GPIFTCL _AT_ 0xE6D9; // EP4 GPIF Transactionr Count Low
+EXTERN xdata _AT_(0xE6DA) volatile BYTE EP4GPIFFLGSEL ; // EP4 GPIF Flag select
+EXTERN xdata _AT_(0xE6DB) volatile BYTE EP4GPIFPFSTOP ; // Stop GPIF EP4 transaction on prog. flag
+EXTERN xdata _AT_(0xE6DC) volatile BYTE EP4GPIFTRIG ; // EP4 FIFO Trigger
+// EXTERN xdata volatile BYTE EP6GPIFTCH _AT_ 0xE6E0; // EP6 GPIF Transaction Count High
+// EXTERN xdata volatile BYTE EP6GPIFTCL _AT_ 0xE6E1; // EP6 GPIF Transaction Count Low
+EXTERN xdata _AT_(0xE6E2) volatile BYTE EP6GPIFFLGSEL ; // EP6 GPIF Flag select
+EXTERN xdata _AT_(0xE6E3) volatile BYTE EP6GPIFPFSTOP ; // Stop GPIF EP6 transaction on prog. flag
+EXTERN xdata _AT_(0xE6E4) volatile BYTE EP6GPIFTRIG ; // EP6 FIFO Trigger
+// EXTERN xdata volatile BYTE EP8GPIFTCH _AT_ 0xE6E8; // EP8 GPIF Transaction Count High
+// EXTERN xdata volatile BYTE EP8GPIFTCL _AT_ 0xE6E9; // EP8GPIF Transaction Count Low
+EXTERN xdata _AT_(0xE6EA) volatile BYTE EP8GPIFFLGSEL ; // EP8 GPIF Flag select
+EXTERN xdata _AT_(0xE6EB) volatile BYTE EP8GPIFPFSTOP ; // Stop GPIF EP8 transaction on prog. flag
+EXTERN xdata _AT_(0xE6EC) volatile BYTE EP8GPIFTRIG ; // EP8 FIFO Trigger
+EXTERN xdata _AT_(0xE6F0) volatile BYTE XGPIFSGLDATH ; // GPIF Data H (16-bit mode only)
+EXTERN xdata _AT_(0xE6F1) volatile BYTE XGPIFSGLDATLX ; // Read/Write GPIF Data L & trigger transac
+EXTERN xdata _AT_(0xE6F2) volatile BYTE XGPIFSGLDATLNOX ; // Read GPIF Data L, no transac trigger
+EXTERN xdata _AT_(0xE6F3) volatile BYTE GPIFREADYCFG ; // Internal RDY,Sync/Async, RDY5CFG
+EXTERN xdata _AT_(0xE6F4) volatile BYTE GPIFREADYSTAT ; // RDY pin states
+EXTERN xdata _AT_(0xE6F5) volatile BYTE GPIFABORT ; // Abort GPIF cycles
+
+// UDMA
+
+EXTERN xdata _AT_(0xE6C6) volatile BYTE FLOWSTATE ; //Defines GPIF flow state
+EXTERN xdata _AT_(0xE6C7) volatile BYTE FLOWLOGIC ; //Defines flow/hold decision criteria
+EXTERN xdata _AT_(0xE6C8) volatile BYTE FLOWEQ0CTL ; //CTL states during active flow state
+EXTERN xdata _AT_(0xE6C9) volatile BYTE FLOWEQ1CTL ; //CTL states during hold flow state
+EXTERN xdata _AT_(0xE6CA) volatile BYTE FLOWHOLDOFF ;
+EXTERN xdata _AT_(0xE6CB) volatile BYTE FLOWSTB ; //CTL/RDY Signal to use as master data strobe
+EXTERN xdata _AT_(0xE6CC) volatile BYTE FLOWSTBEDGE ; //Defines active master strobe edge
+EXTERN xdata _AT_(0xE6CD) volatile BYTE FLOWSTBHPERIOD ; //Half Period of output master strobe
+EXTERN xdata _AT_(0xE60C) volatile BYTE GPIFHOLDAMOUNT ; //Data delay shift
+EXTERN xdata _AT_(0xE67D) volatile BYTE UDMACRCH ; //CRC Upper byte
+EXTERN xdata _AT_(0xE67E) volatile BYTE UDMACRCL ; //CRC Lower byte
+EXTERN xdata _AT_(0xE67F) volatile BYTE UDMACRCQUAL ; //UDMA In only, host terminated use only
+
+
+// Debug/Test
+
+EXTERN xdata _AT_(0xE6F8) volatile BYTE DBUG ; // Debug
+EXTERN xdata _AT_(0xE6F9) volatile BYTE TESTCFG ; // Test configuration
+EXTERN xdata _AT_(0xE6FA) volatile BYTE USBTEST ; // USB Test Modes
+EXTERN xdata _AT_(0xE6FB) volatile BYTE CT1 ; // Chirp Test--Override
+EXTERN xdata _AT_(0xE6FC) volatile BYTE CT2 ; // Chirp Test--FSM
+EXTERN xdata _AT_(0xE6FD) volatile BYTE CT3 ; // Chirp Test--Control Signals
+EXTERN xdata _AT_(0xE6FE) volatile BYTE CT4 ; // Chirp Test--Inputs
+
+// Endpoint Buffers
+
+EXTERN xdata _AT_(0xE740) volatile BYTE EP0BUF[64] ; // EP0 IN-OUT buffer
+EXTERN xdata _AT_(0xE780) volatile BYTE EP1OUTBUF[64] ; // EP1-OUT buffer
+EXTERN xdata _AT_(0xE7C0) volatile BYTE EP1INBUF[64] ; // EP1-IN buffer
+EXTERN xdata _AT_(0xF000) volatile BYTE EP2FIFOBUF[1024] ; // 512/1024-byte EP2 buffer (IN or OUT)
+EXTERN xdata _AT_(0xF400) volatile BYTE EP4FIFOBUF[1024] ; // 512 byte EP4 buffer (IN or OUT)
+EXTERN xdata _AT_(0xF800) volatile BYTE EP6FIFOBUF[1024] ; // 512/1024-byte EP6 buffer (IN or OUT)
+EXTERN xdata _AT_(0xFC00) volatile BYTE EP8FIFOBUF[1024] ; // 512 byte EP8 buffer (IN or OUT)
+
+#undef EXTERN
+#undef _AT_
+
+/*-----------------------------------------------------------------------------
+ Special Function Registers (SFRs)
+ The byte registers and bits defined in the following list are based
+ on the Synopsis definition of the 8051 Special Function Registers for EZ-USB.
+ If you modify the register definitions below, please regenerate the file
+ "ezregs.inc" which includes the same basic information for assembly inclusion.
+-----------------------------------------------------------------------------*/
+
+sfr at 0x80 IOA;
+sfr at 0x81 SP;
+sfr at 0x82 DPL;
+sfr at 0x83 DPH;
+sfr at 0x84 DPL1;
+sfr at 0x85 DPH1;
+sfr at 0x86 DPS;
+ /* DPS */
+ sbit at 0x86+0 SEL;
+sfr at 0x87 PCON; /* PCON */
+ //sbit IDLE = 0x87+0;
+ //sbit STOP = 0x87+1;
+ //sbit GF0 = 0x87+2;
+ //sbit GF1 = 0x87+3;
+ //sbit SMOD0 = 0x87+7;
+sfr at 0x88 TCON;
+ /* TCON */
+ sbit at 0x88+0 IT0;
+ sbit at 0x88+1 IE0;
+ sbit at 0x88+2 IT1;
+ sbit at 0x88+3 IE1;
+ sbit at 0x88+4 TR0;
+ sbit at 0x88+5 TF0;
+ sbit at 0x88+6 TR1;
+ sbit at 0x88+7 TF1;
+sfr at 0x89 TMOD;
+ /* TMOD */
+ //sbit M00 = 0x89+0;
+ //sbit M10 = 0x89+1;
+ //sbit CT0 = 0x89+2;
+ //sbit GATE0 = 0x89+3;
+ //sbit M01 = 0x89+4;
+ //sbit M11 = 0x89+5;
+ //sbit CT1 = 0x89+6;
+ //sbit GATE1 = 0x89+7;
+sfr at 0x8A TL0;
+sfr at 0x8B TL1;
+sfr at 0x8C TH0;
+sfr at 0x8D TH1;
+sfr at 0x8E CKCON;
+ /* CKCON */
+ //sbit MD0 = 0x89+0;
+ //sbit MD1 = 0x89+1;
+ //sbit MD2 = 0x89+2;
+ //sbit T0M = 0x89+3;
+ //sbit T1M = 0x89+4;
+ //sbit T2M = 0x89+5;
+// sfr at 0x8F SPC_FNC; // Was WRS in Reg320
+ /* CKCON */
+ //sbit WRS = 0x8F+0;
+sfr at 0x90 IOB;
+sfr at 0x91 EXIF; // EXIF Bit Values differ from Reg320
+ /* EXIF */
+ //sbit USBINT = 0x91+4;
+ //sbit I2CINT = 0x91+5;
+ //sbit IE4 = 0x91+6;
+ //sbit IE5 = 0x91+7;
+sfr at 0x92 MPAGE;
+sfr at 0x98 SCON0;
+ /* SCON0 */
+ sbit at 0x98+0 RI;
+ sbit at 0x98+1 TI;
+ sbit at 0x98+2 RB8;
+ sbit at 0x98+3 TB8;
+ sbit at 0x98+4 REN;
+ sbit at 0x98+5 SM2;
+ sbit at 0x98+6 SM1;
+ sbit at 0x98+7 SM0;
+sfr at 0x99 SBUF0;
+
+sfr at 0x9A APTR1H;
+sfr at 0x9B APTR1L;
+sfr at 0x9C AUTODAT1;
+sfr at 0x9D AUTOPTRH2;
+sfr at 0x9E AUTOPTRL2;
+sfr at 0x9F AUTODAT2;
+sfr at 0xA0 IOC;
+sfr at 0xA1 INT2CLR;
+sfr at 0xA2 INT4CLR;
+
+#define AUTOPTRH1 APTR1H
+#define AUTOPTRL1 APTR1L
+
+sfr at 0xA8 IE;
+ /* IE */
+ sbit at 0xA8+0 EX0;
+ sbit at 0xA8+1 ET0;
+ sbit at 0xA8+2 EX1;
+ sbit at 0xA8+3 ET1;
+ sbit at 0xA8+4 ES0;
+ sbit at 0xA8+5 ET2;
+ sbit at 0xA8+6 ES1;
+ sbit at 0xA8+7 EA;
+
+sfr at 0xAA EP2468STAT;
+ /* EP2468STAT */
+ //sbit EP2E = 0xAA+0;
+ //sbit EP2F = 0xAA+1;
+ //sbit EP4E = 0xAA+2;
+ //sbit EP4F = 0xAA+3;
+ //sbit EP6E = 0xAA+4;
+ //sbit EP6F = 0xAA+5;
+ //sbit EP8E = 0xAA+6;
+ //sbit EP8F = 0xAA+7;
+
+sfr at 0xAB EP24FIFOFLGS;
+sfr at 0xAC EP68FIFOFLGS;
+sfr at 0xAF AUTOPTRSETUP;
+ /* AUTOPTRSETUP */
+ // sbit EXTACC = 0xAF+0;
+ // sbit APTR1FZ = 0xAF+1;
+ // sbit APTR2FZ = 0xAF+2;
+
+sfr at 0xB0 IOD;
+sfr at 0xB1 IOE;
+sfr at 0xB2 OEA;
+sfr at 0xB3 OEB;
+sfr at 0xB4 OEC;
+sfr at 0xB5 OED;
+sfr at 0xB6 OEE;
+
+sfr at 0xB8 IP;
+ /* IP */
+ sbit at 0xB8+0 PX0;
+ sbit at 0xB8+1 PT0;
+ sbit at 0xB8+2 PX1;
+ sbit at 0xB8+3 PT1;
+ sbit at 0xB8+4 PS0;
+ sbit at 0xB8+5 PT2;
+ sbit at 0xB8+6 PS1;
+
+sfr at 0xBA EP01STAT;
+sfr at 0xBB GPIFTRIG;
+
+sfr at 0xBD GPIFSGLDATH;
+sfr at 0xBE GPIFSGLDATLX;
+sfr at 0xBF GPIFSGLDATLNOX;
+
+sfr at 0xC0 SCON1;
+ /* SCON1 */
+ sbit at 0xC0+0 RI1;
+ sbit at 0xC0+1 TI1;
+ sbit at 0xC0+2 RB81;
+ sbit at 0xC0+3 TB81;
+ sbit at 0xC0+4 REN1;
+ sbit at 0xC0+5 SM21;
+ sbit at 0xC0+6 SM11;
+ sbit at 0xC0+7 SM01;
+sfr at 0xC1 SBUF1;
+sfr at 0xC8 T2CON;
+ /* T2CON */
+ sbit at 0xC8+0 CP_RL2;
+ sbit at 0xC8+1 C_T2;
+ sbit at 0xC8+2 TR2;
+ sbit at 0xC8+3 EXEN2;
+ sbit at 0xC8+4 TCLK;
+ sbit at 0xC8+5 RCLK;
+ sbit at 0xC8+6 EXF2;
+ sbit at 0xC8+7 TF2;
+sfr at 0xCA RCAP2L;
+sfr at 0xCB RCAP2H;
+sfr at 0xCC TL2;
+sfr at 0xCD TH2;
+sfr at 0xD0 PSW;
+ /* PSW */
+ sbit at 0xD0+0 P;
+ sbit at 0xD0+1 FL;
+ sbit at 0xD0+2 OV;
+ sbit at 0xD0+3 RS0;
+ sbit at 0xD0+4 RS1;
+ sbit at 0xD0+5 F0;
+ sbit at 0xD0+6 AC;
+ sbit at 0xD0+7 CY;
+sfr at 0xD8 EICON; // Was WDCON in DS80C320 EICON; Bit Values differ from Reg320
+ /* EICON */
+ sbit at 0xD8+3 INT6;
+ sbit at 0xD8+4 RESI;
+ sbit at 0xD8+5 ERESI;
+ sbit at 0xD8+7 SMOD1;
+sfr at 0xE0 ACC;
+sfr at 0xE8 EIE; // EIE Bit Values differ from Reg320
+ /* EIE */
+ sbit at 0xE8+0 EIUSB;
+ sbit at 0xE8+1 EI2C;
+ sbit at 0xE8+2 EIEX4;
+ sbit at 0xE8+3 EIEX5;
+ sbit at 0xE8+4 EIEX6;
+sfr at 0xF0 B;
+sfr at 0xF8 EIP; // EIP Bit Values differ from Reg320
+ /* EIP */
+ sbit at 0xF8+0 PUSB;
+ sbit at 0xF8+1 PI2C;
+ sbit at 0xF8+2 EIPX4;
+ sbit at 0xF8+3 EIPX5;
+ sbit at 0xF8+4 EIPX6;
+
+/*-----------------------------------------------------------------------------
+ Bit Masks
+-----------------------------------------------------------------------------*/
+
+#define bmBIT0 1
+#define bmBIT1 2
+#define bmBIT2 4
+#define bmBIT3 8
+#define bmBIT4 16
+#define bmBIT5 32
+#define bmBIT6 64
+#define bmBIT7 128
+
+/* CPU Control & Status Register (CPUCS) */
+#define bmPRTCSTB bmBIT5
+#define bmCLKSPD (bmBIT4 | bmBIT3)
+#define bmCLKSPD1 bmBIT4
+#define bmCLKSPD0 bmBIT3
+#define bmCLKINV bmBIT2
+#define bmCLKOE bmBIT1
+#define bm8051RES bmBIT0
+/* Port Alternate Configuration Registers */
+/* Port A (PORTACFG) */
+#define bmFLAGD bmBIT7
+#define bmINT1 bmBIT1
+#define bmINT0 bmBIT0
+/* Port C (PORTCCFG) */
+#define bmGPIFA7 bmBIT7
+#define bmGPIFA6 bmBIT6
+#define bmGPIFA5 bmBIT5
+#define bmGPIFA4 bmBIT4
+#define bmGPIFA3 bmBIT3
+#define bmGPIFA2 bmBIT2
+#define bmGPIFA1 bmBIT1
+#define bmGPIFA0 bmBIT0
+/* Port E (PORTECFG) */
+#define bmGPIFA8 bmBIT7
+#define bmT2EX bmBIT6
+#define bmINT6 bmBIT5
+#define bmRXD1OUT bmBIT4
+#define bmRXD0OUT bmBIT3
+#define bmT2OUT bmBIT2
+#define bmT1OUT bmBIT1
+#define bmT0OUT bmBIT0
+
+/* I2C Control & Status Register (I2CS) */
+#define bmSTART bmBIT7
+#define bmSTOP bmBIT6
+#define bmLASTRD bmBIT5
+#define bmID (bmBIT4 | bmBIT3)
+#define bmBERR bmBIT2
+#define bmACK bmBIT1
+#define bmDONE bmBIT0
+/* I2C Control Register (I2CTL) */
+#define bmSTOPIE bmBIT1
+#define bm400KHZ bmBIT0
+/* Interrupt 2 (USB) Autovector Register (INT2IVEC) */
+#define bmIV4 bmBIT6
+#define bmIV3 bmBIT5
+#define bmIV2 bmBIT4
+#define bmIV1 bmBIT3
+#define bmIV0 bmBIT2
+/* USB Interrupt Request & Enable Registers (USBIE/USBIRQ) */
+#define bmEP0ACK bmBIT6
+#define bmHSGRANT bmBIT5
+#define bmURES bmBIT4
+#define bmSUSP bmBIT3
+#define bmSUTOK bmBIT2
+#define bmSOF bmBIT1
+#define bmSUDAV bmBIT0
+/* Breakpoint register (BREAKPT) */
+#define bmBREAK bmBIT3
+#define bmBPPULSE bmBIT2
+#define bmBPEN bmBIT1
+/* Interrupt 2 & 4 Setup (INTSETUP) */
+#define bmAV2EN bmBIT3
+#define bmINT4IN bmBIT1
+#define bmAV4EN bmBIT0
+/* USB Control & Status Register (USBCS) */
+#define bmHSM bmBIT7
+#define bmDISCON bmBIT3
+#define bmNOSYNSOF bmBIT2
+#define bmRENUM bmBIT1
+#define bmSIGRESUME bmBIT0
+/* Wakeup Control and Status Register (WAKEUPCS) */
+#define bmWU2 bmBIT7
+#define bmWU bmBIT6
+#define bmWU2POL bmBIT5
+#define bmWUPOL bmBIT4
+#define bmDPEN bmBIT2
+#define bmWU2EN bmBIT1
+#define bmWUEN bmBIT0
+/* End Point 0 Control & Status Register (EP0CS) */
+#define bmHSNAK bmBIT7
+/* End Point 0-1 Control & Status Registers (EP0CS/EP1OUTCS/EP1INCS) */
+#define bmEPBUSY bmBIT1
+#define bmEPSTALL bmBIT0
+/* End Point 2-8 Control & Status Registers (EP2CS/EP4CS/EP6CS/EP8CS) */
+#define bmNPAK (bmBIT6 | bmBIT5 | bmBIT4)
+#define bmEPFULL bmBIT3
+#define bmEPEMPTY bmBIT2
+/* Endpoint Status (EP2468STAT) SFR bits */
+#define bmEP8FULL bmBIT7
+#define bmEP8EMPTY bmBIT6
+#define bmEP6FULL bmBIT5
+#define bmEP6EMPTY bmBIT4
+#define bmEP4FULL bmBIT3
+#define bmEP4EMPTY bmBIT2
+#define bmEP2FULL bmBIT1
+#define bmEP2EMPTY bmBIT0
+/* SETUP Data Pointer Auto Mode (SUDPTRCTL) */
+#define bmSDPAUTO bmBIT0
+/* Endpoint Data Toggle Control (TOGCTL) */
+#define bmQUERYTOGGLE bmBIT7
+#define bmSETTOGGLE bmBIT6
+#define bmRESETTOGGLE bmBIT5
+#define bmTOGCTLEPMASK bmBIT3 | bmBIT2 | bmBIT1 | bmBIT0
+/* IBN (In Bulk Nak) enable and request bits (IBNIE/IBNIRQ) */
+#define bmEP8IBN bmBIT5
+#define bmEP6IBN bmBIT4
+#define bmEP4IBN bmBIT3
+#define bmEP2IBN bmBIT2
+#define bmEP1IBN bmBIT1
+#define bmEP0IBN bmBIT0
+
+/* PING-NAK enable and request bits (NAKIE/NAKIRQ) */
+#define bmEP8PING bmBIT7
+#define bmEP6PING bmBIT6
+#define bmEP4PING bmBIT5
+#define bmEP2PING bmBIT4
+#define bmEP1PING bmBIT3
+#define bmEP0PING bmBIT2
+#define bmIBN bmBIT0
+
+/* Interface Configuration bits (IFCONFIG) */
+#define bmIFCLKSRC bmBIT7 // set == INTERNAL
+#define bm3048MHZ bmBIT6 // set == 48 MHz
+#define bmIFCLKOE bmBIT5
+#define bmIFCLKPOL bmBIT4
+#define bmASYNC bmBIT3
+#define bmGSTATE bmBIT2
+#define bmIFCFG1 bmBIT1
+#define bmIFCFG0 bmBIT0
+#define bmIFCFGMASK (bmIFCFG0 | bmIFCFG1)
+#define bmIFGPIF bmIFCFG1
+
+/* EP 2468 FIFO Configuration bits (EP2FIFOCFG,EP4FIFOCFG,EP6FIFOCFG,EP8FIFOCFG) */
+#define bmINFM bmBIT6
+#define bmOEP bmBIT5
+#define bmAUTOOUT bmBIT4
+#define bmAUTOIN bmBIT3
+#define bmZEROLENIN bmBIT2
+// must be zero bmBIT1
+#define bmWORDWIDE bmBIT0
+
+/*
+ * Chip Revision Control Bits (REVCTL) - used to ebable/disable revision specific features
+ */
+#define bmNOAUTOARM bmBIT1 // these don't match the docs
+#define bmSKIPCOMMIT bmBIT0 // these don't match the docs
+
+#define bmDYN_OUT bmBIT1 // these do...
+#define bmENH_PKT bmBIT0
+
+
+/* Fifo Reset bits (FIFORESET) */
+#define bmNAKALL bmBIT7
+
+/* Endpoint Configuration (EPxCFG) */
+#define bmVALID bmBIT7
+#define bmIN bmBIT6
+#define bmTYPE1 bmBIT5
+#define bmTYPE0 bmBIT4
+#define bmISOCHRONOUS bmTYPE0
+#define bmBULK bmTYPE1
+#define bmINTERRUPT (bmTYPE1 | bmTYPE0)
+#define bm1KBUF bmBIT3
+#define bmBUF1 bmBIT1
+#define bmBUF0 bmBIT0
+#define bmQUADBUF 0
+#define bmINVALIDBUF bmBUF0
+#define bmDOUBLEBUF bmBUF1
+#define bmTRIPLEBUF (bmBUF1 | bmBUF0)
+
+/* OUTPKTEND */
+#define bmSKIP bmBIT7 // low 4 bits specify which end point
+
+/* GPIFTRIG defs */
+#define bmGPIF_IDLE bmBIT7 // status bit
+
+#define bmGPIF_EP2_START 0
+#define bmGPIF_EP4_START 1
+#define bmGPIF_EP6_START 2
+#define bmGPIF_EP8_START 3
+#define bmGPIF_READ bmBIT2
+#define bmGPIF_WRITE 0
+
+/* EXIF bits */
+#define bmEXIF_USBINT bmBIT4
+#define bmEXIF_I2CINT bmBIT5
+#define bmEXIF_IE4 bmBIT6
+#define bmEXIF_IE5 bmBIT7
+
+
+#endif /* FX2REGS_H */
diff --git a/firmware/fx2/include/fx2utils.h b/firmware/fx2/include/fx2utils.h
new file mode 100644
index 000000000..b184dec27
--- /dev/null
+++ b/firmware/fx2/include/fx2utils.h
@@ -0,0 +1,31 @@
+/* -*- c -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _FX2UTILS_H_
+#define _FX2UTILS_H_
+
+void fx2_stall_ep0 (void);
+void fx2_reset_data_toggle (unsigned char ep);
+void fx2_renumerate (void);
+
+
+
+#endif /* _FX2UTILS_H_ */
diff --git a/firmware/fx2/include/generate_regs.py b/firmware/fx2/include/generate_regs.py
new file mode 100755
index 000000000..656cd5e81
--- /dev/null
+++ b/firmware/fx2/include/generate_regs.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+
+import os, os.path
+import re
+import sys
+
+
+# set srcdir to the directory that contains Makefile.am
+try:
+ srcdir = os.environ['srcdir']
+except KeyError, e:
+ srcdir = "."
+srcdir = srcdir + '/'
+
+def open_src (name, mode):
+ global srcdir
+ return open (os.path.join (srcdir, name), mode)
+
+
+def generate_fpga_regs (h_filename, v_filename):
+ const_width = 7 # bit width of constants
+
+ h_file = open_src (h_filename, 'r')
+ v_file = open (v_filename, 'w')
+ v_file.write (
+ '''//
+// This file is machine generated from %s
+// Do not edit by hand; your edits will be overwritten.
+//
+''' % (h_filename,))
+
+ pat = re.compile (r'^#define\s*(FR_\w*)\s*(\w*)(.*)$')
+ pat_bitno = re.compile (r'^#define\s*(bitno\w*)\s*(\w*)(.*)$')
+ pat_bm = re.compile (r'^#define\s*(bm\w*)\s*(\w*)(.*)$')
+ for line in h_file:
+ if re.match ('//|\s*$', line): # comment or blank line
+ v_file.write (line)
+ mo = pat.search (line)
+ mo_bitno =pat_bitno.search (line)
+ mo_bm =pat_bm.search (line)
+ if mo:
+ v_file.write ('`define %-25s %d\'d%s%s\n' % (
+ mo.group (1), const_width, mo.group (2), mo.group (3)))
+ elif mo_bitno:
+ v_file.write ('`define %-25s %s%s\n' % (
+ mo_bitno.group (1), mo_bitno.group (2), mo_bitno.group (3)))
+ elif mo_bm:
+ v_file.write ('`define %-25s %s%s\n' % (
+ mo_bm.group (1), mo_bm.group (2), mo_bm.group (3)))
+
+
+if __name__ == '__main__':
+ if len (sys.argv) != 3:
+ sys.stderr.write ('usage: %s file.h file.v\n' % (sys.argv[0]))
+ sys.exit (1)
+ generate_fpga_regs (sys.argv[1], sys.argv[2])
+
diff --git a/firmware/fx2/include/i2c.h b/firmware/fx2/include/i2c.h
new file mode 100644
index 000000000..273526dad
--- /dev/null
+++ b/firmware/fx2/include/i2c.h
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _I2C_H_
+#define _I2C_H_
+
+// returns non-zero if successful, else 0
+unsigned char i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len);
+
+// returns non-zero if successful, else 0
+unsigned char i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len);
+
+#endif /* _I2C_H_ */
diff --git a/firmware/fx2/include/isr.h b/firmware/fx2/include/isr.h
new file mode 100644
index 000000000..856532890
--- /dev/null
+++ b/firmware/fx2/include/isr.h
@@ -0,0 +1,172 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _ISR_H_
+#define _ISR_H_
+
+/*
+ * ----------------------------------------------------------------
+ * routines for managing interrupt services routines
+ * ----------------------------------------------------------------
+ */
+
+/*
+ * The FX2 has three discrete sets of interrupt vectors.
+ * The first set is the standard 8051 vector (13 8-byte entries).
+ * The second set is USB interrupt autovector (32 4-byte entries).
+ * The third set is the FIFO/GPIF autovector (14 4-byte entries).
+ *
+ * Since all the code we're running in the FX2 is ram based, we
+ * forego the typical "initialize the interrupt vectors at link time"
+ * strategy, in favor of calls at run time that install the correct
+ * pointers to functions.
+ */
+
+/*
+ * Standard Vector numbers
+ */
+
+#define SV_INT_0 0x03
+#define SV_TIMER_0 0x0b
+#define SV_INT_1 0x13
+#define SV_TIMER_1 0x1b
+#define SV_SERIAL_0 0x23
+#define SV_TIMER_2 0x2b
+#define SV_RESUME 0x33
+#define SV_SERIAL_1 0x3b
+#define SV_INT_2 0x43 // (INT_2) points at USB autovector
+#define SV_I2C 0x4b
+#define SV_INT_4 0x53 // (INT_4) points at FIFO/GPIF autovector
+#define SV_INT_5 0x5b
+#define SV_INT_6 0x63
+
+#define SV_MIN SV_INT_0
+#define SV_MAX SV_INT_6
+
+/*
+ * USB Auto Vector numbers
+ */
+
+#define UV_SUDAV 0x00
+#define UV_SOF 0x04
+#define UV_SUTOK 0x08
+#define UV_SUSPEND 0x0c
+#define UV_USBRESET 0x10
+#define UV_HIGHSPEED 0x14
+#define UV_EP0ACK 0x18
+#define UV_SPARE_1C 0x1c
+#define UV_EP0IN 0x20
+#define UV_EP0OUT 0x24
+#define UV_EP1IN 0x28
+#define UV_EP1OUT 0x2c
+#define UV_EP2 0x30
+#define UV_EP4 0x34
+#define UV_EP6 0x38
+#define UV_EP8 0x3c
+#define UV_IBN 0x40
+#define UV_SPARE_44 0x44
+#define UV_EP0PINGNAK 0x48
+#define UV_EP1PINGNAK 0x4c
+#define UV_EP2PINGNAK 0x50
+#define UV_EP4PINGNAK 0x54
+#define UV_EP6PINGNAK 0x58
+#define UV_EP8PINGNAK 0x5c
+#define UV_ERRLIMIT 0x60
+#define UV_SPARE_64 0x64
+#define UV_SPARE_68 0x68
+#define UV_SPARE_6C 0x6c
+#define UV_EP2ISOERR 0x70
+#define UV_EP4ISOERR 0x74
+#define UV_EP6ISOERR 0x78
+#define UV_EP8ISOERR 0x7c
+
+#define UV_MIN UV_SUDAV
+#define UV_MAX UV_EP8ISOERR
+
+/*
+ * FIFO/GPIF Auto Vector numbers
+ */
+
+#define FGV_EP2PF 0x00
+#define FGV_EP4PF 0x04
+#define FGV_EP6PF 0x08
+#define FGV_EP8PF 0x0c
+#define FGV_EP2EF 0x10
+#define FGV_EP4EF 0x14
+#define FGV_EP6EF 0x18
+#define FGV_EP8EF 0x1c
+#define FGV_EP2FF 0x20
+#define FGV_EP4FF 0x24
+#define FGV_EP6FF 0x28
+#define FGV_EP8FF 0x2c
+#define FGV_GPIFDONE 0x30
+#define FGV_GPIFWF 0x34
+
+#define FGV_MIN FGV_EP2PF
+#define FGV_MAX FGV_GPIFWF
+
+
+/*
+ * Hook standard interrupt vector.
+ *
+ * vector_number is from the SV_<foo> list above.
+ * addr is the address of the interrupt service routine.
+ */
+void hook_sv (unsigned char vector_number, unsigned short addr);
+
+/*
+ * Hook usb interrupt vector.
+ *
+ * vector_number is from the UV_<foo> list above.
+ * addr is the address of the interrupt service routine.
+ */
+void hook_uv (unsigned char vector_number, unsigned short addr);
+
+/*
+ * Hook fifo/gpif interrupt vector.
+ *
+ * vector_number is from the FGV_<foo> list above.
+ * addr is the address of the interrupt service routine.
+ */
+void hook_fgv (unsigned char vector_number, unsigned short addr);
+
+/*
+ * One time call to enable autovectoring for both USB and FIFO/GPIF
+ */
+void setup_autovectors (void);
+
+
+/*
+ * Must be called in each usb interrupt handler
+ */
+#define clear_usb_irq() \
+ EXIF &= ~bmEXIF_USBINT; \
+ INT2CLR = 0
+
+/*
+ * Must be calledin each fifo/gpif interrupt handler
+ */
+#define clear_fifo_gpif_irq() \
+ EXIF &= ~bmEXIF_IE4; \
+ INT4CLR = 0
+
+#endif /* _ISR_H_ */
diff --git a/firmware/fx2/include/syncdelay.h b/firmware/fx2/include/syncdelay.h
new file mode 100644
index 000000000..0af7d099f
--- /dev/null
+++ b/firmware/fx2/include/syncdelay.h
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _SYNCDELAY_H_
+#define _SYNCDELAY_H_
+
+/*
+ * Magic delay required between access to certain xdata registers (TRM page 15-106).
+ * For our configuration, 48 MHz FX2 / 48 MHz IFCLK, we need three cycles. Each
+ * NOP is a single cycle....
+ *
+ * From TRM page 15-105:
+ *
+ * Under certain conditions, some read and write access to the FX2 registers must
+ * be separated by a "synchronization delay". The delay is necessary only under the
+ * following conditions:
+ *
+ * - between a write to any register in the 0xE600 - 0xE6FF range and a write to one
+ * of the registers listed below.
+ *
+ * - between a write to one of the registers listed below and a read from any register
+ * in the 0xE600 - 0xE6FF range.
+ *
+ * Registers which require a synchronization delay:
+ *
+ * FIFORESET FIFOPINPOLAR
+ * INPKTEND EPxBCH:L
+ * EPxFIFOPFH:L EPxAUTOINLENH:L
+ * EPxFIFOCFG EPxGPIFFLGSEL
+ * PINFLAGSAB PINFLAGSCD
+ * EPxFIFOIE EPxFIFOIRQ
+ * GPIFIE GPIFIRQ
+ * UDMACRCH:L GPIFADRH:L
+ * GPIFTRIG EPxGPIFTRIG
+ * OUTPKTEND REVCTL
+ * GPIFTCB3 GPIFTCB2
+ * GPIFTCB1 GPIFTCB0
+ */
+
+/*
+ * FIXME ensure that the peep hole optimizer isn't screwing us
+ */
+#define SYNCDELAY _asm nop; nop; nop; _endasm
+#define NOP _asm nop; _endasm
+
+
+#endif /* _SYNCDELAY_H_ */
diff --git a/firmware/fx2/include/timer.h b/firmware/fx2/include/timer.h
new file mode 100644
index 000000000..3181874d5
--- /dev/null
+++ b/firmware/fx2/include/timer.h
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _TIMER_H_
+#define _TIMER_H_
+
+/*
+ * Arrange to have isr_tick_handler called at 100 Hz
+ */
+void hook_timer_tick (unsigned short isr_tick_handler);
+
+#define clear_timer_irq() \
+ TF2 = 0 /* clear overflow flag */
+
+
+#endif /* _TIMER_H_ */
diff --git a/firmware/fx2/include/usb_common.h b/firmware/fx2/include/usb_common.h
new file mode 100644
index 000000000..ae07b236c
--- /dev/null
+++ b/firmware/fx2/include/usb_common.h
@@ -0,0 +1,37 @@
+/* -*- c -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _USB_COMMON_H_
+#define _USB_COMMON_H_
+
+extern volatile bit _usb_got_SUDAV;
+
+// Provided by user application to handle VENDOR commands.
+// returns non-zero if it handled the command.
+unsigned char app_vendor_cmd (void);
+
+void usb_install_handlers (void);
+void usb_handle_setup_packet (void);
+
+#define usb_setup_packet_avail() _usb_got_SUDAV
+
+#endif /* _USB_COMMON_H_ */
diff --git a/firmware/fx2/include/usb_descriptors.h b/firmware/fx2/include/usb_descriptors.h
new file mode 100644
index 000000000..0b8c6212f
--- /dev/null
+++ b/firmware/fx2/include/usb_descriptors.h
@@ -0,0 +1,40 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+extern xdata const char high_speed_device_descr[];
+extern xdata const char high_speed_devqual_descr[];
+extern xdata const char high_speed_config_descr[];
+
+extern xdata const char full_speed_device_descr[];
+extern xdata const char full_speed_devqual_descr[];
+extern xdata const char full_speed_config_descr[];
+
+extern xdata unsigned char nstring_descriptors;
+extern xdata char * xdata string_descriptors[];
+
+/*
+ * We patch these locations with info read from the usrp config eeprom
+ */
+extern xdata char usb_desc_hw_rev_binary_patch_location_0[];
+extern xdata char usb_desc_hw_rev_binary_patch_location_1[];
+extern xdata char usb_desc_hw_rev_ascii_patch_location_0[];
+extern xdata char usb_desc_serial_number_ascii[];
diff --git a/firmware/fx2/include/usb_requests.h b/firmware/fx2/include/usb_requests.h
new file mode 100644
index 000000000..7a543abb0
--- /dev/null
+++ b/firmware/fx2/include/usb_requests.h
@@ -0,0 +1,88 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+// Standard USB requests.
+// These are contained in end point 0 setup packets
+
+
+#ifndef _USB_REQUESTS_H_
+#define _USB_REQUESTS_H_
+
+// format of bmRequestType byte
+
+#define bmRT_DIR_MASK (0x1 << 7)
+#define bmRT_DIR_IN (1 << 7)
+#define bmRT_DIR_OUT (0 << 7)
+
+#define bmRT_TYPE_MASK (0x3 << 5)
+#define bmRT_TYPE_STD (0 << 5)
+#define bmRT_TYPE_CLASS (1 << 5)
+#define bmRT_TYPE_VENDOR (2 << 5)
+#define bmRT_TYPE_RESERVED (3 << 5)
+
+#define bmRT_RECIP_MASK (0x1f << 0)
+#define bmRT_RECIP_DEVICE (0 << 0)
+#define bmRT_RECIP_INTERFACE (1 << 0)
+#define bmRT_RECIP_ENDPOINT (2 << 0)
+#define bmRT_RECIP_OTHER (3 << 0)
+
+
+// standard request codes (bRequest)
+
+#define RQ_GET_STATUS 0
+#define RQ_CLEAR_FEATURE 1
+#define RQ_RESERVED_2 2
+#define RQ_SET_FEATURE 3
+#define RQ_RESERVED_4 4
+#define RQ_SET_ADDRESS 5
+#define RQ_GET_DESCR 6
+#define RQ_SET_DESCR 7
+#define RQ_GET_CONFIG 8
+#define RQ_SET_CONFIG 9
+#define RQ_GET_INTERFACE 10
+#define RQ_SET_INTERFACE 11
+#define RQ_SYNCH_FRAME 12
+
+// standard descriptor types
+
+#define DT_DEVICE 1
+#define DT_CONFIG 2
+#define DT_STRING 3
+#define DT_INTERFACE 4
+#define DT_ENDPOINT 5
+#define DT_DEVQUAL 6
+#define DT_OTHER_SPEED 7
+#define DT_INTERFACE_POWER 8
+
+// standard feature selectors
+
+#define FS_ENDPOINT_HALT 0 // recip: endpoint
+#define FS_DEV_REMOTE_WAKEUP 1 // recip: device
+#define FS_TEST_MODE 2 // recip: device
+
+// Get Status device attributes
+
+#define bmGSDA_SELF_POWERED 0x01
+#define bmGSDA_REM_WAKEUP 0x02
+
+
+#endif /* _USB_REQUESTS_H_ */
diff --git a/firmware/fx2/include/usrp_commands.h b/firmware/fx2/include/usrp_commands.h
new file mode 100644
index 000000000..02778c7e3
--- /dev/null
+++ b/firmware/fx2/include/usrp_commands.h
@@ -0,0 +1,106 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003,2004 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _USRP_COMMANDS_H_
+#define _USRP_COMMANDS_H_
+
+#include <usrp_interfaces.h>
+#include <usrp_spi_defs.h>
+
+#define MAX_EP0_PKTSIZE 64 // max size of EP0 packet on FX2
+
+// ----------------------------------------------------------------
+// Vendor bmRequestType's
+// ----------------------------------------------------------------
+
+#define VRT_VENDOR_IN 0xC0
+#define VRT_VENDOR_OUT 0x40
+
+// ----------------------------------------------------------------
+// USRP Vendor Requests
+//
+// Note that Cypress reserves [0xA0,0xAF].
+// 0xA0 is the firmware load function.
+// ----------------------------------------------------------------
+
+
+// IN commands
+
+#define VRQ_GET_STATUS 0x80
+#define GS_TX_UNDERRUN 0 // wIndexL // returns 1 byte
+#define GS_RX_OVERRUN 1 // wIndexL // returns 1 byte
+
+#define VRQ_I2C_READ 0x81 // wValueL: i2c address; length: how much to read
+
+#define VRQ_SPI_READ 0x82 // wValue: optional header bytes
+ // wIndexH: enables
+ // wIndexL: format
+ // len: how much to read
+
+#define VRQ_SPI_TRANSACT 0x83 // wValueH: OUT byte 0
+ // wValueL: OUT byte 1
+ // wIndexH: OUT byte 2
+ // wIndexL: OUT byte 3
+ // wLengthH: enables
+ // wLengthL: transaction length
+
+// OUT commands
+
+#define VRQ_SET_LED 0x01 // wValueL off/on {0,1}; wIndexL: which {0,1}
+
+#define VRQ_FPGA_LOAD 0x02
+# define FL_BEGIN 0 // wIndexL: begin fpga programming cycle. stalls if trouble.
+# define FL_XFER 1 // wIndexL: xfer up to 64 bytes of data
+# define FL_END 2 // wIndexL: end programming cycle, check for success.
+ // stalls endpoint if trouble.
+
+#define VRQ_FPGA_WRITE_REG 0x03 // wIndexL: regno; data: 32-bit regval MSB first
+#define VRQ_FPGA_SET_RESET 0x04 // wValueL: {0,1}
+#define VRQ_FPGA_SET_TX_ENABLE 0x05 // wValueL: {0,1}
+#define VRQ_FPGA_SET_RX_ENABLE 0x06 // wValueL: {0,1}
+// see below VRQ_FPGA_SET_{TX,RX}_RESET
+
+#define VRQ_SET_SLEEP_BITS 0x07 // wValueH: mask; wValueL: bits. set bits given by mask to bits
+
+# define SLEEP_ADC0 0x01
+# define SLEEP_ADC1 0x02
+# define SLEEP_DAC0 0x04
+# define SLEEP_DAC1 0x08
+
+#define VRQ_I2C_WRITE 0x08 // wValueL: i2c address; data: data
+
+#define VRQ_SPI_WRITE 0x09 // wValue: optional header bytes
+ // wIndexH: enables
+ // wIndexL: format
+ // len: how much to write
+
+#define VRQ_FPGA_SET_TX_RESET 0x0a // wValueL: {0, 1}
+#define VRQ_FPGA_SET_RX_RESET 0x0b // wValueL: {0, 1}
+
+
+// -------------------------------------------------------------------
+// we store the hashes at fixed addresses in the FX2 internal memory
+
+#define USRP_HASH_SLOT_0_ADDR 0xe1e0
+#define USRP_HASH_SLOT_1_ADDR 0xe1f0
+
+
+
+#endif /* _USRP_COMMANDS_H_ */
diff --git a/firmware/fx2/include/usrp_config.h b/firmware/fx2/include/usrp_config.h
new file mode 100644
index 000000000..e77f8e4c5
--- /dev/null
+++ b/firmware/fx2/include/usrp_config.h
@@ -0,0 +1,44 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * configuration stuff for debugging
+ */
+
+/*
+ * Define to 0 for normal use of port A, i.e., FPGA control bus.
+ * Define to 1 to write trace to port A for scoping with logic analyzer.
+ */
+#define UC_TRACE_USING_PORT_A 0
+
+
+/*
+ * Define to 0 for normal use of low 3 bits of port E, i.e., A/D, D/A SLEEP bits.
+ * Define to 1 to enable by default driving the GPIF state to the
+ * low three bits of port E.
+ */
+#define UC_START_WITH_GSTATE_OUTPUT_ENABLED 0
+
+
+/*
+ * Define to 1 for normal use (the board really has an FPGA on it).
+ * Define to 0 for debug use on board without FPGA.
+ */
+#define UC_BOARD_HAS_FPGA 1
diff --git a/firmware/fx2/include/usrp_i2c_addr.h b/firmware/fx2/include/usrp_i2c_addr.h
new file mode 100644
index 000000000..0a4f3ea59
--- /dev/null
+++ b/firmware/fx2/include/usrp_i2c_addr.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_USRP_I2C_ADDR_H
+#define INCLUDED_USRP_I2C_ADDR_H
+
+// I2C addresses
+
+#define I2C_DEV_EEPROM 0x50 // 24LC02[45]: 7-bits 1010xxx
+
+#define I2C_ADDR_BOOT (I2C_DEV_EEPROM | 0x0)
+#define I2C_ADDR_TX_A (I2C_DEV_EEPROM | 0x4)
+#define I2C_ADDR_RX_A (I2C_DEV_EEPROM | 0x5)
+#define I2C_ADDR_TX_B (I2C_DEV_EEPROM | 0x6)
+#define I2C_ADDR_RX_B (I2C_DEV_EEPROM | 0x7)
+
+
+// format of FX2 BOOT EEPROM
+// 00: 0xC0 code for ``Read IDs from EEPROM''
+// 01: 0xFE USB Vendor ID (LSB)
+// 02: 0xFF USB Vendor ID (MSB)
+// 03: 0x02 USB Product ID (LSB)
+// 04: 0x00 USB Product ID (MSB)
+// 05: 0x01 USB Device ID (LSB) // rev1
+// 06: 0x00 USB Device ID (MSB) // 0 = unconfig'd (no firmware)
+// 07: 0x00 option byte
+
+
+// format of daughterboard EEPROM
+// 00: 0xDB code for ``I'm a daughterboard''
+// 01: .. Daughterboard ID (LSB)
+// 02: .. Daughterboard ID (MSB)
+// 03: .. io bits 7-0 direction (bit set if it's an output from m'board)
+// 04: .. io bits 15-8 direction (bit set if it's an output from m'board)
+// 05: .. ADC0 DC offset correction (LSB)
+// 06: .. ADC0 DC offset correction (MSB)
+// 07: .. ADC1 DC offset correction (LSB)
+// 08: .. ADC1 DC offset correction (MSB)
+// ...
+// 1f: .. negative of the sum of bytes [0x00, 0x1e]
+
+#define DB_EEPROM_MAGIC 0x00
+#define DB_EEPROM_MAGIC_VALUE 0xDB
+#define DB_EEPROM_ID_LSB 0x01
+#define DB_EEPROM_ID_MSB 0x02
+#define DB_EEPROM_OE_LSB 0x03
+#define DB_EEPROM_OE_MSB 0x04
+#define DB_EEPROM_OFFSET_0_LSB 0x05 // offset correction for ADC or DAC 0
+#define DB_EEPROM_OFFSET_0_MSB 0x06
+#define DB_EEPROM_OFFSET_1_LSB 0x07 // offset correction for ADC or DAC 1
+#define DB_EEPROM_OFFSET_1_MSB 0x08
+#define DB_EEPROM_CHKSUM 0x1f
+
+#define DB_EEPROM_CLEN 0x20 // length of common portion of eeprom
+
+#define DB_EEPROM_CUSTOM_BASE DB_EEPROM_CLEN // first avail offset for
+ // daughterboard specific use
+
+#endif /* INCLUDED_USRP_I2C_ADDR_H */
+
diff --git a/firmware/fx2/include/usrp_ids.h b/firmware/fx2/include/usrp_ids.h
new file mode 100644
index 000000000..46a069434
--- /dev/null
+++ b/firmware/fx2/include/usrp_ids.h
@@ -0,0 +1,68 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003,2006,2007 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * USB Vendor and Product IDs that we use
+ *
+ * (keep in sync with usb_descriptors.a51)
+ */
+
+#ifndef _USRP_IDS_H_
+#define _USRP_IDS_H_
+
+#define USB_VID_CYPRESS 0x04b4
+#define USB_PID_CYPRESS_FX2 0x8613
+
+
+#define USB_VID_FSF 0xfffe // Free Software Folks
+#define USB_PID_FSF_EXP_0 0x0000 // Experimental 0
+#define USB_PID_FSF_EXP_1 0x0001 // Experimental 1
+#define USB_PID_FSF_USRP 0x0002 // Universal Software Radio Peripheral
+#define USB_PID_FSF_USRP_reserved 0x0003 // Universal Software Radio Peripheral
+#define USB_PID_FSF_SSRP 0x0004 // Simple Software Radio Peripheral
+#define USB_PID_FSF_SSRP_reserved 0x0005 // Simple Software Radio Peripheral
+#define USB_PID_FSF_HPSDR 0x0006 // High Performance Software Defined Radio (Internal Boot)
+#define USB_PID_FSF_HPSDR_HA 0x0007 // High Performance Software Defined Radio (Host Assisted Boot)
+#define USB_PID_FSF_QS1R 0x0008 // QS1R HF receiver
+#define USB_PID_FSF_EZDOP 0x0009 // ezdop <jcorgan@aeinet.com>
+#define USB_PID_FSF_BDALE_0 0x000a // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_1 0x000b // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_2 0x000c // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_3 0x000d // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_4 0x000e // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_5 0x000f // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_6 0x0010 // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_7 0x0011 // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_8 0x0012 // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_BDALE_9 0x0013 // Bdale Garbee <bdale@gag.com>
+#define USB_PID_FSF_HPSDR_HERMES 0x0014 // HPSDR Hermes
+#define USB_PID_FSF_THINKRF 0x0015 // Catalin Patulea <catalin.patulea@thinkrf.com>
+#define USB_PID_FSF_MSA 0x0016 // Hans de Bok <hdbok@dionaea.demon.nl> Scotty's Modular Spectrum Analyzer
+
+#define USB_PID_FSF_LBNL_UXO 0x0018 // http://recycle.lbl.gov/~ldoolitt/uxo/
+
+
+#define USB_DID_USRP_0 0x0000 // unconfigured rev 0 USRP
+#define USB_DID_USRP_1 0x0001 // unconfigured rev 1 USRP
+#define USB_DID_USRP_2 0x0002 // unconfigured rev 2 USRP
+
+#endif /* _USRP_IDS_H_ */
diff --git a/firmware/fx2/include/usrp_interfaces.h b/firmware/fx2/include/usrp_interfaces.h
new file mode 100644
index 000000000..8666e0490
--- /dev/null
+++ b/firmware/fx2/include/usrp_interfaces.h
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _USRP_INTERFACES_H_
+#define _USRP_INTERFACES_H_
+
+/*
+ * We've now split the USRP into 3 separate interfaces.
+ *
+ * Interface 0 contains only ep0 and is used for command and status.
+ * Interface 1 is the Tx path and it uses ep2 OUT BULK.
+ * Interface 2 is the Rx path and it uses ep6 IN BULK.
+ */
+
+#define USRP_CMD_INTERFACE 0
+#define USRP_CMD_ALTINTERFACE 0
+#define USRP_CMD_ENDPOINT 0
+
+#define USRP_TX_INTERFACE 1
+#define USRP_TX_ALTINTERFACE 0
+#define USRP_TX_ENDPOINT 2 // streaming data from host to FPGA
+
+#define USRP_RX_INTERFACE 2
+#define USRP_RX_ALTINTERFACE 0
+#define USRP_RX_ENDPOINT 6 // streaming data from FPGA to host
+
+
+#endif /* _USRP_INTERFACES_H_ */
diff --git a/firmware/fx2/include/usrp_spi_defs.h b/firmware/fx2/include/usrp_spi_defs.h
new file mode 100644
index 000000000..963463ef2
--- /dev/null
+++ b/firmware/fx2/include/usrp_spi_defs.h
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_USRP_SPI_DEFS_H
+#define INCLUDED_USRP_SPI_DEFS_H
+
+/*
+ * defines for the VRQ_SPI_READ and VRQ_SPI_WRITE commands
+ *
+ * SPI == "Serial Port Interface". SPI is a 3 wire bus plus a
+ * separate enable for each peripheral. The common lines are SCLK,
+ * SDI and SDO. The FX2 always drives SCLK and SDI, the clock and
+ * data lines from the FX2 to the peripheral. When enabled, a
+ * peripheral may drive SDO, the data line from the peripheral to the
+ * FX2.
+ *
+ * The SPI_READ and SPI_WRITE commands are formatted identically.
+ * Each specifies which peripherals to enable, whether the bits should
+ * be transmistted Most Significant Bit first or Least Significant Bit
+ * first, the number of bytes in the optional header, and the number
+ * of bytes to read or write in the body.
+ *
+ * The body is limited to 64 bytes. The optional header may contain
+ * 0, 1 or 2 bytes. For an SPI_WRITE, the header bytes are
+ * transmitted to the peripheral followed by the the body bytes. For
+ * an SPI_READ, the header bytes are transmitted to the peripheral,
+ * then len bytes are read back from the peripheral.
+ */
+
+/*
+ * SPI_FMT_* goes in wIndexL
+ */
+#define SPI_FMT_xSB_MASK (1 << 7)
+# define SPI_FMT_LSB (1 << 7) // least signficant bit first
+# define SPI_FMT_MSB (0 << 7) // most significant bit first
+#define SPI_FMT_HDR_MASK (3 << 5)
+# define SPI_FMT_HDR_0 (0 << 5) // 0 header bytes
+# define SPI_FMT_HDR_1 (1 << 5) // 1 header byte
+# define SPI_FMT_HDR_2 (2 << 5) // 2 header bytes
+
+/*
+ * SPI_ENABLE_* goes in wIndexH
+ *
+ * For the software interface, the enables are active high.
+ * For reads, it's an error to have more than one enable set.
+ *
+ * [FWIW, the hardware implements them as active low. Don't change the
+ * definitions of these. They are related to usrp_rev1_regs.h]
+ */
+#define SPI_ENABLE_FPGA 0x01 // select FPGA
+#define SPI_ENABLE_CODEC_A 0x02 // select AD9862 A
+#define SPI_ENABLE_CODEC_B 0x04 // select AD9862 B
+#define SPI_ENABLE_reserved 0x08
+#define SPI_ENABLE_TX_A 0x10 // select d'board TX A
+#define SPI_ENABLE_RX_A 0x20 // select d'board RX A
+#define SPI_ENABLE_TX_B 0x40 // select d'board TX B
+#define SPI_ENABLE_RX_B 0x80 // select d'board RX B
+
+/*
+ * If there's one header byte, it goes in wValueL.
+ *
+ * If there are two header bytes, they go in wValueH | wValueL.
+ * The transmit order of the bytes (and bits within them) is
+ * determined by SPI_FMT_*SB
+ */
+
+#endif /* INCLUDED_USRP_SPI_DEFS_H */
diff --git a/firmware/fx2/lib/.gitignore b/firmware/fx2/lib/.gitignore
new file mode 100644
index 000000000..04f253234
--- /dev/null
+++ b/firmware/fx2/lib/.gitignore
@@ -0,0 +1,18 @@
+/*.ihx
+/*.lnk
+/*.lst
+/*.map
+/*.mem
+/*.rel
+/*.rst
+/*.sym
+/blink_leds.asm
+/usrp_common.asm
+/command_loop.asm
+/fpga.asm
+/*.asm
+/usrp_gpif.c
+/usrp_gpif_inline.h
+/*.lib
+/Makefile
+/Makefile.in
diff --git a/firmware/fx2/lib/Makefile.am b/firmware/fx2/lib/Makefile.am
new file mode 100644
index 000000000..f9e1b2317
--- /dev/null
+++ b/firmware/fx2/lib/Makefile.am
@@ -0,0 +1,79 @@
+#
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+EXTRA_DIST = \
+ delay.c \
+ fx2utils.c \
+ i2c.c \
+ isr.c \
+ timer.c \
+ usb_common.c
+
+
+
+DEFINES=
+FW_INCLUDES=-I$(top_srcdir)/include
+
+# with EA = 0, the FX2 implements a portion of the 8051 "external memory"
+# on chip. This memory is mapped like this:
+#
+# The bottom 8K of memory (0x0000 - 0x1fff) is used for both data and
+# code accesses. There's also 512 bytes for data only from 0xe000 - 0xe1ff.
+#
+# We tell the linker to start the xdata segment at 0x1800, 6K up from
+# the bottom.
+
+LINKOPTS = --code-loc 0x0000 --code-size 0x1800 --xram-loc 0x1800 --xram-size 0x0800
+
+LIBRARY = libfx2.lib
+
+LIBOBJS = \
+ delay.rel \
+ fx2utils.rel \
+ i2c.rel \
+ isr.rel \
+ timer.rel \
+ usb_common.rel
+
+
+
+all: libfx2.lib
+
+.c.rel:
+ $(XCC) $(FW_INCLUDES) $(DEFINES) -c $< -o $@
+
+$(LIBRARY): $(LIBOBJS)
+ -rm -f $(LIBRARY)
+ touch $(LIBRARY)
+ for obj in $(LIBOBJS); do basename $$obj .rel >> $(LIBRARY) ; done
+
+
+CLEANFILES = \
+ *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib
+
+DISTCLEANFILES = \
+ *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib
+
+install: all
+
+
+# dependencies
+
diff --git a/firmware/fx2/lib/delay.c b/firmware/fx2/lib/delay.c
new file mode 100644
index 000000000..13cf0eec8
--- /dev/null
+++ b/firmware/fx2/lib/delay.c
@@ -0,0 +1,76 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * Delay approximately 1 microsecond (including overhead in udelay).
+ */
+static void
+udelay1 (void) _naked
+{
+ _asm ; lcall that got us here took 4 bus cycles
+ ret ; 4 bus cycles
+ _endasm;
+}
+
+/*
+ * delay for approximately usecs microseconds
+ */
+void
+udelay (unsigned char usecs)
+{
+ do {
+ udelay1 ();
+ } while (--usecs != 0);
+}
+
+
+/*
+ * Delay approximately 1 millisecond.
+ * We're running at 48 MHz, so we need 48,000 clock cycles.
+ *
+ * Note however, that each bus cycle takes 4 clock cycles (not obvious,
+ * but explains the factor of 4 problem below).
+ */
+static void
+mdelay1 (void) _naked
+{
+ _asm
+ mov dptr,#(-1200 & 0xffff)
+002$:
+ inc dptr ; 3 bus cycles
+ mov a, dpl ; 2 bus cycles
+ orl a, dph ; 2 bus cycles
+ jnz 002$ ; 3 bus cycles
+
+ ret
+ _endasm;
+}
+
+void
+mdelay (unsigned int msecs)
+{
+ do {
+ mdelay1 ();
+ } while (--msecs != 0);
+}
+
+
diff --git a/firmware/fx2/lib/fx2utils.c b/firmware/fx2/lib/fx2utils.c
new file mode 100644
index 000000000..64ffcc896
--- /dev/null
+++ b/firmware/fx2/lib/fx2utils.c
@@ -0,0 +1,54 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "fx2utils.h"
+#include "fx2regs.h"
+#include "delay.h"
+
+void
+fx2_stall_ep0 (void)
+{
+ EP0CS |= bmEPSTALL;
+}
+
+void
+fx2_reset_data_toggle (unsigned char ep)
+{
+ TOGCTL = ((ep & 0x80) >> 3 | (ep & 0x0f));
+ TOGCTL |= bmRESETTOGGLE;
+}
+
+void
+fx2_renumerate (void)
+{
+ USBCS |= bmDISCON | bmRENUM;
+
+ // mdelay (1500); // FIXME why 1.5 seconds?
+ mdelay (250); // FIXME why 1.5 seconds?
+
+ USBIRQ = 0xff; // clear any pending USB irqs...
+ EPIRQ = 0xff; // they're from before the renumeration
+
+ EXIF &= ~bmEXIF_USBINT;
+
+ USBCS &= ~bmDISCON; // reconnect USB
+}
diff --git a/firmware/fx2/lib/i2c-compiler-bug.c b/firmware/fx2/lib/i2c-compiler-bug.c
new file mode 100644
index 000000000..360b779bc
--- /dev/null
+++ b/firmware/fx2/lib/i2c-compiler-bug.c
@@ -0,0 +1,129 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "i2c.h"
+#include "fx2regs.h"
+#include <string.h>
+
+
+// issue a stop bus cycle and wait for completion
+
+
+// returns non-zero if successful, else 0
+unsigned char
+i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len)
+{
+ volatile unsigned char junk;
+
+ if (len == 0) // reading zero bytes always works
+ return 1;
+
+ // memset (buf, 0, len); // FIXME, remove
+
+ while (I2CS & bmSTOP) // wait for stop to clear
+ ;
+
+
+ I2CS = bmSTART;
+ I2DAT = (addr << 1) | 1; // write address and direction (1's the read bit)
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...
+ goto fail;
+
+ if (len == 1)
+ I2CS |= bmLASTRD;
+
+ junk = I2DAT; // trigger the first read cycle
+
+#if 1
+ while (len != 1){
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if (I2CS & bmBERR)
+ goto fail;
+
+ len--;
+ if (len == 1)
+ I2CS |= bmLASTRD;
+
+ *buf++ = I2DAT; // get data, trigger another read
+ }
+#endif
+
+ // wait for final byte
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if (I2CS & bmBERR)
+ goto fail;
+
+ I2CS |= bmSTOP;
+ *buf = I2DAT;
+
+ return 1;
+
+ fail:
+ I2CS |= bmSTOP;
+ return 0;
+}
+
+
+
+// returns non-zero if successful, else 0
+unsigned char
+i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len)
+{
+ while (I2CS & bmSTOP) // wait for stop to clear
+ ;
+
+ I2CS = bmSTART;
+ I2DAT = (addr << 1) | 0; // write address and direction (0's the write bit)
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...
+ goto fail;
+
+ while (len > 0){
+ I2DAT = *buf++;
+ len--;
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...
+ goto fail;
+ }
+
+ I2CS |= bmSTOP;
+ return 1;
+
+ fail:
+ I2CS |= bmSTOP;
+ return 0;
+}
diff --git a/firmware/fx2/lib/i2c.c b/firmware/fx2/lib/i2c.c
new file mode 100644
index 000000000..0f238b5cf
--- /dev/null
+++ b/firmware/fx2/lib/i2c.c
@@ -0,0 +1,123 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "i2c.h"
+#include "fx2regs.h"
+#include <string.h>
+
+
+// issue a stop bus cycle and wait for completion
+
+
+// returns non-zero if successful, else 0
+unsigned char
+i2c_read (unsigned char addr, xdata unsigned char *buf, unsigned char len)
+{
+ volatile unsigned char junk;
+
+ if (len == 0) // reading zero bytes always works
+ return 1;
+
+ while (I2CS & bmSTOP) // wait for stop to clear
+ ;
+
+ I2CS = bmSTART;
+ I2DAT = (addr << 1) | 1; // write address and direction (1's the read bit)
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...
+ goto fail;
+
+ if (len == 1)
+ I2CS |= bmLASTRD;
+
+ junk = I2DAT; // trigger the first read cycle
+
+ while (--len != 0){
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if (I2CS & bmBERR)
+ goto fail;
+
+ if (len == 1)
+ I2CS |= bmLASTRD;
+
+ *buf++ = I2DAT; // get data, trigger another read
+ }
+
+ // wait for final byte
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if (I2CS & bmBERR)
+ goto fail;
+
+ I2CS |= bmSTOP;
+ *buf = I2DAT;
+
+ return 1;
+
+ fail:
+ I2CS |= bmSTOP;
+ return 0;
+}
+
+
+
+// returns non-zero if successful, else 0
+unsigned char
+i2c_write (unsigned char addr, xdata const unsigned char *buf, unsigned char len)
+{
+ while (I2CS & bmSTOP) // wait for stop to clear
+ ;
+
+ I2CS = bmSTART;
+ I2DAT = (addr << 1) | 0; // write address and direction (0's the write bit)
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...
+ goto fail;
+
+ while (len > 0){
+ I2DAT = *buf++;
+ len--;
+
+ while ((I2CS & bmDONE) == 0)
+ ;
+
+ if ((I2CS & bmBERR) || (I2CS & bmACK) == 0) // no device answered...
+ goto fail;
+ }
+
+ I2CS |= bmSTOP;
+ return 1;
+
+ fail:
+ I2CS |= bmSTOP;
+ return 0;
+}
diff --git a/firmware/fx2/lib/isr.c b/firmware/fx2/lib/isr.c
new file mode 100644
index 000000000..05412daf5
--- /dev/null
+++ b/firmware/fx2/lib/isr.c
@@ -0,0 +1,167 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "isr.h"
+#include "fx2regs.h"
+#include "syncdelay.h"
+
+extern xdata unsigned char _standard_interrupt_vector[];
+extern xdata unsigned char _usb_autovector[];
+extern xdata unsigned char _fifo_gpif_autovector[];
+
+#define LJMP_OPCODE 0x02
+
+/*
+ * Hook standard interrupt vector.
+ *
+ * vector_number is from the SV_<foo> list.
+ * addr is the address of the interrupt service routine.
+ */
+void
+hook_sv (unsigned char vector_number, unsigned short addr)
+{
+ bit t;
+
+ // sanity checks
+
+ if (vector_number < SV_MIN || vector_number > SV_MAX)
+ return;
+
+ if ((vector_number & 0x0f) != 0x03 && (vector_number & 0x0f) != 0x0b)
+ return;
+
+ t = EA;
+ EA = 0;
+ _standard_interrupt_vector[vector_number] = LJMP_OPCODE;
+ _standard_interrupt_vector[vector_number + 1] = addr >> 8;
+ _standard_interrupt_vector[vector_number + 2] = addr & 0xff;
+ EA = t;
+}
+
+/*
+ * Hook usb interrupt vector.
+ *
+ * vector_number is from the UV_<foo> list.
+ * addr is the address of the interrupt service routine.
+ */
+void
+hook_uv (unsigned char vector_number, unsigned short addr)
+{
+ bit t;
+
+ // sanity checks
+
+ if (vector_number < UV_MIN || vector_number > UV_MAX)
+ return;
+
+ if ((vector_number & 0x3) != 0)
+ return;
+
+ t = EA;
+ EA = 0;
+ _usb_autovector[vector_number] = LJMP_OPCODE;
+ _usb_autovector[vector_number + 1] = addr >> 8;
+ _usb_autovector[vector_number + 2] = addr & 0xff;
+ EA = t;
+}
+
+/*
+ * Hook fifo/gpif interrupt vector.
+ *
+ * vector_number is from the FGV_<foo> list.
+ * addr is the address of the interrupt service routine.
+ */
+void
+hook_fgv (unsigned char vector_number, unsigned short addr)
+{
+ bit t;
+
+ // sanity checks
+
+ if (vector_number < FGV_MIN || vector_number > FGV_MAX)
+ return;
+
+ if ((vector_number & 0x3) != 0)
+ return;
+
+ t = EA;
+ EA = 0;
+ _fifo_gpif_autovector[vector_number] = LJMP_OPCODE;
+ _fifo_gpif_autovector[vector_number + 1] = addr >> 8;
+ _fifo_gpif_autovector[vector_number + 2] = addr & 0xff;
+ EA = t;
+}
+
+/*
+ * One time call to enable autovectoring for both USB and FIFO/GPIF.
+ *
+ * This disables all USB and FIFO/GPIF interrupts and clears
+ * any pending interrupts too. It leaves the master USB and FIFO/GPIF
+ * interrupts enabled.
+ */
+void
+setup_autovectors (void)
+{
+ // disable master usb and fifo/gpif interrupt enables
+ EIUSB = 0;
+ EIEX4 = 0;
+
+ hook_sv (SV_INT_2, (unsigned short) _usb_autovector);
+ hook_sv (SV_INT_4, (unsigned short) _fifo_gpif_autovector);
+
+ // disable all fifo interrupt enables
+ SYNCDELAY;
+ EP2FIFOIE = 0; SYNCDELAY;
+ EP4FIFOIE = 0; SYNCDELAY;
+ EP6FIFOIE = 0; SYNCDELAY;
+ EP8FIFOIE = 0; SYNCDELAY;
+
+ // clear all pending fifo irqs
+ EP2FIFOIRQ = 0xff; SYNCDELAY;
+ EP4FIFOIRQ = 0xff; SYNCDELAY;
+ EP6FIFOIRQ = 0xff; SYNCDELAY;
+ EP8FIFOIRQ = 0xff; SYNCDELAY;
+
+ IBNIE = 0;
+ IBNIRQ = 0xff;
+ NAKIE = 0;
+ NAKIRQ = 0xff;
+ USBIE = 0;
+ USBIRQ = 0xff;
+ EPIE = 0;
+ EPIRQ = 0xff;
+ SYNCDELAY; GPIFIE = 0;
+ SYNCDELAY; GPIFIRQ = 0xff;
+ USBERRIE = 0;
+ USBERRIRQ = 0xff;
+ CLRERRCNT = 0;
+
+ INTSETUP = bmAV2EN | bmAV4EN | bmINT4IN;
+
+ // clear master irq's for usb and fifo/gpif
+ EXIF &= ~bmEXIF_USBINT;
+ EXIF &= ~bmEXIF_IE4;
+
+ // enable master usb and fifo/gpif interrrupts
+ EIUSB = 1;
+ EIEX4 = 1;
+}
diff --git a/firmware/fx2/lib/timer.c b/firmware/fx2/lib/timer.c
new file mode 100644
index 000000000..97e2f7cf9
--- /dev/null
+++ b/firmware/fx2/lib/timer.c
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "timer.h"
+#include "fx2regs.h"
+#include "isr.h"
+
+/*
+ * Arrange to have isr_tick_handler called at 100 Hz.
+ *
+ * The cpu clock is running at 48e6. The input to the timer
+ * is 48e6 / 12 = 4e6.
+ *
+ * We arrange to have the timer overflow every 40000 clocks == 100 Hz
+ */
+
+#define RELOAD_VALUE ((unsigned short) -40000)
+
+void
+hook_timer_tick (unsigned short isr_tick_handler)
+{
+ ET2 = 0; // disable timer 2 interrupts
+ hook_sv (SV_TIMER_2, isr_tick_handler);
+
+ RCAP2H = RELOAD_VALUE >> 8; // setup the auto reload value
+ RCAP2L = RELOAD_VALUE;
+
+ T2CON = 0x04; // interrupt on overflow; reload; run
+ ET2 = 1; // enable timer 2 interrupts
+}
diff --git a/firmware/fx2/lib/usb_common.c b/firmware/fx2/lib/usb_common.c
new file mode 100644
index 000000000..3b0547b2f
--- /dev/null
+++ b/firmware/fx2/lib/usb_common.c
@@ -0,0 +1,386 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usb_common.h"
+#include "fx2regs.h"
+#include "syncdelay.h"
+#include "fx2utils.h"
+#include "isr.h"
+#include "usb_descriptors.h"
+#include "usb_requests.h"
+
+extern xdata char str0[];
+extern xdata char str1[];
+extern xdata char str2[];
+extern xdata char str3[];
+extern xdata char str4[];
+extern xdata char str5[];
+
+
+#define bRequestType SETUPDAT[0]
+#define bRequest SETUPDAT[1]
+#define wValueL SETUPDAT[2]
+#define wValueH SETUPDAT[3]
+#define wIndexL SETUPDAT[4]
+#define wIndexH SETUPDAT[5]
+#define wLengthL SETUPDAT[6]
+#define wLengthH SETUPDAT[7]
+
+#define MSB(x) (((unsigned short) x) >> 8)
+#define LSB(x) (((unsigned short) x) & 0xff)
+
+volatile bit _usb_got_SUDAV;
+
+unsigned char _usb_config = 0;
+unsigned char _usb_alt_setting = 0; // FIXME really 1/interface
+
+xdata unsigned char *current_device_descr;
+xdata unsigned char *current_devqual_descr;
+xdata unsigned char *current_config_descr;
+xdata unsigned char *other_config_descr;
+
+static void
+setup_descriptors (void)
+{
+ if (USBCS & bmHSM){ // high speed mode
+ current_device_descr = high_speed_device_descr;
+ current_devqual_descr = high_speed_devqual_descr;
+ current_config_descr = high_speed_config_descr;
+ other_config_descr = full_speed_config_descr;
+ }
+ else {
+ current_device_descr = full_speed_device_descr;
+ current_devqual_descr = full_speed_devqual_descr;
+ current_config_descr = full_speed_config_descr;
+ other_config_descr = high_speed_config_descr;
+ }
+
+ // whack the type fields
+ // FIXME, may not be required.
+ // current_config_descr[1] = DT_CONFIG;
+ // other_config_descr[1] = DT_OTHER_SPEED;
+}
+
+static void
+isr_SUDAV (void) interrupt
+{
+ clear_usb_irq ();
+ _usb_got_SUDAV = 1;
+}
+
+static void
+isr_USBRESET (void) interrupt
+{
+ clear_usb_irq ();
+ setup_descriptors ();
+}
+
+static void
+isr_HIGHSPEED (void) interrupt
+{
+ clear_usb_irq ();
+ setup_descriptors ();
+}
+
+void
+usb_install_handlers (void)
+{
+ setup_descriptors (); // ensure that they're set before use
+
+ hook_uv (UV_SUDAV, (unsigned short) isr_SUDAV);
+ hook_uv (UV_USBRESET, (unsigned short) isr_USBRESET);
+ hook_uv (UV_HIGHSPEED, (unsigned short) isr_HIGHSPEED);
+
+ USBIE = bmSUDAV | bmURES | bmHSGRANT;
+}
+
+// On the FX2 the only plausible endpoints are 0, 1, 2, 4, 6, 8
+// This doesn't check to see that they're enabled
+
+unsigned char
+plausible_endpoint (unsigned char ep)
+{
+ ep &= ~0x80; // ignore direction bit
+
+ if (ep > 8)
+ return 0;
+
+ if (ep == 1)
+ return 1;
+
+ return (ep & 0x1) == 0; // must be even
+}
+
+// return pointer to control and status register for endpoint.
+// only called with plausible_endpoints
+
+xdata volatile unsigned char *
+epcs (unsigned char ep)
+{
+ if (ep == 0x01) // ep1 has different in and out CS regs
+ return EP1OUTCS;
+
+ if (ep == 0x81)
+ return EP1INCS;
+
+ ep &= ~0x80; // ignore direction bit
+
+ if (ep == 0x00) // ep0
+ return EP0CS;
+
+ return EP2CS + (ep >> 1); // 2, 4, 6, 8 are consecutive
+}
+
+void
+usb_handle_setup_packet (void)
+{
+ _usb_got_SUDAV = 0;
+
+ // handle the standard requests...
+
+ switch (bRequestType & bmRT_TYPE_MASK){
+
+ case bmRT_TYPE_CLASS:
+ case bmRT_TYPE_RESERVED:
+ fx2_stall_ep0 (); // we don't handle these. indicate error
+ break;
+
+ case bmRT_TYPE_VENDOR:
+ // call the application code.
+ // If it handles the command it returns non-zero
+
+ if (!app_vendor_cmd ())
+ fx2_stall_ep0 ();
+ break;
+
+ case bmRT_TYPE_STD:
+ // these are the standard requests...
+
+ if ((bRequestType & bmRT_DIR_MASK) == bmRT_DIR_IN){
+
+ ////////////////////////////////////
+ // handle the IN requests
+ ////////////////////////////////////
+
+ switch (bRequest){
+
+ case RQ_GET_CONFIG:
+ EP0BUF[0] = _usb_config; // FIXME app should handle
+ EP0BCH = 0;
+ EP0BCL = 1;
+ break;
+
+ // --------------------------------
+
+ case RQ_GET_INTERFACE:
+ EP0BUF[0] = _usb_alt_setting; // FIXME app should handle
+ EP0BCH = 0;
+ EP0BCL = 1;
+ break;
+
+ // --------------------------------
+
+ case RQ_GET_DESCR:
+ switch (wValueH){
+
+ case DT_DEVICE:
+ SUDPTRH = MSB (current_device_descr);
+ SUDPTRL = LSB (current_device_descr);
+ break;
+
+ case DT_DEVQUAL:
+ SUDPTRH = MSB (current_devqual_descr);
+ SUDPTRL = LSB (current_devqual_descr);
+ break;
+
+ case DT_CONFIG:
+ if (0 && wValueL != 1) // FIXME only a single configuration
+ fx2_stall_ep0 ();
+ else {
+ SUDPTRH = MSB (current_config_descr);
+ SUDPTRL = LSB (current_config_descr);
+ }
+ break;
+
+ case DT_OTHER_SPEED:
+ if (0 && wValueL != 1) // FIXME only a single configuration
+ fx2_stall_ep0 ();
+ else {
+ SUDPTRH = MSB (other_config_descr);
+ SUDPTRL = LSB (other_config_descr);
+ }
+ break;
+
+ case DT_STRING:
+ if (wValueL >= nstring_descriptors)
+ fx2_stall_ep0 ();
+ else {
+ xdata char *p = string_descriptors[wValueL];
+ SUDPTRH = MSB (p);
+ SUDPTRL = LSB (p);
+ }
+ break;
+
+ default:
+ fx2_stall_ep0 (); // invalid request
+ break;
+ }
+ break;
+
+ // --------------------------------
+
+ case RQ_GET_STATUS:
+ switch (bRequestType & bmRT_RECIP_MASK){
+ case bmRT_RECIP_DEVICE:
+ EP0BUF[0] = bmGSDA_SELF_POWERED; // FIXME app should handle
+ EP0BUF[1] = 0;
+ EP0BCH = 0;
+ EP0BCL = 2;
+ break;
+
+ case bmRT_RECIP_INTERFACE:
+ EP0BUF[0] = 0;
+ EP0BUF[1] = 0;
+ EP0BCH = 0;
+ EP0BCL = 2;
+ break;
+
+ case bmRT_RECIP_ENDPOINT:
+ if (plausible_endpoint (wIndexL)){
+ EP0BUF[0] = *epcs (wIndexL) & bmEPSTALL;
+ EP0BUF[1] = 0;
+ EP0BCH = 0;
+ EP0BCL = 2;
+ }
+ else
+ fx2_stall_ep0 ();
+ break;
+
+ default:
+ fx2_stall_ep0 ();
+ break;
+ }
+ break;
+
+ // --------------------------------
+
+ case RQ_SYNCH_FRAME: // not implemented
+ default:
+ fx2_stall_ep0 ();
+ break;
+ }
+ }
+
+ else {
+
+ ////////////////////////////////////
+ // handle the OUT requests
+ ////////////////////////////////////
+
+ switch (bRequest){
+
+ case RQ_SET_CONFIG:
+ _usb_config = wValueL; // FIXME app should handle
+ break;
+
+ case RQ_SET_INTERFACE:
+ _usb_alt_setting = wValueL; // FIXME app should handle
+ break;
+
+ // --------------------------------
+
+ case RQ_CLEAR_FEATURE:
+ switch (bRequestType & bmRT_RECIP_MASK){
+
+ case bmRT_RECIP_DEVICE:
+ switch (wValueL){
+ case FS_DEV_REMOTE_WAKEUP:
+ default:
+ fx2_stall_ep0 ();
+ }
+ break;
+
+ case bmRT_RECIP_ENDPOINT:
+ if (wValueL == FS_ENDPOINT_HALT && plausible_endpoint (wIndexL)){
+ *epcs (wIndexL) &= ~bmEPSTALL;
+ fx2_reset_data_toggle (wIndexL);
+ }
+ else
+ fx2_stall_ep0 ();
+ break;
+
+ default:
+ fx2_stall_ep0 ();
+ break;
+ }
+ break;
+
+ // --------------------------------
+
+ case RQ_SET_FEATURE:
+ switch (bRequestType & bmRT_RECIP_MASK){
+
+ case bmRT_RECIP_DEVICE:
+ switch (wValueL){
+ case FS_TEST_MODE:
+ // hardware handles this after we complete SETUP phase handshake
+ break;
+
+ case FS_DEV_REMOTE_WAKEUP:
+ default:
+ fx2_stall_ep0 ();
+ break;
+ }
+ }
+ break;
+
+ case bmRT_RECIP_ENDPOINT:
+ switch (wValueL){
+ case FS_ENDPOINT_HALT:
+ if (plausible_endpoint (wIndexL))
+ *epcs (wIndexL) |= bmEPSTALL;
+ else
+ fx2_stall_ep0 ();
+ break;
+
+ default:
+ fx2_stall_ep0 ();
+ break;
+ }
+ break;
+
+ // --------------------------------
+
+ case RQ_SET_ADDRESS: // handled by fx2 hardware
+ case RQ_SET_DESCR: // not implemented
+ default:
+ fx2_stall_ep0 ();
+ }
+
+ }
+ break;
+
+ } // bmRT_TYPE_MASK
+
+ // ack handshake phase of device request
+ EP0CS |= bmHSNAK;
+}
diff --git a/firmware/fx2/src/.gitignore b/firmware/fx2/src/.gitignore
new file mode 100644
index 000000000..d46c52c00
--- /dev/null
+++ b/firmware/fx2/src/.gitignore
@@ -0,0 +1,17 @@
+/*.ihx
+/*.lnk
+/*.lst
+/*.map
+/*.mem
+/*.rel
+/*.rst
+/*.sym
+/blink_leds.asm
+/usrp_common.asm
+/command_loop.asm
+/fpga.asm
+/*.asm
+/usrp_gpif.c
+/usrp_gpif_inline.h
+/Makefile
+/Makefile.in
diff --git a/firmware/fx2/src/Makefile.am b/firmware/fx2/src/Makefile.am
new file mode 100644
index 000000000..5dcff2c85
--- /dev/null
+++ b/firmware/fx2/src/Makefile.am
@@ -0,0 +1,22 @@
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+SUBDIRS = common usrp1
diff --git a/firmware/fx2/src/common/.gitignore b/firmware/fx2/src/common/.gitignore
new file mode 100644
index 000000000..d46c52c00
--- /dev/null
+++ b/firmware/fx2/src/common/.gitignore
@@ -0,0 +1,17 @@
+/*.ihx
+/*.lnk
+/*.lst
+/*.map
+/*.mem
+/*.rel
+/*.rst
+/*.sym
+/blink_leds.asm
+/usrp_common.asm
+/command_loop.asm
+/fpga.asm
+/*.asm
+/usrp_gpif.c
+/usrp_gpif_inline.h
+/Makefile
+/Makefile.in
diff --git a/firmware/fx2/src/common/Makefile.am b/firmware/fx2/src/common/Makefile.am
new file mode 100644
index 000000000..95232324d
--- /dev/null
+++ b/firmware/fx2/src/common/Makefile.am
@@ -0,0 +1,50 @@
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+EXTRA_DIST = \
+ _startup.a51 \
+ blink_leds.c \
+ check_mdelay.c \
+ check_udelay.c \
+ edit-gpif \
+ fpga.h \
+ fpga_load.h \
+ fpga_load.c \
+ gpif.c \
+ gpif.gpf \
+ init_gpif.c \
+ usrp_common.c \
+ usrp_globals.h \
+ vectors.a51 \
+ build_eeprom.py
+
+all: usrp_gpif.c
+
+usrp_gpif.c usrp_gpif_inline.h : gpif.c
+ srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h
+
+CLEANFILES = \
+ *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \
+ usrp_gpif.c usrp_gpif_inline.h
+
+DISTCLEANFILES = \
+ *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib \
+ usrp_gpif.c usrp_gpif_inline.h
diff --git a/firmware/fx2/src/common/_startup.a51 b/firmware/fx2/src/common/_startup.a51
new file mode 100644
index 000000000..30a907857
--- /dev/null
+++ b/firmware/fx2/src/common/_startup.a51
@@ -0,0 +1,80 @@
+;;; -*- asm -*-
+;;;
+;;; Copyright 2003,2004 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio 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 3, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+;;; the Free Software Foundation, Inc., 51 Franklin Street,
+;;; Boston, MA 02110-1301, USA.
+
+
+;;; The default external memory initialization provided by sdcc is not
+;;; appropriate to the FX2. This is derived from the sdcc code, but uses
+;;; the FX2 specific _MPAGE sfr.
+
+
+ ;; .area XISEG (XDATA) ; the initialized external data area
+ ;; .area XINIT (CODE) ; the code space consts to init XISEG
+ .area XSEG (XDATA) ; zero initialized xdata
+ .area USBDESCSEG (XDATA) ; usb descriptors
+
+
+ .area CSEG (CODE)
+
+ ;; sfr that sets upper address byte of MOVX using @r0 or @r1
+ _MPAGE = 0x0092
+
+__sdcc_external_startup::
+ ;; This system is now compiled with the --no-xinit-opt
+ ;; which means that any initialized XDATA is handled
+ ;; inline by code in the GSINIT segs emitted for each file.
+ ;;
+ ;; We zero XSEG and all of the internal ram to ensure
+ ;; a known good state for uninitialized variables.
+
+; _mcs51_genRAMCLEAR() start
+ mov r0,#l_XSEG
+ mov a,r0
+ orl a,#(l_XSEG >> 8)
+ jz 00002$
+ mov r1,#((l_XSEG + 255) >> 8)
+ mov dptr,#s_XSEG
+ clr a
+
+00001$: movx @dptr,a
+ inc dptr
+ djnz r0,00001$
+ djnz r1,00001$
+
+ ;; We're about to clear internal memory. This will overwrite
+ ;; the stack which contains our return address.
+ ;; Pop our return address into DPH, DPL
+00002$: pop dph
+ pop dpl
+
+ ;; R0 and A contain 0. This loop will execute 256 times.
+ ;;
+ ;; FWIW the first iteration writes direct address 0x00,
+ ;; which is the location of r0. We get lucky, we're
+ ;; writing the correct value (0)
+
+00003$: mov @r0,a
+ djnz r0,00003$
+
+ push dpl ; restore our return address
+ push dph
+
+ mov dpl,#0 ; indicate that data init is still required
+ ret
diff --git a/firmware/fx2/src/common/_startup.a51.brittle b/firmware/fx2/src/common/_startup.a51.brittle
new file mode 100644
index 000000000..2996275cf
--- /dev/null
+++ b/firmware/fx2/src/common/_startup.a51.brittle
@@ -0,0 +1,78 @@
+;;; -*- asm -*-
+;;;
+;;; Copyright 2003 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio 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 3, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+;;; the Free Software Foundation, Inc., 51 Franklin Street,
+;;; Boston, MA 02110-1301, USA.
+
+
+;;; The default external memory initialization provided by sdcc is not
+;;; appropriate to the FX2. This is derived from the sdcc code, but uses
+;;; the FX2 specific _MPAGE sfr.
+
+
+ .area XISEG (XDATA) ; the initialized external data area
+ .area XINIT (CODE) ; the code space consts to init XISEG
+ .area XSEG (XDATA) ; zero initialized xdata
+ .area USBDESCSEG (XDATA); usb descriptors
+
+
+ ;; BIG TIME KLUDGE!
+ ;; Look at usrp_main.rst and count the bytes from our
+ ;; "normal return location" to the first instruction following
+ ;; the comment: "_mcs51_getRAMCLEAR () start"
+
+ INSTRUCTION_BYTES_TO_SKIP = 0x29 ; valid for sdcc 2.4.0
+
+
+ .area CSEG (CODE)
+
+ ;; sfr that sets upper address byte of MOVX using @r0 or @r1
+ _MPAGE = 0x0092
+
+__sdcc_external_startup::
+; _mcs51_genXINIT() start
+ mov r1,#l_XINIT
+ mov a,r1
+ orl a,#(l_XINIT >> 8)
+ jz 00003$
+ mov r2,#((l_XINIT+255) >> 8)
+ mov dptr,#s_XINIT
+ mov r0,#s_XISEG
+ mov _MPAGE,#(s_XISEG >> 8)
+00001$: clr a
+ movc a,@a+dptr
+ movx @r0,a
+ inc dptr
+ inc r0
+ cjne r0,#0,00002$
+ inc _MPAGE
+00002$: djnz r1,00001$
+ djnz r2,00001$
+ mov _MPAGE,#0xFF
+00003$:
+
+ ;; Danger! Total KLUDGE!
+ ;; We pop the return address, add a magic number to it
+ ;; then jump to that address. Believe it or not, this
+ ;; looks like the least kludgy way to handle this,
+ ;; short of patching the compiler...
+
+ pop dph
+ pop dpl
+ mov a,#INSTRUCTION_BYTES_TO_SKIP
+ jmp @a+dptr
diff --git a/firmware/fx2/src/common/blink_leds.c b/firmware/fx2/src/common/blink_leds.c
new file mode 100644
index 000000000..255c69733
--- /dev/null
+++ b/firmware/fx2/src/common/blink_leds.c
@@ -0,0 +1,36 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#include "usrp_common.h"
+
+void
+main (void)
+{
+ unsigned short counter = 0;
+
+ init_usrp ();
+
+ while (1){
+ unsigned char counter_high = counter >> 8;
+ set_led_0 (counter_high & 0x40);
+ set_led_1 (counter_high & 0x80);
+ counter++;
+ }
+}
diff --git a/firmware/fx2/src/common/build_eeprom.py b/firmware/fx2/src/common/build_eeprom.py
new file mode 100755
index 000000000..ae62587db
--- /dev/null
+++ b/firmware/fx2/src/common/build_eeprom.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+#
+# Copyright 2004,2006 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+import re
+import sys
+import os, os.path
+from optparse import OptionParser
+
+# USB Vendor and Product ID's
+
+VID = 0xfffe # Free Software Folks
+PID = 0x0002 # Universal Software Radio Peripheral
+
+def msb (x):
+ return (x >> 8) & 0xff
+
+def lsb (x):
+ return x & 0xff
+
+def build_eeprom_image (filename, rev):
+ """Build a ``C2 Load'' EEPROM image.
+
+ For details on this format, see section 3.4.3 of
+ the EZ-USB FX2 Technical Reference Manual
+ """
+ # get the code we want to run
+ f = open(filename, 'rb')
+ bytes = f.read()
+
+ devid = rev
+ start_addr = 0 #prove me wrong
+
+ rom_header = [
+ 0xC2, # boot from EEPROM
+ lsb (VID),
+ msb (VID),
+ lsb (PID),
+ msb (PID),
+ lsb (devid),
+ msb (devid),
+ 0 # configuration byte
+ ]
+
+ # 4 byte header that indicates where to load
+ # the immediately follow code bytes.
+ code_header = [
+ msb (len (bytes)),
+ lsb (len (bytes)),
+ msb (start_addr),
+ lsb (start_addr)
+ ]
+
+ # writes 0 to CPUCS reg (brings FX2 out of reset)
+ trailer = [
+ 0x80,
+ 0x01,
+ 0xe6,
+ 0x00,
+ 0x00
+ ]
+
+ image = rom_header + code_header + [ord(c) for c in bytes] + trailer
+
+ assert (len (image) <= 256)
+ return image
+
+if __name__ == '__main__':
+ usage = "usage: %prog -r REV [options] bootfile.bin outfile.bin"
+ parser = OptionParser (usage=usage)
+ parser.add_option ("-r", "--rev", type="int", default=-1,
+ help="Specify USRP revision number REV (2 or 4)")
+ (options, args) = parser.parse_args ()
+ if len (args) != 2:
+ parser.print_help ()
+ sys.exit (1)
+ if options.rev < 0:
+ sys.stderr.write (
+ "You must specify the USRP revision number (2 or 4) with -r REV\n")
+ sys.exit (1)
+
+ infile = args[0]
+ outfile = args[1]
+
+ image = "".join(chr(c) for c in build_eeprom_image(infile, options.rev))
+
+ f = open(outfile, 'wb')
+ f.write(str(image))
+ f.close()
diff --git a/firmware/fx2/src/common/check_mdelay.c b/firmware/fx2/src/common/check_mdelay.c
new file mode 100644
index 000000000..de1af47f6
--- /dev/null
+++ b/firmware/fx2/src/common/check_mdelay.c
@@ -0,0 +1,37 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#include "usrp_common.h"
+#include "delay.h"
+
+void
+main (void)
+{
+ init_usrp ();
+
+ // CPUCS = 0; // 12 MHz
+ // CPUCS = bmCLKSPD0; // 24 MHz
+ CPUCS = bmCLKSPD1; // 48 MHz
+
+ while (1){
+ USRP_LED_REG ^= bmLED0;
+ mdelay (10);
+ }
+}
diff --git a/firmware/fx2/src/common/check_udelay.c b/firmware/fx2/src/common/check_udelay.c
new file mode 100644
index 000000000..46885a067
--- /dev/null
+++ b/firmware/fx2/src/common/check_udelay.c
@@ -0,0 +1,37 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#include "usrp_common.h"
+#include "delay.h"
+
+void
+main (void)
+{
+ init_usrp ();
+
+ // CPUCS = 0; // 12 MHz
+ // CPUCS = bmCLKSPD0; // 24 MHz
+ CPUCS = bmCLKSPD1; // 48 MHz
+
+ while (1){
+ USRP_LED_REG ^= bmLED0;
+ udelay (250);
+ }
+}
diff --git a/firmware/fx2/src/common/edit-gpif b/firmware/fx2/src/common/edit-gpif
new file mode 100755
index 000000000..5367b75a5
--- /dev/null
+++ b/firmware/fx2/src/common/edit-gpif
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# -*- Python -*-
+#
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+
+# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and
+# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our
+# uses.
+
+import re
+import string
+import sys
+
+def check_flow_state (line, flow_state_dict):
+ mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line)
+ if mo:
+ wave = int (mo.group (1))
+ data = mo.group (2)
+ split = data.split (',', 8)
+ v = map (lambda x : int (x, 16), split)
+ # print "%s, %s" % (wave, data)
+ # print "split: ", split
+ # print "v : ", v
+ flow_state_dict[wave] = v
+
+
+def delta (xseq, yseq):
+ # set subtraction
+ z = []
+ for x in xseq:
+ if x not in yseq:
+ z.append (x)
+ return z
+
+
+def write_define (output, name, pairs):
+ output.write ('#define %s()\t\\\n' % name)
+ output.write ('do {\t\t\t\t\t\\\n')
+ for reg, val in pairs:
+ output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val))
+ output.write ('} while (0)\n\n')
+
+def write_inlines (output, dict):
+ regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF',
+ 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT']
+
+ READ_FLOW_STATE = 2
+ WRITE_FLOW_STATE = 3
+
+ read_info = zip (regs, dict[READ_FLOW_STATE])
+ write_info = zip (regs, dict[WRITE_FLOW_STATE])
+
+ output.write ('''/*
+ * Machine generated by "edit-gpif". Do not edit by hand.
+ */
+
+''')
+ write_define (output, 'setup_flowstate_common', read_info)
+ write_define (output, 'setup_flowstate_read', delta (read_info, write_info))
+ write_define (output, 'setup_flowstate_write', delta (write_info, read_info))
+
+
+def edit_gpif (input_name, output_name, inline_name):
+ input = open (input_name, 'r')
+ output = open (output_name, 'w')
+ inline = open (inline_name, 'w')
+ flow_state_dict = {}
+
+ output.write ('''/*
+ * Machine generated by "edit-gpif". Do not edit by hand.
+ */
+
+''')
+
+ while 1:
+ line = input.readline ()
+ line = string.replace (line, '\r','')
+ line = re.sub (r' *$', r'', line)
+
+ check_flow_state (line, flow_state_dict)
+
+ line = re.sub (r'#include', r'// #include', line)
+ line = re.sub (r'xdata ', r'', line)
+ if re.search (r'GpifInit', line):
+ break
+
+ output.write (line)
+
+ output.close ()
+ write_inlines (inline, flow_state_dict)
+ inline.close ()
+
+
+# gpif.c usrp_gpif.c usrp_gpif_inline.h
+edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3])
diff --git a/firmware/fx2/src/common/fpga.h b/firmware/fx2/src/common/fpga.h
new file mode 100644
index 000000000..6cd5de8e2
--- /dev/null
+++ b/firmware/fx2/src/common/fpga.h
@@ -0,0 +1,31 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_FPGA_H
+#define INCLUDED_FPGA_H
+
+#include "fpga_load.h"
+
+#if defined(HAVE_USRP2)
+#include "fpga_rev2.h"
+#endif
+
+#endif /* INCLUDED_FPGA_H */
diff --git a/firmware/fx2/src/common/fpga_load.c b/firmware/fx2/src/common/fpga_load.c
new file mode 100644
index 000000000..c3ae9e707
--- /dev/null
+++ b/firmware/fx2/src/common/fpga_load.c
@@ -0,0 +1,193 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#include "usrp_common.h"
+#include "fpga_load.h"
+#include "delay.h"
+
+/*
+ * setup altera FPGA serial load (PS).
+ *
+ * On entry:
+ * don't care
+ *
+ * On exit:
+ * ALTERA_DCLK = 0
+ * ALTERA_NCONFIG = 1
+ * ALTERA_NSTATUS = 1 (input)
+ */
+unsigned char
+fpga_load_begin (void)
+{
+ USRP_ALTERA_CONFIG &= ~bmALTERA_BITS; // clear all bits (NCONFIG low)
+ udelay (40); // wait 40 us
+ USRP_ALTERA_CONFIG |= bmALTERA_NCONFIG; // set NCONFIG high
+
+ if (UC_BOARD_HAS_FPGA){
+ // FIXME should really cap this loop with a counter so we
+ // don't hang forever on a hardware failure.
+ while ((USRP_ALTERA_CONFIG & bmALTERA_NSTATUS) == 0) // wait for NSTATUS to go high
+ ;
+ }
+
+ // ready to xfer now
+
+ return 1;
+}
+
+/*
+ * clock out the low bit of bits.
+ *
+ * On entry:
+ * ALTERA_DCLK = 0
+ * ALTERA_NCONFIG = 1
+ * ALTERA_NSTATUS = 1 (input)
+ *
+ * On exit:
+ * ALTERA_DCLK = 0
+ * ALTERA_NCONFIG = 1
+ * ALTERA_NSTATUS = 1 (input)
+ */
+
+
+#if 0
+
+static void
+clock_out_config_byte (unsigned char bits)
+{
+ unsigned char i;
+
+ // clock out configuration byte, least significant bit first
+
+ for (i = 0; i < 8; i++){
+
+ USRP_ALTERA_CONFIG = ((USRP_ALTERA_CONFIG & ~bmALTERA_DATA0) | ((bits & 1) ? bmALTERA_DATA0 : 0));
+ USRP_ALTERA_CONFIG |= bmALTERA_DCLK; /* set DCLK to 1 */
+ USRP_ALTERA_CONFIG &= ~bmALTERA_DCLK; /* set DCLK to 0 */
+
+ bits = bits >> 1;
+ }
+}
+
+#else
+
+static void
+clock_out_config_byte (unsigned char bits) _naked
+{
+ _asm
+ mov a, dpl
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ rrc a
+ mov _bitALTERA_DATA0,c
+ setb _bitALTERA_DCLK
+ clr _bitALTERA_DCLK
+
+ ret
+
+ _endasm;
+}
+
+#endif
+
+static void
+clock_out_bytes (unsigned char bytecount,
+ unsigned char xdata *p)
+{
+ while (bytecount-- > 0)
+ clock_out_config_byte (*p++);
+}
+
+/*
+ * Transfer block of bytes from packet to FPGA serial configuration port
+ *
+ * On entry:
+ * ALTERA_DCLK = 0
+ * ALTERA_NCONFIG = 1
+ * ALTERA_NSTATUS = 1 (input)
+ *
+ * On exit:
+ * ALTERA_DCLK = 0
+ * ALTERA_NCONFIG = 1
+ * ALTERA_NSTATUS = 1 (input)
+ */
+unsigned char
+fpga_load_xfer (xdata unsigned char *p, unsigned char bytecount)
+{
+ clock_out_bytes (bytecount, p);
+ return 1;
+}
+
+/*
+ * check for successful load...
+ */
+unsigned char
+fpga_load_end (void)
+{
+ unsigned char status = USRP_ALTERA_CONFIG;
+
+ if (!UC_BOARD_HAS_FPGA) // always true if we don't have FPGA
+ return 1;
+
+ if ((status & bmALTERA_NSTATUS) == 0) // failed to program
+ return 0;
+
+ if ((status & bmALTERA_CONF_DONE) == bmALTERA_CONF_DONE)
+ return 1; // everything's cool
+
+ // I don't think this should happen. It indicates that
+ // programming is still in progress.
+
+ return 0;
+}
diff --git a/firmware/fx2/src/common/fpga_load.h b/firmware/fx2/src/common/fpga_load.h
new file mode 100644
index 000000000..7c36a04c8
--- /dev/null
+++ b/firmware/fx2/src/common/fpga_load.h
@@ -0,0 +1,28 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#ifndef INCLUDED_FPGA_LOAD_H
+#define INCLUDED_FPGA_LOAD_H
+
+unsigned char fpga_load_begin (void);
+unsigned char fpga_load_xfer (xdata unsigned char *p, unsigned char len);
+unsigned char fpga_load_end (void);
+
+#endif /* INCLUDED_FPGA_LOAD_H */
diff --git a/firmware/fx2/src/common/gpif.c b/firmware/fx2/src/common/gpif.c
new file mode 100755
index 000000000..489e6e81a
--- /dev/null
+++ b/firmware/fx2/src/common/gpif.c
@@ -0,0 +1,292 @@
+// This program configures the General Programmable Interface (GPIF) for FX2.
+// Please do not modify sections of text which are marked as "DO NOT EDIT ...".
+//
+// DO NOT EDIT ...
+// GPIF Initialization
+// Interface Timing Async
+// Internal Ready Init IntRdy=1
+// CTL Out Tristate-able Binary
+// SingleWrite WF Select 1
+// SingleRead WF Select 0
+// FifoWrite WF Select 3
+// FifoRead WF Select 2
+// Data Bus Idle Drive Tristate
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+// GPIF Wave Names
+// Wave 0 = singlerd
+// Wave 1 = singlewr
+// Wave 2 = FIFORd
+// Wave 3 = FIFOWr
+
+// GPIF Ctrl Outputs Level
+// CTL 0 = WEN# CMOS
+// CTL 1 = REN# CMOS
+// CTL 2 = OE# CMOS
+// CTL 3 = CLRST CMOS
+// CTL 4 = unused CMOS
+// CTL 5 = BOGUS CMOS
+
+// GPIF Rdy Inputs
+// RDY0 = EF#
+// RDY1 = FF#
+// RDY2 = unused
+// RDY3 = unused
+// RDY4 = unused
+// RDY5 = TCXpire
+// FIFOFlag = FIFOFlag
+// IntReady = IntReady
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 0: singlerd
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1
+// Term A
+// LFunc
+// Term B
+// Branch1
+// Branch0
+// Re-Exec
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 0 0 0 0 0 0 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 0 0 0 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 1: singlewr
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode Activate Activate Activate Activate Activate Activate Activate
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1
+// Term A EF#
+// LFunc AND
+// Term B EF#
+// Branch1 ThenIdle
+// Branch0 ElseIdle
+// Re-Exec No
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 1 1 1 1 1 1 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 0 0 0 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 2: FIFORd
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1
+// Term A TCXpire TCXpire
+// LFunc AND AND
+// Term B TCXpire TCXpire
+// Branch1 Then 2 ThenIdle
+// Branch0 Else 1 ElseIdle
+// Re-Exec No No
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 0 0 0 0 0 0 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 1 1 1 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 3: FIFOWr
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode NO Data Activate Activate Activate Activate Activate Activate
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1
+// Term A TCXpire
+// LFunc AND
+// Term B TCXpire
+// Branch1 ThenIdle
+// Branch0 Else 1
+// Re-Exec No
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 0 0 0 0 0 0 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 0 0 0 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+
+// GPIF Program Code
+
+// DO NOT EDIT ...
+#include "fx2.h"
+#include "fx2regs.h"
+#include "fx2sdly.h" // SYNCDELAY macro
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+const char xdata WaveData[128] =
+{
+// Wave 0
+/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+// Wave 1
+/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+// Wave 2
+/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+/* Output*/ 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F,
+// Wave 3
+/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+};
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+const char xdata FlowStates[36] =
+{
+/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00,
+/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00,
+};
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+const char xdata InitData[7] =
+{
+/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00
+};
+// END DO NOT EDIT
+
+// TO DO: You may add additional code below.
+
+void GpifInit( void )
+{
+ BYTE i;
+
+ // Registers which require a synchronization delay, see section 15.14
+ // FIFORESET FIFOPINPOLAR
+ // INPKTEND OUTPKTEND
+ // EPxBCH:L REVCTL
+ // GPIFTCB3 GPIFTCB2
+ // GPIFTCB1 GPIFTCB0
+ // EPxFIFOPFH:L EPxAUTOINLENH:L
+ // EPxFIFOCFG EPxGPIFFLGSEL
+ // PINFLAGSxx EPxFIFOIRQ
+ // EPxFIFOIE GPIFIRQ
+ // GPIFIE GPIFADRH:L
+ // UDMACRCH:L EPxGPIFTRIG
+ // GPIFTRIG
+
+ // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
+ // ...these have been replaced by GPIFTC[B3:B0] registers
+
+ // 8051 doesn't have access to waveform memories 'til
+ // the part is in GPIF mode.
+
+ IFCONFIG = 0xEE;
+ // IFCLKSRC=1 , FIFOs executes on internal clk source
+ // xMHz=1 , 48MHz internal clk rate
+ // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz
+ // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk
+ // ASYNC=1 , master samples asynchronous
+ // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF
+ // IFCFG[1:0]=10, FX2 in GPIF master mode
+
+ GPIFABORT = 0xFF; // abort any waveforms pending
+
+ GPIFREADYCFG = InitData[ 0 ];
+ GPIFCTLCFG = InitData[ 1 ];
+ GPIFIDLECS = InitData[ 2 ];
+ GPIFIDLECTL = InitData[ 3 ];
+ GPIFWFSELECT = InitData[ 5 ];
+ GPIFREADYSTAT = InitData[ 6 ];
+
+ // use dual autopointer feature...
+ AUTOPTRSETUP = 0x07; // inc both pointers,
+ // ...warning: this introduces pdata hole(s)
+ // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2)
+
+ // source
+ AUTOPTRH1 = MSB( &WaveData );
+ AUTOPTRL1 = LSB( &WaveData );
+
+ // destination
+ AUTOPTRH2 = 0xE4;
+ AUTOPTRL2 = 0x00;
+
+ // transfer
+ for ( i = 0x00; i < 128; i++ )
+ {
+ EXTAUTODAT2 = EXTAUTODAT1;
+ }
+
+// Configure GPIF Address pins, output initial value,
+ PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0]
+ OEC = 0xFF; // and as outputs
+ PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8]
+ OEE |= 0x80; // and as output
+
+// ...OR... tri-state GPIFADR[8:0] pins
+// PORTCCFG = 0x00; // [7:0] as port I/O
+// OEC = 0x00; // and as inputs
+// PORTECFG &= 0x7F; // [8] as port I/O
+// OEE &= 0x7F; // and as input
+
+// GPIF address pins update when GPIFADRH/L written
+ SYNCDELAY; //
+ GPIFADRH = 0x00; // bits[7:1] always 0
+ SYNCDELAY; //
+ GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000
+
+// Configure GPIF FlowStates registers for Wave 0 of WaveData
+ FLOWSTATE = FlowStates[ 0 ];
+ FLOWLOGIC = FlowStates[ 1 ];
+ FLOWEQ0CTL = FlowStates[ 2 ];
+ FLOWEQ1CTL = FlowStates[ 3 ];
+ FLOWHOLDOFF = FlowStates[ 4 ];
+ FLOWSTB = FlowStates[ 5 ];
+ FLOWSTBEDGE = FlowStates[ 6 ];
+ FLOWSTBHPERIOD = FlowStates[ 7 ];
+}
+
diff --git a/firmware/fx2/src/common/gpif.gpf b/firmware/fx2/src/common/gpif.gpf
new file mode 100755
index 000000000..a954ac193
--- /dev/null
+++ b/firmware/fx2/src/common/gpif.gpf
Binary files differ
diff --git a/firmware/fx2/src/common/init_gpif.c b/firmware/fx2/src/common/init_gpif.c
new file mode 100644
index 000000000..edde919be
--- /dev/null
+++ b/firmware/fx2/src/common/init_gpif.c
@@ -0,0 +1,59 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#include "usrp_common.h"
+
+// These are the tables generated by the Cypress GPIF Designer
+
+extern const char WaveData[128];
+extern const char FlowStates[36];
+extern const char InitData[7];
+
+// The tool is kind of screwed up, in that it doesn't configure some
+// of the ports correctly. We just use their tables and handle the
+// initialization ourselves. They also declare that their static
+// initialized data is in xdata, which screws us too.
+
+void
+init_gpif (void)
+{
+ // we've already setup IFCONFIG before calling this...
+
+ GPIFABORT = 0xFF; // abort any waveforms pending
+ SYNCDELAY;
+
+ GPIFREADYCFG = InitData[ 0 ];
+ GPIFCTLCFG = InitData[ 1 ];
+ GPIFIDLECS = InitData[ 2 ];
+ GPIFIDLECTL = InitData[ 3 ];
+ // Hmmm, what's InitData[ 4 ] ...
+ GPIFWFSELECT = InitData[ 5 ];
+ // GPIFREADYSTAT = InitData[ 6 ]; // I think this register is read only...
+
+ {
+ BYTE i;
+
+ for (i = 0; i < 128; i++){
+ GPIF_WAVE_DATA[i] = WaveData[i];
+ }
+ }
+
+ FLOWSTATE = 0; /* ensure it's off */
+}
diff --git a/firmware/fx2/src/common/usrp_common.c b/firmware/fx2/src/common/usrp_common.c
new file mode 100644
index 000000000..0998653c2
--- /dev/null
+++ b/firmware/fx2/src/common/usrp_common.c
@@ -0,0 +1,109 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * common code for USRP
+ */
+
+#include "usrp_common.h"
+
+void init_board (void);
+
+void
+init_usrp (void)
+{
+ CPUCS = bmCLKSPD1; // CPU runs @ 48 MHz
+ CKCON = 0; // MOVX takes 2 cycles
+
+ // IFCLK is generated internally and runs at 48 MHz; GPIF "master mode"
+
+ IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmIFCLKPOL | bmIFGPIF;
+ SYNCDELAY;
+
+ // configure IO ports (B and D are used by GPIF)
+
+ IOA = bmPORT_A_INITIAL; // Port A initial state
+ OEA = bmPORT_A_OUTPUTS; // Port A direction register
+
+ IOC = bmPORT_C_INITIAL; // Port C initial state
+ OEC = bmPORT_C_OUTPUTS; // Port C direction register
+
+ IOE = bmPORT_E_INITIAL; // Port E initial state
+ OEE = bmPORT_E_OUTPUTS; // Port E direction register
+
+
+ // REVCTL = bmDYN_OUT | bmENH_PKT; // highly recommended by docs
+ // SYNCDELAY;
+
+ // configure end points
+
+ EP1OUTCFG = bmVALID | bmBULK; SYNCDELAY;
+ EP1INCFG = bmVALID | bmBULK | bmIN; SYNCDELAY;
+
+ EP2CFG = bmVALID | bmBULK | bmQUADBUF; SYNCDELAY; // 512 quad bulk OUT
+ EP4CFG = 0; SYNCDELAY; // disabled
+ EP6CFG = bmVALID | bmBULK | bmQUADBUF | bmIN; SYNCDELAY; // 512 quad bulk IN
+ EP8CFG = 0; SYNCDELAY; // disabled
+
+ // reset FIFOs
+
+ FIFORESET = bmNAKALL; SYNCDELAY;
+ FIFORESET = 2; SYNCDELAY;
+ // FIFORESET = 4; SYNCDELAY;
+ FIFORESET = 6; SYNCDELAY;
+ // FIFORESET = 8; SYNCDELAY;
+ FIFORESET = 0; SYNCDELAY;
+
+ // configure end point FIFOs
+
+ // let core see 0 to 1 transistion of autoout bit
+
+ EP2FIFOCFG = bmWORDWIDE; SYNCDELAY;
+ EP2FIFOCFG = bmAUTOOUT | bmWORDWIDE; SYNCDELAY;
+ EP6FIFOCFG = bmAUTOIN | bmWORDWIDE; SYNCDELAY;
+
+
+ // prime the pump
+
+#if 0
+ EP2BCL = 0x80; SYNCDELAY;
+ EP2BCL = 0x80; SYNCDELAY;
+ EP2BCL = 0x80; SYNCDELAY;
+ EP2BCL = 0x80; SYNCDELAY;
+#endif
+
+ EP0BCH = 0; SYNCDELAY;
+
+ // arm EP1OUT so we can receive "out" packets (TRM pg 8-8)
+
+ EP1OUTBC = 0; SYNCDELAY;
+
+ EP2GPIFFLGSEL = 0x01; SYNCDELAY; // For EP2OUT, GPIF uses EF flag
+ EP6GPIFFLGSEL = 0x02; SYNCDELAY; // For EP6IN, GPIF uses FF flag
+
+ // set autoin length for EP6
+ // FIXME should be f(enumeration)
+
+ EP6AUTOINLENH = (512) >> 8; SYNCDELAY; // this is the length for high speed
+ EP6AUTOINLENL = (512) & 0xff; SYNCDELAY;
+
+ init_board ();
+}
+
diff --git a/firmware/fx2/src/common/usrp_globals.h b/firmware/fx2/src/common/usrp_globals.h
new file mode 100644
index 000000000..445e9e6b4
--- /dev/null
+++ b/firmware/fx2/src/common/usrp_globals.h
@@ -0,0 +1,32 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2003 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef _USRP_GLOBALS_H_
+#define _USRP_GLOBALS_H_
+
+extern unsigned char g_tx_enable;
+extern unsigned char g_rx_enable;
+extern unsigned char g_fpga_reset;
+extern unsigned char g_rx_overrun;
+extern unsigned char g_tx_underrun;
+
+
+#endif /* _USRP_GLOBALS_H_ */
diff --git a/firmware/fx2/src/common/vectors.a51 b/firmware/fx2/src/common/vectors.a51
new file mode 100644
index 000000000..e9382ab84
--- /dev/null
+++ b/firmware/fx2/src/common/vectors.a51
@@ -0,0 +1,180 @@
+;;; -*- asm -*-
+;;;
+;;; Copyright 2003 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio 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 3, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+;;; the Free Software Foundation, Inc., 51 Franklin Street,
+;;; Boston, MA 02110-1301, USA.
+;;;
+
+;;; Interrupt vectors.
+
+;;; N.B. This object module must come first in the list of modules
+
+ .module vectors
+
+;;; ----------------------------------------------------------------
+;;; standard FX2 interrupt vectors
+;;; ----------------------------------------------------------------
+
+ .area CSEG (CODE)
+ .area GSINIT (CODE)
+ .area CSEG (CODE)
+__standard_interrupt_vector::
+__reset_vector::
+ ljmp s_GSINIT
+
+ ;; 13 8-byte entries. We point them all at __isr_nop
+ ljmp __isr_nop ; 3 bytes
+ .ds 5 ; + 5 = 8 bytes for vector slot
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+ ljmp __isr_nop
+ .ds 5
+
+__isr_nop::
+ reti
+
+;;; ----------------------------------------------------------------
+;;; the FIFO/GPIF autovector. 14 4-byte entries.
+;;; must start on a 128 byte boundary.
+;;; ----------------------------------------------------------------
+
+ . = __reset_vector + 0x0080
+
+__fifo_gpif_autovector::
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+
+
+;;; ----------------------------------------------------------------
+;;; the USB autovector. 32 4-byte entries.
+;;; must start on a 256 byte boundary.
+;;; ----------------------------------------------------------------
+
+ . = __reset_vector + 0x0100
+
+__usb_autovector::
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
+ ljmp __isr_nop
+ nop
diff --git a/firmware/fx2/src/usrp1/.gitignore b/firmware/fx2/src/usrp1/.gitignore
new file mode 100644
index 000000000..54a9e9415
--- /dev/null
+++ b/firmware/fx2/src/usrp1/.gitignore
@@ -0,0 +1,20 @@
+/*.ihx
+/*.lnk
+/*.lst
+/*.map
+/*.mem
+/*.rel
+/*.rst
+/*.sym
+/blink_leds.asm
+/usrp_common.asm
+/command_loop.asm
+/fpga.asm
+/*.asm
+/Makefile
+/Makefile.in
+/usrp_gpif.c
+/usrp_gpif_inline.h
+/Makefile.in
+/burn-usrp2-eeprom
+/burn-usrp4-eeprom
diff --git a/firmware/fx2/src/usrp1/Makefile.am b/firmware/fx2/src/usrp1/Makefile.am
new file mode 100644
index 000000000..a964f9198
--- /dev/null
+++ b/firmware/fx2/src/usrp1/Makefile.am
@@ -0,0 +1,141 @@
+#
+# Copyright 2003,2006 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+#firmwaredir = $(prefix)/share/uhd/images
+#firmware_DATA = usrp1_fw.ihx
+
+#eepromdir = $(firmwaredir)
+#eepromfile = eeprom_boot.ihx
+#eeprom_DATA = usrp1_eeprom.bin
+
+EXTRA_DIST = \
+ edit-gpif \
+ _startup.a51 \
+ blink_leds.c \
+ board_specific.c \
+ check_mdelay.c \
+ check_udelay.c \
+ eeprom_boot.a51 \
+ eeprom_init.c \
+ eeprom_io.c \
+ eeprom_io.h \
+ fpga_load.c \
+ fpga_rev2.c \
+ fpga_rev2.h \
+ gpif.c \
+ init_gpif.c \
+ spi.c \
+ spi.h \
+ usb_descriptors.a51 \
+ usrp_common.c \
+ usrp_common.h \
+ usrp_gpif.c \
+ usrp_main.c \
+ usrp_rev2_regs.h \
+ vectors.a51
+
+
+DEFINES=-DHAVE_USRP2
+FW_INCLUDES=-I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/usrp1 \
+ -I$(top_srcdir)/src/common \
+ -I$(top_builddir)/src/common
+
+# with EA = 0, the FX2 implements a portion of the 8051 "external memory"
+# on chip. This memory is mapped like this:
+#
+# The bottom 8K of memory (0x0000 - 0x1fff) is used for both data and
+# code accesses. There's also 512 bytes for data only from 0xe000 - 0xe1ff.
+#
+# We tell the linker to start the xdata segment at 0x1800, 6K up from
+# the bottom.
+
+MEMOPTS = --code-loc 0x0000 --code-size 0x1800 --xram-loc 0x1800 --xram-size 0x0800 \
+ -Wl '-b USBDESCSEG = 0xE000'
+
+LIBOPTS = -L ../../lib libfx2.lib
+LIBDEP = ../../lib/libfx2.lib
+
+LINKOPTS = $(MEMOPTS) $(LIBOPTS)
+
+EXECUTABLES = \
+ std.ihx \
+ blink_leds.ihx \
+ check_mdelay.ihx \
+ check_udelay.ihx \
+ eeprom_boot.ihx
+
+STARTUP = _startup.rel
+
+.c.rel:
+ $(XCC) $(FW_INCLUDES) $(DEFINES) \
+ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+.a51.rel:
+ test -f `basename '$<'` || $(LN_S) '$<' .
+ test -f ../common/`basename '$<'` -o \
+ \! -f `dirname '$<'`/../common/`basename '$<'` \
+ || $(LN_S) `dirname '$<'`/../common/`basename '$<'` ../common/`basename '$<'`
+ $(XAS) `basename '$<'`
+
+
+EEPROM_BOOT_OBJS = eeprom_boot.rel eeprom_init.rel $(STARTUP)
+
+eeprom_boot.ihx: $(EEPROM_BOOT_OBJS) $(LIBDEP)
+ $(XCC) $(LINKOPTS) -o $@ $(EEPROM_BOOT_OBJS)
+
+usrp1_eeprom.bin: eeprom_boot.bin
+ $(PYTHON) ../common/build_eeprom.py -r4 $< $@
+
+eeprom_boot.bin: eeprom_boot.ihx
+ objcopy -I ihex -O binary $< $@
+
+USRP_OBJS = \
+ vectors.rel \
+ usrp_main.rel usrp_common.rel board_specific.rel \
+ fpga_load.rel fpga_rev2.rel init_gpif.rel usrp_gpif.rel \
+ usb_descriptors.rel spi.rel eeprom_io.rel $(STARTUP)
+
+std.ihx: $(USRP_OBJS) $(LIBDEP)
+ $(XCC) $(LINKOPTS) -o $@ $(USRP_OBJS)
+
+CLEANFILES = \
+ *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib *.bin \
+ usrp_gpif.c usrp_gpif_inline.h
+
+DISTCLEANFILES = \
+ *.ihx *.lnk *.lst *.map *.mem *.rel *.rst *.sym *.asm *.lib *.bin
+
+# build gpif stuff
+
+all: usrp_gpif.c std.ihx usrp1_eeprom.bin
+
+usrp_gpif.c usrp_gpif_inline.h : gpif.c
+ srcdir=$(srcdir) $(PYTHON) $(srcdir)/edit-gpif $(srcdir)/gpif.c usrp_gpif.c usrp_gpif_inline.h
+
+# dependencies
+
+usrp_main.rel: usrp_gpif_inline.h
+
+#usrp_main.rel: fpga.h usrp_common.h ../../include/usrp_commands.h usrp_gpif_inline.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h
+#usrp_common.rel: usrp_common.h ../../include/usrp_commands.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h
+#fpga.rel: usrp_common.h ../../include/usrp_commands.h fpga.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h
+#init_gpif.rel: usrp_common.h ../../include/usrp_config.h usrp_rev2_regs.h ../../include/fx2regs.h
diff --git a/firmware/fx2/src/usrp1/_startup.a51 b/firmware/fx2/src/usrp1/_startup.a51
new file mode 100644
index 000000000..4f5309922
--- /dev/null
+++ b/firmware/fx2/src/usrp1/_startup.a51
@@ -0,0 +1 @@
+ .include "../common/_startup.a51"
diff --git a/firmware/fx2/src/usrp1/blink_leds.c b/firmware/fx2/src/usrp1/blink_leds.c
new file mode 100644
index 000000000..c633d5d48
--- /dev/null
+++ b/firmware/fx2/src/usrp1/blink_leds.c
@@ -0,0 +1 @@
+#include "../common/blink_leds.c"
diff --git a/firmware/fx2/src/usrp1/board_specific.c b/firmware/fx2/src/usrp1/board_specific.c
new file mode 100644
index 000000000..ef0081d84
--- /dev/null
+++ b/firmware/fx2/src/usrp1/board_specific.c
@@ -0,0 +1,113 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usrp_common.h"
+#include "spi.h"
+
+void
+set_led_0 (unsigned char on)
+{
+ if (!on) // active low
+ USRP_PC |= bmPC_LED0;
+ else
+ USRP_PC &= ~bmPC_LED0;
+}
+
+void
+set_led_1 (unsigned char on)
+{
+ if (!on) // active low
+ USRP_PC |= bmPC_LED1;
+ else
+ USRP_PC &= ~bmPC_LED1;
+}
+
+void
+toggle_led_0 (void)
+{
+ USRP_PC ^= bmPC_LED0;
+}
+
+void
+toggle_led_1 (void)
+{
+ USRP_PC ^= bmPC_LED1;
+}
+
+void
+la_trace_init (void)
+{
+}
+
+void
+set_sleep_bits (unsigned char bits, unsigned char mask)
+{
+ // NOP on usrp1
+}
+
+static xdata unsigned char xbuf[1];
+
+void
+write_9862 (unsigned char which, unsigned char regno, unsigned char value)
+{
+ xbuf[0] = value;
+
+ spi_write (0, regno & 0x3f,
+ which == 0 ? SPI_ENABLE_CODEC_A : SPI_ENABLE_CODEC_B,
+ SPI_FMT_MSB | SPI_FMT_HDR_1,
+ xbuf, 1);
+}
+
+void
+write_both_9862s (unsigned char regno, unsigned char value)
+{
+ xbuf[0] = value;
+
+ spi_write (0, regno & 0x3f,
+ SPI_ENABLE_CODEC_A | SPI_ENABLE_CODEC_B,
+ SPI_FMT_MSB | SPI_FMT_HDR_1,
+ xbuf, 1);
+}
+
+#define REG_RX_PWR_DN 1
+#define REG_TX_PWR_DN 8
+#define REG_TX_MODULATOR 20
+
+static void
+power_down_9862s (void)
+{
+ write_both_9862s (REG_RX_PWR_DN, 0x01);
+ write_both_9862s (REG_TX_PWR_DN, 0x0f); // pwr dn digital and analog_both
+ write_both_9862s (REG_TX_MODULATOR, 0x00); // coarse & fine modulators disabled
+}
+
+void
+init_board (void)
+{
+ la_trace_init ();
+ init_spi ();
+
+ USRP_PC &= ~bmPC_nRESET; // active low reset
+ USRP_PC |= bmPC_nRESET;
+
+ power_down_9862s ();
+}
diff --git a/firmware/fx2/src/usrp1/check_mdelay.c b/firmware/fx2/src/usrp1/check_mdelay.c
new file mode 100644
index 000000000..ea4ccdb14
--- /dev/null
+++ b/firmware/fx2/src/usrp1/check_mdelay.c
@@ -0,0 +1 @@
+#include "../common/check_mdelay.c"
diff --git a/firmware/fx2/src/usrp1/check_udelay.c b/firmware/fx2/src/usrp1/check_udelay.c
new file mode 100644
index 000000000..d01622e5e
--- /dev/null
+++ b/firmware/fx2/src/usrp1/check_udelay.c
@@ -0,0 +1 @@
+#include "../common/check_udelay.c"
diff --git a/firmware/fx2/src/usrp1/edit-gpif b/firmware/fx2/src/usrp1/edit-gpif
new file mode 100755
index 000000000..5367b75a5
--- /dev/null
+++ b/firmware/fx2/src/usrp1/edit-gpif
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+# -*- Python -*-
+#
+# Copyright 2003 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+
+# Edit the gpif.c file generated by the Cypress GPIF Designer Tool and
+# produce usrp_gpif.c, and usrp_gpif_inline.h, files suitable for our
+# uses.
+
+import re
+import string
+import sys
+
+def check_flow_state (line, flow_state_dict):
+ mo = re.match (r'/\* Wave (\d) FlowStates \*/ (.*),', line)
+ if mo:
+ wave = int (mo.group (1))
+ data = mo.group (2)
+ split = data.split (',', 8)
+ v = map (lambda x : int (x, 16), split)
+ # print "%s, %s" % (wave, data)
+ # print "split: ", split
+ # print "v : ", v
+ flow_state_dict[wave] = v
+
+
+def delta (xseq, yseq):
+ # set subtraction
+ z = []
+ for x in xseq:
+ if x not in yseq:
+ z.append (x)
+ return z
+
+
+def write_define (output, name, pairs):
+ output.write ('#define %s()\t\\\n' % name)
+ output.write ('do {\t\t\t\t\t\\\n')
+ for reg, val in pairs:
+ output.write ('%14s = 0x%02x;\t\t\t\\\n' % (reg, val))
+ output.write ('} while (0)\n\n')
+
+def write_inlines (output, dict):
+ regs = ['FLOWSTATE', 'FLOWLOGIC', 'FLOWEQ0CTL', 'FLOWEQ1CTL', 'FLOWHOLDOFF',
+ 'FLOWSTB', 'FLOWSTBEDGE', 'FLOWSTBHPERIOD', 'GPIFHOLDAMOUNT']
+
+ READ_FLOW_STATE = 2
+ WRITE_FLOW_STATE = 3
+
+ read_info = zip (regs, dict[READ_FLOW_STATE])
+ write_info = zip (regs, dict[WRITE_FLOW_STATE])
+
+ output.write ('''/*
+ * Machine generated by "edit-gpif". Do not edit by hand.
+ */
+
+''')
+ write_define (output, 'setup_flowstate_common', read_info)
+ write_define (output, 'setup_flowstate_read', delta (read_info, write_info))
+ write_define (output, 'setup_flowstate_write', delta (write_info, read_info))
+
+
+def edit_gpif (input_name, output_name, inline_name):
+ input = open (input_name, 'r')
+ output = open (output_name, 'w')
+ inline = open (inline_name, 'w')
+ flow_state_dict = {}
+
+ output.write ('''/*
+ * Machine generated by "edit-gpif". Do not edit by hand.
+ */
+
+''')
+
+ while 1:
+ line = input.readline ()
+ line = string.replace (line, '\r','')
+ line = re.sub (r' *$', r'', line)
+
+ check_flow_state (line, flow_state_dict)
+
+ line = re.sub (r'#include', r'// #include', line)
+ line = re.sub (r'xdata ', r'', line)
+ if re.search (r'GpifInit', line):
+ break
+
+ output.write (line)
+
+ output.close ()
+ write_inlines (inline, flow_state_dict)
+ inline.close ()
+
+
+# gpif.c usrp_gpif.c usrp_gpif_inline.h
+edit_gpif (sys.argv[1], sys.argv[2], sys.argv[3])
diff --git a/firmware/fx2/src/usrp1/eeprom_boot.a51 b/firmware/fx2/src/usrp1/eeprom_boot.a51
new file mode 100644
index 000000000..65e452668
--- /dev/null
+++ b/firmware/fx2/src/usrp1/eeprom_boot.a51
@@ -0,0 +1,573 @@
+;--------------------------------------------------------
+; Hand tweaked minimal eeprom boot code
+;--------------------------------------------------------
+ .module eeprom_boot
+ .optsdcc -mmcs51 --model-small
+
+;--------------------------------------------------------
+; Public variables in this module
+;--------------------------------------------------------
+ .globl _eeprom_init
+ .globl _EP8FIFOBUF
+ .globl _EP6FIFOBUF
+ .globl _EP4FIFOBUF
+ .globl _EP2FIFOBUF
+ .globl _EP1INBUF
+ .globl _EP1OUTBUF
+ .globl _EP0BUF
+ .globl _CT4
+ .globl _CT3
+ .globl _CT2
+ .globl _CT1
+ .globl _USBTEST
+ .globl _TESTCFG
+ .globl _DBUG
+ .globl _UDMACRCQUAL
+ .globl _UDMACRCL
+ .globl _UDMACRCH
+ .globl _GPIFHOLDAMOUNT
+ .globl _FLOWSTBHPERIOD
+ .globl _FLOWSTBEDGE
+ .globl _FLOWSTB
+ .globl _FLOWHOLDOFF
+ .globl _FLOWEQ1CTL
+ .globl _FLOWEQ0CTL
+ .globl _FLOWLOGIC
+ .globl _FLOWSTATE
+ .globl _GPIFABORT
+ .globl _GPIFREADYSTAT
+ .globl _GPIFREADYCFG
+ .globl _XGPIFSGLDATLNOX
+ .globl _XGPIFSGLDATLX
+ .globl _XGPIFSGLDATH
+ .globl _EP8GPIFTRIG
+ .globl _EP8GPIFPFSTOP
+ .globl _EP8GPIFFLGSEL
+ .globl _EP6GPIFTRIG
+ .globl _EP6GPIFPFSTOP
+ .globl _EP6GPIFFLGSEL
+ .globl _EP4GPIFTRIG
+ .globl _EP4GPIFPFSTOP
+ .globl _EP4GPIFFLGSEL
+ .globl _EP2GPIFTRIG
+ .globl _EP2GPIFPFSTOP
+ .globl _EP2GPIFFLGSEL
+ .globl _GPIFTCB0
+ .globl _GPIFTCB1
+ .globl _GPIFTCB2
+ .globl _GPIFTCB3
+ .globl _GPIFADRL
+ .globl _GPIFADRH
+ .globl _GPIFCTLCFG
+ .globl _GPIFIDLECTL
+ .globl _GPIFIDLECS
+ .globl _GPIFWFSELECT
+ .globl _SETUPDAT
+ .globl _SUDPTRCTL
+ .globl _SUDPTRL
+ .globl _SUDPTRH
+ .globl _EP8FIFOBCL
+ .globl _EP8FIFOBCH
+ .globl _EP6FIFOBCL
+ .globl _EP6FIFOBCH
+ .globl _EP4FIFOBCL
+ .globl _EP4FIFOBCH
+ .globl _EP2FIFOBCL
+ .globl _EP2FIFOBCH
+ .globl _EP8FIFOFLGS
+ .globl _EP6FIFOFLGS
+ .globl _EP4FIFOFLGS
+ .globl _EP2FIFOFLGS
+ .globl _EP8CS
+ .globl _EP6CS
+ .globl _EP4CS
+ .globl _EP2CS
+ .globl _EP1INCS
+ .globl _EP1OUTCS
+ .globl _EP0CS
+ .globl _EP8BCL
+ .globl _EP8BCH
+ .globl _EP6BCL
+ .globl _EP6BCH
+ .globl _EP4BCL
+ .globl _EP4BCH
+ .globl _EP2BCL
+ .globl _EP2BCH
+ .globl _EP1INBC
+ .globl _EP1OUTBC
+ .globl _EP0BCL
+ .globl _EP0BCH
+ .globl _FNADDR
+ .globl _MICROFRAME
+ .globl _USBFRAMEL
+ .globl _USBFRAMEH
+ .globl _TOGCTL
+ .globl _WAKEUPCS
+ .globl _SUSPEND
+ .globl _USBCS
+ .globl _XAUTODAT2
+ .globl _XAUTODAT1
+ .globl _I2CTL
+ .globl _I2DAT
+ .globl _I2CS
+ .globl _PORTECFG
+ .globl _PORTCCFG
+ .globl _PORTACFG
+ .globl _INTSETUP
+ .globl _INT4IVEC
+ .globl _INT2IVEC
+ .globl _CLRERRCNT
+ .globl _ERRCNTLIM
+ .globl _USBERRIRQ
+ .globl _USBERRIE
+ .globl _GPIFIRQ
+ .globl _GPIFIE
+ .globl _EPIRQ
+ .globl _EPIE
+ .globl _USBIRQ
+ .globl _USBIE
+ .globl _NAKIRQ
+ .globl _NAKIE
+ .globl _IBNIRQ
+ .globl _IBNIE
+ .globl _EP8FIFOIRQ
+ .globl _EP8FIFOIE
+ .globl _EP6FIFOIRQ
+ .globl _EP6FIFOIE
+ .globl _EP4FIFOIRQ
+ .globl _EP4FIFOIE
+ .globl _EP2FIFOIRQ
+ .globl _EP2FIFOIE
+ .globl _OUTPKTEND
+ .globl _INPKTEND
+ .globl _EP8ISOINPKTS
+ .globl _EP6ISOINPKTS
+ .globl _EP4ISOINPKTS
+ .globl _EP2ISOINPKTS
+ .globl _EP8FIFOPFL
+ .globl _EP8FIFOPFH
+ .globl _EP6FIFOPFL
+ .globl _EP6FIFOPFH
+ .globl _EP4FIFOPFL
+ .globl _EP4FIFOPFH
+ .globl _EP2FIFOPFL
+ .globl _EP2FIFOPFH
+ .globl _EP8AUTOINLENL
+ .globl _EP8AUTOINLENH
+ .globl _EP6AUTOINLENL
+ .globl _EP6AUTOINLENH
+ .globl _EP4AUTOINLENL
+ .globl _EP4AUTOINLENH
+ .globl _EP2AUTOINLENL
+ .globl _EP2AUTOINLENH
+ .globl _EP8FIFOCFG
+ .globl _EP6FIFOCFG
+ .globl _EP4FIFOCFG
+ .globl _EP2FIFOCFG
+ .globl _EP8CFG
+ .globl _EP6CFG
+ .globl _EP4CFG
+ .globl _EP2CFG
+ .globl _EP1INCFG
+ .globl _EP1OUTCFG
+ .globl _REVCTL
+ .globl _REVID
+ .globl _FIFOPINPOLAR
+ .globl _UART230
+ .globl _BPADDRL
+ .globl _BPADDRH
+ .globl _BREAKPT
+ .globl _FIFORESET
+ .globl _PINFLAGSCD
+ .globl _PINFLAGSAB
+ .globl _IFCONFIG
+ .globl _CPUCS
+ .globl _RES_WAVEDATA_END
+ .globl _GPIF_WAVE_DATA
+;--------------------------------------------------------
+; special function registers
+;--------------------------------------------------------
+_IOA = 0x0080
+_SP = 0x0081
+_DPL = 0x0082
+_DPH = 0x0083
+_DPL1 = 0x0084
+_DPH1 = 0x0085
+_DPS = 0x0086
+_PCON = 0x0087
+_TCON = 0x0088
+_TMOD = 0x0089
+_TL0 = 0x008a
+_TL1 = 0x008b
+_TH0 = 0x008c
+_TH1 = 0x008d
+_CKCON = 0x008e
+_IOB = 0x0090
+_EXIF = 0x0091
+_MPAGE = 0x0092
+_SCON0 = 0x0098
+_SBUF0 = 0x0099
+_APTR1H = 0x009a
+_APTR1L = 0x009b
+_AUTODAT1 = 0x009c
+_AUTOPTRH2 = 0x009d
+_AUTOPTRL2 = 0x009e
+_AUTODAT2 = 0x009f
+_IOC = 0x00a0
+_INT2CLR = 0x00a1
+_INT4CLR = 0x00a2
+_IE = 0x00a8
+_EP2468STAT = 0x00aa
+_EP24FIFOFLGS = 0x00ab
+_EP68FIFOFLGS = 0x00ac
+_AUTOPTRSETUP = 0x00af
+_IOD = 0x00b0
+_IOE = 0x00b1
+_OEA = 0x00b2
+_OEB = 0x00b3
+_OEC = 0x00b4
+_OED = 0x00b5
+_OEE = 0x00b6
+_IP = 0x00b8
+_EP01STAT = 0x00ba
+_GPIFTRIG = 0x00bb
+_GPIFSGLDATH = 0x00bd
+_GPIFSGLDATLX = 0x00be
+_GPIFSGLDATLNOX = 0x00bf
+_SCON1 = 0x00c0
+_SBUF1 = 0x00c1
+_T2CON = 0x00c8
+_RCAP2L = 0x00ca
+_RCAP2H = 0x00cb
+_TL2 = 0x00cc
+_TH2 = 0x00cd
+_PSW = 0x00d0
+_EICON = 0x00d8
+_ACC = 0x00e0
+_EIE = 0x00e8
+_B = 0x00f0
+_EIP = 0x00f8
+;--------------------------------------------------------
+; special function bits
+;--------------------------------------------------------
+_SEL = 0x0086
+_IT0 = 0x0088
+_IE0 = 0x0089
+_IT1 = 0x008a
+_IE1 = 0x008b
+_TR0 = 0x008c
+_TF0 = 0x008d
+_TR1 = 0x008e
+_TF1 = 0x008f
+_RI = 0x0098
+_TI = 0x0099
+_RB8 = 0x009a
+_TB8 = 0x009b
+_REN = 0x009c
+_SM2 = 0x009d
+_SM1 = 0x009e
+_SM0 = 0x009f
+_EX0 = 0x00a8
+_ET0 = 0x00a9
+_EX1 = 0x00aa
+_ET1 = 0x00ab
+_ES0 = 0x00ac
+_ET2 = 0x00ad
+_ES1 = 0x00ae
+_EA = 0x00af
+_PX0 = 0x00b8
+_PT0 = 0x00b9
+_PX1 = 0x00ba
+_PT1 = 0x00bb
+_PS0 = 0x00bc
+_PT2 = 0x00bd
+_PS1 = 0x00be
+_RI1 = 0x00c0
+_TI1 = 0x00c1
+_RB81 = 0x00c2
+_TB81 = 0x00c3
+_REN1 = 0x00c4
+_SM21 = 0x00c5
+_SM11 = 0x00c6
+_SM01 = 0x00c7
+_CP_RL2 = 0x00c8
+_C_T2 = 0x00c9
+_TR2 = 0x00ca
+_EXEN2 = 0x00cb
+_TCLK = 0x00cc
+_RCLK = 0x00cd
+_EXF2 = 0x00ce
+_TF2 = 0x00cf
+_P = 0x00d0
+_FL = 0x00d1
+_OV = 0x00d2
+_RS0 = 0x00d3
+_RS1 = 0x00d4
+_F0 = 0x00d5
+_AC = 0x00d6
+_CY = 0x00d7
+_INT6 = 0x00db
+_RESI = 0x00dc
+_ERESI = 0x00dd
+_SMOD1 = 0x00df
+_EIUSB = 0x00e8
+_EI2C = 0x00e9
+_EIEX4 = 0x00ea
+_EIEX5 = 0x00eb
+_EIEX6 = 0x00ec
+_PUSB = 0x00f8
+_PI2C = 0x00f9
+_EIPX4 = 0x00fa
+_EIPX5 = 0x00fb
+_EIPX6 = 0x00fc
+_bitS_CLK = 0x0080
+_bitS_OUT = 0x0081
+_bitS_IN = 0x0082
+_bitALTERA_DATA0 = 0x00a1
+_bitALTERA_DCLK = 0x00a3
+;--------------------------------------------------------
+; overlayable register banks
+;--------------------------------------------------------
+ .area REG_BANK_0 (REL,OVR,DATA)
+ .ds 8
+;--------------------------------------------------------
+; internal ram data
+;--------------------------------------------------------
+ .area DSEG (DATA)
+;--------------------------------------------------------
+; overlayable items in internal ram
+;--------------------------------------------------------
+ .area OSEG (OVR,DATA)
+;--------------------------------------------------------
+; Stack segment in internal ram
+;--------------------------------------------------------
+ .area SSEG (DATA)
+__start__stack:
+ .ds 1
+
+;--------------------------------------------------------
+; indirectly addressable internal ram data
+;--------------------------------------------------------
+ .area ISEG (DATA)
+;--------------------------------------------------------
+; bit data
+;--------------------------------------------------------
+ .area BSEG (BIT)
+;--------------------------------------------------------
+; external ram data
+;--------------------------------------------------------
+ .area XSEG (XDATA)
+_GPIF_WAVE_DATA = 0xe400
+_RES_WAVEDATA_END = 0xe480
+_CPUCS = 0xe600
+_IFCONFIG = 0xe601
+_PINFLAGSAB = 0xe602
+_PINFLAGSCD = 0xe603
+_FIFORESET = 0xe604
+_BREAKPT = 0xe605
+_BPADDRH = 0xe606
+_BPADDRL = 0xe607
+_UART230 = 0xe608
+_FIFOPINPOLAR = 0xe609
+_REVID = 0xe60a
+_REVCTL = 0xe60b
+_EP1OUTCFG = 0xe610
+_EP1INCFG = 0xe611
+_EP2CFG = 0xe612
+_EP4CFG = 0xe613
+_EP6CFG = 0xe614
+_EP8CFG = 0xe615
+_EP2FIFOCFG = 0xe618
+_EP4FIFOCFG = 0xe619
+_EP6FIFOCFG = 0xe61a
+_EP8FIFOCFG = 0xe61b
+_EP2AUTOINLENH = 0xe620
+_EP2AUTOINLENL = 0xe621
+_EP4AUTOINLENH = 0xe622
+_EP4AUTOINLENL = 0xe623
+_EP6AUTOINLENH = 0xe624
+_EP6AUTOINLENL = 0xe625
+_EP8AUTOINLENH = 0xe626
+_EP8AUTOINLENL = 0xe627
+_EP2FIFOPFH = 0xe630
+_EP2FIFOPFL = 0xe631
+_EP4FIFOPFH = 0xe632
+_EP4FIFOPFL = 0xe633
+_EP6FIFOPFH = 0xe634
+_EP6FIFOPFL = 0xe635
+_EP8FIFOPFH = 0xe636
+_EP8FIFOPFL = 0xe637
+_EP2ISOINPKTS = 0xe640
+_EP4ISOINPKTS = 0xe641
+_EP6ISOINPKTS = 0xe642
+_EP8ISOINPKTS = 0xe643
+_INPKTEND = 0xe648
+_OUTPKTEND = 0xe649
+_EP2FIFOIE = 0xe650
+_EP2FIFOIRQ = 0xe651
+_EP4FIFOIE = 0xe652
+_EP4FIFOIRQ = 0xe653
+_EP6FIFOIE = 0xe654
+_EP6FIFOIRQ = 0xe655
+_EP8FIFOIE = 0xe656
+_EP8FIFOIRQ = 0xe657
+_IBNIE = 0xe658
+_IBNIRQ = 0xe659
+_NAKIE = 0xe65a
+_NAKIRQ = 0xe65b
+_USBIE = 0xe65c
+_USBIRQ = 0xe65d
+_EPIE = 0xe65e
+_EPIRQ = 0xe65f
+_GPIFIE = 0xe660
+_GPIFIRQ = 0xe661
+_USBERRIE = 0xe662
+_USBERRIRQ = 0xe663
+_ERRCNTLIM = 0xe664
+_CLRERRCNT = 0xe665
+_INT2IVEC = 0xe666
+_INT4IVEC = 0xe667
+_INTSETUP = 0xe668
+_PORTACFG = 0xe670
+_PORTCCFG = 0xe671
+_PORTECFG = 0xe672
+_I2CS = 0xe678
+_I2DAT = 0xe679
+_I2CTL = 0xe67a
+_XAUTODAT1 = 0xe67b
+_XAUTODAT2 = 0xe67c
+_USBCS = 0xe680
+_SUSPEND = 0xe681
+_WAKEUPCS = 0xe682
+_TOGCTL = 0xe683
+_USBFRAMEH = 0xe684
+_USBFRAMEL = 0xe685
+_MICROFRAME = 0xe686
+_FNADDR = 0xe687
+_EP0BCH = 0xe68a
+_EP0BCL = 0xe68b
+_EP1OUTBC = 0xe68d
+_EP1INBC = 0xe68f
+_EP2BCH = 0xe690
+_EP2BCL = 0xe691
+_EP4BCH = 0xe694
+_EP4BCL = 0xe695
+_EP6BCH = 0xe698
+_EP6BCL = 0xe699
+_EP8BCH = 0xe69c
+_EP8BCL = 0xe69d
+_EP0CS = 0xe6a0
+_EP1OUTCS = 0xe6a1
+_EP1INCS = 0xe6a2
+_EP2CS = 0xe6a3
+_EP4CS = 0xe6a4
+_EP6CS = 0xe6a5
+_EP8CS = 0xe6a6
+_EP2FIFOFLGS = 0xe6a7
+_EP4FIFOFLGS = 0xe6a8
+_EP6FIFOFLGS = 0xe6a9
+_EP8FIFOFLGS = 0xe6aa
+_EP2FIFOBCH = 0xe6ab
+_EP2FIFOBCL = 0xe6ac
+_EP4FIFOBCH = 0xe6ad
+_EP4FIFOBCL = 0xe6ae
+_EP6FIFOBCH = 0xe6af
+_EP6FIFOBCL = 0xe6b0
+_EP8FIFOBCH = 0xe6b1
+_EP8FIFOBCL = 0xe6b2
+_SUDPTRH = 0xe6b3
+_SUDPTRL = 0xe6b4
+_SUDPTRCTL = 0xe6b5
+_SETUPDAT = 0xe6b8
+_GPIFWFSELECT = 0xe6c0
+_GPIFIDLECS = 0xe6c1
+_GPIFIDLECTL = 0xe6c2
+_GPIFCTLCFG = 0xe6c3
+_GPIFADRH = 0xe6c4
+_GPIFADRL = 0xe6c5
+_GPIFTCB3 = 0xe6ce
+_GPIFTCB2 = 0xe6cf
+_GPIFTCB1 = 0xe6d0
+_GPIFTCB0 = 0xe6d1
+_EP2GPIFFLGSEL = 0xe6d2
+_EP2GPIFPFSTOP = 0xe6d3
+_EP2GPIFTRIG = 0xe6d4
+_EP4GPIFFLGSEL = 0xe6da
+_EP4GPIFPFSTOP = 0xe6db
+_EP4GPIFTRIG = 0xe6dc
+_EP6GPIFFLGSEL = 0xe6e2
+_EP6GPIFPFSTOP = 0xe6e3
+_EP6GPIFTRIG = 0xe6e4
+_EP8GPIFFLGSEL = 0xe6ea
+_EP8GPIFPFSTOP = 0xe6eb
+_EP8GPIFTRIG = 0xe6ec
+_XGPIFSGLDATH = 0xe6f0
+_XGPIFSGLDATLX = 0xe6f1
+_XGPIFSGLDATLNOX = 0xe6f2
+_GPIFREADYCFG = 0xe6f3
+_GPIFREADYSTAT = 0xe6f4
+_GPIFABORT = 0xe6f5
+_FLOWSTATE = 0xe6c6
+_FLOWLOGIC = 0xe6c7
+_FLOWEQ0CTL = 0xe6c8
+_FLOWEQ1CTL = 0xe6c9
+_FLOWHOLDOFF = 0xe6ca
+_FLOWSTB = 0xe6cb
+_FLOWSTBEDGE = 0xe6cc
+_FLOWSTBHPERIOD = 0xe6cd
+_GPIFHOLDAMOUNT = 0xe60c
+_UDMACRCH = 0xe67d
+_UDMACRCL = 0xe67e
+_UDMACRCQUAL = 0xe67f
+_DBUG = 0xe6f8
+_TESTCFG = 0xe6f9
+_USBTEST = 0xe6fa
+_CT1 = 0xe6fb
+_CT2 = 0xe6fc
+_CT3 = 0xe6fd
+_CT4 = 0xe6fe
+_EP0BUF = 0xe740
+_EP1OUTBUF = 0xe780
+_EP1INBUF = 0xe7c0
+_EP2FIFOBUF = 0xf000
+_EP4FIFOBUF = 0xf400
+_EP6FIFOBUF = 0xf800
+_EP8FIFOBUF = 0xfc00
+;--------------------------------------------------------
+; external initialized ram data
+;--------------------------------------------------------
+;--------------------------------------------------------
+; interrupt vector
+;--------------------------------------------------------
+ .area CSEG (CODE)
+__interrupt_vect:
+ ljmp __sdcc_gsinit_startup
+;--------------------------------------------------------
+; global & static initialisations
+;--------------------------------------------------------
+ .area GSINIT (CODE)
+ .area GSFINAL (CODE)
+ .area GSINIT (CODE)
+__sdcc_gsinit_startup:
+ mov sp,#__start__stack - 1
+ lcall __sdcc_external_startup
+ mov a,dpl
+ jz __sdcc_init_data
+ ljmp __sdcc_program_startup
+__sdcc_init_data:
+ .area GSFINAL (CODE)
+ ljmp __sdcc_program_startup
+;--------------------------------------------------------
+; Home
+;--------------------------------------------------------
+ .area HOME (CODE)
+ .area CSEG (CODE)
+;--------------------------------------------------------
+; code
+;--------------------------------------------------------
+ .area CSEG (CODE)
+__sdcc_program_startup:
+ lcall _eeprom_init
+; return from _eeprom_init will spin here
+ sjmp .
+ .area CSEG (CODE)
diff --git a/firmware/fx2/src/usrp1/eeprom_init.c b/firmware/fx2/src/usrp1/eeprom_init.c
new file mode 100644
index 000000000..a6f6cbe2d
--- /dev/null
+++ b/firmware/fx2/src/usrp1/eeprom_init.c
@@ -0,0 +1,116 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "usrp_common.h"
+#include "usrp_commands.h"
+#include "spi.h"
+
+/*
+ * the host side fpga loader code pushes an MD5 hash of the bitstream
+ * into hash1.
+ */
+#define USRP_HASH_SIZE 16
+xdata at USRP_HASH_SLOT_0_ADDR unsigned char hash0[USRP_HASH_SIZE];
+
+
+#define enable_codecs() USRP_PA &= ~(bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B)
+#define disable_all() USRP_PA |= (bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B)
+
+static void
+write_byte_msb (unsigned char v);
+
+void
+write_both_9862s (unsigned char header_lo, unsigned char v)
+{
+ enable_codecs ();
+
+ write_byte_msb (header_lo);
+ write_byte_msb (v);
+
+ disable_all ();
+}
+
+// ----------------------------------------------------------------
+
+static void
+write_byte_msb (unsigned char v)
+{
+ unsigned char n = 8;
+ do {
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+ } while (--n != 0);
+}
+
+// ----------------------------------------------------------------
+
+#define REG_RX_PWR_DN 1
+#define REG_TX_PWR_DN 8
+#define REG_TX_MODULATOR 20
+
+void eeprom_init (void)
+{
+ unsigned short counter;
+ unsigned char i;
+
+ // configure IO ports (B and D are used by GPIF)
+
+ IOA = bmPORT_A_INITIAL; // Port A initial state
+ OEA = bmPORT_A_OUTPUTS; // Port A direction register
+
+ IOC = bmPORT_C_INITIAL; // Port C initial state
+ OEC = bmPORT_C_OUTPUTS; // Port C direction register
+
+ IOE = bmPORT_E_INITIAL; // Port E initial state
+ OEE = bmPORT_E_OUTPUTS; // Port E direction register
+
+ EP0BCH = 0; SYNCDELAY;
+
+ // USBCS &= ~bmRENUM; // chip firmware handles commands
+ USBCS = 0; // chip firmware handles commands
+
+ USRP_PC &= ~bmPC_nRESET; // active low reset
+ USRP_PC |= bmPC_nRESET;
+
+ // init_spi ();
+ bitS_OUT = 0; /* idle state has CLK = 0 */
+
+ write_both_9862s (REG_RX_PWR_DN, 0x01);
+ write_both_9862s (REG_TX_PWR_DN, 0x0f); // pwr dn digital and analog_both
+ write_both_9862s (REG_TX_MODULATOR, 0x00); // coarse & fine modulators disabled
+
+ // zero firmware hash slot
+ i = 0;
+ do {
+ hash0[i] = 0;
+ i++;
+ } while (i != USRP_HASH_SIZE);
+
+ counter = 0;
+ while (1){
+ counter++;
+ if (counter & 0x8000)
+ IOC ^= bmPC_LED0;
+ }
+}
diff --git a/firmware/fx2/src/usrp1/eeprom_io.c b/firmware/fx2/src/usrp1/eeprom_io.c
new file mode 100644
index 000000000..9eeb53636
--- /dev/null
+++ b/firmware/fx2/src/usrp1/eeprom_io.c
@@ -0,0 +1,65 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "eeprom_io.h"
+#include "i2c.h"
+#include "delay.h"
+
+// returns non-zero if successful, else 0
+unsigned char
+eeprom_read (unsigned char i2c_addr, unsigned char eeprom_offset,
+ xdata unsigned char *buf, unsigned char len)
+{
+ // We setup a random read by first doing a "zero byte write".
+ // Writes carry an address. Reads use an implicit address.
+
+ static xdata unsigned char cmd[1];
+ cmd[0] = eeprom_offset;
+ if (!i2c_write(i2c_addr, cmd, 1))
+ return 0;
+
+ return i2c_read(i2c_addr, buf, len);
+}
+
+
+#if 0
+
+// returns non-zero if successful, else 0
+unsigned char
+eeprom_write (unsigned char i2c_addr, unsigned char eeprom_offset,
+ const xdata unsigned char *buf, unsigned char len)
+{
+ static xdata unsigned char cmd[2];
+ unsigned char ok;
+
+ while (len-- > 0){
+ cmd[0] = eeprom_offset++;
+ cmd[1] = *buf++;
+ ok = i2c_write(i2c_addr, cmd, 2);
+ mdelay(10); // delay 10ms worst case write time
+ if (!ok)
+ return 0;
+ }
+ return 1;
+}
+
+#endif
diff --git a/firmware/fx2/src/usrp1/eeprom_io.h b/firmware/fx2/src/usrp1/eeprom_io.h
new file mode 100644
index 000000000..558017b12
--- /dev/null
+++ b/firmware/fx2/src/usrp1/eeprom_io.h
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_EEPROM_IO_H
+#define INCLUDED_EEPROM_IO_H
+
+
+// returns non-zero if successful, else 0
+unsigned char
+eeprom_read (unsigned char i2c_addr, unsigned char eeprom_offset,
+ xdata unsigned char *buf, unsigned char len);
+
+// returns non-zero if successful, else 0
+unsigned char
+eeprom_write (unsigned char i2c_addr, unsigned char eeprom_offset,
+ const xdata unsigned char *buf, unsigned char len);
+
+
+#endif /* INCLUDED_EEPROM_IO_H */
diff --git a/firmware/fx2/src/usrp1/fpga_load.c b/firmware/fx2/src/usrp1/fpga_load.c
new file mode 100644
index 000000000..b0256e925
--- /dev/null
+++ b/firmware/fx2/src/usrp1/fpga_load.c
@@ -0,0 +1 @@
+#include "../common/fpga_load.c"
diff --git a/firmware/fx2/src/usrp1/fpga_rev2.c b/firmware/fx2/src/usrp1/fpga_rev2.c
new file mode 100644
index 000000000..cca961dc4
--- /dev/null
+++ b/firmware/fx2/src/usrp1/fpga_rev2.c
@@ -0,0 +1,122 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "fpga.h"
+#include "fpga_regs_common.h"
+#include "usrp_common.h"
+#include "usrp_globals.h"
+#include "spi.h"
+
+unsigned char g_tx_reset = 0;
+unsigned char g_rx_reset = 0;
+
+void
+fpga_write_reg (unsigned char regno, const xdata unsigned char *regval)
+{
+ spi_write (0, 0x00 | (regno & 0x7f),
+ SPI_ENABLE_FPGA,
+ SPI_FMT_MSB | SPI_FMT_HDR_1,
+ regval, 4);
+}
+
+
+static xdata unsigned char regval[4] = {0, 0, 0, 0};
+
+static void
+write_fpga_master_ctrl (void)
+{
+ unsigned char v = 0;
+ if (g_tx_enable)
+ v |= bmFR_MC_ENABLE_TX;
+ if (g_rx_enable)
+ v |= bmFR_MC_ENABLE_RX;
+ if (g_tx_reset)
+ v |= bmFR_MC_RESET_TX;
+ if (g_rx_reset)
+ v |= bmFR_MC_RESET_RX;
+ regval[3] = v;
+
+ fpga_write_reg (FR_MASTER_CTRL, regval);
+}
+
+// Resets both AD9862's and the FPGA serial bus interface.
+
+void
+fpga_set_reset (unsigned char on)
+{
+ on &= 0x1;
+
+ if (on){
+ USRP_PC &= ~bmPC_nRESET; // active low
+ g_tx_enable = 0;
+ g_rx_enable = 0;
+ g_tx_reset = 0;
+ g_rx_reset = 0;
+ }
+ else
+ USRP_PC |= bmPC_nRESET;
+}
+
+void
+fpga_set_tx_enable (unsigned char on)
+{
+ on &= 0x1;
+ g_tx_enable = on;
+
+ write_fpga_master_ctrl ();
+
+ if (on){
+ g_tx_underrun = 0;
+ fpga_clear_flags ();
+ }
+}
+
+void
+fpga_set_rx_enable (unsigned char on)
+{
+ on &= 0x1;
+ g_rx_enable = on;
+
+ write_fpga_master_ctrl ();
+ if (on){
+ g_rx_overrun = 0;
+ fpga_clear_flags ();
+ }
+}
+
+void
+fpga_set_tx_reset (unsigned char on)
+{
+ on &= 0x1;
+ g_tx_reset = on;
+
+ write_fpga_master_ctrl ();
+}
+
+void
+fpga_set_rx_reset (unsigned char on)
+{
+ on &= 0x1;
+ g_rx_reset = on;
+
+ write_fpga_master_ctrl ();
+}
diff --git a/firmware/fx2/src/usrp1/fpga_rev2.h b/firmware/fx2/src/usrp1/fpga_rev2.h
new file mode 100644
index 000000000..54ec3f9fa
--- /dev/null
+++ b/firmware/fx2/src/usrp1/fpga_rev2.h
@@ -0,0 +1,58 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003,2004 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#ifndef INCLUDED_FPGA_REV1_H
+#define INCLUDED_FPGA_REV1_H
+
+void fpga_set_reset (unsigned char v);
+void fpga_set_tx_enable (unsigned char v);
+void fpga_set_rx_enable (unsigned char v);
+void fpga_set_tx_reset (unsigned char v);
+void fpga_set_rx_reset (unsigned char v);
+
+unsigned char fpga_has_room_for_packet (void);
+unsigned char fpga_has_packet_avail (void);
+
+#if (UC_BOARD_HAS_FPGA)
+/*
+ * return TRUE iff FPGA internal fifo has room for 512 bytes.
+ */
+#define fpga_has_room_for_packet() (GPIFREADYSTAT & bmFPGA_HAS_SPACE)
+
+/*
+ * return TRUE iff FPGA internal fifo has at least 512 bytes available.
+ */
+#define fpga_has_packet_avail() (GPIFREADYSTAT & bmFPGA_PKT_AVAIL)
+
+#else /* no FPGA on board. fake it. */
+
+#define fpga_has_room_for_packet() TRUE
+#define fpga_has_packet_avail() TRUE
+
+#endif
+
+#define fpga_clear_flags() \
+ do { \
+ USRP_PE |= bmPE_FPGA_CLR_STATUS; \
+ USRP_PE &= ~bmPE_FPGA_CLR_STATUS; \
+ } while (0)
+
+
+#endif /* INCLUDED_FPGA_REV1_H */
diff --git a/firmware/fx2/src/usrp1/gpif.c b/firmware/fx2/src/usrp1/gpif.c
new file mode 100644
index 000000000..f6745a43b
--- /dev/null
+++ b/firmware/fx2/src/usrp1/gpif.c
@@ -0,0 +1,292 @@
+// This program configures the General Programmable Interface (GPIF) for FX2.
+// Please do not modify sections of text which are marked as "DO NOT EDIT ...".
+//
+// DO NOT EDIT ...
+// GPIF Initialization
+// Interface Timing Async
+// Internal Ready Init IntRdy=1
+// CTL Out Tristate-able Binary
+// SingleWrite WF Select 1
+// SingleRead WF Select 0
+// FifoWrite WF Select 3
+// FifoRead WF Select 2
+// Data Bus Idle Drive Tristate
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+// GPIF Wave Names
+// Wave 0 = singlerd
+// Wave 1 = singlewr
+// Wave 2 = FIFORd
+// Wave 3 = FIFOWr
+
+// GPIF Ctrl Outputs Level
+// CTL 0 = WEN# CMOS
+// CTL 1 = REN# CMOS
+// CTL 2 = OE# CMOS
+// CTL 3 = CLRST CMOS
+// CTL 4 = unused CMOS
+// CTL 5 = BOGUS CMOS
+
+// GPIF Rdy Inputs
+// RDY0 = EF#
+// RDY1 = FF#
+// RDY2 = unused
+// RDY3 = unused
+// RDY4 = unused
+// RDY5 = TCXpire
+// FIFOFlag = FIFOFlag
+// IntReady = IntReady
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 0: singlerd
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode NO Data NO Data NO Data NO Data NO Data NO Data NO Data
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1 Wait 1
+// Term A
+// LFunc
+// Term B
+// Branch1
+// Branch0
+// Re-Exec
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 0 0 0 0 0 0 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 0 0 0 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 1: singlewr
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode Activate Activate Activate Activate Activate Activate Activate
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1
+// Term A EF#
+// LFunc AND
+// Term B EF#
+// Branch1 ThenIdle
+// Branch0 ElseIdle
+// Re-Exec No
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 1 1 1 1 1 1 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 0 0 0 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 2: FIFORd
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode NO Data Activate NO Data NO Data NO Data NO Data NO Data
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 IF Wait 1 IF Wait 1 Wait 1 Wait 1
+// Term A TCXpire TCXpire
+// LFunc AND AND
+// Term B TCXpire TCXpire
+// Branch1 Then 2 ThenIdle
+// Branch0 Else 1 ElseIdle
+// Re-Exec No No
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 0 0 0 0 0 0 0
+// REN# 1 0 0 0 0 0 0 0
+// OE# 1 1 1 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+// DO NOT EDIT ...
+//
+// GPIF Waveform 3: FIFOWr
+//
+// Interval 0 1 2 3 4 5 6 Idle (7)
+// _________ _________ _________ _________ _________ _________ _________ _________
+//
+// AddrMode Same Val Same Val Same Val Same Val Same Val Same Val Same Val
+// DataMode NO Data Activate Activate Activate Activate Activate Activate
+// NextData SameData SameData SameData SameData SameData SameData SameData
+// Int Trig No Int No Int No Int No Int No Int No Int No Int
+// IF/Wait Wait 1 IF Wait 1 Wait 1 Wait 1 Wait 1 Wait 1
+// Term A TCXpire
+// LFunc AND
+// Term B TCXpire
+// Branch1 ThenIdle
+// Branch0 Else 1
+// Re-Exec No
+// Sngl/CRC Default Default Default Default Default Default Default
+// WEN# 0 0 0 0 0 0 0 0
+// REN# 0 0 0 0 0 0 0 0
+// OE# 0 0 0 0 0 0 0 0
+// CLRST 0 0 0 0 0 0 0 0
+// unused 0 0 0 0 0 0 0 0
+// BOGUS 0 0 0 0 0 0 0 0
+//
+// END DO NOT EDIT
+
+// GPIF Program Code
+
+// DO NOT EDIT ...
+#include "fx2.h"
+#include "fx2regs.h"
+#include "fx2sdly.h" // SYNCDELAY macro
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+const char xdata WaveData[128] =
+{
+// Wave 0
+/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+// Wave 1
+/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x22, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+/* Output*/ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+// Wave 2
+/* LenBr */ 0x01, 0x11, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+/* Output*/ 0x06, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* LFun */ 0x00, 0x2D, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x3F,
+// Wave 3
+/* LenBr */ 0x01, 0x39, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
+/* Opcode*/ 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
+/* Output*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* LFun */ 0x00, 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+};
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+const char xdata FlowStates[36] =
+{
+/* Wave 0 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* Wave 1 FlowStates */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+/* Wave 2 FlowStates */ 0x81,0x2D,0x26,0x00,0x04,0x04,0x03,0x02,0x00,
+/* Wave 3 FlowStates */ 0x81,0x2D,0x21,0x00,0x04,0x04,0x03,0x02,0x00,
+};
+// END DO NOT EDIT
+
+// DO NOT EDIT ...
+const char xdata InitData[7] =
+{
+/* Regs */ 0xA0,0x00,0x00,0x00,0xEE,0x4E,0x00
+};
+// END DO NOT EDIT
+
+// TO DO: You may add additional code below.
+
+void GpifInit( void )
+{
+ BYTE i;
+
+ // Registers which require a synchronization delay, see section 15.14
+ // FIFORESET FIFOPINPOLAR
+ // INPKTEND OUTPKTEND
+ // EPxBCH:L REVCTL
+ // GPIFTCB3 GPIFTCB2
+ // GPIFTCB1 GPIFTCB0
+ // EPxFIFOPFH:L EPxAUTOINLENH:L
+ // EPxFIFOCFG EPxGPIFFLGSEL
+ // PINFLAGSxx EPxFIFOIRQ
+ // EPxFIFOIE GPIFIRQ
+ // GPIFIE GPIFADRH:L
+ // UDMACRCH:L EPxGPIFTRIG
+ // GPIFTRIG
+
+ // Note: The pre-REVE EPxGPIFTCH/L register are affected, as well...
+ // ...these have been replaced by GPIFTC[B3:B0] registers
+
+ // 8051 doesn't have access to waveform memories 'til
+ // the part is in GPIF mode.
+
+ IFCONFIG = 0xEE;
+ // IFCLKSRC=1 , FIFOs executes on internal clk source
+ // xMHz=1 , 48MHz internal clk rate
+ // IFCLKOE=0 , Don't drive IFCLK pin signal at 48MHz
+ // IFCLKPOL=0 , Don't invert IFCLK pin signal from internal clk
+ // ASYNC=1 , master samples asynchronous
+ // GSTATE=1 , Drive GPIF states out on PORTE[2:0], debug WF
+ // IFCFG[1:0]=10, FX2 in GPIF master mode
+
+ GPIFABORT = 0xFF; // abort any waveforms pending
+
+ GPIFREADYCFG = InitData[ 0 ];
+ GPIFCTLCFG = InitData[ 1 ];
+ GPIFIDLECS = InitData[ 2 ];
+ GPIFIDLECTL = InitData[ 3 ];
+ GPIFWFSELECT = InitData[ 5 ];
+ GPIFREADYSTAT = InitData[ 6 ];
+
+ // use dual autopointer feature...
+ AUTOPTRSETUP = 0x07; // inc both pointers,
+ // ...warning: this introduces pdata hole(s)
+ // ...at E67B (XAUTODAT1) and E67C (XAUTODAT2)
+
+ // source
+ AUTOPTRH1 = MSB( &WaveData );
+ AUTOPTRL1 = LSB( &WaveData );
+
+ // destination
+ AUTOPTRH2 = 0xE4;
+ AUTOPTRL2 = 0x00;
+
+ // transfer
+ for ( i = 0x00; i < 128; i++ )
+ {
+ EXTAUTODAT2 = EXTAUTODAT1;
+ }
+
+// Configure GPIF Address pins, output initial value,
+ PORTCCFG = 0xFF; // [7:0] as alt. func. GPIFADR[7:0]
+ OEC = 0xFF; // and as outputs
+ PORTECFG |= 0x80; // [8] as alt. func. GPIFADR[8]
+ OEE |= 0x80; // and as output
+
+// ...OR... tri-state GPIFADR[8:0] pins
+// PORTCCFG = 0x00; // [7:0] as port I/O
+// OEC = 0x00; // and as inputs
+// PORTECFG &= 0x7F; // [8] as port I/O
+// OEE &= 0x7F; // and as input
+
+// GPIF address pins update when GPIFADRH/L written
+ SYNCDELAY; //
+ GPIFADRH = 0x00; // bits[7:1] always 0
+ SYNCDELAY; //
+ GPIFADRL = 0x00; // point to PERIPHERAL address 0x0000
+
+// Configure GPIF FlowStates registers for Wave 0 of WaveData
+ FLOWSTATE = FlowStates[ 0 ];
+ FLOWLOGIC = FlowStates[ 1 ];
+ FLOWEQ0CTL = FlowStates[ 2 ];
+ FLOWEQ1CTL = FlowStates[ 3 ];
+ FLOWHOLDOFF = FlowStates[ 4 ];
+ FLOWSTB = FlowStates[ 5 ];
+ FLOWSTBEDGE = FlowStates[ 6 ];
+ FLOWSTBHPERIOD = FlowStates[ 7 ];
+}
+
diff --git a/firmware/fx2/src/usrp1/gpif.gpf b/firmware/fx2/src/usrp1/gpif.gpf
new file mode 100755
index 000000000..854e25399
--- /dev/null
+++ b/firmware/fx2/src/usrp1/gpif.gpf
Binary files differ
diff --git a/firmware/fx2/src/usrp1/init_gpif.c b/firmware/fx2/src/usrp1/init_gpif.c
new file mode 100644
index 000000000..0f5944b3b
--- /dev/null
+++ b/firmware/fx2/src/usrp1/init_gpif.c
@@ -0,0 +1 @@
+#include "../common/init_gpif.c"
diff --git a/firmware/fx2/src/usrp1/spi.c b/firmware/fx2/src/usrp1/spi.c
new file mode 100644
index 000000000..0aaffea5d
--- /dev/null
+++ b/firmware/fx2/src/usrp1/spi.c
@@ -0,0 +1,472 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004,2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "spi.h"
+#include "usrp_rev2_regs.h"
+
+static void
+setup_enables (unsigned char enables)
+{
+ // Software eanbles are active high.
+ // Hardware enables are active low.
+
+ // Uhh, the CODECs are active low, but the FPGA is active high...
+ enables ^= SPI_ENABLE_FPGA;
+
+ // KLUDGE: This code is fragile, but reasonably fast...
+ // low three bits of enables go into port A
+ USRP_PA = USRP_PA | (0x7 << 3); // disable FPGA, CODEC_A, CODEC_B
+ USRP_PA ^= (enables & 0x7) << 3; // enable specified devs
+
+ // high four bits of enables go into port E
+ USRP_PE = USRP_PE | (0xf << 4); // disable TX_A, RX_A, TX_B, RX_B
+ USRP_PE ^= (enables & 0xf0); // enable specified devs
+}
+
+#define disable_all() setup_enables (0)
+
+void
+init_spi (void)
+{
+ disable_all (); /* disable all devs */
+ bitS_OUT = 0; /* idle state has CLK = 0 */
+}
+
+#if 0
+static unsigned char
+count_bits8 (unsigned char v)
+{
+ static unsigned char count4[16] = {
+ 0, // 0
+ 1, // 1
+ 1, // 2
+ 2, // 3
+ 1, // 4
+ 2, // 5
+ 2, // 6
+ 3, // 7
+ 1, // 8
+ 2, // 9
+ 2, // a
+ 3, // b
+ 2, // c
+ 3, // d
+ 3, // e
+ 4 // f
+ };
+ return count4[v & 0xf] + count4[(v >> 4) & 0xf];
+}
+
+#else
+
+static unsigned char
+count_bits8 (unsigned char v)
+{
+ unsigned char count = 0;
+ if (v & (1 << 0)) count++;
+ if (v & (1 << 1)) count++;
+ if (v & (1 << 2)) count++;
+ if (v & (1 << 3)) count++;
+ if (v & (1 << 4)) count++;
+ if (v & (1 << 5)) count++;
+ if (v & (1 << 6)) count++;
+ if (v & (1 << 7)) count++;
+ return count;
+}
+#endif
+
+static void
+write_byte_msb (unsigned char v);
+
+unsigned char
+transact_byte_msb (unsigned char v);
+
+static void
+write_bytes_msb (const xdata unsigned char *buf, unsigned char len);
+
+static void
+read_bytes_msb (xdata unsigned char *buf, unsigned char len);
+
+static void
+transact_bytes_msb (xdata unsigned char *buf, unsigned char len);
+
+// returns non-zero if successful, else 0
+unsigned char
+spi_read (unsigned char header_hi, unsigned char header_lo,
+ unsigned char enables, unsigned char format,
+ xdata unsigned char *buf, unsigned char len)
+{
+ if (count_bits8 (enables) > 1)
+ return 0; // error, too many enables set
+
+ setup_enables (enables);
+
+ if (format & SPI_FMT_LSB){ // order: LSB
+#if 1
+ return 0; // error, not implemented
+#else
+ switch (format & SPI_FMR_HDR_MASK){
+ case SPI_FMT_HDR_0:
+ break;
+ case SPI_FMT_HDR_1:
+ write_byte_lsb (header_lo);
+ break;
+ case SPI_FMT_HDR_2:
+ write_byte_lsb (header_lo);
+ write_byte_lsb (header_hi);
+ break;
+ default:
+ return 0; // error
+ }
+ if (len != 0)
+ read_bytes_lsb (buf, len);
+#endif
+ }
+
+ else { // order: MSB
+
+ switch (format & SPI_FMT_HDR_MASK){
+ case SPI_FMT_HDR_0:
+ break;
+ case SPI_FMT_HDR_1:
+ write_byte_msb (header_lo);
+ break;
+ case SPI_FMT_HDR_2:
+ write_byte_msb (header_hi);
+ write_byte_msb (header_lo);
+ break;
+ default:
+ return 0; // error
+ }
+ if (len != 0)
+ read_bytes_msb (buf, len);
+ }
+
+ disable_all ();
+ return 1; // success
+}
+
+
+// returns non-zero if successful, else 0
+unsigned char
+spi_write (unsigned char header_hi, unsigned char header_lo,
+ unsigned char enables, unsigned char format,
+ const xdata unsigned char *buf, unsigned char len)
+{
+ setup_enables (enables);
+
+ if (format & SPI_FMT_LSB){ // order: LSB
+#if 1
+ return 0; // error, not implemented
+#else
+ switch (format & SPI_FMR_HDR_MASK){
+ case SPI_FMT_HDR_0:
+ break;
+ case SPI_FMT_HDR_1:
+ write_byte_lsb (header_lo);
+ break;
+ case SPI_FMT_HDR_2:
+ write_byte_lsb (header_lo);
+ write_byte_lsb (header_hi);
+ break;
+ default:
+ return 0; // error
+ }
+ if (len != 0)
+ write_bytes_lsb (buf, len);
+#endif
+ }
+
+ else { // order: MSB
+
+ switch (format & SPI_FMT_HDR_MASK){
+ case SPI_FMT_HDR_0:
+ break;
+ case SPI_FMT_HDR_1:
+ write_byte_msb (header_lo);
+ break;
+ case SPI_FMT_HDR_2:
+ write_byte_msb (header_hi);
+ write_byte_msb (header_lo);
+ break;
+ default:
+ return 0; // error
+ }
+ if (len != 0)
+ write_bytes_msb (buf, len);
+ }
+
+ disable_all ();
+ return 1; // success
+}
+
+unsigned char
+spi_transact (unsigned char data0, unsigned char data1,
+ unsigned char data2, unsigned char data3,
+ unsigned char enables, xdata unsigned char *buf,
+ unsigned char len)
+{
+ if (count_bits8 (enables) > 1)
+ return 0; // error, too many enables set
+
+ if (len > 4)
+ return 0;
+
+ setup_enables (enables);
+
+ buf[0] = data0;
+ buf[1] = data1;
+ buf[2] = data2;
+ buf[3] = data3;
+
+ if (len != 0)
+ transact_bytes_msb(buf, len);
+
+ disable_all ();
+ return 1; // success
+}
+
+static unsigned char
+transact_byte_msb (unsigned char v)
+{
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN; // read into bottom bit
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7);
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ return v;
+}
+
+static void
+transact_bytes_msb (xdata unsigned char *buf, unsigned char len)
+{
+ while (len-- != 0){
+ *buf++ = transact_byte_msb (*buf);
+ }
+}
+
+static void
+write_byte_msb (unsigned char v)
+{
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+
+ v = (v << 1) | (v >> 7); // rotate left (MSB into bottom bit)
+ bitS_OUT = v & 0x1;
+ bitS_CLK = 1;
+ bitS_CLK = 0;
+}
+
+static void
+write_bytes_msb (const xdata unsigned char *buf, unsigned char len)
+{
+ while (len-- != 0){
+ write_byte_msb (*buf++);
+ }
+}
+
+#if 0
+/*
+ * This is incorrectly compiled by SDCC 2.4.0
+ */
+static unsigned char
+read_byte_msb (void)
+{
+ unsigned char v = 0;
+
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ v = v << 1;
+ bitS_CLK = 1;
+ v |= bitS_IN;
+ bitS_CLK = 0;
+
+ return v;
+}
+#else
+static unsigned char
+read_byte_msb (void) _naked
+{
+ _asm
+ clr a
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ setb _bitS_CLK
+ mov c, _bitS_IN
+ rlc a
+ clr _bitS_CLK
+
+ mov dpl,a
+ ret
+ _endasm;
+}
+#endif
+
+static void
+read_bytes_msb (xdata unsigned char *buf, unsigned char len)
+{
+ while (len-- != 0){
+ *buf++ = read_byte_msb ();
+ }
+}
+
diff --git a/firmware/fx2/src/usrp1/spi.h b/firmware/fx2/src/usrp1/spi.h
new file mode 100644
index 000000000..5342b82b8
--- /dev/null
+++ b/firmware/fx2/src/usrp1/spi.h
@@ -0,0 +1,50 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2004 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio 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 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_SPI_H
+#define INCLUDED_SPI_H
+
+#include "usrp_spi_defs.h"
+
+void init_spi (void); // one time call to init
+
+// returns non-zero if successful, else 0
+unsigned char
+spi_read (unsigned char header_hi, unsigned char header_lo,
+ unsigned char enables, unsigned char format,
+ xdata unsigned char *buf, unsigned char len);
+
+// returns non-zero if successful, else 0
+unsigned char
+spi_write (unsigned char header_hi, unsigned char header_lo,
+ unsigned char enables, unsigned char format,
+ const xdata unsigned char *buf, unsigned char len);
+
+// returns non-zero if successful, else 0
+unsigned char
+spi_transact (unsigned char data0, unsigned char data1,
+ unsigned char data2, unsigned char data3,
+ unsigned char enables, xdata unsigned char *buf,
+ unsigned char len);
+
+
+#endif /* INCLUDED_SPI_H */
diff --git a/firmware/fx2/src/usrp1/usb_descriptors.a51 b/firmware/fx2/src/usrp1/usb_descriptors.a51
new file mode 100644
index 000000000..a60adbef8
--- /dev/null
+++ b/firmware/fx2/src/usrp1/usb_descriptors.a51
@@ -0,0 +1,404 @@
+;;; -*- asm -*-
+;;;
+;;; Copyright 2003 Free Software Foundation, Inc.
+;;;
+;;; This file is part of GNU Radio
+;;;
+;;; GNU Radio 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 3, or (at your option)
+;;; any later version.
+;;;
+;;; GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+;;; the Free Software Foundation, Inc., 51 Franklin Street,
+;;; Boston, MA 02110-1301, USA.
+;;;
+
+;;; USB Descriptor table for the USRP
+;;;
+;;; We're a high-speed only device (480 Mb/sec) with 1 configuration
+;;; and 3 interfaces.
+;;;
+;;; interface 0: command and status (ep0 COMMAND)
+;;; interface 1: Transmit path (ep2 OUT BULK)
+;;; interface 2: Receive path (ep6 IN BULK)
+
+ .module usb_descriptors
+
+ VID_FREE = 0xfffe ; Free Software Folks
+ PID_USRP = 0x0002 ; USRP
+
+ ;; We distinguish configured from unconfigured USRPs using the Device ID.
+ ;; If the MSB of the DID is 0, the device is unconfigured.
+ ;; The LSB of the DID is reserved for hardware revs.
+
+ DID_USRP = 0x0100 ; Device ID (bcd)
+
+
+ DSCR_DEVICE = 1 ; Descriptor type: Device
+ DSCR_CONFIG = 2 ; Descriptor type: Configuration
+ DSCR_STRING = 3 ; Descriptor type: String
+ DSCR_INTRFC = 4 ; Descriptor type: Interface
+ DSCR_ENDPNT = 5 ; Descriptor type: Endpoint
+ DSCR_DEVQUAL = 6 ; Descriptor type: Device Qualifier
+
+ DSCR_DEVICE_LEN = 18
+ DSCR_CONFIG_LEN = 9
+ DSCR_INTRFC_LEN = 9
+ DSCR_ENDPNT_LEN = 7
+ DSCR_DEVQUAL_LEN = 10
+
+ ET_CONTROL = 0 ; Endpoint type: Control
+ ET_ISO = 1 ; Endpoint type: Isochronous
+ ET_BULK = 2 ; Endpoint type: Bulk
+ ET_INT = 3 ; Endpoint type: Interrupt
+
+
+ ;; configuration attributes
+ bmSELF_POWERED = 1 << 6
+
+;;; --------------------------------------------------------
+;;; external ram data
+;;;--------------------------------------------------------
+
+ .area USBDESCSEG (XDATA)
+
+;;; ----------------------------------------------------------------
+;;; descriptors used when operating at high speed (480Mb/sec)
+;;; ----------------------------------------------------------------
+
+ .even ; descriptors must be 2-byte aligned for SUDPTR{H,L} to work
+
+ ;; The .even directive isn't really honored by the linker. Bummer!
+ ;; (There's no way to specify an alignment requirement for a given area,
+ ;; hence when they're concatenated together, even doesn't work.)
+ ;;
+ ;; We work around this by telling the linker to put USBDESCSEG
+ ;; at 0xE000 absolute. This means that the maximimum length of this
+ ;; segment is 480 bytes, leaving room for the two hash slots
+ ;; at 0xE1EO to 0xE1FF.
+ ;;
+ ;; As of July 7, 2004, this segment is 326 bytes long
+
+_high_speed_device_descr::
+ .db DSCR_DEVICE_LEN
+ .db DSCR_DEVICE
+ .db <0x0200 ; Specification version (LSB)
+ .db >0x0200 ; Specification version (MSB)
+ .db 0xff ; device class (vendor specific)
+ .db 0xff ; device subclass (vendor specific)
+ .db 0xff ; device protocol (vendor specific)
+ .db 64 ; bMaxPacketSize0 for endpoint 0
+ .db <VID_FREE ; idVendor
+ .db >VID_FREE ; idVendor
+ .db <PID_USRP ; idProduct
+ .db >PID_USRP ; idProduct
+_usb_desc_hw_rev_binary_patch_location_0::
+ .db <DID_USRP ; bcdDevice
+ .db >DID_USRP ; bcdDevice
+ .db SI_VENDOR ; iManufacturer (string index)
+ .db SI_PRODUCT ; iProduct (string index)
+ .db SI_SERIAL ; iSerial number (string index)
+ .db 1 ; bNumConfigurations
+
+;;; describes the other speed (12Mb/sec)
+ .even
+_high_speed_devqual_descr::
+ .db DSCR_DEVQUAL_LEN
+ .db DSCR_DEVQUAL
+ .db <0x0200 ; bcdUSB (LSB)
+ .db >0x0200 ; bcdUSB (MSB)
+ .db 0xff ; bDeviceClass
+ .db 0xff ; bDeviceSubClass
+ .db 0xff ; bDeviceProtocol
+ .db 64 ; bMaxPacketSize0
+ .db 1 ; bNumConfigurations (one config at 12Mb/sec)
+ .db 0 ; bReserved
+
+ .even
+_high_speed_config_descr::
+ .db DSCR_CONFIG_LEN
+ .db DSCR_CONFIG
+ .db <(_high_speed_config_descr_end - _high_speed_config_descr) ; LSB
+ .db >(_high_speed_config_descr_end - _high_speed_config_descr) ; MSB
+ .db 3 ; bNumInterfaces
+ .db 1 ; bConfigurationValue
+ .db 0 ; iConfiguration
+ .db 0x80 | bmSELF_POWERED ; bmAttributes
+ .db 0 ; bMaxPower
+
+ ;; interface descriptor 0 (command & status, ep0 COMMAND)
+
+ .db DSCR_INTRFC_LEN
+ .db DSCR_INTRFC
+ .db 0 ; bInterfaceNumber (zero based)
+ .db 0 ; bAlternateSetting
+ .db 0 ; bNumEndpoints
+ .db 0xff ; bInterfaceClass (vendor specific)
+ .db 0xff ; bInterfaceSubClass (vendor specific)
+ .db 0xff ; bInterfaceProtocol (vendor specific)
+ .db SI_COMMAND_AND_STATUS ; iInterface (description)
+
+ ;; interface descriptor 1 (transmit path, ep2 OUT BULK)
+
+ .db DSCR_INTRFC_LEN
+ .db DSCR_INTRFC
+ .db 1 ; bInterfaceNumber (zero based)
+ .db 0 ; bAlternateSetting
+ .db 1 ; bNumEndpoints
+ .db 0xff ; bInterfaceClass (vendor specific)
+ .db 0xff ; bInterfaceSubClass (vendor specific)
+ .db 0xff ; bInterfaceProtocol (vendor specific)
+ .db SI_TX_PATH ; iInterface (description)
+
+ ;; interface 1's end point
+
+ .db DSCR_ENDPNT_LEN
+ .db DSCR_ENDPNT
+ .db 0x02 ; bEndpointAddress (ep 2 OUT)
+ .db ET_BULK ; bmAttributes
+ .db <512 ; wMaxPacketSize (LSB)
+ .db >512 ; wMaxPacketSize (MSB)
+ .db 0 ; bInterval (iso only)
+
+ ;; interface descriptor 2 (receive path, ep6 IN BULK)
+
+ .db DSCR_INTRFC_LEN
+ .db DSCR_INTRFC
+ .db 2 ; bInterfaceNumber (zero based)
+ .db 0 ; bAlternateSetting
+ .db 1 ; bNumEndpoints
+ .db 0xff ; bInterfaceClass (vendor specific)
+ .db 0xff ; bInterfaceSubClass (vendor specific)
+ .db 0xff ; bInterfaceProtocol (vendor specific)
+ .db SI_RX_PATH ; iInterface (description)
+
+ ;; interface 2's end point
+
+ .db DSCR_ENDPNT_LEN
+ .db DSCR_ENDPNT
+ .db 0x86 ; bEndpointAddress (ep 6 IN)
+ .db ET_BULK ; bmAttributes
+ .db <512 ; wMaxPacketSize (LSB)
+ .db >512 ; wMaxPacketSize (MSB)
+ .db 0 ; bInterval (iso only)
+
+_high_speed_config_descr_end:
+
+;;; ----------------------------------------------------------------
+;;; descriptors used when operating at full speed (12Mb/sec)
+;;; ----------------------------------------------------------------
+
+ .even
+_full_speed_device_descr::
+ .db DSCR_DEVICE_LEN
+ .db DSCR_DEVICE
+ .db <0x0200 ; Specification version (LSB)
+ .db >0x0200 ; Specification version (MSB)
+ .db 0xff ; device class (vendor specific)
+ .db 0xff ; device subclass (vendor specific)
+ .db 0xff ; device protocol (vendor specific)
+ .db 64 ; bMaxPacketSize0 for endpoint 0
+ .db <VID_FREE ; idVendor
+ .db >VID_FREE ; idVendor
+ .db <PID_USRP ; idProduct
+ .db >PID_USRP ; idProduct
+_usb_desc_hw_rev_binary_patch_location_1::
+ .db <DID_USRP ; bcdDevice
+ .db >DID_USRP ; bcdDevice
+ .db SI_VENDOR ; iManufacturer (string index)
+ .db SI_PRODUCT ; iProduct (string index)
+ .db SI_NONE ; iSerial number (None)
+ .db 1 ; bNumConfigurations
+
+
+;;; describes the other speed (480Mb/sec)
+ .even
+_full_speed_devqual_descr::
+ .db DSCR_DEVQUAL_LEN
+ .db DSCR_DEVQUAL
+ .db <0x0200 ; bcdUSB
+ .db >0x0200 ; bcdUSB
+ .db 0xff ; bDeviceClass
+ .db 0xff ; bDeviceSubClass
+ .db 0xff ; bDeviceProtocol
+ .db 64 ; bMaxPacketSize0
+ .db 1 ; bNumConfigurations (one config at 480Mb/sec)
+ .db 0 ; bReserved
+
+ .even
+_full_speed_config_descr::
+ .db DSCR_CONFIG_LEN
+ .db DSCR_CONFIG
+ .db <(_full_speed_config_descr_end - _full_speed_config_descr) ; LSB
+ .db >(_full_speed_config_descr_end - _full_speed_config_descr) ; MSB
+ .db 1 ; bNumInterfaces
+ .db 1 ; bConfigurationValue
+ .db 0 ; iConfiguration
+ .db 0x80 | bmSELF_POWERED ; bmAttributes
+ .db 0 ; bMaxPower
+
+ ;; interface descriptor 0 (command & status, ep0 COMMAND)
+
+ .db DSCR_INTRFC_LEN
+ .db DSCR_INTRFC
+ .db 0 ; bInterfaceNumber (zero based)
+ .db 0 ; bAlternateSetting
+ .db 0 ; bNumEndpoints
+ .db 0xff ; bInterfaceClass (vendor specific)
+ .db 0xff ; bInterfaceSubClass (vendor specific)
+ .db 0xff ; bInterfaceProtocol (vendor specific)
+ .db SI_COMMAND_AND_STATUS ; iInterface (description)
+
+_full_speed_config_descr_end:
+
+;;; ----------------------------------------------------------------
+;;; string descriptors
+;;; ----------------------------------------------------------------
+
+_nstring_descriptors::
+ .db (_string_descriptors_end - _string_descriptors) / 2
+
+_string_descriptors::
+ .db <str0, >str0
+ .db <str1, >str1
+ .db <str2, >str2
+ .db <str3, >str3
+ .db <str4, >str4
+ .db <str5, >str5
+ .db <str6, >str6
+_string_descriptors_end:
+
+ SI_NONE = 0
+ ;; str0 contains the language ID's.
+ .even
+str0: .db str0_end - str0
+ .db DSCR_STRING
+ .db 0
+ .db 0
+ .db <0x0409 ; magic code for US English (LSB)
+ .db >0x0409 ; magic code for US English (MSB)
+str0_end:
+
+ SI_VENDOR = 1
+ .even
+str1: .db str1_end - str1
+ .db DSCR_STRING
+ .db 'F, 0 ; 16-bit unicode
+ .db 'r, 0
+ .db 'e, 0
+ .db 'e, 0
+ .db ' , 0
+ .db 'S, 0
+ .db 'o, 0
+ .db 'f, 0
+ .db 't, 0
+ .db 'w, 0
+ .db 'a, 0
+ .db 'r, 0
+ .db 'e, 0
+ .db ' , 0
+ .db 'F, 0
+ .db 'o, 0
+ .db 'l, 0
+ .db 'k, 0
+ .db 's, 0
+str1_end:
+
+ SI_PRODUCT = 2
+ .even
+str2: .db str2_end - str2
+ .db DSCR_STRING
+ .db 'U, 0
+ .db 'S, 0
+ .db 'R, 0
+ .db 'P, 0
+ .db ' , 0
+ .db 'R, 0
+ .db 'e, 0
+ .db 'v, 0
+ .db ' , 0
+_usb_desc_hw_rev_ascii_patch_location_0::
+ .db '?, 0
+str2_end:
+
+ SI_COMMAND_AND_STATUS = 3
+ .even
+str3: .db str3_end - str3
+ .db DSCR_STRING
+ .db 'C, 0
+ .db 'o, 0
+ .db 'm, 0
+ .db 'm, 0
+ .db 'a, 0
+ .db 'n, 0
+ .db 'd, 0
+ .db ' , 0
+ .db '&, 0
+ .db ' , 0
+ .db 'S, 0
+ .db 't, 0
+ .db 'a, 0
+ .db 't, 0
+ .db 'u, 0
+ .db 's, 0
+str3_end:
+
+ SI_TX_PATH = 4
+ .even
+str4: .db str4_end - str4
+ .db DSCR_STRING
+ .db 'T, 0
+ .db 'r, 0
+ .db 'a, 0
+ .db 'n, 0
+ .db 's, 0
+ .db 'm, 0
+ .db 'i, 0
+ .db 't, 0
+ .db ' , 0
+ .db 'P, 0
+ .db 'a, 0
+ .db 't, 0
+ .db 'h, 0
+str4_end:
+
+ SI_RX_PATH = 5
+ .even
+str5: .db str5_end - str5
+ .db DSCR_STRING
+ .db 'R, 0
+ .db 'e, 0
+ .db 'c, 0
+ .db 'e, 0
+ .db 'i, 0
+ .db 'v, 0
+ .db 'e, 0
+ .db ' , 0
+ .db 'P, 0
+ .db 'a, 0
+ .db 't, 0
+ .db 'h, 0
+str5_end:
+
+ SI_SERIAL = 6
+ .even
+str6: .db str6_end - str6
+ .db DSCR_STRING
+_usb_desc_serial_number_ascii::
+ .db '3, 0
+ .db '., 0
+ .db '1, 0
+ .db '4, 0
+ .db '1, 0
+ .db '5, 0
+ .db '9, 0
+ .db '3, 0
+str6_end:
+
diff --git a/firmware/fx2/src/usrp1/usrp_common.c b/firmware/fx2/src/usrp1/usrp_common.c
new file mode 100644
index 000000000..f389d9253
--- /dev/null
+++ b/firmware/fx2/src/usrp1/usrp_common.c
@@ -0,0 +1 @@
+#include "../common/usrp_common.c"
diff --git a/firmware/fx2/src/usrp1/usrp_common.h b/firmware/fx2/src/usrp1/usrp_common.h
new file mode 100644
index 000000000..738ba6b37
--- /dev/null
+++ b/firmware/fx2/src/usrp1/usrp_common.h
@@ -0,0 +1,77 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003,2006 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * common defines and prototypes for USRP
+ *
+ * In comments below "TRM" refers to the EZ-USB FX2 Technical Reference Manual
+ */
+
+#ifndef _USRPCOMMON_H_
+#define _USRPCOMMON_H_
+
+#include <usrp_config.h>
+#include <usrp_rev2_regs.h>
+#include <syncdelay.h>
+
+/*
+ * From TRM page 15-105:
+ *
+ * Under certain conditions, some read and write access to the FX2
+ * registers must be separated by a "synchronization delay". The
+ * delay is necessary only under the following conditions:
+ *
+ * - between a write to any register in the 0xE600 - 0xE6FF range
+ * and a write to one of the registers listed below.
+ *
+ * - between a write to one of the registers listed below and a read
+ * from any register in the 0xE600 - 0xE6FF range.
+ *
+ * Registers which require a synchronization delay:
+ *
+ * FIFORESET FIFOPINPOLAR
+ * INPKTEND EPxBCH:L
+ * EPxFIFOPFH:L EPxAUTOINLENH:L
+ * EPxFIFOCFG EPxGPIFFLGSEL
+ * PINFLAGSAB PINFLAGSCD
+ * EPxFIFOIE EPxFIFOIRQ
+ * GPIFIE GPIFIRQ
+ * UDMACRCH:L GPIFADRH:L
+ * GPIFTRIG EPxGPIFTRIG
+ * OUTPKTEND REVCTL
+ * GPIFTCB3 GPIFTCB2
+ * GPIFTCB1 GPIFTCB0
+ */
+
+#define TRUE 1
+#define FALSE 0
+
+
+void init_usrp (void);
+void init_gpif (void);
+
+void set_led_0 (unsigned char on);
+void set_led_1 (unsigned char on);
+void toggle_led_0 (void);
+void toggle_led_1 (void);
+
+#define la_trace(v)
+
+#endif /* _USRPCOMMON_H_ */
diff --git a/firmware/fx2/src/usrp1/usrp_main.c b/firmware/fx2/src/usrp1/usrp_main.c
new file mode 100644
index 000000000..b8c2e98ec
--- /dev/null
+++ b/firmware/fx2/src/usrp1/usrp_main.c
@@ -0,0 +1,388 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003,2004 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+#include "usrp_common.h"
+#include "usrp_commands.h"
+#include "fpga.h"
+#include "usrp_gpif_inline.h"
+#include "timer.h"
+#include "i2c.h"
+#include "isr.h"
+#include "usb_common.h"
+#include "fx2utils.h"
+#include "usrp_globals.h"
+#include "usrp_i2c_addr.h"
+#include <string.h>
+#include "spi.h"
+#include "eeprom_io.h"
+#include "usb_descriptors.h"
+
+/*
+ * offsets into boot eeprom for configuration values
+ */
+#define HW_REV_OFFSET 5
+#define SERIAL_NO_OFFSET 248
+#define SERIAL_NO_LEN 8
+
+
+#define bRequestType SETUPDAT[0]
+#define bRequest SETUPDAT[1]
+#define wValueL SETUPDAT[2]
+#define wValueH SETUPDAT[3]
+#define wIndexL SETUPDAT[4]
+#define wIndexH SETUPDAT[5]
+#define wLengthL SETUPDAT[6]
+#define wLengthH SETUPDAT[7]
+
+
+unsigned char g_tx_enable = 0;
+unsigned char g_rx_enable = 0;
+unsigned char g_rx_overrun = 0;
+unsigned char g_tx_underrun = 0;
+
+/*
+ * the host side fpga loader code pushes an MD5 hash of the bitstream
+ * into hash1.
+ */
+#define USRP_HASH_SIZE 16
+xdata at USRP_HASH_SLOT_1_ADDR unsigned char hash1[USRP_HASH_SIZE];
+
+static void
+get_ep0_data (void)
+{
+ EP0BCL = 0; // arm EP0 for OUT xfer. This sets the busy bit
+
+ while (EP0CS & bmEPBUSY) // wait for busy to clear
+ ;
+}
+
+/*
+ * Handle our "Vendor Extension" commands on endpoint 0.
+ * If we handle this one, return non-zero.
+ */
+unsigned char
+app_vendor_cmd (void)
+{
+ if (bRequestType == VRT_VENDOR_IN){
+
+ /////////////////////////////////
+ // handle the IN requests
+ /////////////////////////////////
+
+ switch (bRequest){
+
+ case VRQ_GET_STATUS:
+ switch (wIndexL){
+
+ case GS_TX_UNDERRUN:
+ EP0BUF[0] = g_tx_underrun;
+ g_tx_underrun = 0;
+ EP0BCH = 0;
+ EP0BCL = 1;
+ break;
+
+ case GS_RX_OVERRUN:
+ EP0BUF[0] = g_rx_overrun;
+ g_rx_overrun = 0;
+ EP0BCH = 0;
+ EP0BCL = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ break;
+
+ case VRQ_I2C_READ:
+ if (!i2c_read (wValueL, EP0BUF, wLengthL))
+ return 0;
+
+ EP0BCH = 0;
+ EP0BCL = wLengthL;
+ break;
+
+ case VRQ_SPI_READ:
+ if (!spi_read (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, wLengthL))
+ return 0;
+
+ EP0BCH = 0;
+ EP0BCL = wLengthL;
+ break;
+
+ case VRQ_SPI_TRANSACT:
+ if (!spi_transact (wValueH, wValueL, wIndexH, wIndexL, wLengthH, EP0BUF, wLengthL))
+ return 0;
+
+ EP0BCH = 0;
+ EP0BCL = wLengthL;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+
+ else if (bRequestType == VRT_VENDOR_OUT){
+
+ /////////////////////////////////
+ // handle the OUT requests
+ /////////////////////////////////
+
+ switch (bRequest){
+
+ case VRQ_SET_LED:
+ switch (wIndexL){
+ case 0:
+ set_led_0 (wValueL);
+ break;
+
+ case 1:
+ set_led_1 (wValueL);
+ break;
+
+ default:
+ return 0;
+ }
+ break;
+
+ case VRQ_FPGA_LOAD:
+ switch (wIndexL){ // sub-command
+ case FL_BEGIN:
+ return fpga_load_begin ();
+
+ case FL_XFER:
+ get_ep0_data ();
+ return fpga_load_xfer (EP0BUF, EP0BCL);
+
+ case FL_END:
+ return fpga_load_end ();
+
+ default:
+ return 0;
+ }
+ break;
+
+
+ case VRQ_FPGA_SET_RESET:
+ fpga_set_reset (wValueL);
+ break;
+
+ case VRQ_FPGA_SET_TX_ENABLE:
+ fpga_set_tx_enable (wValueL);
+ break;
+
+ case VRQ_FPGA_SET_RX_ENABLE:
+ fpga_set_rx_enable (wValueL);
+ break;
+
+ case VRQ_FPGA_SET_TX_RESET:
+ fpga_set_tx_reset (wValueL);
+ break;
+
+ case VRQ_FPGA_SET_RX_RESET:
+ fpga_set_rx_reset (wValueL);
+ break;
+
+ case VRQ_I2C_WRITE:
+ get_ep0_data ();
+ if (!i2c_write (wValueL, EP0BUF, EP0BCL))
+ return 0;
+ break;
+
+ case VRQ_SPI_WRITE:
+ get_ep0_data ();
+ if (!spi_write (wValueH, wValueL, wIndexH, wIndexL, EP0BUF, EP0BCL))
+ return 0;
+ break;
+
+ default:
+ return 0;
+ }
+
+ }
+ else
+ return 0; // invalid bRequestType
+
+ return 1;
+}
+
+
+
+static void
+main_loop (void)
+{
+ setup_flowstate_common ();
+
+ while (1){
+
+ if (usb_setup_packet_avail ())
+ usb_handle_setup_packet ();
+
+
+ if (GPIFTRIG & bmGPIF_IDLE){
+
+ // OK, GPIF is idle. Let's try to give it some work.
+
+ // First check for underruns and overruns
+
+ if (UC_BOARD_HAS_FPGA && (USRP_PA & (bmPA_TX_UNDERRUN | bmPA_RX_OVERRUN))){
+
+ // record the under/over run
+ if (USRP_PA & bmPA_TX_UNDERRUN)
+ g_tx_underrun = 1;
+
+ if (USRP_PA & bmPA_RX_OVERRUN)
+ g_rx_overrun = 1;
+
+ // tell the FPGA to clear the flags
+ fpga_clear_flags ();
+ }
+
+ // Next see if there are any "OUT" packets waiting for our attention,
+ // and if so, if there's room in the FPGA's FIFO for them.
+
+ if (g_tx_enable && !(EP24FIFOFLGS & 0x02)){ // USB end point fifo is not empty...
+
+ if (fpga_has_room_for_packet ()){ // ... and FPGA has room for packet
+
+ GPIFTCB1 = 0x01; SYNCDELAY;
+ GPIFTCB0 = 0x00; SYNCDELAY;
+
+ setup_flowstate_write ();
+
+ SYNCDELAY;
+ GPIFTRIG = bmGPIF_EP2_START | bmGPIF_WRITE; // start the xfer
+ SYNCDELAY;
+
+ while (!(GPIFTRIG & bmGPIF_IDLE)){
+ // wait for the transaction to complete
+ }
+ }
+ }
+
+ // See if there are any requests for "IN" packets, and if so
+ // whether the FPGA's got any packets for us.
+
+ if (g_rx_enable && !(EP6CS & bmEPFULL)){ // USB end point fifo is not full...
+
+ if (fpga_has_packet_avail ()){ // ... and FPGA has packet available
+
+ GPIFTCB1 = 0x01; SYNCDELAY;
+ GPIFTCB0 = 0x00; SYNCDELAY;
+
+ setup_flowstate_read ();
+
+ SYNCDELAY;
+ GPIFTRIG = bmGPIF_EP6_START | bmGPIF_READ; // start the xfer
+ SYNCDELAY;
+
+ while (!(GPIFTRIG & bmGPIF_IDLE)){
+ // wait for the transaction to complete
+ }
+
+ SYNCDELAY;
+ INPKTEND = 6; // tell USB we filled buffer (6 is our endpoint num)
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * called at 100 Hz from timer2 interrupt
+ *
+ * Toggle led 0
+ */
+void
+isr_tick (void) interrupt
+{
+ static unsigned char count = 1;
+
+ if (--count == 0){
+ count = 50;
+ USRP_LED_REG ^= bmLED0;
+ }
+
+ clear_timer_irq ();
+}
+
+/*
+ * Read h/w rev code and serial number out of boot eeprom and
+ * patch the usb descriptors with the values.
+ */
+void
+patch_usb_descriptors(void)
+{
+ static xdata unsigned char hw_rev;
+ static xdata unsigned char serial_no[8];
+ unsigned char i;
+
+ eeprom_read(I2C_ADDR_BOOT, HW_REV_OFFSET, &hw_rev, 1); // LSB of device id
+ usb_desc_hw_rev_binary_patch_location_0[0] = hw_rev;
+ usb_desc_hw_rev_binary_patch_location_1[0] = hw_rev;
+ usb_desc_hw_rev_ascii_patch_location_0[0] = hw_rev + '0'; // FIXME if we get > 9
+
+ eeprom_read(I2C_ADDR_BOOT, SERIAL_NO_OFFSET, serial_no, SERIAL_NO_LEN);
+
+ for (i = 0; i < SERIAL_NO_LEN; i++){
+ unsigned char ch = serial_no[i];
+ if (ch == 0xff) // make unprogrammed EEPROM default to '0'
+ ch = '0';
+ usb_desc_serial_number_ascii[i << 1] = ch;
+ }
+}
+
+void
+main (void)
+{
+#if 0
+ g_rx_enable = 0; // FIXME (work around initialization bug)
+ g_tx_enable = 0;
+ g_rx_overrun = 0;
+ g_tx_underrun = 0;
+#endif
+
+ memset (hash1, 0, USRP_HASH_SIZE); // zero fpga bitstream hash. This forces reload
+
+ init_usrp ();
+ init_gpif ();
+
+ // if (UC_START_WITH_GSTATE_OUTPUT_ENABLED)
+ IFCONFIG |= bmGSTATE; // no conflict, start with it on
+
+ set_led_0 (0);
+ set_led_1 (0);
+
+ EA = 0; // disable all interrupts
+
+ patch_usb_descriptors();
+
+ setup_autovectors ();
+ usb_install_handlers ();
+ hook_timer_tick ((unsigned short) isr_tick);
+
+ EIEX4 = 1; // disable INT4 FIXME
+ EA = 1; // global interrupt enable
+
+ fx2_renumerate (); // simulates disconnect / reconnect
+
+ main_loop ();
+}
diff --git a/firmware/fx2/src/usrp1/usrp_rev2_regs.h b/firmware/fx2/src/usrp1/usrp_rev2_regs.h
new file mode 100644
index 000000000..a4f1d9896
--- /dev/null
+++ b/firmware/fx2/src/usrp1/usrp_rev2_regs.h
@@ -0,0 +1,163 @@
+/*
+ * USRP - Universal Software Radio Peripheral
+ *
+ * Copyright (C) 2003 Free Software Foundation, Inc.
+ *
+ * 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 3 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 Street, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * These are the register definitions for the Rev 1 USRP prototype
+ * The Rev 1 is the version with the AD9862's and daughterboards
+ */
+
+#ifndef _USRP_REV1_REGS_H_
+#define _USRP_REV1_REGS_H_
+
+#include "fx2regs.h"
+
+/*
+ * Port A (bit addressable):
+ */
+
+#define USRP_PA IOA // Port A
+#define USRP_PA_OE OEA // Port A direction register
+
+#define bmPA_S_CLK bmBIT0 // SPI serial clock
+#define bmPA_S_DATA_TO_PERIPH bmBIT1 // SPI SDI (peripheral rel name)
+#define bmPA_S_DATA_FROM_PERIPH bmBIT2 // SPI SDO (peripheral rel name)
+#define bmPA_SEN_FPGA bmBIT3 // serial enable for FPGA (active low)
+#define bmPA_SEN_CODEC_A bmBIT4 // serial enable AD9862 A (active low)
+#define bmPA_SEN_CODEC_B bmBIT5 // serial enable AD9862 B (active low)
+//#define bmPA_FX2_2 bmBIT6 // misc pin to FPGA (overflow)
+//#define bmPA_FX2_3 bmBIT7 // misc pin to FPGA (underflow)
+#define bmPA_RX_OVERRUN bmBIT6 // misc pin to FPGA (overflow)
+#define bmPA_TX_UNDERRUN bmBIT7 // misc pin to FPGA (underflow)
+
+
+sbit at 0x80+0 bitS_CLK; // 0x80 is the bit address of PORT A
+sbit at 0x80+1 bitS_OUT; // out from FX2 point of view
+sbit at 0x80+2 bitS_IN; // in from FX2 point of view
+
+
+/* all outputs except S_DATA_FROM_PERIPH, FX2_2, FX2_3 */
+
+#define bmPORT_A_OUTPUTS (bmPA_S_CLK \
+ | bmPA_S_DATA_TO_PERIPH \
+ | bmPA_SEN_FPGA \
+ | bmPA_SEN_CODEC_A \
+ | bmPA_SEN_CODEC_B \
+ )
+
+#define bmPORT_A_INITIAL (bmPA_SEN_FPGA | bmPA_SEN_CODEC_A | bmPA_SEN_CODEC_B)
+
+
+/* Port B: GPIF FD[7:0] */
+
+/*
+ * Port C (bit addressable):
+ * 5:1 FPGA configuration
+ */
+
+#define USRP_PC IOC // Port C
+#define USRP_PC_OE OEC // Port C direction register
+
+#define USRP_ALTERA_CONFIG USRP_PC
+
+#define bmPC_nRESET bmBIT0 // reset line to codecs (active low)
+#define bmALTERA_DATA0 bmBIT1
+#define bmALTERA_NCONFIG bmBIT2
+#define bmALTERA_DCLK bmBIT3
+#define bmALTERA_CONF_DONE bmBIT4
+#define bmALTERA_NSTATUS bmBIT5
+#define bmPC_LED0 bmBIT6 // active low
+#define bmPC_LED1 bmBIT7 // active low
+
+sbit at 0xA0+1 bitALTERA_DATA0; // 0xA0 is the bit address of PORT C
+sbit at 0xA0+3 bitALTERA_DCLK;
+
+
+#define bmALTERA_BITS (bmALTERA_DATA0 \
+ | bmALTERA_NCONFIG \
+ | bmALTERA_DCLK \
+ | bmALTERA_CONF_DONE \
+ | bmALTERA_NSTATUS)
+
+#define bmPORT_C_OUTPUTS (bmPC_nRESET \
+ | bmALTERA_DATA0 \
+ | bmALTERA_NCONFIG \
+ | bmALTERA_DCLK \
+ | bmPC_LED0 \
+ | bmPC_LED1 \
+ )
+
+#define bmPORT_C_INITIAL (bmPC_LED0 | bmPC_LED1)
+
+
+#define USRP_LED_REG USRP_PC
+#define bmLED0 bmPC_LED0
+#define bmLED1 bmPC_LED1
+
+
+/* Port D: GPIF FD[15:8] */
+
+/* Port E: not bit addressible */
+
+#define USRP_PE IOE // Port E
+#define USRP_PE_OE OEE // Port E direction register
+
+#define bmPE_PE0 bmBIT0 // GPIF debug output
+#define bmPE_PE1 bmBIT1 // GPIF debug output
+#define bmPE_PE2 bmBIT2 // GPIF debug output
+#define bmPE_FPGA_CLR_STATUS bmBIT3 // misc pin to FPGA (clear status)
+#define bmPE_SEN_TX_A bmBIT4 // serial enable d'board TX A (active low)
+#define bmPE_SEN_RX_A bmBIT5 // serial enable d'board RX A (active low)
+#define bmPE_SEN_TX_B bmBIT6 // serial enable d'board TX B (active low)
+#define bmPE_SEN_RX_B bmBIT7 // serial enable d'board RX B (active low)
+
+
+#define bmPORT_E_OUTPUTS (bmPE_FPGA_CLR_STATUS \
+ | bmPE_SEN_TX_A \
+ | bmPE_SEN_RX_A \
+ | bmPE_SEN_TX_B \
+ | bmPE_SEN_RX_B \
+ )
+
+
+#define bmPORT_E_INITIAL (bmPE_SEN_TX_A \
+ | bmPE_SEN_RX_A \
+ | bmPE_SEN_TX_B \
+ | bmPE_SEN_RX_B \
+ )
+
+/*
+ * FPGA output lines that are tied to FX2 RDYx inputs.
+ * These are readable using GPIFREADYSTAT.
+ */
+#define bmFPGA_HAS_SPACE bmBIT0 // usbrdy[0] has room for 512 byte packet
+#define bmFPGA_PKT_AVAIL bmBIT1 // usbrdy[1] has >= 512 bytes available
+// #define bmTX_UNDERRUN bmBIT2 // usbrdy[2] D/A ran out of data
+// #define bmRX_OVERRUN bmBIT3 // usbrdy[3] A/D ran out of buffer
+
+/*
+ * FPGA input lines that are tied to the FX2 CTLx outputs.
+ *
+ * These are controlled by the GPIF microprogram...
+ */
+// WR bmBIT0 // usbctl[0]
+// RD bmBIT1 // usbctl[1]
+// OE bmBIT2 // usbctl[2]
+
+#endif /* _USRP_REV1_REGS_H_ */
diff --git a/firmware/fx2/src/usrp1/vectors.a51 b/firmware/fx2/src/usrp1/vectors.a51
new file mode 100644
index 000000000..fa579ba8a
--- /dev/null
+++ b/firmware/fx2/src/usrp1/vectors.a51
@@ -0,0 +1 @@
+ .include "../common/vectors.a51"
diff --git a/fpga/usrp2/sdr_lib/dsp_core_rx.v b/fpga/usrp2/sdr_lib/dsp_core_rx.v
index 1e689fc7f..1318809d6 100644
--- a/fpga/usrp2/sdr_lib/dsp_core_rx.v
+++ b/fpga/usrp2/sdr_lib/dsp_core_rx.v
@@ -57,41 +57,32 @@ module dsp_core_rx
(.clk(clk),.rst(rst),.set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
.adc_in(adc_b),.adc_out(adc_b_ofs));
- wire [3:0] muxctrl;
- setting_reg #(.my_addr(BASE+5)) sr_8
+ wire [7:0] muxctrl;
+ setting_reg #(.my_addr(BASE+5), .width(8)) sr_8
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({UNUSED_2,muxctrl}),.changed());
wire [1:0] gpio_ena;
- setting_reg #(.my_addr(BASE+6)) sr_9
+ setting_reg #(.my_addr(BASE+6), .width(2)) sr_9
(.clk(clk),.rst(rst),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({UNUSED_3,gpio_ena}),.changed());
- // The TVRX connects to what is called adc_b, thus A and B are
- // swapped throughout the design.
- //
- // In the interest of expediency and keeping the s/w sane, we just remap them here.
- // The I & Q fields are mapped the same:
- // 0 -> "the real A" (as determined by the TVRX)
- // 1 -> "the real B"
- // 2 -> const zero
-
always @(posedge clk)
- case(muxctrl[1:0]) // The I mapping
- 0: adc_i <= adc_b_ofs; // "the real A"
- 1: adc_i <= adc_a_ofs;
+ case(muxctrl[3:0]) // The I mapping
+ 0: adc_i <= adc_a_ofs;
+ 1: adc_i <= adc_b_ofs;
2: adc_i <= 0;
default: adc_i <= 0;
- endcase // case(muxctrl[1:0])
-
+ endcase // case (muxctrl[3:0])
+
always @(posedge clk)
- case(muxctrl[3:2]) // The Q mapping
- 0: adc_q <= adc_b_ofs; // "the real A"
- 1: adc_q <= adc_a_ofs;
+ case(muxctrl[7:4]) // The Q mapping
+ 0: adc_q <= adc_a_ofs;
+ 1: adc_q <= adc_b_ofs;
2: adc_q <= 0;
default: adc_q <= 0;
- endcase // case(muxctrl[3:2])
-
+ endcase // case (muxctrl[7:4])
+
always @(posedge clk)
if(rst)
phase <= 0;
diff --git a/fpga/usrp2/top/u2_rev3/u2_core_udp.v b/fpga/usrp2/top/u2_rev3/u2_core_udp.v
index 124930c23..c9502898b 100644
--- a/fpga/usrp2/top/u2_rev3/u2_core_udp.v
+++ b/fpga/usrp2/top/u2_rev3/u2_core_udp.v
@@ -425,7 +425,7 @@ module u2_core
cycle_count <= cycle_count + 1;
//compatibility number -> increment when the fpga has been sufficiently altered
- localparam compat_num = 32'd1;
+ localparam compat_num = 32'd2;
wb_readback_mux buff_pool_status
(.wb_clk_i(wb_clk), .wb_rst_i(wb_rst), .wb_stb_i(s5_stb),
diff --git a/fpga/usrp2/top/u2_rev3/u2_rev3.v b/fpga/usrp2/top/u2_rev3/u2_rev3.v
index 3a43e4ffe..4daa66212 100644
--- a/fpga/usrp2/top/u2_rev3/u2_rev3.v
+++ b/fpga/usrp2/top/u2_rev3/u2_rev3.v
@@ -203,12 +203,13 @@ module u2_rev3
reg [13:0] adc_a_reg1, adc_b_reg1, adc_a_reg2, adc_b_reg2;
reg adc_ovf_a_reg1, adc_ovf_a_reg2, adc_ovf_b_reg1, adc_ovf_b_reg2;
+ // ADC A and B are swapped in schematic to facilitate clean layout
always @(posedge dsp_clk)
begin
- adc_a_reg1 <= adc_a;
- adc_b_reg1 <= adc_b;
- adc_ovf_a_reg1 <= adc_ovf_a;
- adc_ovf_b_reg1 <= adc_ovf_b;
+ adc_a_reg1 <= adc_b;
+ adc_b_reg1 <= adc_a;
+ adc_ovf_a_reg1 <= adc_ovf_b;
+ adc_ovf_b_reg1 <= adc_ovf_a;
end
always @(posedge dsp_clk)
@@ -327,8 +328,10 @@ module u2_rev3
end
wire [15:0] dac_a_int, dac_b_int;
- always @(negedge dsp_clk) dac_a <= dac_a_int;
- always @(negedge dsp_clk) dac_b <= dac_b_int;
+ // DAC A and B are swapped in schematic to facilitate clean layout
+ // DAC A is also inverted in schematic to facilitate clean layout
+ always @(negedge dsp_clk) dac_a <= ~dac_b_int;
+ always @(negedge dsp_clk) dac_b <= dac_a_int;
/*
OFDDRRSE OFDDRRSE_serdes_inst
diff --git a/host/AUTHORS b/host/AUTHORS
index 137eba0e6..e0775f3a1 100644
--- a/host/AUTHORS
+++ b/host/AUTHORS
@@ -1,5 +1,6 @@
Matt Ettus - matt@ettus.com
- USRP1/USRP2 FPGA code
+ USRP1 FPGA code
+ USRP2 FPGA code
Josh Blum - josh@ettus.com
driver framework
@@ -14,4 +15,15 @@ Jason Abele - jason@ettus.com
WBX host code
Eric Blossom - eb@comsec.com
+ USRP1 firmware
USRP2 firmware
+
+Tom Tsou - ttsou@vt.edu
+ UHD-USB framework
+ LIBUSB host code
+ USRP1 host code
+ USRP1 firmware
+
+Nick Foster - nick@nerdnetworks.org
+ LIBUSB host code
+ USRP1 host code
diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt
index b4383f88d..bbb8812b0 100644
--- a/host/docs/CMakeLists.txt
+++ b/host/docs/CMakeLists.txt
@@ -25,6 +25,7 @@ SET(manual_sources
dboards.rst
general.rst
images.rst
+ usrp1.rst
usrp2.rst
)
diff --git a/host/docs/build.rst b/host/docs/build.rst
index 8f0d0db59..d7dfd05e5 100644
--- a/host/docs/build.rst
+++ b/host/docs/build.rst
@@ -53,6 +53,14 @@ Boost
* **Download URL (windows installer):** http://www.boostpro.com/download
^^^^^^^^^^^^^^^^
+LibUSB
+^^^^^^^^^^^^^^^^
+* **Purpose:** USB userspace library
+* **Version:** at least 1.0
+* **Required for:** build time + run time (optional)
+* **Download URL:** http://www.libusb.org/
+
+^^^^^^^^^^^^^^^^
Python
^^^^^^^^^^^^^^^^
* **Purpose:** used by Cheetah and utility scripts
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst
index b66fd2069..985fbc12b 100644
--- a/host/docs/dboards.rst
+++ b/host/docs/dboards.rst
@@ -28,7 +28,11 @@ greater than the Nyquist rate of the ADC.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Basic TX and and LFTX
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The Basic TX and LFTX boards have 1 quadrature subdevice using both antennas.
+The Basic TX and LFTX boards have 3 subdevices:
+
+* **Subdevice A:** real signal on antenna TXA
+* **Subdevice B:** real signal on antenna TXB
+* **Subdevice AB:** quadrature subdevice using both antennas
The boards have no tunable elements or programmable gains.
Though the magic of aliasing, you can up-convert signals
@@ -137,7 +141,7 @@ With the daughterboard plugged-in, run the following commands:
::
cd <prefix>/share/uhd/utils
- ./usrp_burn_db_eeprom --id=0x000d --unit=RX --args=<args> --db=<db>
+ ./usrp_burn_db_eeprom --id=0x000d --unit=RX --args=<args> --slot=<slot>
* <args> are device address arguments (optional if only one USRP is on your machine)
-* <db> is the name of the daughterboard slot (optional if the USRP has only one slot)
+* <slot> is the name of the daughterboard slot (optional if the USRP has only one slot)
diff --git a/host/docs/index.rst b/host/docs/index.rst
index 6973ede19..bd55edc0b 100644
--- a/host/docs/index.rst
+++ b/host/docs/index.rst
@@ -22,6 +22,7 @@ Application Notes
^^^^^^^^^^^^^^^^^^^^^
* `General App Notes <./general.html>`_
* `Firmware and FPGA Image Notes <./images.html>`_
+* `USRP1 App Notes <./usrp1.html>`_
* `USRP2 App Notes <./usrp2.html>`_
* `Daughterboard App Notes <./dboards.html>`_
diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst
new file mode 100644
index 000000000..3c1431d30
--- /dev/null
+++ b/host/docs/usrp1.rst
@@ -0,0 +1,115 @@
+========================================================================
+UHD - USRP1 Application Notes
+========================================================================
+
+.. contents:: Table of Contents
+
+------------------------------------------------------------------------
+Addressing the device
+------------------------------------------------------------------------
+A USRP1 can be identified though its 8 digit serial number,
+designated by the "serial" key in the device address.
+
+The device address string representation for a USRP1 with serial 12345678:
+
+::
+
+ serial=12345678
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Change the serial number
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The USRP1 serial number can be changed to any 8 byte string. Examples:
+
+::
+
+ cd <prefix>/share/uhd/utils
+ ./usrp1_serial_burner --new=87654321
+
+ -- OR --
+
+ ./usrp1_serial_burner --new=Beatrice
+
+ -- OR --
+
+ ./usrp1_serial_burner --old=12345678 --new=87654321
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Specify a non-standard image
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The standard USRP1 images installer comes with two FPGA images:
+ * **usrp1_fpga.rbf:** 2 DDCs + 2 DUCs
+ * **usrp1_fpga_4rx.rbf:** 4 DDCs + 0 DUCs
+
+By default, the USRP1 uses the FPGA image with 2 DDCs and 2 DUCs.
+However, a device address parameter can be used to override
+the FPGA image selection to use an alternate or a custom FPGA image.
+See the images application notes for installing custom images.
+
+Example device address string representations to specify non-standard firmware and/or FPGA images:
+
+::
+
+ fpga=usrp1_fpga_4rx.rbf
+
+ -- OR --
+
+ fw=usrp1_fw_custom.ihx
+
+ -- OR --
+
+ fpga=usrp1_fpga_4rx.rbf, fw=usrp1_fw_custom.ihx
+
+------------------------------------------------------------------------
+Specifying the subdevice to use
+------------------------------------------------------------------------
+The USRP1 has multiple daughterboard slots, known as slot A and slot B.
+The subdevice specification can be used to select
+the daughterboard and subdevice for each channel.
+For daughterboards with one one subdevice,
+the subdevice name may be left blank for automatic selection.
+
+Ex: The subdev spec markup string to select a WBX on slot B.
+Notice the use of the blank subdevice name for automatic selection.
+
+::
+
+ B:
+
+ -- OR --
+
+ B:0
+
+Ex: The subdev spec markup string to select a BasicRX on slot B.
+Notice that the subdevice name is always specified in the 3 possible cases.
+
+::
+
+ B:AB
+
+ -- OR --
+
+ B:A
+
+ -- OR --
+
+ B:B
+
+------------------------------------------------------------------------
+OS Specific Notes
+------------------------------------------------------------------------
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Setup Udev on Linux
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+On Linux, Udev handles USB plug and unplug events.
+The following command creates a Udev rule for the USRP1
+so that non-root users may access the device:
+
+::
+
+ echo 'ACTION=="add", BUS=="usb", SYSFS{idVendor}=="fffe", SYSFS{idProduct}=="0002", MODE:="0666"' > tmpfile
+ sudo chown root.root tmpfile
+ sudo mv tmpfile /etc/udev/rules.d/10-usrp.rules
+ sudo udevadm control --reload-rules
+
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index 3ac326f58..745361b77 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -205,3 +205,27 @@ Example, set the args string to the following:
::
addr=192.168.10.2, recv_buff_size=100e6
+
+------------------------------------------------------------------------
+Hardware setup notes
+------------------------------------------------------------------------
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Ref Clock - 10MHz
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Using an external 10MHz reference clock requires a signal level between
++5dBm and +20dBm at 10MHz applied to the Ref Clock SMA port on the front panel.
+
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+PPS - Pulse Per Second
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Using a PPS signal for timestamp synchronization requires a 5Vpp square wave signal
+
+Test the PPS input of the USRP2 with the following app:
+::
+
+ cd <prefix>/share/uhd/examples
+ ./test_pps_input --args=<args>
+
+* <args> are device address arguments (optional if only one USRP is on your machine)
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index c3bbbcd04..d19838335 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -15,13 +15,19 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-
+########################################################################
ADD_EXECUTABLE(benchmark_rx_rate benchmark_rx_rate.cpp)
TARGET_LINK_LIBRARIES(benchmark_rx_rate uhd)
ADD_EXECUTABLE(rx_timed_samples rx_timed_samples.cpp)
TARGET_LINK_LIBRARIES(rx_timed_samples uhd)
+ADD_EXECUTABLE(test_async_messages test_async_messages.cpp)
+TARGET_LINK_LIBRARIES(test_async_messages uhd)
+
+ADD_EXECUTABLE(test_pps_input test_pps_input.cpp)
+TARGET_LINK_LIBRARIES(test_pps_input uhd)
+
ADD_EXECUTABLE(tx_timed_samples tx_timed_samples.cpp)
TARGET_LINK_LIBRARIES(tx_timed_samples uhd)
@@ -31,6 +37,8 @@ TARGET_LINK_LIBRARIES(tx_waveforms uhd)
INSTALL(TARGETS
benchmark_rx_rate
rx_timed_samples
+ test_async_messages
+ test_pps_input
tx_timed_samples
tx_waveforms
RUNTIME DESTINATION ${PKG_DATA_DIR}/examples
diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp
new file mode 100644
index 000000000..e02bc5f40
--- /dev/null
+++ b/host/examples/test_async_messages.cpp
@@ -0,0 +1,208 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/usrp/simple_usrp.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <complex>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+static const size_t async_to_ms = 100;
+
+/*!
+ * Test that no messages are received:
+ * Send a burst of many samples that will fragment internally.
+ * We expect to not get any async messages.
+ */
+void test_no_async_message(uhd::usrp::simple_usrp::sptr sdev){
+ uhd::device::sptr dev = sdev->get_device();
+ std::cout << "Test no async message... " << std::flush;
+
+ uhd::tx_metadata_t md;
+ md.start_of_burst = true;
+ md.end_of_burst = true;
+ md.has_time_spec = false;
+
+ //3 times max-sps guarantees a SOB, no burst, and EOB packet
+ std::vector<std::complex<float> > buff(dev->get_max_send_samps_per_packet()*3);
+
+ dev->send(
+ &buff.front(), buff.size(), md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::SEND_MODE_FULL_BUFF
+ );
+
+ uhd::async_metadata_t async_md;
+ if (dev->recv_async_msg(async_md, async_to_ms)){
+ std::cout << boost::format(
+ "failed:\n"
+ " Got unexpected event code 0x%x.\n"
+ ) % async_md.event_code << std::endl;
+ //clear the async messages
+ while (dev->recv_async_msg(async_md, 0));
+ }
+ else{
+ std::cout << boost::format(
+ "success:\n"
+ " Did not get an async message.\n"
+ ) << std::endl;
+ }
+}
+
+/*!
+ * Test the underflow message:
+ * Send a start of burst packet with no following end of burst.
+ * We expect to get an underflow(within a burst) async message.
+ */
+void test_underflow_message(uhd::usrp::simple_usrp::sptr sdev){
+ uhd::device::sptr dev = sdev->get_device();
+ std::cout << "Test underflow message... " << std::flush;
+
+ uhd::tx_metadata_t md;
+ md.start_of_burst = true;
+ md.end_of_burst = false;
+ md.has_time_spec = false;
+
+ dev->send(NULL, 0, md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::SEND_MODE_FULL_BUFF
+ );
+
+ uhd::async_metadata_t async_md;
+ if (not dev->recv_async_msg(async_md, async_to_ms)){
+ std::cout << boost::format(
+ "failed:\n"
+ " Async message recv timed out.\n"
+ ) << std::endl;
+ return;
+ }
+
+ switch(async_md.event_code){
+ case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
+ std::cout << boost::format(
+ "success:\n"
+ " Got event code underflow message.\n"
+ ) << std::endl;
+ break;
+
+ default:
+ std::cout << boost::format(
+ "failed:\n"
+ " Got unexpected event code 0x%x.\n"
+ ) % async_md.event_code << std::endl;
+ }
+}
+
+/*!
+ * Test the time error message:
+ * Send a burst packet that occurs at a time in the past.
+ * We expect to get a time error async message.
+ */
+void test_time_error_message(uhd::usrp::simple_usrp::sptr sdev){
+ uhd::device::sptr dev = sdev->get_device();
+ std::cout << "Test time error message... " << std::flush;
+
+ uhd::tx_metadata_t md;
+ md.start_of_burst = true;
+ md.end_of_burst = true;
+ md.has_time_spec = true;
+ md.time_spec = uhd::time_spec_t(100.0); //send at 100s
+
+ sdev->set_time_now(uhd::time_spec_t(200.0)); //time at 200s
+
+ dev->send(NULL, 0, md,
+ uhd::io_type_t::COMPLEX_FLOAT32,
+ uhd::device::SEND_MODE_FULL_BUFF
+ );
+
+ uhd::async_metadata_t async_md;
+ if (not dev->recv_async_msg(async_md, async_to_ms)){
+ std::cout << boost::format(
+ "failed:\n"
+ " Async message recv timed out.\n"
+ ) << std::endl;
+ return;
+ }
+
+ switch(async_md.event_code){
+ case uhd::async_metadata_t::EVENT_CODE_TIME_ERROR:
+ std::cout << boost::format(
+ "success:\n"
+ " Got event code time error message.\n"
+ ) << std::endl;
+ break;
+
+ default:
+ std::cout << boost::format(
+ "failed:\n"
+ " Got unexpected event code 0x%x.\n"
+ ) % async_md.event_code << std::endl;
+ }
+}
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ uhd::set_thread_priority_safe();
+
+ //variables to be set by po
+ std::string args;
+ double rate;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args")
+ ("rate", po::value<double>(&rate)->default_value(1.5e6), "rate of outgoing samples")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("UHD Test Async Messages %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //create a usrp device
+ std::cout << std::endl;
+ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
+ uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args);
+ std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl;
+
+ //set the tx sample rate
+ std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl;
+ sdev->set_tx_rate(rate);
+ std::cout << boost::format("Actual TX Rate: %f Msps...") % (sdev->get_tx_rate()/1e6) << std::endl << std::endl;
+
+ //------------------------------------------------------------------
+ // begin asyc messages test
+ //------------------------------------------------------------------
+ test_no_async_message(sdev);
+ test_underflow_message(sdev);
+ test_time_error_message(sdev);
+
+ //finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return 0;
+}
diff --git a/host/examples/test_pps_input.cpp b/host/examples/test_pps_input.cpp
new file mode 100644
index 000000000..e01d32910
--- /dev/null
+++ b/host/examples/test_pps_input.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/simple_usrp.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <boost/thread.hpp>
+#include <iostream>
+#include <complex>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ uhd::set_thread_priority_safe();
+
+ //variables to be set by po
+ std::string args;
+ float seconds;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args")
+ ;
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("UHD Test PPS Input %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //create a usrp device
+ std::cout << std::endl;
+ std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
+ uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args);
+ uhd::device::sptr dev = sdev->get_device();
+ std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl;
+
+ //set a known time value
+ std::cout << "Set time to known value (100.0) without regard to pps:" << std::endl;
+ sdev->set_time_now(uhd::time_spec_t(100.0));
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ std::cout << boost::format("Reading time 1 second later: %f\n") % (sdev->get_time_now().get_full_secs()) << std::endl;
+
+ //store the time to see if PPS resets it
+ seconds = sdev->get_time_now().get_full_secs();
+
+ //set a known time at next PPS, check that time increments
+ uhd::time_spec_t time_spec = uhd::time_spec_t(0.0);
+ std::cout << "Set time to known value (0.0) at next pps:" << std::endl;
+ sdev->set_time_next_pps(time_spec);
+ boost::this_thread::sleep(boost::posix_time::seconds(1));
+ std::cout << boost::format("Reading time 1 second later: %f\n") % (sdev->get_time_now().get_full_secs()) << std::endl;
+
+ //finished
+ if (seconds > sdev->get_time_now().get_full_secs()){
+ std::cout << std::endl << "Success!" << std::endl << std::endl;
+ return 0;
+ } else {
+ std::cout << std::endl << "Failed!" << std::endl << std::endl
+ << "If you expected PPS to work:" << std::endl
+ << "\tsee Device App Notes for PPS level information"
+ << std::endl << std::endl;
+ return -1;
+ }
+}
diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp
index 9886000b1..3f319cf68 100644
--- a/host/examples/tx_waveforms.cpp
+++ b/host/examples/tx_waveforms.cpp
@@ -17,6 +17,7 @@
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
+#include <uhd/utils/static.hpp>
#include <uhd/usrp/simple_usrp.hpp>
#include <boost/program_options.hpp>
#include <boost/thread/thread_time.hpp> //system time
@@ -44,9 +45,16 @@ float gen_ramp(float x){
return std::fmod(x, 1)*2 - 1;
}
+#define sine_table_len 2048
+static float sine_table[sine_table_len];
+UHD_STATIC_BLOCK(gen_sine_table){
+ static const float m_pi = std::acos(float(-1));
+ for (size_t i = 0; i < sine_table_len; i++)
+ sine_table[i] = std::sin((2*m_pi*i)/sine_table_len);
+}
+
float gen_sine(float x){
- static const float two_pi = 2*std::acos(float(-1));
- return std::sin(x*two_pi);
+ return sine_table[size_t(x*sine_table_len)%sine_table_len];
}
int UHD_SAFE_MAIN(int argc, char *argv[]){
@@ -65,11 +73,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("args", po::value<std::string>(&args)->default_value(""), "simple uhd device address args")
("duration", po::value<size_t>(&total_duration)->default_value(3), "number of seconds to transmit")
("spb", po::value<size_t>(&spb)->default_value(10000), "samples per buffer")
- ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples")
+ ("rate", po::value<double>(&rate)->default_value(1.5e6), "rate of outgoing samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of the waveform")
("gain", po::value<float>(&gain)->default_value(float(0)), "gain for the RF chain")
- ("wave-type", po::value<std::string>(&wave_type)->default_value("SINE"), "waveform type (CONST, SQUARE, RAMP, SINE)")
+ ("wave-type", po::value<std::string>(&wave_type)->default_value("CONST"), "waveform type (CONST, SQUARE, RAMP, SINE)")
("wave-freq", po::value<double>(&wave_freq)->default_value(0), "waveform frequency in Hz")
;
po::variables_map vm;
@@ -113,6 +121,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
if (std::abs(wave_freq) > sdev->get_tx_rate()/2){
throw std::runtime_error("wave freq out of Nyquist zone");
}
+ if (sdev->get_tx_rate()/std::abs(wave_freq) > sine_table_len/2 and wave_type == "SINE"){
+ throw std::runtime_error("sine freq too small for table");
+ }
//store the generator function for the selected waveform
boost::function<float(float)> wave_gen;
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt
index 93e9a6485..2c84c0724 100644
--- a/host/include/uhd/transport/CMakeLists.txt
+++ b/host/include/uhd/transport/CMakeLists.txt
@@ -22,9 +22,13 @@ INSTALL(FILES
bounded_buffer.hpp
bounded_buffer.ipp
convert_types.hpp
+ convert_types.ipp
if_addrs.hpp
udp_simple.hpp
udp_zero_copy.hpp
+ usb_control.hpp
+ usb_zero_copy.hpp
+ usb_device_handle.hpp
vrt_if_packet.hpp
zero_copy.hpp
DESTINATION ${INCLUDE_DIR}/uhd/transport
diff --git a/host/include/uhd/transport/convert_types.hpp b/host/include/uhd/transport/convert_types.hpp
index a4d999240..dc7fa6c1a 100644
--- a/host/include/uhd/transport/convert_types.hpp
+++ b/host/include/uhd/transport/convert_types.hpp
@@ -21,6 +21,7 @@
#include <uhd/config.hpp>
#include <uhd/types/io_type.hpp>
#include <uhd/types/otw_type.hpp>
+#include <vector>
namespace uhd{ namespace transport{
@@ -40,6 +41,23 @@ UHD_API void convert_io_type_to_otw_type(
);
/*!
+ * Convert IO samples to OWT samples + interleave.
+ *
+ * \param io_buffs buffers containing samples
+ * \param io_type the type of these samples
+ * \param otw_buff memory to write converted samples
+ * \param otw_type the type of these samples
+ * \param nsamps_per_io_buff samples per io_buff
+ */
+UHD_API void convert_io_type_to_otw_type(
+ const std::vector<const void *> &io_buffs,
+ const io_type_t &io_type,
+ void *otw_buff,
+ const otw_type_t &otw_type,
+ size_t nsamps_per_io_buff
+);
+
+/*!
* Convert OTW samples to IO samples.
*
* \param otw_buff memory containing samples
@@ -54,6 +72,25 @@ UHD_API void convert_otw_type_to_io_type(
size_t num_samps
);
+/*!
+ * Convert OTW samples to IO samples + de-interleave.
+ *
+ * \param otw_buff memory containing samples
+ * \param otw_type the type of these samples
+ * \param io_buffs buffers to write converted samples
+ * \param io_type the type of these samples
+ * \param nsamps_per_io_buff samples per io_buff
+ */
+UHD_API void convert_otw_type_to_io_type(
+ const void *otw_buff,
+ const otw_type_t &otw_type,
+ std::vector<void *> &io_buffs,
+ const io_type_t &io_type,
+ size_t nsamps_per_io_buff
+);
+
}} //namespace
+#include <uhd/transport/convert_types.ipp>
+
#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP */
diff --git a/host/include/uhd/transport/convert_types.ipp b/host/include/uhd/transport/convert_types.ipp
new file mode 100644
index 000000000..914ca6f17
--- /dev/null
+++ b/host/include/uhd/transport/convert_types.ipp
@@ -0,0 +1,43 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP
+#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP
+
+UHD_INLINE void uhd::transport::convert_io_type_to_otw_type(
+ const void *io_buff, const io_type_t &io_type,
+ void *otw_buff, const otw_type_t &otw_type,
+ size_t num_samps
+){
+ std::vector<const void *> buffs(1, io_buff);
+ return uhd::transport::convert_io_type_to_otw_type(
+ buffs, io_type, otw_buff, otw_type, num_samps
+ );
+}
+
+UHD_INLINE void uhd::transport::convert_otw_type_to_io_type(
+ const void *otw_buff, const otw_type_t &otw_type,
+ void *io_buff, const io_type_t &io_type,
+ size_t num_samps
+){
+ std::vector<void *> buffs(1, io_buff);
+ return uhd::transport::convert_otw_type_to_io_type(
+ otw_buff, otw_type, buffs, io_type, num_samps
+ );
+}
+
+#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP */
diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp
new file mode 100644
index 000000000..6137ecf84
--- /dev/null
+++ b/host/include/uhd/transport/usb_control.hpp
@@ -0,0 +1,65 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP
+#define INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP
+
+#include "usb_device_handle.hpp"
+
+namespace uhd { namespace transport {
+
+class UHD_API usb_control : boost::noncopyable {
+public:
+ typedef boost::shared_ptr<usb_control> sptr;
+
+ /*!
+ * Create a new usb control transport:
+ * This transport is for sending and receiving control information from
+ * the host to device using the Default Control Pipe.
+ *
+ * \param handle a device handle that uniquely identifies a USB device
+ */
+ static sptr make(usb_device_handle::sptr handle);
+
+ /*!
+ * Submit a USB device request:
+ * Blocks until the request returns
+ *
+ * For format and corresponding USB request fields
+ * see USB Specification Revision 2.0 - 9.3 USB Device Requests
+ *
+ * Usage is device specific
+ *
+ * \param request_type 1-byte bitmask (bmRequestType)
+ * \param request 1-byte (bRequest)
+ * \param value 2-byte (wValue)
+ * \param index 2-byte (wIndex)
+ * \param buff buffer to hold send or receive data
+ * \param length 2-byte (wLength)
+ * \return number of bytes submitted
+ */
+ virtual size_t submit(boost::uint8_t request_type,
+ boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length) = 0;
+};
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP */
diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp
new file mode 100644
index 000000000..c3eb72b00
--- /dev/null
+++ b/host/include/uhd/transport/usb_device_handle.hpp
@@ -0,0 +1,79 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP
+#define INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP
+
+#include <uhd/config.hpp>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/cstdint.hpp>
+#include <vector>
+
+namespace uhd { namespace transport {
+
+/*!
+ * Device handle class that represents a USB device
+ * Used for identifying devices on the USB bus and selecting which device is
+ * used when creating a USB transport. A minimal subset of USB descriptor
+ * fields are used. Fields can be found in the USB 2.0 specification Table
+ * 9-8 (Standard Device Descriptor). In addition to fields of the device
+ * descriptor, the interface returns the device's USB device address.
+ *
+ * Note: The USB 2.0 Standard Device Descriptor contains an index rather then
+ * a true descriptor serial number string. This interface returns the
+ * actual string descriptor.
+ */
+class UHD_API usb_device_handle : boost::noncopyable {
+public:
+ typedef boost::shared_ptr<usb_device_handle> sptr;
+
+ /*!
+ * Return the device's serial number
+ * \return a string describing the device's serial number
+ */
+ virtual UHD_API std::string get_serial() const = 0;
+
+ /*!
+ * Return the device's Vendor ID (usually assigned by the USB-IF)
+ * \return a Vendor ID
+ */
+ virtual UHD_API boost::uint16_t get_vendor_id() const = 0;
+
+ /*!
+ * Return the device's Product ID (usually assigned by manufacturer)
+ * \return a Product ID
+ */
+ virtual UHD_API boost::uint16_t get_product_id() const = 0;
+
+ /*!
+ * Return the device's USB address
+ * \return a Product ID
+ */
+ virtual UHD_API boost::uint16_t get_device_addr() const = 0;
+
+ /*!
+ * Return a vector of USB devices on this host
+ * \return a vector of USB device handles that match vid and pid
+ */
+ static UHD_API std::vector<usb_device_handle::sptr> get_device_list(boost::uint16_t vid, boost::uint16_t pid);
+
+}; //namespace usb
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP */
diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp
new file mode 100644
index 000000000..2edd6d91d
--- /dev/null
+++ b/host/include/uhd/transport/usb_zero_copy.hpp
@@ -0,0 +1,62 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP
+#define INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP
+
+#include "usb_device_handle.hpp"
+#include <uhd/transport/zero_copy.hpp>
+
+namespace uhd { namespace transport {
+
+/*!
+ * A zero copy usb transport provides an efficient way to handle data.
+ * by avoiding the extra copy when recv() or send() is called on the handle.
+ * Rather, the zero copy transport gives the caller memory references.
+ * The caller informs the transport when it is finished with the reference.
+ *
+ * On linux systems, the zero copy transport can use a kernel packet ring.
+ * If no platform specific solution is available, make returns a boost asio
+ * implementation that wraps functionality around standard send/recv calls.
+ */
+class UHD_API usb_zero_copy : public virtual zero_copy_if {
+public:
+ typedef boost::shared_ptr<usb_zero_copy> sptr;
+
+ /*!
+ * Make a new zero copy usb transport:
+ * This transport is for sending and receiving between the host
+ * and a pair of USB bulk transfer endpoints.
+ * The primary usage for this transport is data transactions.
+ * The underlying implementation may be platform specific.
+ *
+ * \param handle a device handle that uniquely identifying the device
+ * \param rx_endpoint an integer specifiying an IN endpoint number
+ * \param tx_endpoint an integer specifiying an OUT endpoint number
+ * \param buff_size total number of bytes of buffer space to allocate
+ * \param block_size number of bytes allocated for each I/O transaction
+ */
+ static sptr make(usb_device_handle::sptr handle,
+ unsigned int rx_endpoint,
+ unsigned int tx_endpoint,
+ size_t buff_size = 0,
+ size_t block_size = 0);
+};
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP */
diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp
index 56aa0df20..2f32509b9 100644
--- a/host/include/uhd/usrp/subdev_spec.hpp
+++ b/host/include/uhd/usrp/subdev_spec.hpp
@@ -56,17 +56,8 @@ namespace uhd{ namespace usrp{
*
* The subdevice specification can be represented as a markup-string.
* The markup-string is a whitespace separated list of dboard:subdev pairs.
- * The "dboard:" part is optional on boards with only one daughterboard slot.
* The first pair represents the subdevice for channel zero,
* the second pair represents the subdevice for channel one, and so on.
- *
- * Examples:
- * - Use subdevice AB on daughterboard A (USRP1): "A:AB"
- * - Use subdevice A on daughterboard A for channel zero and subdevice A on daughterboard B for channel one (USRP1): "A:A B:A"
- * - Use subdevice AB (USRP2): "AB" or ":AB"
- *
- * An empty subdevice specification can be used to automatically
- * select the first subdevice on the first present daughterboard.
*/
class UHD_API subdev_spec_t : public std::vector<subdev_spec_pair_t>{
public:
diff --git a/host/lib/transport/CMakeLists.txt b/host/lib/transport/CMakeLists.txt
index bde2b72b9..71a3a1494 100644
--- a/host/lib/transport/CMakeLists.txt
+++ b/host/lib/transport/CMakeLists.txt
@@ -18,6 +18,30 @@
#This file will be included by cmake, use absolute paths!
########################################################################
+# Setup libusb
+########################################################################
+LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/lib/transport)
+FIND_PACKAGE(USB1 REQUIRED)
+
+IF(LIBUSB_FOUND)
+ INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIR})
+ LIBUHD_APPEND_LIBS(${LIBUSB_LIBRARIES})
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_control.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_zero_copy.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_base.cpp
+ ${CMAKE_SOURCE_DIR}/lib/transport/libusb1_device_handle.cpp
+ )
+ SET(HAVE_USB_SUPPORT TRUE)
+ENDIF(LIBUSB_FOUND)
+
+IF(HAVE_USB_SUPPORT)
+ MESSAGE(STATUS "Has USB support - found")
+ELSE(HAVE_USB_SUPPORT)
+ MESSAGE(STATUS "Has USB support - not found")
+ENDIF(HAVE_USB_SUPPORT)
+
+########################################################################
# Check for SIMD headers
########################################################################
INCLUDE(CheckIncludeFileCXX)
diff --git a/host/lib/transport/FindUSB1.cmake b/host/lib/transport/FindUSB1.cmake
new file mode 100644
index 000000000..ebcac99eb
--- /dev/null
+++ b/host/lib/transport/FindUSB1.cmake
@@ -0,0 +1,38 @@
+# - Try to find the freetype library
+# Once done this defines
+#
+# LIBUSB_FOUND - system has libusb
+# LIBUSB_INCLUDE_DIR - the libusb include directory
+# LIBUSB_LIBRARIES - Link these to use libusb
+
+# Copyright (c) 2006, 2008 Laurent Montel, <montel@kde.org>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+
+if (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
+
+ # in cache already
+ set(LIBUSB_FOUND TRUE)
+
+else (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
+ IF (NOT WIN32)
+ # use pkg-config to get the directories and then use these values
+ # in the FIND_PATH() and FIND_LIBRARY() calls
+ find_package(PkgConfig)
+ pkg_check_modules(PC_LIBUSB libusb-1.0)
+ ENDIF(NOT WIN32)
+
+ FIND_PATH(LIBUSB_INCLUDE_DIR libusb.h
+ PATHS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS})
+
+ FIND_LIBRARY(LIBUSB_LIBRARIES NAMES usb-1.0
+ PATHS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS})
+
+ include(FindPackageHandleStandardArgs)
+ FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR)
+
+ MARK_AS_ADVANCED(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
+
+endif (LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
diff --git a/host/lib/transport/convert_types_impl.hpp b/host/lib/transport/convert_types_impl.hpp
index 5958b08cb..90618dec6 100644
--- a/host/lib/transport/convert_types_impl.hpp
+++ b/host/lib/transport/convert_types_impl.hpp
@@ -28,6 +28,10 @@
#define USE_EMMINTRIN_H //use sse2 intrinsics
#endif
+#if defined(USE_EMMINTRIN_H)
+ #include <emmintrin.h>
+#endif
+
/***********************************************************************
* Typedefs
**********************************************************************/
@@ -38,41 +42,56 @@ typedef boost::uint32_t item32_t;
/***********************************************************************
* Convert complex short buffer to items32
**********************************************************************/
+static UHD_INLINE item32_t sc16_to_item32(sc16_t num){
+ boost::uint16_t real = num.real();
+ boost::uint16_t imag = num.imag();
+ return (item32_t(real) << 16) | (item32_t(imag) << 0);
+}
+
static UHD_INLINE void sc16_to_item32_nswap(
const sc16_t *input, item32_t *output, size_t nsamps
){
- std::memcpy(output, input, nsamps*sizeof(item32_t));
+ for (size_t i = 0; i < nsamps; i++){
+ output[i] = sc16_to_item32(input[i]);
+ }
}
static UHD_INLINE void sc16_to_item32_bswap(
const sc16_t *input, item32_t *output, size_t nsamps
){
- const item32_t *item32_input = (const item32_t *)input;
for (size_t i = 0; i < nsamps; i++){
- output[i] = uhd::byteswap(item32_input[i]);
+ output[i] = uhd::byteswap(sc16_to_item32(input[i]));
}
}
/***********************************************************************
* Convert items32 buffer to complex short
**********************************************************************/
+static UHD_INLINE sc16_t item32_to_sc16(item32_t item){
+ return sc16_t(
+ boost::int16_t(item >> 16),
+ boost::int16_t(item >> 0)
+ );
+}
+
static UHD_INLINE void item32_to_sc16_nswap(
const item32_t *input, sc16_t *output, size_t nsamps
){
- std::memcpy(output, input, nsamps*sizeof(item32_t));
+ for (size_t i = 0; i < nsamps; i++){
+ output[i] = item32_to_sc16(input[i]);
+ }
}
static UHD_INLINE void item32_to_sc16_bswap(
const item32_t *input, sc16_t *output, size_t nsamps
){
- item32_t *item32_output = (item32_t *)output;
for (size_t i = 0; i < nsamps; i++){
- item32_output[i] = uhd::byteswap(input[i]);
+ output[i] = item32_to_sc16(uhd::byteswap(input[i]));
}
}
/***********************************************************************
- * Convert complex float buffer to items32
+ * Convert complex float buffer to items32 (no swap)
**********************************************************************/
static const float shorts_per_float = float(32767);
@@ -82,6 +101,41 @@ static UHD_INLINE item32_t fc32_to_item32(fc32_t num){
return (item32_t(real) << 16) | (item32_t(imag) << 0);
}
+////////////////////////////////////
+// none-swap
+////////////////////////////////////
+#if defined(USE_EMMINTRIN_H)
+static UHD_INLINE void fc32_to_item32_nswap(
+ const fc32_t *input, item32_t *output, size_t nsamps
+){
+ __m128 scalar = _mm_set_ps1(shorts_per_float);
+
+ //convert blocks of samples with intrinsics
+ size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
+ //load from input
+ __m128 tmplo = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+0));
+ __m128 tmphi = _mm_loadu_ps(reinterpret_cast<const float *>(input+i+2));
+
+ //convert and scale
+ __m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
+ __m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
+
+ //pack + swap 16-bit pairs
+ __m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
+ tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+ tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+
+ //store to output
+ _mm_storeu_si128(reinterpret_cast<__m128i *>(output+i), tmpi);
+ }
+
+ //convert remainder
+ for (; i < nsamps; i++){
+ output[i] = fc32_to_item32(input[i]);
+ }
+}
+
+#else
static UHD_INLINE void fc32_to_item32_nswap(
const fc32_t *input, item32_t *output, size_t nsamps
){
@@ -90,9 +144,12 @@ static UHD_INLINE void fc32_to_item32_nswap(
}
}
-#if defined(USE_EMMINTRIN_H)
-#include <emmintrin.h>
+#endif
+////////////////////////////////////
+// byte-swap
+////////////////////////////////////
+#if defined(USE_EMMINTRIN_H)
static UHD_INLINE void fc32_to_item32_bswap(
const fc32_t *input, item32_t *output, size_t nsamps
){
@@ -108,7 +165,7 @@ static UHD_INLINE void fc32_to_item32_bswap(
__m128i tmpilo = _mm_cvtps_epi32(_mm_mul_ps(tmplo, scalar));
__m128i tmpihi = _mm_cvtps_epi32(_mm_mul_ps(tmphi, scalar));
- //pack + byteswap -> byteswap 32 bit words
+ //pack + byteswap -> byteswap 16 bit words
__m128i tmpi = _mm_packs_epi32(tmpilo, tmpihi);
tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
@@ -145,6 +202,43 @@ static UHD_INLINE fc32_t item32_to_fc32(item32_t item){
);
}
+////////////////////////////////////
+// none-swap
+////////////////////////////////////
+#if defined(USE_EMMINTRIN_H)
+static UHD_INLINE void item32_to_fc32_nswap(
+ const item32_t *input, fc32_t *output, size_t nsamps
+){
+ __m128 scalar = _mm_set_ps1(floats_per_short/(1 << 16));
+ __m128i zeroi = _mm_setzero_si128();
+
+ //convert blocks of samples with intrinsics
+ size_t i = 0; for (; i < (nsamps & ~0x3); i+=4){
+ //load from input
+ __m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
+
+ //unpack + swap 16-bit pairs
+ tmpi = _mm_shufflelo_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+ tmpi = _mm_shufflehi_epi16(tmpi, _MM_SHUFFLE(2, 3, 0, 1));
+ __m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
+ __m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
+
+ //convert and scale
+ __m128 tmplo = _mm_mul_ps(_mm_cvtepi32_ps(tmpilo), scalar);
+ __m128 tmphi = _mm_mul_ps(_mm_cvtepi32_ps(tmpihi), scalar);
+
+ //store to output
+ _mm_storeu_ps(reinterpret_cast<float *>(output+i+0), tmplo);
+ _mm_storeu_ps(reinterpret_cast<float *>(output+i+2), tmphi);
+ }
+
+ //convert remainder
+ for (; i < nsamps; i++){
+ output[i] = item32_to_fc32(input[i]);
+ }
+}
+
+#else
static UHD_INLINE void item32_to_fc32_nswap(
const item32_t *input, fc32_t *output, size_t nsamps
){
@@ -152,10 +246,12 @@ static UHD_INLINE void item32_to_fc32_nswap(
output[i] = item32_to_fc32(input[i]);
}
}
+#endif
+////////////////////////////////////
+// byte-swap
+////////////////////////////////////
#if defined(USE_EMMINTRIN_H)
-#include <emmintrin.h>
-
static UHD_INLINE void item32_to_fc32_bswap(
const item32_t *input, fc32_t *output, size_t nsamps
){
@@ -167,7 +263,7 @@ static UHD_INLINE void item32_to_fc32_bswap(
//load from input
__m128i tmpi = _mm_loadu_si128(reinterpret_cast<const __m128i *>(input+i));
- //byteswap + unpack -> byteswap 32 bit words
+ //byteswap + unpack -> byteswap 16 bit words
tmpi = _mm_or_si128(_mm_srli_epi16(tmpi, 8), _mm_slli_epi16(tmpi, 8));
__m128i tmpilo = _mm_unpacklo_epi16(zeroi, tmpi); //value in upper 16 bits
__m128i tmpihi = _mm_unpackhi_epi16(zeroi, tmpi);
diff --git a/host/lib/transport/gen_convert_types.py b/host/lib/transport/gen_convert_types.py
index 951b634d9..adbd22868 100755
--- a/host/lib/transport/gen_convert_types.py
+++ b/host/lib/transport/gen_convert_types.py
@@ -36,7 +36,8 @@ using namespace uhd;
**********************************************************************/
UHD_INLINE boost::uint8_t get_pred(
const io_type_t &io_type,
- const otw_type_t &otw_type
+ const otw_type_t &otw_type,
+ size_t num_chans
){
boost::uint8_t pred = 0;
@@ -63,6 +64,14 @@ UHD_INLINE boost::uint8_t get_pred(
default: throw std::runtime_error("unhandled io type id");
}
+ switch(num_chans){
+ case 1: pred |= $ph.chan1_p; break;
+ case 2: pred |= $ph.chan2_p; break;
+ case 3: pred |= $ph.chan3_p; break;
+ case 4: pred |= $ph.chan4_p; break;
+ default: throw std::runtime_error("unhandled number of channels");
+ }
+
return pred;
}
@@ -70,17 +79,37 @@ UHD_INLINE boost::uint8_t get_pred(
* Convert host type to device type
**********************************************************************/
void transport::convert_io_type_to_otw_type(
- const void *io_buff, const io_type_t &io_type,
- void *otw_buff, const otw_type_t &otw_type,
- size_t num_samps
+ const std::vector<const void *> &io_buffs,
+ const io_type_t &io_type,
+ void *otw_buff,
+ const otw_type_t &otw_type,
+ size_t nsamps_per_io_buff
){
- switch(get_pred(io_type, otw_type)){
+ switch(get_pred(io_type, otw_type, io_buffs.size())){
#for $pred in range(2**$ph.nbits)
case $pred:
#set $out_type = $ph.get_dev_type($pred)
#set $in_type = $ph.get_host_type($pred)
- #set $converter = '_'.join([$in_type, 'to', $out_type, $ph.get_swap_type($pred)])
- $(converter)((const $(in_type)_t *)io_buff, ($(out_type)_t *)otw_buff, num_samps);
+ #set $num_chans = $ph.get_num_chans($pred)
+ #set $converter = '_'.join([$in_type, 'to', $out_type])
+ #if $num_chans == 1
+ $(converter)_$ph.get_swap_type($pred)(
+ reinterpret_cast<const $(in_type)_t *>(io_buffs.front()),
+ reinterpret_cast<$(out_type)_t *>(otw_buff),
+ nsamps_per_io_buff
+ );
+ #else
+ for (size_t i = 0; i < nsamps_per_io_buff; i++){
+ #for $j in range($num_chans)
+ reinterpret_cast<$(out_type)_t *>(otw_buff)[i*$num_chans + $j] =
+ #if $ph.get_swap_type($pred) == 'bswap'
+ uhd::byteswap($(converter)(reinterpret_cast<const $(in_type)_t *>(io_buffs[$j])[i]));
+ #else
+ $(converter)(reinterpret_cast<const $(in_type)_t *>(io_buffs[$j])[i]);
+ #end if
+ #end for
+ }
+ #end if
break;
#end for
}
@@ -90,17 +119,37 @@ void transport::convert_io_type_to_otw_type(
* Convert device type to host type
**********************************************************************/
void transport::convert_otw_type_to_io_type(
- const void *otw_buff, const otw_type_t &otw_type,
- void *io_buff, const io_type_t &io_type,
- size_t num_samps
+ const void *otw_buff,
+ const otw_type_t &otw_type,
+ std::vector<void *> &io_buffs,
+ const io_type_t &io_type,
+ size_t nsamps_per_io_buff
){
- switch(get_pred(io_type, otw_type)){
- #for $pred in range(4)
+ switch(get_pred(io_type, otw_type, io_buffs.size())){
+ #for $pred in range(2**$ph.nbits)
case $pred:
#set $out_type = $ph.get_host_type($pred)
#set $in_type = $ph.get_dev_type($pred)
- #set $converter = '_'.join([$in_type, 'to', $out_type, $ph.get_swap_type($pred)])
- $(converter)((const $(in_type)_t *)otw_buff, ($(out_type)_t *)io_buff, num_samps);
+ #set $num_chans = $ph.get_num_chans($pred)
+ #set $converter = '_'.join([$in_type, 'to', $out_type])
+ #if $num_chans == 1
+ $(converter)_$ph.get_swap_type($pred)(
+ reinterpret_cast<const $(in_type)_t *>(otw_buff),
+ reinterpret_cast<$(out_type)_t *>(io_buffs.front()),
+ nsamps_per_io_buff
+ );
+ #else
+ for (size_t i = 0; i < nsamps_per_io_buff; i++){
+ #for $j in range($num_chans)
+ reinterpret_cast<$(out_type)_t *>(io_buffs[$j])[i] =
+ #if $ph.get_swap_type($pred) == 'bswap'
+ $(converter)(uhd::byteswap(reinterpret_cast<const $(in_type)_t *>(otw_buff)[i*$num_chans + $j]));
+ #else
+ $(converter)(reinterpret_cast<const $(in_type)_t *>(otw_buff)[i*$num_chans + $j]);
+ #end if
+ #end for
+ }
+ #end if
break;
#end for
}
@@ -118,27 +167,43 @@ class ph:
item32_p = 0b00000
sc16_p = 0b00010
fc32_p = 0b00000
+ chan1_p = 0b00000
+ chan2_p = 0b00100
+ chan3_p = 0b01000
+ chan4_p = 0b01100
- nbits = 2 #see above
+ nbits = 4 #see above
@staticmethod
- def has(pred, flag): return (pred & flag) == flag
+ def has(pred, mask, flag): return (pred & mask) == flag
@staticmethod
def get_swap_type(pred):
- if ph.has(pred, ph.bswap_p): return 'bswap'
- if ph.has(pred, ph.nswap_p): return 'nswap'
+ mask = 0b1
+ if ph.has(pred, mask, ph.bswap_p): return 'bswap'
+ if ph.has(pred, mask, ph.nswap_p): return 'nswap'
raise NotImplementedError
@staticmethod
def get_dev_type(pred):
- if ph.has(pred, ph.item32_p): return 'item32'
+ mask = 0b0
+ if ph.has(pred, mask, ph.item32_p): return 'item32'
raise NotImplementedError
@staticmethod
def get_host_type(pred):
- if ph.has(pred, ph.sc16_p): return 'sc16'
- if ph.has(pred, ph.fc32_p): return 'fc32'
+ mask = 0b10
+ if ph.has(pred, mask, ph.sc16_p): return 'sc16'
+ if ph.has(pred, mask, ph.fc32_p): return 'fc32'
+ raise NotImplementedError
+
+ @staticmethod
+ def get_num_chans(pred):
+ mask = 0b1100
+ if ph.has(pred, mask, ph.chan1_p): return 1
+ if ph.has(pred, mask, ph.chan2_p): return 2
+ if ph.has(pred, mask, ph.chan3_p): return 3
+ if ph.has(pred, mask, ph.chan4_p): return 4
raise NotImplementedError
if __name__ == '__main__':
diff --git a/host/lib/transport/libusb1_base.cpp b/host/lib/transport/libusb1_base.cpp
new file mode 100644
index 000000000..e21c39aa3
--- /dev/null
+++ b/host/lib/transport/libusb1_base.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "libusb1_base.hpp"
+#include <uhd/utils/assert.hpp>
+#include <iostream>
+
+using namespace uhd::transport;
+
+/**********************************************************
+ * Helper Methods
+ **********************************************************/
+
+/**********************************************************
+ * libusb namespace
+ **********************************************************/
+void libusb::init(libusb_context **ctx, int debug_level)
+{
+ if (libusb_init(ctx) < 0)
+ std::cerr << "error: libusb_init" << std::endl;
+
+ libusb_set_debug(*ctx, debug_level);
+}
+
+libusb_device_handle *libusb::open_device(libusb_context *ctx,
+ usb_device_handle::sptr handle)
+{
+ libusb_device_handle *dev_handle = NULL;
+ libusb_device **libusb_dev_list;
+ size_t dev_cnt = libusb_get_device_list(ctx, &libusb_dev_list);
+
+ //find and open the USB device
+ for (size_t i = 0; i < dev_cnt; i++) {
+ libusb_device *dev = libusb_dev_list[i];
+
+ if (compare_device(dev, handle)) {
+ libusb_open(dev, &dev_handle);
+ libusb_unref_device(dev);
+ break;
+ }
+
+ libusb_unref_device(dev);
+ }
+
+ return dev_handle;
+}
+
+//note: changed order of checks so it only tries to get_serial and get_device_address if vid and pid match
+//doing this so it doesn't try to open the device if it's not ours
+bool libusb::compare_device(libusb_device *dev,
+ usb_device_handle::sptr handle)
+{
+ std::string serial = handle->get_serial();
+ boost::uint16_t vendor_id = handle->get_vendor_id();
+ boost::uint16_t product_id = handle->get_product_id();
+ boost::uint8_t device_addr = handle->get_device_addr();
+
+ libusb_device_descriptor libusb_desc;
+ if (libusb_get_device_descriptor(dev, &libusb_desc) < 0)
+ return false;
+ if (vendor_id != libusb_desc.idVendor)
+ return false;
+ if (product_id != libusb_desc.idProduct)
+ return false;
+ if (serial != get_serial(dev))
+ return false;
+ if (device_addr != libusb_get_device_address(dev))
+ return false;
+
+ return true;
+}
+
+
+bool libusb::open_interface(libusb_device_handle *dev_handle,
+ int interface)
+{
+ int ret = libusb_claim_interface(dev_handle, interface);
+ if (ret < 0) {
+ std::cerr << "error: libusb_claim_interface() " << ret << std::endl;
+ return false;
+ }
+ else {
+ return true;
+ }
+}
+
+
+std::string libusb::get_serial(libusb_device *dev)
+{
+ unsigned char buff[32];
+
+ libusb_device_descriptor desc;
+ if (libusb_get_device_descriptor(dev, &desc) < 0)
+ return "";
+
+ if (desc.iSerialNumber == 0)
+ return "";
+
+ //open the device because we have to
+ libusb_device_handle *dev_handle;
+ if (libusb_open(dev, &dev_handle) < 0)
+ return "";
+
+ if (libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber,
+ buff, sizeof(buff)) < 0) {
+ return "";
+ }
+
+ libusb_close(dev_handle);
+
+ return (char*) buff;
+}
diff --git a/host/lib/transport/libusb1_base.hpp b/host/lib/transport/libusb1_base.hpp
new file mode 100644
index 000000000..abe5e22a2
--- /dev/null
+++ b/host/lib/transport/libusb1_base.hpp
@@ -0,0 +1,94 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_TRANSPORT_LIBUSB_HPP
+#define INCLUDED_TRANSPORT_LIBUSB_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/transport/usb_device_handle.hpp>
+#include <libusb-1.0/libusb.h>
+
+namespace uhd { namespace transport {
+
+namespace libusb {
+ /*
+ * Initialize libusb and set debug level
+ * Takes a pointer to context pointer because that's
+ * how libusb rolls. Debug levels.
+ *
+ * Level 0: no messages ever printed by the library (default)
+ * Level 1: error messages are printed to stderr
+ * Level 2: warning and error messages are printed to stderr
+ * Level 3: informational messages are printed to stdout, warning
+ * and error messages are printed to stderr
+ *
+ * \param ctx pointer to context pointer
+ * \param debug_level
+ */
+ void init(libusb_context **ctx, int debug_level);
+
+ /*
+ * Open the device specified by a generic handle
+ * Find the libusb_device cooresponding to the generic handle
+ * and open it for I/O, which returns a libusb_device_handle
+ * ready for an interface
+ * \param ctx the libusb context used for init
+ * \return a libusb_device_handle ready for action
+ */
+ libusb_device_handle *open_device(libusb_context *ctx,
+ usb_device_handle::sptr handle);
+
+ /*
+ * Compare a libusb device with a generic handle
+ * Check the descriptors and open the device to check the
+ * serial number string. Compare values against the given
+ * handle. The libusb context is already implied in the
+ * libusb_device.
+ * \param dev a libusb_device pointer
+ * \param handle a generic handle specifier
+ * \return true if handle and device match, false otherwise
+ */
+ bool compare_device(libusb_device *dev, usb_device_handle::sptr handle);
+
+ /*
+ * Open an interface to the device
+ * This is a logical operation for operating system housekeeping as
+ * nothing is sent over the bus. The interface much correspond
+ * to the USB device descriptors.
+ * \param dev_handle libusb handle to an opened device
+ * \param interface integer of the interface to use
+ * \return true on success, false on error
+ */
+ bool open_interface(libusb_device_handle *dev_handle, int interface);
+
+ /*
+ * Get serial number
+ * The standard USB device descriptor contains an index to an
+ * actual serial number string descriptor. The index is readily
+ * readble, but the string descriptor requires probing the device.
+ * Because this call attempts to open the device, it may not
+ * succeed because not all USB devices are readily opened.
+ * The default language is used for the request (English).
+ * \param dev a libusb_device pointer
+ * \return string serial number or 0 on error or unavailablity
+ */
+ std::string get_serial(libusb_device *dev);
+}
+
+}} //namespace
+
+#endif /* INCLUDED_TRANSPORT_LIBUSB_HPP */
diff --git a/host/lib/transport/libusb1_control.cpp b/host/lib/transport/libusb1_control.cpp
new file mode 100644
index 000000000..3531128b2
--- /dev/null
+++ b/host/lib/transport/libusb1_control.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "libusb1_base.hpp"
+#include <uhd/transport/usb_control.hpp>
+
+using namespace uhd::transport;
+
+const int libusb_debug_level = 0;
+const int libusb_timeout = 0;
+
+/***********************************************************************
+ * libusb-1.0 implementation of USB control transport
+ **********************************************************************/
+class libusb_control_impl : public usb_control {
+public:
+ libusb_control_impl(usb_device_handle::sptr handle);
+ ~libusb_control_impl();
+
+ size_t submit(boost::uint8_t request_type,
+ boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length);
+
+private:
+ libusb_context *_ctx;
+ libusb_device_handle *_dev_handle;
+};
+
+
+libusb_control_impl::libusb_control_impl(usb_device_handle::sptr handle)
+{
+ libusb::init(&_ctx, libusb_debug_level);
+
+ // Find and open the libusb_device corresponding to the
+ // given handle and return the libusb_device_handle
+ // that can be used for I/O purposes.
+ _dev_handle = libusb::open_device(_ctx, handle);
+
+ // Open USB interfaces for control using magic value
+ // IN interface: 2
+ // OUT interface: 1
+ // Control interface: 0
+ libusb::open_interface(_dev_handle, 0);
+}
+
+
+libusb_control_impl::~libusb_control_impl()
+{
+ libusb_close(_dev_handle);
+ libusb_exit(_ctx);
+}
+
+
+size_t libusb_control_impl::submit(boost::uint8_t request_type,
+ boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length)
+{
+ return libusb_control_transfer(_dev_handle,
+ request_type,
+ request,
+ value,
+ index,
+ buff,
+ length,
+ libusb_timeout);
+}
+
+
+/***********************************************************************
+ * USB control public make functions
+ **********************************************************************/
+usb_control::sptr usb_control::make(usb_device_handle::sptr handle)
+{
+ return sptr(new libusb_control_impl(handle));
+}
diff --git a/host/lib/transport/libusb1_device_handle.cpp b/host/lib/transport/libusb1_device_handle.cpp
new file mode 100644
index 000000000..43d0f0e26
--- /dev/null
+++ b/host/lib/transport/libusb1_device_handle.cpp
@@ -0,0 +1,117 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "libusb1_base.hpp"
+#include <uhd/utils/assert.hpp>
+#include <iostream>
+
+using namespace uhd::transport;
+
+const int libusb_debug_level = 0;
+
+/****************************************************************
+ * libusb USB device handle implementation class
+ ***************************************************************/
+class libusb1_device_handle_impl : public usb_device_handle {
+public:
+ libusb1_device_handle_impl(std::string serial,
+ boost::uint32_t product_id,
+ boost::uint32_t vendor_id,
+ boost::uint32_t device_addr)
+ : _serial(serial), _product_id(product_id),
+ _vendor_id(vendor_id), _device_addr(device_addr)
+ {
+ /* NOP */
+ }
+
+ ~libusb1_device_handle_impl()
+ {
+ /* NOP */
+ }
+
+ std::string get_serial() const
+ {
+ return _serial;
+ }
+
+ boost::uint16_t get_vendor_id() const
+ {
+ return _vendor_id;
+ }
+
+
+ boost::uint16_t get_product_id() const
+ {
+ return _product_id;
+ }
+
+ boost::uint16_t get_device_addr() const
+ {
+ return _device_addr;
+ }
+
+private:
+ std::string _serial;
+ boost::uint32_t _product_id;
+ boost::uint32_t _vendor_id;
+ boost::uint32_t _device_addr;
+};
+
+
+usb_device_handle::sptr make_usb_device_handle(libusb_device *dev)
+{
+ libusb_device_descriptor desc;
+
+ if (libusb_get_device_descriptor(dev, &desc) < 0) {
+ UHD_ASSERT_THROW("USB: failed to get device descriptor");
+ }
+
+ std::string serial = libusb::get_serial(dev);
+ boost::uint32_t product_id = desc.idProduct;
+ boost::uint32_t vendor_id = desc.idVendor;
+ boost::uint32_t device_addr = libusb_get_device_address(dev);
+
+ return usb_device_handle::sptr(new libusb1_device_handle_impl(
+ serial,
+ product_id,
+ vendor_id,
+ device_addr));
+}
+
+std::vector<usb_device_handle::sptr> usb_device_handle::get_device_list(boost::uint16_t vid, boost::uint16_t pid)
+{
+ libusb_context *ctx = NULL;
+ libusb_device** libusb_device_list;
+ std::vector<usb_device_handle::sptr> device_handle_list;
+ libusb_device_descriptor desc;
+
+ libusb::init(&ctx, libusb_debug_level);
+
+ size_t dev_size = libusb_get_device_list(ctx, &libusb_device_list);
+ for (size_t i = 0; i < dev_size; i++) {
+ libusb_device *dev = libusb_device_list[i];
+ if(libusb_get_device_descriptor(dev, &desc) < 0) {
+ UHD_ASSERT_THROW("USB: failed to get device descriptor");
+ }
+ if(desc.idVendor == vid && desc.idProduct == pid) {
+ device_handle_list.push_back(make_usb_device_handle(dev));
+ }
+ }
+
+ libusb_exit(ctx);
+ return device_handle_list;
+}
diff --git a/host/lib/transport/libusb1_zero_copy.cpp b/host/lib/transport/libusb1_zero_copy.cpp
new file mode 100644
index 000000000..b890a87f9
--- /dev/null
+++ b/host/lib/transport/libusb1_zero_copy.cpp
@@ -0,0 +1,767 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "libusb1_base.hpp"
+#include <uhd/transport/usb_zero_copy.hpp>
+#include <uhd/utils/assert.hpp>
+#include <boost/asio.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+#include <iomanip>
+
+using namespace uhd::transport;
+
+const int libusb_debug_level = 0;
+const int libusb_timeout = 0;
+
+/***********************************************************************
+ * Helper functions
+ ***********************************************************************/
+/*
+ * Print the values of a libusb_transfer struct
+ * http://libusb.sourceforge.net/api-1.0/structlibusb__transfer.html
+ */
+void pp_transfer(libusb_transfer *lut)
+{
+ std::cout << "Libusb transfer" << std::endl;
+ std::cout << " flags: 0x" << std::hex << (unsigned int) lut->flags << std::endl;
+ std::cout << " endpoint: 0x" << std::hex << (unsigned int) lut->endpoint << std::endl;
+ std::cout << " type: 0x" << std::hex << (unsigned int) lut->type << std::endl;
+ std::cout << " timeout: " << std::dec << lut->timeout << std::endl;
+ std::cout << " status: 0x" << std::hex << lut->status << std::endl;
+ std::cout << " length: " << std::dec << lut->length << std::endl;
+ std::cout << " actual_length: " << std::dec << lut->actual_length << std::endl;
+}
+
+/***********************************************************************
+ * USB asynchronous zero_copy endpoint
+ * This endpoint implementation provides asynchronous I/O to libusb-1.0
+ * devices. Each endpoint is directional and two can be combined to
+ * create a bidirectional interface. It is a zero copy implementation
+ * with respect to libusb, however, each send and recv requires a copy
+ * operation from kernel to userspace; this is due to the usbfs
+ * interface provided by the kernel.
+ **********************************************************************/
+class usb_endpoint {
+private:
+ libusb_device_handle *_dev_handle;
+ libusb_context *_ctx;
+ int _endpoint;
+ bool _input;
+
+ size_t _transfer_size;
+ size_t _num_transfers;
+
+ // Transfer state lists (transfers are free, pending, or completed)
+ std::list<libusb_transfer *> _free_list;
+ std::list<libusb_transfer *> _pending_list;
+ std::list<libusb_transfer *> _completed_list;
+
+ // Calls for processing asynchronous I/O
+ libusb_transfer *allocate_transfer(int buff_len);
+ bool cancel(libusb_transfer *lut);
+ bool cancel_all();
+ bool reap_pending_list();
+ bool reap_pending_list_timeout();
+ bool reap_completed_list();
+
+ // Transfer state manipulators
+ void free_list_add(libusb_transfer *lut);
+ void pending_list_add(libusb_transfer *lut);
+ void completed_list_add(libusb_transfer *lut);
+ libusb_transfer *free_list_get();
+ libusb_transfer *completed_list_get();
+ bool pending_list_remove(libusb_transfer *lut);
+
+ // Debug use
+ void print_transfer_status(libusb_transfer *lut);
+
+public:
+ usb_endpoint(libusb_device_handle *dev_handle,
+ libusb_context *ctx, int endpoint, bool input,
+ size_t transfer_size, size_t num_transfers);
+
+ ~usb_endpoint();
+
+ // Exposed interface for submitting / retrieving transfer buffers
+ bool submit(libusb_transfer *lut);
+ libusb_transfer *get_completed_transfer();
+ libusb_transfer *get_free_transfer();
+
+ //Callback use only
+ void callback_handle_transfer(libusb_transfer *lut);
+};
+
+
+/*
+ * Callback function called when submitted transfers complete.
+ * The endpoint upon which the transfer is part of is recovered
+ * and the transfer moved from pending to completed state.
+ * Callbacks occur during the reaping calls where libusb_handle_events()
+ * is used. The callback only modifies the transfer state by moving
+ * it from the pending to completed status list.
+ * \param lut pointer to libusb_transfer
+ */
+static void callback(libusb_transfer *lut)
+{
+ usb_endpoint *endpoint = (usb_endpoint *) lut->user_data;
+ endpoint->callback_handle_transfer(lut);
+}
+
+
+/*
+ * Accessor call to allow list access from callback space
+ * \param pointer to libusb_transfer
+ */
+void usb_endpoint::callback_handle_transfer(libusb_transfer *lut)
+{
+ if (!pending_list_remove(lut)) {
+ std::cerr << "USB: pending remove failed" << std::endl;
+ return;
+ }
+
+ completed_list_add(lut);
+}
+
+
+/*
+ * Constructor
+ * Allocate libusb transfers and mark as free. For IN endpoints,
+ * submit the transfers so that they're ready to return when
+ * data is available.
+ */
+usb_endpoint::usb_endpoint(libusb_device_handle *dev_handle,
+ libusb_context *ctx, int endpoint, bool input,
+ size_t transfer_size, size_t num_transfers)
+ : _dev_handle(dev_handle),
+ _ctx(ctx), _endpoint(endpoint), _input(input),
+ _transfer_size(transfer_size), _num_transfers(num_transfers)
+{
+ unsigned int i;
+ for (i = 0; i < _num_transfers; i++) {
+ free_list_add(allocate_transfer(_transfer_size));
+
+ if (_input)
+ submit(free_list_get());
+ }
+}
+
+
+/*
+ * Destructor
+ * Make sure all the memory is freed. Cancel any pending transfers.
+ * When all completed transfers are moved to the free list, release
+ * the transfers. Libusb will deallocate the data buffer held by
+ * each transfer.
+ */
+usb_endpoint::~usb_endpoint()
+{
+ cancel_all();
+
+ while (!_pending_list.empty()) {
+ if (!reap_pending_list())
+ std::cerr << "error: destructor failed to reap" << std::endl;
+ }
+
+ while (!_completed_list.empty()) {
+ if (!reap_completed_list())
+ std::cerr << "error: destructor failed to reap" << std::endl;
+ }
+
+ while (!_free_list.empty()) {
+ libusb_free_transfer(free_list_get());
+ }
+}
+
+
+/*
+ * Allocate a libusb transfer
+ * The allocated transfer - and buffer it contains - is repeatedly
+ * submitted, reaped, and reused and should not be freed until shutdown.
+ * \param buff_len size of the individual buffer held by each transfer
+ * \return pointer to an allocated libusb_transfer
+ */
+libusb_transfer *usb_endpoint::allocate_transfer(int buff_len)
+{
+ libusb_transfer *lut = libusb_alloc_transfer(0);
+
+ unsigned char *buff = new unsigned char[buff_len];
+
+ unsigned int endpoint = ((_endpoint & 0x7f) | (_input ? 0x80 : 0));
+
+ libusb_fill_bulk_transfer(lut, // transfer
+ _dev_handle, // dev_handle
+ endpoint, // endpoint
+ buff, // buffer
+ buff_len, // length
+ callback, // callback
+ this, // user_data
+ 0); // timeout
+ return lut;
+}
+
+
+/*
+ * Asynchonous transfer submission
+ * Submit a libusb transfer to libusb add pending status
+ * \param lut pointer to libusb_transfer
+ * \return true on success or false on error
+ */
+bool usb_endpoint::submit(libusb_transfer *lut)
+{
+ int retval;
+ if ((retval = libusb_submit_transfer(lut)) < 0) {
+ std::cerr << "error: libusb_submit_transfer: " << retval << std::endl;
+ return false;
+ }
+
+ pending_list_add(lut);
+ return true;
+}
+
+
+/*
+ * Cancel a pending transfer
+ * Search the pending list for the transfer and cancel if found.
+ * \param lut pointer to libusb_transfer to cancel
+ * \return true on success or false if transfer is not found
+ *
+ * Note: success only indicates submission of cancelation request.
+ * Sucessful cancelation is not known until the callback occurs.
+ */
+bool usb_endpoint::cancel(libusb_transfer *lut)
+{
+ std::list<libusb_transfer*>::iterator iter;
+ for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) {
+ if (*iter == lut) {
+ libusb_cancel_transfer(lut);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/*
+ * Cancel all pending transfers
+ * \return bool true if cancelation request is submitted
+ *
+ * Note: success only indicates submission of cancelation request.
+ * Sucessful cancelation is not known until the callback occurs.
+ */
+bool usb_endpoint::cancel_all()
+{
+ std::list<libusb_transfer*>::iterator iter;
+
+ for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) {
+ if (libusb_cancel_transfer(*iter) < 0) {
+ std::cerr << "error: libusb_cancal_transfer() failed" << std::endl;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/*
+ * Reap completed transfers
+ * return true if at least one transfer was reaped, false otherwise.
+ * Check completed transfers for errors and mark as free. This is a
+ * blocking call.
+ * \return bool true if a libusb transfer is reaped, false otherwise
+ */
+bool usb_endpoint::reap_completed_list()
+{
+ libusb_transfer *lut;
+
+ if (_completed_list.empty()) {
+ if (!reap_pending_list_timeout())
+ return false;
+ }
+
+ while (!_completed_list.empty()) {
+ lut = completed_list_get();
+ print_transfer_status(lut);
+ free_list_add(lut);
+ }
+
+ return true;
+}
+
+
+/*
+ * Print status errors of a completed transfer
+ * \param lut pointer to an libusb_transfer
+ */
+void usb_endpoint::print_transfer_status(libusb_transfer *lut)
+{
+ switch (lut->status) {
+ case LIBUSB_TRANSFER_COMPLETED:
+ if (lut->actual_length < lut->length) {
+ std::cerr << "USB: transfer completed with short write,"
+ << " length = " << lut->length
+ << " actual = " << lut->actual_length << std::endl;
+ }
+
+ if ((lut->actual_length < 0) || (lut->length < 0)) {
+ std::cerr << "USB: transfer completed with invalid response"
+ << std::endl;
+ }
+ break;
+ case LIBUSB_TRANSFER_CANCELLED:
+ break;
+ case LIBUSB_TRANSFER_NO_DEVICE:
+ std::cerr << "USB: device was disconnected" << std::endl;
+ break;
+ case LIBUSB_TRANSFER_OVERFLOW:
+ std::cerr << "USB: device sent more data than requested" << std::endl;
+ break;
+ case LIBUSB_TRANSFER_TIMED_OUT:
+ std::cerr << "USB: transfer timed out" << std::endl;
+ break;
+ case LIBUSB_TRANSFER_STALL:
+ std::cerr << "USB: halt condition detected (stalled)" << std::endl;
+ break;
+ case LIBUSB_TRANSFER_ERROR:
+ std::cerr << "USB: transfer failed" << std::endl;
+ break;
+ default:
+ std::cerr << "USB: received unknown transfer status" << std::endl;
+ }
+}
+
+
+/*
+ * Reap pending transfers without timeout
+ * This is a blocking call. Reaping submitted transfers is
+ * handled by libusb and the assigned callback function.
+ * Block until at least one transfer is reaped.
+ * \return true true if a transfer was reaped or false otherwise
+ */
+bool usb_endpoint::reap_pending_list()
+{
+ int retval;
+
+ if ((retval = libusb_handle_events(_ctx)) < 0) {
+ std::cerr << "error: libusb_handle_events: " << retval << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+/*
+ * Reap pending transfers with timeout
+ * This call blocks until a transfer is reaped or timeout.
+ * Reaping submitted transfers is handled by libusb and the
+ * assigned callback function. Block until at least one
+ * transfer is reaped or timeout occurs.
+ * \return true if a transfer was reaped or false otherwise
+ */
+bool usb_endpoint::reap_pending_list_timeout()
+{
+ int retval;
+ timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000; //100ms
+
+ size_t pending_list_size = _pending_list.size();
+
+ if ((retval = libusb_handle_events_timeout(_ctx, &tv)) < 0) {
+ std::cerr << "error: libusb_handle_events: " << retval << std::endl;
+ return false;
+ }
+
+ if (_pending_list.size() < pending_list_size) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+/*
+ * Get a free transfer
+ * The transfer has an empty data bufer for OUT requests
+ * \return pointer to a libusb_transfer
+ */
+libusb_transfer *usb_endpoint::get_free_transfer()
+{
+ if (_free_list.empty()) {
+ if (!reap_completed_list())
+ return NULL;
+ }
+
+ return free_list_get();
+}
+
+
+/*
+ * Get a completed transfer
+ * The transfer has a full data buffer for IN requests
+ * \return pointer to libusb_transfer
+ */
+libusb_transfer *usb_endpoint::get_completed_transfer()
+{
+ if (_completed_list.empty()) {
+ if (!reap_pending_list_timeout())
+ return NULL;
+ }
+
+ return completed_list_get();
+}
+
+/*
+ * List operations
+ */
+void usb_endpoint::free_list_add(libusb_transfer *lut)
+{
+ _free_list.push_back(lut);
+}
+
+void usb_endpoint::pending_list_add(libusb_transfer *lut)
+{
+ _pending_list.push_back(lut);
+}
+
+void usb_endpoint::completed_list_add(libusb_transfer *lut)
+{
+ _completed_list.push_back(lut);
+}
+
+
+/*
+ * Free and completed lists don't have ordered content
+ * Pop transfers from the front as needed
+ */
+libusb_transfer *usb_endpoint::free_list_get()
+{
+ libusb_transfer *lut;
+
+ if (_free_list.size() == 0) {
+ return NULL;
+ }
+ else {
+ lut = _free_list.front();
+ _free_list.pop_front();
+ return lut;
+ }
+}
+
+
+/*
+ * Free and completed lists don't have ordered content
+ * Pop transfers from the front as needed
+ */
+libusb_transfer *usb_endpoint::completed_list_get()
+{
+ libusb_transfer *lut;
+
+ if (_completed_list.empty()) {
+ return NULL;
+ }
+ else {
+ lut = _completed_list.front();
+ _completed_list.pop_front();
+ return lut;
+ }
+}
+
+
+/*
+ * Search and remove transfer from pending list
+ * Assuming that the callbacks occur in order, the front element
+ * should yield the correct transfer. If not, then something else
+ * is going on. If no transfers match, then something went wrong.
+ */
+bool usb_endpoint::pending_list_remove(libusb_transfer *lut)
+{
+ std::list<libusb_transfer*>::iterator iter;
+ for (iter = _pending_list.begin(); iter != _pending_list.end(); iter++) {
+ if (*iter == lut) {
+ _pending_list.erase(iter);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/***********************************************************************
+ * Managed buffers
+ **********************************************************************/
+/*
+ * Libusb managed receive buffer
+ * Construct a recv buffer from a libusb transfer. The memory held by
+ * the libusb transfer is exposed through the managed buffer interface.
+ * Upon destruction, the transfer and buffer are resubmitted to the
+ * endpoint for further use.
+ */
+class libusb_managed_recv_buffer_impl : public managed_recv_buffer {
+public:
+ libusb_managed_recv_buffer_impl(libusb_transfer *lut,
+ usb_endpoint *endpoint)
+ : _buff(lut->buffer, lut->length)
+ {
+ _lut = lut;
+ _endpoint = endpoint;
+ }
+
+ ~libusb_managed_recv_buffer_impl()
+ {
+ if (!_endpoint->submit(_lut))
+ std::cerr << "USB: failed to submit IN transfer" << std::endl;
+ }
+
+private:
+ const boost::asio::const_buffer &get() const
+ {
+ return _buff;
+ }
+
+ libusb_transfer *_lut;
+ usb_endpoint *_endpoint;
+ const boost::asio::const_buffer _buff;
+};
+
+/*
+ * Libusb managed send buffer
+ * Construct a send buffer from a libusb transfer. The memory held by
+ * the libusb transfer is exposed through the managed buffer interface.
+ * Committing the buffer will set the data length and submit the buffer
+ * to the endpoint. Submitting a buffer multiple times or destroying
+ * the buffer before committing is an error. For the latter, the transfer
+ * is returned to the endpoint with no data for reuse.
+ */
+class libusb_managed_send_buffer_impl : public managed_send_buffer {
+public:
+ libusb_managed_send_buffer_impl(libusb_transfer *lut,
+ usb_endpoint *endpoint,
+ size_t buff_size)
+ : _buff(lut->buffer, buff_size), _committed(false)
+ {
+ _lut = lut;
+ _endpoint = endpoint;
+ }
+
+ ~libusb_managed_send_buffer_impl()
+ {
+ if (!_committed) {
+ _lut->length = 0;
+ _lut->actual_length = 0;
+ _endpoint->submit(_lut);
+ }
+ }
+
+ ssize_t commit(size_t num_bytes)
+ {
+ if (_committed) {
+ std::cerr << "UHD: send buffer already committed" << std::endl;
+ return 0;
+ }
+
+ UHD_ASSERT_THROW(num_bytes <= boost::asio::buffer_size(_buff));
+
+ _lut->length = num_bytes;
+ _lut->actual_length = 0;
+
+ if (_endpoint->submit(_lut)) {
+ _committed = true;
+ return num_bytes;
+ }
+ else {
+ return 0;
+ }
+ }
+
+private:
+ const boost::asio::mutable_buffer &get() const
+ {
+ return _buff;
+ }
+
+ libusb_transfer *_lut;
+ usb_endpoint *_endpoint;
+ const boost::asio::mutable_buffer _buff;
+ bool _committed;
+};
+
+
+/***********************************************************************
+ * USB zero_copy device class
+ **********************************************************************/
+class libusb_zero_copy_impl : public usb_zero_copy
+{
+private:
+ usb_endpoint *_rx_ep;
+ usb_endpoint *_tx_ep;
+
+ // Maintain libusb values
+ libusb_context *_rx_ctx;
+ libusb_context *_tx_ctx;
+ libusb_device_handle *_rx_dev_handle;
+ libusb_device_handle *_tx_dev_handle;
+
+ size_t _recv_buff_size;
+ size_t _send_buff_size;
+ size_t _num_frames;
+
+public:
+ typedef boost::shared_ptr<libusb_zero_copy_impl> sptr;
+
+ libusb_zero_copy_impl(usb_device_handle::sptr handle,
+ unsigned int rx_endpoint,
+ unsigned int tx_endpoint,
+ size_t recv_buff_size,
+ size_t send_buff_size);
+
+ ~libusb_zero_copy_impl();
+
+ managed_recv_buffer::sptr get_recv_buff(void);
+ managed_send_buffer::sptr get_send_buff(void);
+
+ size_t get_num_recv_frames(void) const { return _num_frames; }
+ size_t get_num_send_frames(void) const { return _num_frames; }
+};
+
+/*
+ * Constructor
+ * Initializes libusb, opens devices, and sets up interfaces for I/O.
+ * Finally, creates endpoints for asynchronous I/O.
+ */
+libusb_zero_copy_impl::libusb_zero_copy_impl(usb_device_handle::sptr handle,
+ unsigned int rx_endpoint,
+ unsigned int tx_endpoint,
+ size_t buff_size,
+ size_t block_size)
+ : _rx_ctx(NULL), _tx_ctx(NULL), _rx_dev_handle(NULL), _tx_dev_handle(NULL),
+ _recv_buff_size(block_size), _send_buff_size(block_size),
+ _num_frames(buff_size / block_size)
+{
+ // Initialize libusb with separate contexts to allow
+ // thread safe operation of transmit and receive
+ libusb::init(&_rx_ctx, libusb_debug_level);
+ libusb::init(&_tx_ctx, libusb_debug_level);
+
+ UHD_ASSERT_THROW((_rx_ctx != NULL) && (_tx_ctx != NULL));
+
+ // Find and open the libusb_device corresponding to the
+ // given handle and return the libusb_device_handle
+ // that can be used for I/O purposes.
+ _rx_dev_handle = libusb::open_device(_rx_ctx, handle);
+ _tx_dev_handle = libusb::open_device(_tx_ctx, handle);
+
+ // Open USB interfaces for tx/rx using magic values.
+ // IN interface: 2
+ // OUT interface: 1
+ // Control interface: 0
+ libusb::open_interface(_rx_dev_handle, 2);
+ libusb::open_interface(_tx_dev_handle, 1);
+
+ _rx_ep = new usb_endpoint(_rx_dev_handle, // libusb device_handle
+ _rx_ctx, // libusb context
+ rx_endpoint, // USB endpoint number
+ true, // IN endpoint
+ _recv_buff_size, // buffer size per transfer
+ _num_frames); // number of libusb transfers
+
+ _tx_ep = new usb_endpoint(_tx_dev_handle, // libusb device_handle
+ _tx_ctx, // libusb context
+ tx_endpoint, // USB endpoint number
+ false, // OUT endpoint
+ _send_buff_size, // buffer size per transfer
+ _num_frames); // number of libusb transfers
+}
+
+
+libusb_zero_copy_impl::~libusb_zero_copy_impl()
+{
+ delete _rx_ep;
+ delete _tx_ep;
+
+ libusb_close(_rx_dev_handle);
+ libusb_close(_tx_dev_handle);
+
+ libusb_exit(_rx_ctx);
+ libusb_exit(_tx_ctx);
+}
+
+
+/*
+ * Construct a managed receive buffer from a completed libusb transfer
+ * (happy with buffer full of data) obtained from the receive endpoint.
+ * Return empty pointer if no transfer is available (timeout or error).
+ * \return pointer to a managed receive buffer
+ */
+managed_recv_buffer::sptr libusb_zero_copy_impl::get_recv_buff()
+{
+ libusb_transfer *lut = _rx_ep->get_completed_transfer();
+ if (lut == NULL) {
+ return managed_recv_buffer::sptr();
+ }
+ else {
+ return managed_recv_buffer::sptr(
+ new libusb_managed_recv_buffer_impl(lut,
+ _rx_ep));
+ }
+}
+
+
+/*
+ * Construct a managed send buffer from a free libusb transfer (with
+ * empty buffer). Return empty pointer of no transfer is available
+ * (timeout or error).
+ * \return pointer to a managed send buffer
+ */
+managed_send_buffer::sptr libusb_zero_copy_impl::get_send_buff()
+{
+ libusb_transfer *lut = _tx_ep->get_free_transfer();
+ if (lut == NULL) {
+ return managed_send_buffer::sptr();
+ }
+ else {
+ return managed_send_buffer::sptr(
+ new libusb_managed_send_buffer_impl(lut,
+ _tx_ep,
+ _send_buff_size));
+ }
+}
+
+
+/***********************************************************************
+ * USB zero_copy make functions
+ **********************************************************************/
+usb_zero_copy::sptr usb_zero_copy::make(usb_device_handle::sptr handle,
+ unsigned int rx_endpoint,
+ unsigned int tx_endpoint,
+ size_t buff_size,
+ size_t block_size)
+
+{
+ return sptr(new libusb_zero_copy_impl(handle,
+ rx_endpoint,
+ tx_endpoint,
+ buff_size,
+ block_size));
+}
+
+
+
diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt
index 2b408e479..b5c545988 100644
--- a/host/lib/usrp/CMakeLists.txt
+++ b/host/lib/usrp/CMakeLists.txt
@@ -31,4 +31,5 @@ LIBUHD_APPEND_SOURCES(
)
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/dboard/CMakeLists.txt)
+INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/CMakeLists.txt)
INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/CMakeLists.txt)
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index 0b6e4a75a..2a9bf2ca5 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -57,6 +57,12 @@ private:
double _max_freq;
};
+static const uhd::dict<std::string, subdev_conn_t> sd_name_to_conn = map_list_of
+ ("AB", SUBDEV_CONN_COMPLEX_IQ)
+ ("A", SUBDEV_CONN_REAL_I)
+ ("B", SUBDEV_CONN_REAL_Q)
+;
+
/***********************************************************************
* Register the basic and LF dboards
**********************************************************************/
@@ -77,10 +83,10 @@ static dboard_base::sptr make_lf_tx(dboard_base::ctor_args_t args){
}
UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){
- dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX");
- dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", list_of("AB")("A")("B"));
- dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX");
- dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", list_of("AB")("A")("B"));
+ dboard_manager::register_dboard(0x0000, &make_basic_tx, "Basic TX", sd_name_to_conn.keys());
+ dboard_manager::register_dboard(0x0001, &make_basic_rx, "Basic RX", sd_name_to_conn.keys());
+ dboard_manager::register_dboard(0x000e, &make_lf_tx, "LF TX", sd_name_to_conn.keys());
+ dboard_manager::register_dboard(0x000f, &make_lf_rx, "LF RX", sd_name_to_conn.keys());
}
/***********************************************************************
@@ -138,14 +144,9 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, ""); //vector of 1 empty string
return;
- case SUBDEV_PROP_CONNECTION:{
- static const uhd::dict<std::string, subdev_conn_t> name_to_conn = map_list_of
- ("A", SUBDEV_CONN_REAL_I)
- ("B", SUBDEV_CONN_REAL_Q)
- ("AB", SUBDEV_CONN_COMPLEX_IQ)
- ;
- val = name_to_conn[get_subdev_name()];
- } return;
+ case SUBDEV_PROP_CONNECTION:
+ val = sd_name_to_conn[get_subdev_name()];
+ return;
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
@@ -197,7 +198,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
//handle the get request conditioned on the key
switch(key.as<subdev_prop_t>()){
case SUBDEV_PROP_NAME:
- val = get_tx_id().to_pp_string();
+ val = std::string(str(boost::format("%s - %s")
+ % get_tx_id().to_pp_string()
+ % get_subdev_name()
+ ));
return;
case SUBDEV_PROP_OTHERS:
@@ -233,7 +237,7 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_CONNECTION:
- val = SUBDEV_CONN_COMPLEX_IQ;
+ val = sd_name_to_conn[get_subdev_name()];
return;
case SUBDEV_PROP_USE_LO_OFFSET:
diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp
index 06cf91d3b..81434f054 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -205,7 +205,12 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){
//set the gpio directions and atr controls (identically)
this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr
- this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs
+ if (this->get_iface()->get_special_props().soft_clock_divider){
+ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock
+ }
+ else{
+ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs
+ }
//send initial register settings
this->send_reg(0x0, 0x5);
diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp
index fe1313af1..10ae9a086 100644
--- a/host/lib/usrp/dsp_utils.cpp
+++ b/host/lib/usrp/dsp_utils.cpp
@@ -30,22 +30,36 @@ template <class T> T ceil_log2(T num){
return std::ceil(std::log(num)/std::log(T(2)));
}
+/*!
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-------------------------------+-------+-------+-------+-------+
+ * | | DDC0Q | DDC0I |
+ * +-------------------------------+-------+-------+-------+-------+
+ */
boost::uint32_t dsp_type1::calc_rx_mux_word(subdev_conn_t subdev_conn){
switch(subdev_conn){
- case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0
- case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1
- case SUBDEV_CONN_REAL_I: return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0
- case SUBDEV_CONN_REAL_Q: return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO
+ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DDC0Q=ADC0Q, DDC0I=ADC0I
+ case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DDC0Q=ADC0I, DDC0I=ADC0Q
+ case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0I
+ case SUBDEV_CONN_REAL_Q: return (0x1 << 4) | (0xf << 0); //DDC0Q=ADC0Q, DDC0I=ZERO
default: UHD_THROW_INVALID_CODE_PATH();
}
}
+/*!
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-------------------------------+-------+-------+-------+-------+
+ * | | DAC0Q | DAC0I |
+ * +-------------------------------+-------+-------+-------+-------+
+ */
boost::uint32_t dsp_type1::calc_tx_mux_word(subdev_conn_t subdev_conn){
switch(subdev_conn){
- case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I
- case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q
- case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DAC1=ZERO, DAC0=DUC0I
- case SUBDEV_CONN_REAL_Q: return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO
+ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC0Q=DUC0Q, DAC0I=DUC0I
+ case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC0Q=DUC0I, DAC0I=DUC0Q
+ case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DAC0Q=ZERO, DAC0I=DUC0I
+ case SUBDEV_CONN_REAL_Q: return (0x0 << 4) | (0xf << 0); //DAC0Q=DUC0I, DAC0I=ZERO
default: UHD_THROW_INVALID_CODE_PATH();
}
}
diff --git a/host/lib/usrp/misc_utils.cpp b/host/lib/usrp/misc_utils.cpp
index a1664d810..5cfcdc8d3 100644
--- a/host/lib/usrp/misc_utils.cpp
+++ b/host/lib/usrp/misc_utils.cpp
@@ -164,13 +164,22 @@ static void verify_xx_subdev_spec(
//empty db name means select dboard automatically
if (pair.db_name.empty()){
if (dboard_names.size() != 1) throw std::runtime_error(
- "A daughterboard name must be provided for multi-slot boards: " + subdev_spec.to_string()
+ "A daughterboard name must be provided for multi-slot motherboards: " + subdev_spec.to_string()
);
pair.db_name == dboard_names.front();
}
uhd::assert_has(dboard_names, pair.db_name, xx_type + " dboard name");
wax::obj dboard = mboard[named_prop_t(dboard_prop, pair.db_name)];
- uhd::assert_has(dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>(), pair.sd_name, xx_type + " subdev name");
+ prop_names_t subdev_names = dboard[DBOARD_PROP_SUBDEV_NAMES].as<prop_names_t>();
+
+ //empty sd name means select the subdev automatically
+ if (pair.sd_name.empty()){
+ if (subdev_names.size() != 1) throw std::runtime_error(
+ "A subdevice name must be provided for multi-subdev daughterboards: " + subdev_spec.to_string()
+ );
+ pair.sd_name == subdev_names.front();
+ }
+ uhd::assert_has(subdev_names, pair.sd_name, xx_type + " subdev name");
}
}catch(const std::exception &e){
throw std::runtime_error(str(boost::format(
diff --git a/host/lib/usrp/usrp1/CMakeLists.txt b/host/lib/usrp/usrp1/CMakeLists.txt
new file mode 100644
index 000000000..67487f99e
--- /dev/null
+++ b/host/lib/usrp/usrp1/CMakeLists.txt
@@ -0,0 +1,65 @@
+#
+# Copyright 2010 Ettus Research LLC
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+#
+
+#This file will be included by cmake, use absolute paths!
+
+########################################################################
+# Conditionally configure the USRP1 support
+########################################################################
+MESSAGE(STATUS "Configuring USRP1 support...")
+
+IF(DEFINED ENABLE_USRP1)
+ IF(ENABLE_USRP1)
+ MESSAGE(STATUS "USRP1 support enabled by configure flag")
+ ELSE(ENABLE_USRP1)
+ MESSAGE(STATUS "USRP1 support disabled by configure flag")
+ ENDIF(ENABLE_USRP1)
+ELSE(DEFINED ENABLE_USRP1) #not defined: automatic enabling of component
+ SET(ENABLE_USRP1 ${HAVE_USB_SUPPORT})
+ENDIF(DEFINED ENABLE_USRP1)
+SET(ENABLE_USRP1 ${ENABLE_USRP1} CACHE BOOL "enable USRP1 support")
+
+#sanity check when USRP1 support enabled
+IF(ENABLE_USRP1 AND NOT HAVE_USB_SUPPORT)
+ MESSAGE(FATAL_ERROR "USRP1 support enabled without USB support")
+ENDIF(ENABLE_USRP1 AND NOT HAVE_USB_SUPPORT)
+
+IF(ENABLE_USRP1)
+ MESSAGE(STATUS " Building USRP1 support.")
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/../firmware/fx2/include)
+
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/clock_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/codec_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dboard_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/dsp_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/io_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/mboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_iface.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_impl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp1/usrp1_ctrl.hpp
+ )
+ELSE(ENABLE_USRP1)
+ MESSAGE(STATUS " Skipping USRP1 support.")
+ENDIF(ENABLE_USRP1)
diff --git a/host/lib/usrp/usrp1/clock_ctrl.cpp b/host/lib/usrp/usrp1/clock_ctrl.cpp
new file mode 100644
index 000000000..68c5f5320
--- /dev/null
+++ b/host/lib/usrp/usrp1/clock_ctrl.cpp
@@ -0,0 +1,60 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "clock_ctrl.hpp"
+#include "fpga_regs_standard.h"
+#include <uhd/utils/assert.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <utility>
+#include <iostream>
+
+using namespace uhd;
+
+/***********************************************************************
+ * Constants
+ **********************************************************************/
+static const double master_clock_rate = 64e6;
+
+/***********************************************************************
+ * Clock Control Implementation
+ **********************************************************************/
+class usrp1_clock_ctrl_impl : public usrp1_clock_ctrl {
+public:
+ usrp1_clock_ctrl_impl(usrp1_iface::sptr iface)
+ {
+ _iface = iface;
+ }
+
+ double get_master_clock_freq(void)
+ {
+ return master_clock_rate;
+ }
+
+private:
+ usrp1_iface::sptr _iface;
+
+};
+
+/***********************************************************************
+ * Clock Control Make
+ **********************************************************************/
+usrp1_clock_ctrl::sptr usrp1_clock_ctrl::make(usrp1_iface::sptr iface)
+{
+ return sptr(new usrp1_clock_ctrl_impl(iface));
+}
diff --git a/host/lib/usrp/usrp1/clock_ctrl.hpp b/host/lib/usrp/usrp1/clock_ctrl.hpp
new file mode 100644
index 000000000..366869dab
--- /dev/null
+++ b/host/lib/usrp/usrp1/clock_ctrl.hpp
@@ -0,0 +1,50 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_USRP1_CLOCK_CTRL_HPP
+#define INCLUDED_USRP1_CLOCK_CTRL_HPP
+
+#include "usrp1_iface.hpp"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include <vector>
+
+/*!
+ * The usrp1 clock control:
+ * - Setup system clocks.
+ * - Disable/enable clock lines.
+ */
+class usrp1_clock_ctrl : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<usrp1_clock_ctrl> sptr;
+
+ /*!
+ * Make a new clock control object.
+ * \param iface the usrp1 iface object
+ * \return the clock control object
+ */
+ static sptr make(usrp1_iface::sptr iface);
+
+ /*!
+ * Get the rate of the fpga clock line.
+ * \return the fpga clock rate in Hz
+ */
+ virtual double get_master_clock_freq(void) = 0;
+
+};
+
+#endif /* INCLUDED_USRP1_CLOCK_CTRL_HPP */
diff --git a/host/lib/usrp/usrp1/codec_ctrl.cpp b/host/lib/usrp/usrp1/codec_ctrl.cpp
new file mode 100644
index 000000000..08f2d2a8e
--- /dev/null
+++ b/host/lib/usrp/usrp1/codec_ctrl.cpp
@@ -0,0 +1,429 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "codec_ctrl.hpp"
+#include "usrp_commands.h"
+#include "clock_ctrl.hpp"
+#include "ad9862_regs.hpp"
+#include <uhd/types/dict.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/byteswap.hpp>
+#include <boost/cstdint.hpp>
+#include <boost/format.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/math/special_functions/round.hpp>
+#include <boost/assign/list_of.hpp>
+#include <iostream>
+#include <iomanip>
+
+using namespace uhd;
+
+static const bool codec_debug = false;
+
+const gain_range_t usrp1_codec_ctrl::tx_pga_gain_range(-20, 0, float(0.1));
+const gain_range_t usrp1_codec_ctrl::rx_pga_gain_range(0, 20, 1);
+
+/***********************************************************************
+ * Codec Control Implementation
+ **********************************************************************/
+class usrp1_codec_ctrl_impl : public usrp1_codec_ctrl {
+public:
+ //structors
+ usrp1_codec_ctrl_impl(usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock,
+ int spi_slave);
+ ~usrp1_codec_ctrl_impl(void);
+
+ //aux adc and dac control
+ float read_aux_adc(aux_adc_t which);
+ void write_aux_dac(aux_dac_t which, float volts);
+
+ //duc control
+ void set_duc_freq(double freq);
+
+ //pga gain control
+ void set_tx_pga_gain(float);
+ float get_tx_pga_gain(void);
+ void set_rx_pga_gain(float, char);
+ float get_rx_pga_gain(char);
+
+private:
+ usrp1_iface::sptr _iface;
+ usrp1_clock_ctrl::sptr _clock_ctrl;
+ int _spi_slave;
+ ad9862_regs_t _ad9862_regs;
+ aux_adc_t _last_aux_adc_a, _last_aux_adc_b;
+ void send_reg(boost::uint8_t addr);
+ void recv_reg(boost::uint8_t addr);
+
+ double coarse_tune(double codec_rate, double freq);
+ double fine_tune(double codec_rate, double freq);
+};
+
+/***********************************************************************
+ * Codec Control Structors
+ **********************************************************************/
+usrp1_codec_ctrl_impl::usrp1_codec_ctrl_impl(usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock,
+ int spi_slave)
+{
+ _iface = iface;
+ _clock_ctrl = clock;
+ _spi_slave = spi_slave;
+
+ //soft reset
+ _ad9862_regs.soft_reset = 1;
+ this->send_reg(0);
+
+ //initialize the codec register settings
+ _ad9862_regs.sdio_bidir = ad9862_regs_t::SDIO_BIDIR_SDIO_SDO;
+ _ad9862_regs.lsb_first = ad9862_regs_t::LSB_FIRST_MSB;
+ _ad9862_regs.soft_reset = 0;
+
+ //setup rx side of codec
+ _ad9862_regs.byp_buffer_a = 1;
+ _ad9862_regs.byp_buffer_b = 1;
+ _ad9862_regs.buffer_a_pd = 1;
+ _ad9862_regs.buffer_b_pd = 1;
+ _ad9862_regs.rx_pga_a = 0;
+ _ad9862_regs.rx_pga_b = 0;
+ _ad9862_regs.rx_twos_comp = 1;
+ _ad9862_regs.rx_hilbert = ad9862_regs_t::RX_HILBERT_DIS;
+
+ //setup tx side of codec
+ _ad9862_regs.two_data_paths = ad9862_regs_t::TWO_DATA_PATHS_BOTH;
+ _ad9862_regs.interleaved = ad9862_regs_t::INTERLEAVED_INTERLEAVED;
+ _ad9862_regs.tx_pga_gain = 199;
+ _ad9862_regs.tx_hilbert = ad9862_regs_t::TX_HILBERT_DIS;
+ _ad9862_regs.interp = ad9862_regs_t::INTERP_4;
+ _ad9862_regs.tx_twos_comp = 1;
+ _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO;
+ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS;
+ _ad9862_regs.dac_a_coarse_gain = 0x3;
+ _ad9862_regs.dac_b_coarse_gain = 0x3;
+
+ //setup the dll
+ _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL;
+ _ad9862_regs.dll_mult = ad9862_regs_t::DLL_MULT_2;
+ _ad9862_regs.dll_mode = ad9862_regs_t::DLL_MODE_FAST;
+
+ //setup clockout
+ _ad9862_regs.clkout2_div_factor = ad9862_regs_t::CLKOUT2_DIV_FACTOR_2;
+
+ //write the register settings to the codec
+ for (uint8_t addr = 0; addr <= 25; addr++) {
+ this->send_reg(addr);
+ }
+
+ //aux adc clock
+ _ad9862_regs.clk_4 = ad9862_regs_t::CLK_4_1_4;
+ this->send_reg(34);
+}
+
+usrp1_codec_ctrl_impl::~usrp1_codec_ctrl_impl(void)
+{
+ //set aux dacs to zero
+ this->write_aux_dac(AUX_DAC_A, 0);
+ this->write_aux_dac(AUX_DAC_B, 0);
+ this->write_aux_dac(AUX_DAC_C, 0);
+ this->write_aux_dac(AUX_DAC_D, 0);
+
+ //power down
+ _ad9862_regs.all_rx_pd = 1;
+ this->send_reg(1);
+ _ad9862_regs.tx_digital_pd = 1;
+ _ad9862_regs.tx_analog_pd = ad9862_regs_t::TX_ANALOG_PD_BOTH;
+ this->send_reg(8);
+}
+
+/***********************************************************************
+ * Codec Control Gain Control Methods
+ **********************************************************************/
+static const int mtpgw = 255; //maximum tx pga gain word
+
+void usrp1_codec_ctrl_impl::set_tx_pga_gain(float gain){
+ int gain_word = int(mtpgw*(gain - tx_pga_gain_range.min)/(tx_pga_gain_range.max - tx_pga_gain_range.min));
+ _ad9862_regs.tx_pga_gain = std::clip(gain_word, 0, mtpgw);
+ this->send_reg(16);
+}
+
+float usrp1_codec_ctrl_impl::get_tx_pga_gain(void){
+ return (_ad9862_regs.tx_pga_gain*(tx_pga_gain_range.max - tx_pga_gain_range.min)/mtpgw) + tx_pga_gain_range.min;
+}
+
+static const int mrpgw = 0x14; //maximum rx pga gain word
+
+void usrp1_codec_ctrl_impl::set_rx_pga_gain(float gain, char which){
+ int gain_word = int(mrpgw*(gain - rx_pga_gain_range.min)/(rx_pga_gain_range.max - rx_pga_gain_range.min));
+ gain_word = std::clip(gain_word, 0, mrpgw);
+ switch(which){
+ case 'A':
+ _ad9862_regs.rx_pga_a = gain_word;
+ this->send_reg(2);
+ return;
+ case 'B':
+ _ad9862_regs.rx_pga_b = gain_word;
+ this->send_reg(3);
+ return;
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
+float usrp1_codec_ctrl_impl::get_rx_pga_gain(char which){
+ int gain_word;
+ switch(which){
+ case 'A': gain_word = _ad9862_regs.rx_pga_a; break;
+ case 'B': gain_word = _ad9862_regs.rx_pga_b; break;
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+ return (gain_word*(rx_pga_gain_range.max - rx_pga_gain_range.min)/mrpgw) + rx_pga_gain_range.min;
+}
+
+/***********************************************************************
+ * Codec Control AUX ADC Methods
+ **********************************************************************/
+static float aux_adc_to_volts(boost::uint8_t high, boost::uint8_t low)
+{
+ return float((boost::uint16_t(high) << 2) | low)*3.3/0x3ff;
+}
+
+float usrp1_codec_ctrl_impl::read_aux_adc(aux_adc_t which)
+{
+ //check to see if the switch needs to be set
+ bool write_switch = false;
+ switch(which) {
+
+ case AUX_ADC_A1:
+ case AUX_ADC_A2:
+ if (which != _last_aux_adc_a) {
+ _ad9862_regs.select_a = (which == AUX_ADC_A1)?
+ ad9862_regs_t::SELECT_A_AUX_ADC1: ad9862_regs_t::SELECT_A_AUX_ADC2;
+ _last_aux_adc_a = which;
+ write_switch = true;
+ }
+ break;
+
+ case AUX_ADC_B1:
+ case AUX_ADC_B2:
+ if (which != _last_aux_adc_b) {
+ _ad9862_regs.select_b = (which == AUX_ADC_B1)?
+ ad9862_regs_t::SELECT_B_AUX_ADC1: ad9862_regs_t::SELECT_B_AUX_ADC2;
+ _last_aux_adc_b = which;
+ write_switch = true;
+ }
+ break;
+
+ }
+
+ //write the switch if it changed
+ if(write_switch) this->send_reg(34);
+
+ //map aux adcs to register values to read
+ static const uhd::dict<aux_adc_t, boost::uint8_t> aux_dac_to_addr = boost::assign::map_list_of
+ (AUX_ADC_A2, 26) (AUX_ADC_A1, 28)
+ (AUX_ADC_B2, 30) (AUX_ADC_B1, 32)
+ ;
+
+ //read the value
+ this->recv_reg(aux_dac_to_addr[which]+0);
+ this->recv_reg(aux_dac_to_addr[which]+1);
+
+ //return the value scaled to volts
+ switch(which) {
+ case AUX_ADC_A1: return aux_adc_to_volts(_ad9862_regs.aux_adc_a1_9_2, _ad9862_regs.aux_adc_a1_1_0);
+ case AUX_ADC_A2: return aux_adc_to_volts(_ad9862_regs.aux_adc_a2_9_2, _ad9862_regs.aux_adc_a2_1_0);
+ case AUX_ADC_B1: return aux_adc_to_volts(_ad9862_regs.aux_adc_b1_9_2, _ad9862_regs.aux_adc_b1_1_0);
+ case AUX_ADC_B2: return aux_adc_to_volts(_ad9862_regs.aux_adc_b2_9_2, _ad9862_regs.aux_adc_b2_1_0);
+ }
+ UHD_ASSERT_THROW(false);
+}
+
+/***********************************************************************
+ * Codec Control AUX DAC Methods
+ **********************************************************************/
+void usrp1_codec_ctrl_impl::write_aux_dac(aux_dac_t which, float volts)
+{
+ //special case for aux dac d (aka sigma delta word)
+ if (which == AUX_DAC_D) {
+ boost::uint16_t dac_word = std::clip(boost::math::iround(volts*0xfff/3.3), 0, 0xfff);
+ _ad9862_regs.sig_delt_11_4 = boost::uint8_t(dac_word >> 4);
+ _ad9862_regs.sig_delt_3_0 = boost::uint8_t(dac_word & 0xf);
+ this->send_reg(42);
+ this->send_reg(43);
+ return;
+ }
+
+ //calculate the dac word for aux dac a, b, c
+ boost::uint8_t dac_word = std::clip(boost::math::iround(volts*0xff/3.3), 0, 0xff);
+
+ //setup a lookup table for the aux dac params (reg ref, reg addr)
+ typedef boost::tuple<boost::uint8_t*, boost::uint8_t> dac_params_t;
+ uhd::dict<aux_dac_t, dac_params_t> aux_dac_to_params = boost::assign::map_list_of
+ (AUX_DAC_A, dac_params_t(&_ad9862_regs.aux_dac_a, 36))
+ (AUX_DAC_B, dac_params_t(&_ad9862_regs.aux_dac_b, 37))
+ (AUX_DAC_C, dac_params_t(&_ad9862_regs.aux_dac_c, 38))
+ ;
+
+ //set the aux dac register
+ UHD_ASSERT_THROW(aux_dac_to_params.has_key(which));
+ boost::uint8_t *reg_ref, reg_addr;
+ boost::tie(reg_ref, reg_addr) = aux_dac_to_params[which];
+ *reg_ref = dac_word;
+ this->send_reg(reg_addr);
+}
+
+/***********************************************************************
+ * Codec Control SPI Methods
+ **********************************************************************/
+void usrp1_codec_ctrl_impl::send_reg(boost::uint8_t addr)
+{
+ boost::uint32_t reg = _ad9862_regs.get_write_reg(addr);
+
+ if (codec_debug) {
+ std::cout.fill('0');
+ std::cout << "codec control write reg: 0x";
+ std::cout << std::setw(8) << std::hex << reg << std::endl;
+ }
+ _iface->transact_spi(_spi_slave,
+ spi_config_t::EDGE_RISE, reg, 16, false);
+}
+
+void usrp1_codec_ctrl_impl::recv_reg(boost::uint8_t addr)
+{
+ boost::uint32_t reg = _ad9862_regs.get_read_reg(addr);
+
+ if (codec_debug) {
+ std::cout.fill('0');
+ std::cout << "codec control read reg: 0x";
+ std::cout << std::setw(8) << std::hex << reg << std::endl;
+ }
+
+ boost::uint32_t ret = _iface->transact_spi(_spi_slave,
+ spi_config_t::EDGE_RISE, reg, 16, true);
+
+ if (codec_debug) {
+ std::cout.fill('0');
+ std::cout << "codec control read ret: 0x";
+ std::cout << std::setw(8) << std::hex << ret << std::endl;
+ }
+
+ _ad9862_regs.set_reg(addr, boost::uint16_t(ret));
+}
+
+/***********************************************************************
+ * DUC tuning
+ **********************************************************************/
+double usrp1_codec_ctrl_impl::coarse_tune(double codec_rate, double freq)
+{
+ double coarse_freq;
+
+ double coarse_freq_1 = codec_rate / 8;
+ double coarse_freq_2 = codec_rate / 4;
+ double coarse_limit_1 = coarse_freq_1 / 2;
+ double coarse_limit_2 = (coarse_freq_1 + coarse_freq_2) / 2;
+ double max_freq = coarse_freq_2 + .09375 * codec_rate;
+
+ if (freq < -max_freq) {
+ return false;
+ }
+ else if (freq < -coarse_limit_2) {
+ _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;
+ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4;
+ coarse_freq = -coarse_freq_2;
+ }
+ else if (freq < -coarse_limit_1) {
+ _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_NEG_SHIFT;
+ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8;
+ coarse_freq = -coarse_freq_1;
+ }
+ else if (freq < coarse_limit_1) {
+ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS;
+ coarse_freq = 0;
+ }
+ else if (freq < coarse_limit_2) {
+ _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;
+ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_8;
+ coarse_freq = coarse_freq_1;
+ }
+ else if (freq <= max_freq) {
+ _ad9862_regs.neg_coarse_tune = ad9862_regs_t::NEG_COARSE_TUNE_POS_SHIFT;
+ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_FDAC_4;
+ coarse_freq = coarse_freq_2;
+ }
+ else {
+ return 0;
+ }
+
+ return coarse_freq;
+}
+
+double usrp1_codec_ctrl_impl::fine_tune(double codec_rate, double target_freq)
+{
+ static const double scale_factor = std::pow(2.0, 24);
+
+ boost::uint32_t freq_word = boost::uint32_t(
+ boost::math::round(abs((target_freq / codec_rate) * scale_factor)));
+
+ double actual_freq = freq_word * codec_rate / scale_factor;
+
+ if (target_freq < 0) {
+ _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_NEG_SHIFT;
+ actual_freq = -actual_freq;
+ }
+ else {
+ _ad9862_regs.neg_fine_tune = ad9862_regs_t::NEG_FINE_TUNE_POS_SHIFT;
+ }
+
+ _ad9862_regs.fine_mode = ad9862_regs_t::FINE_MODE_NCO;
+ _ad9862_regs.ftw_23_16 = (freq_word >> 16) & 0xff;
+ _ad9862_regs.ftw_15_8 = (freq_word >> 8) & 0xff;
+ _ad9862_regs.ftw_7_0 = (freq_word >> 0) & 0xff;
+
+ return actual_freq;
+}
+
+void usrp1_codec_ctrl_impl::set_duc_freq(double freq)
+{
+ double codec_rate = _clock_ctrl->get_master_clock_freq() * 2;
+ double coarse_freq = coarse_tune(codec_rate, freq);
+ double fine_freq = fine_tune(codec_rate / 4, freq - coarse_freq);
+
+ if (codec_debug) {
+ std::cout << "ad9862 tuning result:" << std::endl;
+ std::cout << " requested: " << freq << std::endl;
+ std::cout << " actual: " << coarse_freq + fine_freq << std::endl;
+ std::cout << " coarse freq: " << coarse_freq << std::endl;
+ std::cout << " fine freq: " << fine_freq << std::endl;
+ std::cout << " codec rate: " << codec_rate << std::endl;
+ }
+
+ this->send_reg(20);
+ this->send_reg(21);
+ this->send_reg(22);
+ this->send_reg(23);
+}
+
+/***********************************************************************
+ * Codec Control Make
+ **********************************************************************/
+usrp1_codec_ctrl::sptr usrp1_codec_ctrl::make(usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock,
+ int spi_slave)
+{
+ return sptr(new usrp1_codec_ctrl_impl(iface, clock, spi_slave));
+}
diff --git a/host/lib/usrp/usrp1/codec_ctrl.hpp b/host/lib/usrp/usrp1/codec_ctrl.hpp
new file mode 100644
index 000000000..259d10ef4
--- /dev/null
+++ b/host/lib/usrp/usrp1/codec_ctrl.hpp
@@ -0,0 +1,97 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_USRP1_CODEC_CTRL_HPP
+#define INCLUDED_USRP1_CODEC_CTRL_HPP
+
+#include "usrp1_iface.hpp"
+#include "clock_ctrl.hpp"
+#include <uhd/types/ranges.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+/*!
+ * The usrp1 codec control:
+ * - Init/power down codec.
+ * - Read aux adc, write aux dac.
+ */
+class usrp1_codec_ctrl : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<usrp1_codec_ctrl> sptr;
+
+ static const uhd::gain_range_t tx_pga_gain_range;
+ static const uhd::gain_range_t rx_pga_gain_range;
+
+ /*!
+ * Make a new clock control object.
+ * \param iface the usrp1 iface object
+ * \param spi_slave which spi device
+ * \return the clock control object
+ */
+ static sptr make(usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock, int spi_slave
+ );
+
+ //! aux adc identifier constants
+ enum aux_adc_t{
+ AUX_ADC_A2 = 0xA2,
+ AUX_ADC_A1 = 0xA1,
+ AUX_ADC_B2 = 0xB2,
+ AUX_ADC_B1 = 0xB1
+ };
+
+ /*!
+ * Read an auxiliary adc:
+ * The internals remember which aux adc was read last.
+ * Therefore, the aux adc switch is only changed as needed.
+ * \param which which of the 4 adcs
+ * \return a value in volts
+ */
+ virtual float read_aux_adc(aux_adc_t which) = 0;
+
+ //! aux dac identifier constants
+ enum aux_dac_t{
+ AUX_DAC_A = 0xA,
+ AUX_DAC_B = 0xB,
+ AUX_DAC_C = 0xC,
+ AUX_DAC_D = 0xD
+ };
+
+ /*!
+ * Write an auxiliary dac.
+ * \param which which of the 4 dacs
+ * \param volts the level in in volts
+ */
+ virtual void write_aux_dac(aux_dac_t which, float volts) = 0;
+
+ //! Set the TX PGA gain
+ virtual void set_tx_pga_gain(float gain) = 0;
+
+ //! Get the TX PGA gain
+ virtual float get_tx_pga_gain(void) = 0;
+
+ //! Set the RX PGA gain ('A' or 'B')
+ virtual void set_rx_pga_gain(float gain, char which) = 0;
+
+ //! Get the RX PGA gain ('A' or 'B')
+ virtual float get_rx_pga_gain(char which) = 0;
+
+ //! Set the TX modulator frequency
+ virtual void set_duc_freq(double freq) = 0;
+};
+
+#endif /* INCLUDED_USRP1_CODEC_CTRL_HPP */
diff --git a/host/lib/usrp/usrp1/codec_impl.cpp b/host/lib/usrp/usrp1/codec_impl.cpp
new file mode 100644
index 000000000..1756c1ed4
--- /dev/null
+++ b/host/lib/usrp/usrp1/codec_impl.cpp
@@ -0,0 +1,157 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_impl.hpp"
+#include <uhd/utils/assert.hpp>
+#include <uhd/usrp/codec_props.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Helper Methods
+ **********************************************************************/
+void usrp1_impl::codec_init(void)
+{
+ //make proxies
+ BOOST_FOREACH(dboard_slot_t dboard_slot, _dboard_slots){
+ _rx_codec_proxies[dboard_slot] = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::rx_codec_get, this, _1, _2, dboard_slot),
+ boost::bind(&usrp1_impl::rx_codec_set, this, _1, _2, dboard_slot));
+
+ _tx_codec_proxies[dboard_slot] = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::tx_codec_get, this, _1, _2, dboard_slot),
+ boost::bind(&usrp1_impl::tx_codec_set, this, _1, _2, dboard_slot));
+ }
+}
+
+/***********************************************************************
+ * RX Codec Properties
+ **********************************************************************/
+static const std::string ad9862_pga_gain_name = "ad9862 pga";
+
+void usrp1_impl::rx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<codec_prop_t>()) {
+ case CODEC_PROP_NAME:
+ val = str(boost::format("usrp1 adc - ad9862 - slot %c") % char(dboard_slot));
+ return;
+
+ case CODEC_PROP_OTHERS:
+ val = prop_names_t();
+ return;
+
+ case CODEC_PROP_GAIN_NAMES:
+ val = prop_names_t(1, ad9862_pga_gain_name);
+ return;
+
+ case CODEC_PROP_GAIN_RANGE:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ val = usrp1_codec_ctrl::rx_pga_gain_range;
+ return;
+
+ case CODEC_PROP_GAIN_I:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('A');
+ return;
+
+ case CODEC_PROP_GAIN_Q:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ val = _codec_ctrls[dboard_slot]->get_rx_pga_gain('B');
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void usrp1_impl::rx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_slot_t dboard_slot)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the set request conditioned on the key
+ switch(key.as<codec_prop_t>()) {
+ case CODEC_PROP_GAIN_I:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as<float>(), 'A');
+ return;
+
+ case CODEC_PROP_GAIN_Q:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ _codec_ctrls[dboard_slot]->set_rx_pga_gain(val.as<float>(), 'B');
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * TX Codec Properties
+ **********************************************************************/
+void usrp1_impl::tx_codec_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<codec_prop_t>()) {
+ case CODEC_PROP_NAME:
+ val = str(boost::format("usrp1 dac - ad9862 - slot %c") % char(dboard_slot));
+ return;
+
+ case CODEC_PROP_OTHERS:
+ val = prop_names_t();
+ return;
+
+ case CODEC_PROP_GAIN_NAMES:
+ val = prop_names_t(1, ad9862_pga_gain_name);
+ return;
+
+ case CODEC_PROP_GAIN_RANGE:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ val = usrp1_codec_ctrl::tx_pga_gain_range;
+ return;
+
+ case CODEC_PROP_GAIN_I: //only one gain for I and Q
+ case CODEC_PROP_GAIN_Q:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ val = _codec_ctrls[dboard_slot]->get_tx_pga_gain();
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+void usrp1_impl::tx_codec_set(const wax::obj &key_, const wax::obj &val, dboard_slot_t dboard_slot)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the set request conditioned on the key
+ switch(key.as<codec_prop_t>()){
+ case CODEC_PROP_GAIN_I: //only one gain for I and Q
+ case CODEC_PROP_GAIN_Q:
+ UHD_ASSERT_THROW(key.name == ad9862_pga_gain_name);
+ _codec_ctrls[dboard_slot]->set_tx_pga_gain(val.as<float>());
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp
new file mode 100644
index 000000000..4791b55ce
--- /dev/null
+++ b/host/lib/usrp/usrp1/dboard_iface.cpp
@@ -0,0 +1,371 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_iface.hpp"
+#include "usrp1_impl.hpp"
+#include "fpga_regs_common.h"
+#include "usrp_spi_defs.h"
+#include "fpga_regs_standard.h"
+#include "clock_ctrl.hpp"
+#include "codec_ctrl.hpp"
+#include <uhd/usrp/dboard_iface.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/utils/assert.hpp>
+#include <boost/assign/list_of.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace boost::assign;
+
+class usrp1_dboard_iface : public dboard_iface {
+public:
+
+ usrp1_dboard_iface(usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock,
+ usrp1_codec_ctrl::sptr codec,
+ usrp1_impl::dboard_slot_t dboard_slot,
+ const dboard_id_t &rx_dboard_id
+ ):
+ _dboard_slot(dboard_slot),
+ _rx_dboard_id(rx_dboard_id)
+ {
+ _iface = iface;
+ _clock = clock;
+ _codec = codec;
+
+ //init the clock rate shadows
+ this->set_clock_rate(UNIT_RX, this->get_clock_rates(UNIT_RX).front());
+ this->set_clock_rate(UNIT_TX, this->get_clock_rates(UNIT_TX).front());
+ }
+
+ ~usrp1_dboard_iface()
+ {
+ /* NOP */
+ }
+
+ special_props_t get_special_props()
+ {
+ special_props_t props;
+ props.soft_clock_divider = true;
+ props.mangle_i2c_addrs = (_dboard_slot == usrp1_impl::DBOARD_SLOT_B);
+ return props;
+ }
+
+ void write_aux_dac(unit_t, aux_dac_t, float);
+ float read_aux_adc(unit_t, aux_adc_t);
+
+ void set_pin_ctrl(unit_t, boost::uint16_t);
+ void set_atr_reg(unit_t, atr_reg_t, boost::uint16_t);
+ void set_gpio_ddr(unit_t, boost::uint16_t);
+ void write_gpio(unit_t, boost::uint16_t);
+ void set_gpio_debug(unit_t, int);
+ boost::uint16_t read_gpio(unit_t);
+
+ void write_i2c(boost::uint8_t, const byte_vector_t &);
+ byte_vector_t read_i2c(boost::uint8_t, size_t);
+
+ void write_spi(unit_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits);
+
+ boost::uint32_t read_write_spi(unit_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits);
+
+ void set_clock_rate(unit_t, double);
+ std::vector<double> get_clock_rates(unit_t);
+ double get_clock_rate(unit_t);
+ void set_clock_enabled(unit_t, bool);
+
+private:
+ usrp1_iface::sptr _iface;
+ usrp1_clock_ctrl::sptr _clock;
+ usrp1_codec_ctrl::sptr _codec;
+ uhd::dict<unit_t, double> _clock_rates;
+ const usrp1_impl::dboard_slot_t _dboard_slot;
+ const dboard_id_t &_rx_dboard_id;
+};
+
+/***********************************************************************
+ * Make Function
+ **********************************************************************/
+dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock,
+ usrp1_codec_ctrl::sptr codec,
+ dboard_slot_t dboard_slot,
+ const dboard_id_t &rx_dboard_id
+){
+ return dboard_iface::sptr(new usrp1_dboard_iface(
+ iface, clock, codec, dboard_slot, rx_dboard_id
+ ));
+}
+
+/***********************************************************************
+ * Clock Rates
+ **********************************************************************/
+static const dboard_id_t dbsrx_classic_id(0x0002);
+
+/*
+ * Daughterboard reference clock register
+ *
+ * Bit 7 - 1 turns on refclk, 0 allows IO use
+ * Bits 6:0 - Divider value
+ */
+void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate)
+{
+ assert_has(this->get_clock_rates(unit), rate, "dboard clock rate");
+ _clock_rates[unit] = rate;
+
+ if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){
+ size_t divider = size_t(_clock->get_master_clock_freq()/rate);
+ switch(_dboard_slot){
+ case usrp1_impl::DBOARD_SLOT_A:
+ _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80);
+ break;
+
+ case usrp1_impl::DBOARD_SLOT_B:
+ _iface->poke32(FR_RX_B_REFCLK, (divider & 0x7f) | 0x80);
+ break;
+ }
+ }
+}
+
+std::vector<double> usrp1_dboard_iface::get_clock_rates(unit_t unit)
+{
+ std::vector<double> rates;
+ if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){
+ for (size_t div = 1; div <= 127; div++)
+ rates.push_back(_clock->get_master_clock_freq() / div);
+ }
+ else{
+ rates.push_back(_clock->get_master_clock_freq());
+ }
+ return rates;
+}
+
+double usrp1_dboard_iface::get_clock_rate(unit_t unit)
+{
+ return _clock_rates[unit];
+}
+
+void usrp1_dboard_iface::set_clock_enabled(unit_t, bool)
+{
+ //TODO we can only enable for special case anyway...
+}
+
+/***********************************************************************
+ * GPIO
+ **********************************************************************/
+void usrp1_dboard_iface::set_pin_ctrl(unit_t unit, boost::uint16_t value)
+{
+ switch(unit) {
+ case UNIT_RX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_ATR_MASK_1, value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_ATR_MASK_3, value);
+ break;
+ case UNIT_TX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_ATR_MASK_0, value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_ATR_MASK_2, value);
+ break;
+ }
+}
+
+void usrp1_dboard_iface::set_gpio_ddr(unit_t unit, boost::uint16_t value)
+{
+ switch(unit) {
+ case UNIT_RX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_OE_1, 0xffff0000 | value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_OE_3, 0xffff0000 | value);
+ break;
+ case UNIT_TX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_OE_0, 0xffff0000 | value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_OE_2, 0xffff0000 | value);
+ break;
+ }
+}
+
+void usrp1_dboard_iface::write_gpio(unit_t unit, boost::uint16_t value)
+{
+ switch(unit) {
+ case UNIT_RX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_IO_1, 0xffff0000 | value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_IO_3, 0xffff0000 | value);
+ break;
+ case UNIT_TX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_IO_0, 0xffff0000 | value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_IO_2, 0xffff0000 | value);
+ break;
+ }
+}
+
+void usrp1_dboard_iface::set_gpio_debug(unit_t, int)
+{
+ /* NOP */
+}
+
+boost::uint16_t usrp1_dboard_iface::read_gpio(unit_t unit)
+{
+ boost::uint32_t out_value;
+
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ out_value = _iface->peek32(1);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ out_value = _iface->peek32(2);
+ else
+ UHD_THROW_INVALID_CODE_PATH();
+
+ switch(unit) {
+ case UNIT_RX:
+ return (boost::uint16_t)((out_value >> 16) & 0x0000ffff);
+ case UNIT_TX:
+ return (boost::uint16_t)((out_value >> 0) & 0x0000ffff);
+ }
+ UHD_ASSERT_THROW(false);
+}
+
+void usrp1_dboard_iface::set_atr_reg(unit_t unit,
+ atr_reg_t atr, boost::uint16_t value)
+{
+ // Ignore unsupported states
+ if ((atr == ATR_REG_IDLE) || (atr == ATR_REG_FULL_DUPLEX))
+ return;
+
+ switch(unit) {
+ case UNIT_RX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_ATR_RXVAL_1, value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_ATR_RXVAL_3, value);
+ break;
+ case UNIT_TX:
+ if (_dboard_slot == usrp1_impl::DBOARD_SLOT_A)
+ _iface->poke32(FR_ATR_TXVAL_0, value);
+ else if (_dboard_slot == usrp1_impl::DBOARD_SLOT_B)
+ _iface->poke32(FR_ATR_TXVAL_2, value);
+ break;
+ }
+}
+/***********************************************************************
+ * SPI
+ **********************************************************************/
+/*!
+ * Static function to convert a unit type to a spi slave device number.
+ * \param unit the dboard interface unit type enum
+ * \param slot the side (A or B) the dboard is attached
+ * \return the slave device number
+ */
+static boost::uint32_t unit_to_otw_spi_dev(dboard_iface::unit_t unit,
+ usrp1_impl::dboard_slot_t slot)
+{
+ switch(unit) {
+ case dboard_iface::UNIT_TX:
+ if (slot == usrp1_impl::DBOARD_SLOT_A)
+ return SPI_ENABLE_TX_A;
+ else if (slot == usrp1_impl::DBOARD_SLOT_B)
+ return SPI_ENABLE_TX_B;
+ else
+ break;
+ case dboard_iface::UNIT_RX:
+ if (slot == usrp1_impl::DBOARD_SLOT_A)
+ return SPI_ENABLE_RX_A;
+ else if (slot == usrp1_impl::DBOARD_SLOT_B)
+ return SPI_ENABLE_RX_B;
+ else
+ break;
+ }
+ throw std::invalid_argument("unknown unit type");
+}
+
+void usrp1_dboard_iface::write_spi(unit_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits)
+{
+ _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot),
+ config, data, num_bits, false);
+}
+
+boost::uint32_t usrp1_dboard_iface::read_write_spi(unit_t unit,
+ const spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits)
+{
+ return _iface->transact_spi(unit_to_otw_spi_dev(unit, _dboard_slot),
+ config, data, num_bits, true);
+}
+
+/***********************************************************************
+ * I2C
+ **********************************************************************/
+void usrp1_dboard_iface::write_i2c(boost::uint8_t addr,
+ const byte_vector_t &bytes)
+{
+ return _iface->write_i2c(addr, bytes);
+}
+
+byte_vector_t usrp1_dboard_iface::read_i2c(boost::uint8_t addr,
+ size_t num_bytes)
+{
+ return _iface->read_i2c(addr, num_bytes);
+}
+
+/***********************************************************************
+ * Aux DAX/ADC
+ **********************************************************************/
+void usrp1_dboard_iface::write_aux_dac(dboard_iface::unit_t,
+ aux_dac_t which, float value)
+{
+ //same aux dacs for each unit
+ static const uhd::dict<aux_dac_t, usrp1_codec_ctrl::aux_dac_t>
+ which_to_aux_dac = map_list_of
+ (AUX_DAC_A, usrp1_codec_ctrl::AUX_DAC_A)
+ (AUX_DAC_B, usrp1_codec_ctrl::AUX_DAC_B)
+ (AUX_DAC_C, usrp1_codec_ctrl::AUX_DAC_C)
+ (AUX_DAC_D, usrp1_codec_ctrl::AUX_DAC_D);
+
+ _codec->write_aux_dac(which_to_aux_dac[which], value);
+}
+
+float usrp1_dboard_iface::read_aux_adc(dboard_iface::unit_t unit,
+ aux_adc_t which)
+{
+ static const
+ uhd::dict<unit_t, uhd::dict<aux_adc_t, usrp1_codec_ctrl::aux_adc_t> >
+ unit_to_which_to_aux_adc = map_list_of(UNIT_RX, map_list_of
+ (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A1)
+ (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B1))
+ (UNIT_TX, map_list_of
+ (AUX_ADC_A, usrp1_codec_ctrl::AUX_ADC_A2)
+ (AUX_ADC_B, usrp1_codec_ctrl::AUX_ADC_B2));
+
+ return _codec->read_aux_adc(unit_to_which_to_aux_adc[unit][which]);
+}
diff --git a/host/lib/usrp/usrp1/dboard_impl.cpp b/host/lib/usrp/usrp1/dboard_impl.cpp
new file mode 100644
index 000000000..3a8480e1b
--- /dev/null
+++ b/host/lib/usrp/usrp1/dboard_impl.cpp
@@ -0,0 +1,217 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_impl.hpp"
+#include "usrp_i2c_addr.h"
+#include <uhd/usrp/dsp_utils.hpp>
+#include <uhd/usrp/misc_utils.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/usrp/dboard_props.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <boost/bind.hpp>
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Helper Functions
+ **********************************************************************/
+static boost::uint8_t get_rx_ee_addr(usrp1_impl::dboard_slot_t dboard_slot){
+ switch(dboard_slot){
+ case usrp1_impl::DBOARD_SLOT_A: return I2C_ADDR_RX_A;
+ case usrp1_impl::DBOARD_SLOT_B: return I2C_ADDR_RX_B;
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
+static boost::uint8_t get_tx_ee_addr(usrp1_impl::dboard_slot_t dboard_slot){
+ switch(dboard_slot){
+ case usrp1_impl::DBOARD_SLOT_A: return I2C_ADDR_TX_A;
+ case usrp1_impl::DBOARD_SLOT_B: return I2C_ADDR_TX_B;
+ default: UHD_THROW_INVALID_CODE_PATH();
+ }
+}
+
+/***********************************************************************
+ * Dboard Initialization
+ **********************************************************************/
+void usrp1_impl::dboard_init(void)
+{
+ BOOST_FOREACH(dboard_slot_t dboard_slot, _dboard_slots){
+
+ //read the tx and rx dboard eeproms
+ _rx_db_eeproms[dboard_slot] = dboard_eeprom_t(_iface->read_eeprom(
+ get_rx_ee_addr(dboard_slot), 0, dboard_eeprom_t::num_bytes()
+ ));
+
+ _tx_db_eeproms[dboard_slot] = dboard_eeprom_t(_iface->read_eeprom(
+ get_tx_ee_addr(dboard_slot), 0, dboard_eeprom_t::num_bytes()
+ ));
+
+ //create a new dboard interface and manager
+ _dboard_ifaces[dboard_slot] = make_dboard_iface(
+ _iface, _clock_ctrl, _codec_ctrls[dboard_slot],
+ dboard_slot, _rx_db_eeproms[dboard_slot].id
+ );
+
+ _dboard_managers[dboard_slot] = dboard_manager::make(
+ _rx_db_eeproms[dboard_slot].id,
+ _tx_db_eeproms[dboard_slot].id,
+ _dboard_ifaces[dboard_slot]
+ );
+
+ //setup the dboard proxies
+ _rx_dboard_proxies[dboard_slot] = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::rx_dboard_get, this, _1, _2, dboard_slot),
+ boost::bind(&usrp1_impl::rx_dboard_set, this, _1, _2, dboard_slot));
+
+ _tx_dboard_proxies[dboard_slot] = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::tx_dboard_get, this, _1, _2, dboard_slot),
+ boost::bind(&usrp1_impl::tx_dboard_set, this, _1, _2, dboard_slot));
+ }
+
+}
+
+/***********************************************************************
+ * RX Dboard Get
+ **********************************************************************/
+void usrp1_impl::rx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<dboard_prop_t>()){
+ case DBOARD_PROP_NAME:
+ val = str(boost::format("usrp1 dboard (rx unit) - %c") % char(dboard_slot));
+ return;
+
+ case DBOARD_PROP_SUBDEV:
+ val = _dboard_managers[dboard_slot]->get_rx_subdev(key.name);
+ return;
+
+ case DBOARD_PROP_SUBDEV_NAMES:
+ val = _dboard_managers[dboard_slot]->get_rx_subdev_names();
+ return;
+
+ case DBOARD_PROP_DBOARD_ID:
+ val = _rx_db_eeproms[dboard_slot].id;
+ return;
+
+ case DBOARD_PROP_DBOARD_IFACE:
+ val = _dboard_ifaces[dboard_slot];
+ return;
+
+ case DBOARD_PROP_CODEC:
+ val = _rx_codec_proxies[dboard_slot]->get_link();
+ return;
+
+ case DBOARD_PROP_GAIN_GROUP:
+ val = make_gain_group(
+ _dboard_managers[dboard_slot]->get_rx_subdev(key.name),
+ _rx_codec_proxies[dboard_slot]->get_link(),
+ GAIN_GROUP_POLICY_RX
+ );
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * RX Dboard Set
+ **********************************************************************/
+void usrp1_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_slot_t dboard_slot)
+{
+ switch(key.as<dboard_prop_t>()) {
+ case DBOARD_PROP_DBOARD_ID:
+ _rx_db_eeproms[dboard_slot].id = val.as<dboard_id_t>();
+ _iface->write_eeprom(
+ get_rx_ee_addr(dboard_slot), 0,
+ _rx_db_eeproms[dboard_slot].get_eeprom_bytes()
+ );
+ return;
+
+ default:
+ UHD_THROW_PROP_SET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * TX Dboard Get
+ **********************************************************************/
+void usrp1_impl::tx_dboard_get(const wax::obj &key_, wax::obj &val, dboard_slot_t dboard_slot)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<dboard_prop_t>()){
+ case DBOARD_PROP_NAME:
+ val = str(boost::format("usrp1 dboard (tx unit) - %c") % char(dboard_slot));
+ return;
+
+ case DBOARD_PROP_SUBDEV:
+ val = _dboard_managers[dboard_slot]->get_tx_subdev(key.name);
+ return;
+
+ case DBOARD_PROP_SUBDEV_NAMES:
+ val = _dboard_managers[dboard_slot]->get_tx_subdev_names();
+ return;
+
+ case DBOARD_PROP_DBOARD_ID:
+ val = _tx_db_eeproms[dboard_slot].id;
+ return;
+
+ case DBOARD_PROP_DBOARD_IFACE:
+ val = _dboard_ifaces[dboard_slot];
+ return;
+
+ case DBOARD_PROP_CODEC:
+ val = _tx_codec_proxies[dboard_slot]->get_link();
+ return;
+
+ case DBOARD_PROP_GAIN_GROUP:
+ val = make_gain_group(
+ _dboard_managers[dboard_slot]->get_tx_subdev(key.name),
+ _tx_codec_proxies[dboard_slot]->get_link(),
+ GAIN_GROUP_POLICY_TX
+ );
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * TX Dboard Set
+ **********************************************************************/
+void usrp1_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val, dboard_slot_t dboard_slot)
+{
+ switch(key.as<dboard_prop_t>()) {
+ case DBOARD_PROP_DBOARD_ID:
+ _tx_db_eeproms[dboard_slot].id = val.as<dboard_id_t>();
+ _iface->write_eeprom(
+ get_tx_ee_addr(dboard_slot), 0,
+ _tx_db_eeproms[dboard_slot].get_eeprom_bytes()
+ );
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
diff --git a/host/lib/usrp/usrp1/dsp_impl.cpp b/host/lib/usrp/usrp1/dsp_impl.cpp
new file mode 100644
index 000000000..d5a88fa2d
--- /dev/null
+++ b/host/lib/usrp/usrp1/dsp_impl.cpp
@@ -0,0 +1,205 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_impl.hpp"
+#include "fpga_regs_standard.h"
+#include <uhd/usrp/dsp_utils.hpp>
+#include <uhd/usrp/dsp_props.hpp>
+#include <boost/bind.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+#include <cmath>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * RX DDC Initialization
+ **********************************************************************/
+void usrp1_impl::rx_dsp_init(void)
+{
+ _rx_dsp_proxy = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::rx_dsp_get, this, _1, _2),
+ boost::bind(&usrp1_impl::rx_dsp_set, this, _1, _2));
+
+ rx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() / 16);
+}
+
+/***********************************************************************
+ * RX DDC Get
+ **********************************************************************/
+void usrp1_impl::rx_dsp_get(const wax::obj &key, wax::obj &val)
+{
+ switch(key.as<dsp_prop_t>()){
+ case DSP_PROP_NAME:
+ val = std::string("usrp1 ddc0");
+ return;
+
+ case DSP_PROP_OTHERS:
+ val = prop_names_t();
+ return;
+
+ case DSP_PROP_FREQ_SHIFT:
+ val = _rx_dsp_freq;
+ return;
+
+ case DSP_PROP_CODEC_RATE:
+ val = _clock_ctrl->get_master_clock_freq();
+ return;
+
+ case DSP_PROP_HOST_RATE:
+ val = _clock_ctrl->get_master_clock_freq()/_rx_dsp_decim;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+
+}
+
+/***********************************************************************
+ * RX DDC Set
+ **********************************************************************/
+void usrp1_impl::rx_dsp_set(const wax::obj &key, const wax::obj &val)
+{
+ switch(key.as<dsp_prop_t>()) {
+ case DSP_PROP_FREQ_SHIFT: {
+ double new_freq = val.as<double>();
+ boost::uint32_t reg_word = dsp_type1::calc_cordic_word_and_update(
+ new_freq, _clock_ctrl->get_master_clock_freq());
+
+ //TODO TODO TODO TODO TODO TODO TODO TODO TODO
+ //
+ // Handle multiple receive channels / DDC's
+ //
+ //TODO TODO TODO TODO TODO TODO TODO TODO TODO
+ _iface->poke32(FR_RX_FREQ_0, reg_word);
+ _iface->poke32(FR_RX_FREQ_1, reg_word);
+ _iface->poke32(FR_RX_FREQ_2, reg_word);
+ _iface->poke32(FR_RX_FREQ_3, reg_word);
+
+ _rx_dsp_freq = new_freq;
+ return;
+ }
+ case DSP_PROP_HOST_RATE: {
+ unsigned int rate =
+ _clock_ctrl->get_master_clock_freq() / val.as<double>();
+
+ if ((rate & 0x01) || (rate < 4) || (rate > 256)) {
+ std::cerr << "Decimation must be even and between 4 and 256"
+ << std::endl;
+ return;
+ }
+
+ _rx_dsp_decim = rate;
+ //TODO Poll every 100ms. Make it selectable?
+ _rx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() / rate;
+
+ _iface->poke32(FR_DECIM_RATE, _rx_dsp_decim/2 - 1);
+ }
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+
+}
+
+/***********************************************************************
+ * TX DUC Initialization
+ **********************************************************************/
+void usrp1_impl::tx_dsp_init(void)
+{
+ _tx_dsp_proxy = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::tx_dsp_get, this, _1, _2),
+ boost::bind(&usrp1_impl::tx_dsp_set, this, _1, _2));
+
+ //initial config and update
+ tx_dsp_set(DSP_PROP_HOST_RATE, _clock_ctrl->get_master_clock_freq() * 2 / 16);
+}
+
+/***********************************************************************
+ * TX DUC Get
+ **********************************************************************/
+void usrp1_impl::tx_dsp_get(const wax::obj &key, wax::obj &val)
+{
+ switch(key.as<dsp_prop_t>()) {
+ case DSP_PROP_NAME:
+ val = std::string("usrp1 duc0");
+ return;
+
+ case DSP_PROP_OTHERS:
+ val = prop_names_t(); //empty
+ return;
+
+ case DSP_PROP_FREQ_SHIFT:
+ val = _tx_dsp_freq;
+ return;
+
+ case DSP_PROP_CODEC_RATE:
+ val = _clock_ctrl->get_master_clock_freq() * 2;
+ return;
+
+ case DSP_PROP_HOST_RATE:
+ val = _clock_ctrl->get_master_clock_freq() * 2 / _tx_dsp_interp;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+
+}
+
+/***********************************************************************
+ * TX DUC Set
+ **********************************************************************/
+void usrp1_impl::tx_dsp_set(const wax::obj &key, const wax::obj &val)
+{
+ switch(key.as<dsp_prop_t>()) {
+
+ //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
+ //
+ // Set both codec frequencies until we have duality properties
+ //
+ //TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
+ case DSP_PROP_FREQ_SHIFT: {
+ double new_freq = val.as<double>();
+ _codec_ctrls[DBOARD_SLOT_A]->set_duc_freq(new_freq);
+ _codec_ctrls[DBOARD_SLOT_B]->set_duc_freq(new_freq);
+ _tx_dsp_freq = new_freq;
+ return;
+ }
+
+ case DSP_PROP_HOST_RATE: {
+ unsigned int rate =
+ _clock_ctrl->get_master_clock_freq() * 2 / val.as<double>();
+
+ if ((rate & 0x01) || (rate < 8) || (rate > 512)) {
+ std::cerr << "Interpolation rate must be even and between 8 and 512"
+ << std::endl;
+ return;
+ }
+
+ _tx_dsp_interp = rate;
+
+ //TODO Poll every 100ms. Make it selectable?
+ _tx_samps_per_poll_interval = 0.1 * _clock_ctrl->get_master_clock_freq() * 2 / rate;
+
+ _iface->poke32(FR_INTERP_RATE, _tx_dsp_interp / 4 - 1);
+ return;
+ }
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+
+}
diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp
new file mode 100644
index 000000000..92e8bc20a
--- /dev/null
+++ b/host/lib/usrp/usrp1/io_impl.cpp
@@ -0,0 +1,326 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "../../transport/vrt_packet_handler.hpp"
+#include "usrp_commands.h"
+#include "usrp1_impl.hpp"
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/transport/convert_types.hpp>
+#include <uhd/transport/bounded_buffer.hpp>
+#include <boost/bind.hpp>
+#include <boost/format.hpp>
+#include <boost/asio.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace uhd::transport;
+namespace asio = boost::asio;
+
+struct usrp1_send_state {
+ uhd::transport::managed_send_buffer::sptr send_buff;
+ size_t bytes_written;
+ size_t underrun_poll_samp_count;
+
+ size_t bytes_free()
+ {
+ if (send_buff != NULL)
+ return send_buff->size() - bytes_written;
+ else
+ return 0;
+ }
+};
+
+struct usrp1_recv_state {
+ uhd::transport::managed_recv_buffer::sptr recv_buff;
+ size_t bytes_read;
+ size_t overrun_poll_samp_count;
+
+ size_t bytes_avail()
+ {
+ if (recv_buff != NULL)
+ return recv_buff->size() - bytes_read;
+ else
+ return 0;
+ }
+};
+
+/***********************************************************************
+ * IO Implementation Details
+ **********************************************************************/
+struct usrp1_impl::io_impl {
+ io_impl();
+ ~io_impl(void);
+
+ //state handling for buffer management
+ usrp1_recv_state recv_state;
+ usrp1_send_state send_state;
+
+ //send transport management
+ bool get_send_buffer(zero_copy_if::sptr zc_if);
+ size_t copy_convert_send_samps(const void *buff, size_t num_samps,
+ size_t sample_offset, const io_type_t io_type,
+ otw_type_t otw_type);
+ bool conditional_buff_commit(bool force);
+ bool check_underrun(usrp_ctrl::sptr ctrl_if,
+ size_t poll_interval, bool force);
+
+ //recv transport management
+ bool get_recv_buffer(zero_copy_if::sptr zc_if);
+ size_t copy_convert_recv_samps(void *buff, size_t num_samps,
+ size_t sample_offset, const io_type_t io_type,
+ otw_type_t otw_type);
+ bool check_overrun(usrp_ctrl::sptr ctrl_if,
+ size_t poll_interval, bool force);
+};
+
+usrp1_impl::io_impl::io_impl()
+{
+ send_state.send_buff = uhd::transport::managed_send_buffer::sptr();
+ recv_state.recv_buff = uhd::transport::managed_recv_buffer::sptr();
+}
+
+usrp1_impl::io_impl::~io_impl(void)
+{
+ /* NOP */
+}
+
+void usrp1_impl::io_init(void)
+{
+ _rx_otw_type.width = 16;
+ _rx_otw_type.shift = 0;
+ _rx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
+
+ _tx_otw_type.width = 16;
+ _tx_otw_type.shift = 0;
+ _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
+
+ _io_impl = UHD_PIMPL_MAKE(io_impl, ());
+}
+
+/***********************************************************************
+ * Data Send
+ **********************************************************************/
+bool usrp1_impl::io_impl::get_send_buffer(zero_copy_if::sptr zc_if)
+{
+ if (send_state.send_buff == NULL) {
+
+ send_state.send_buff = zc_if->get_send_buff();
+ if (send_state.send_buff == NULL)
+ return false;
+
+ send_state.bytes_written = 0;
+ }
+
+ return true;
+}
+
+size_t usrp1_impl::io_impl::copy_convert_send_samps(const void *buff,
+ size_t num_samps,
+ size_t sample_offset,
+ const io_type_t io_type,
+ otw_type_t otw_type)
+{
+ UHD_ASSERT_THROW(send_state.bytes_free() % otw_type.get_sample_size() == 0);
+
+ size_t samps_free = send_state.bytes_free() / otw_type.get_sample_size();
+ size_t copy_samps = std::min(num_samps - sample_offset, samps_free);
+
+ const boost::uint8_t *io_mem =
+ reinterpret_cast<const boost::uint8_t *>(buff);
+
+ boost::uint8_t *otw_mem = send_state.send_buff->cast<boost::uint8_t *>();
+
+ convert_io_type_to_otw_type(io_mem + sample_offset * io_type.size,
+ io_type,
+ otw_mem + send_state.bytes_written,
+ otw_type,
+ copy_samps);
+
+ send_state.bytes_written += copy_samps * otw_type.get_sample_size();
+ send_state.underrun_poll_samp_count += copy_samps;
+
+ return copy_samps;
+}
+
+bool usrp1_impl::io_impl::conditional_buff_commit(bool force)
+{
+ if (send_state.bytes_written % 512)
+ return false;
+
+ if (force || send_state.bytes_free() == 0) {
+ send_state.send_buff->commit(send_state.bytes_written);
+ send_state.send_buff = uhd::transport::managed_send_buffer::sptr();
+ return true;
+ }
+
+ return false;
+}
+
+bool usrp1_impl::io_impl::check_underrun(usrp_ctrl::sptr ctrl_if,
+ size_t poll_interval,
+ bool force)
+{
+ unsigned char underrun = 0;
+
+ bool ready_to_poll = send_state.underrun_poll_samp_count > poll_interval;
+
+ if (force || ready_to_poll) {
+ int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS,
+ 0,
+ GS_TX_UNDERRUN,
+ &underrun, sizeof(char));
+ if (ret < 0)
+ std::cerr << "USRP: underrun check failed" << std::endl;
+ if (underrun)
+ std::cerr << "U" << std::flush;
+
+ send_state.underrun_poll_samp_count = 0;
+ }
+
+ return (bool) underrun;
+}
+
+size_t usrp1_impl::send(const std::vector<const void *> &buffs,
+ size_t num_samps,
+ const tx_metadata_t &,
+ const io_type_t &io_type,
+ send_mode_t)
+{
+ UHD_ASSERT_THROW(buffs.size() == 1);
+
+ size_t total_samps_sent = 0;
+
+ while (total_samps_sent < num_samps) {
+ if (!_io_impl->get_send_buffer(_data_transport))
+ return 0;
+
+ total_samps_sent += _io_impl->copy_convert_send_samps(buffs[0],
+ num_samps,
+ total_samps_sent,
+ io_type,
+ _tx_otw_type);
+ if (total_samps_sent == num_samps)
+ _io_impl->conditional_buff_commit(true);
+ else
+ _io_impl->conditional_buff_commit(false);
+
+ _io_impl->check_underrun(_ctrl_transport,
+ _tx_samps_per_poll_interval, false);
+ }
+
+ return total_samps_sent;
+}
+
+/***********************************************************************
+ * Data Recv
+ **********************************************************************/
+bool usrp1_impl::io_impl::get_recv_buffer(zero_copy_if::sptr zc_if)
+{
+ if ((recv_state.recv_buff == NULL) || (recv_state.bytes_avail() == 0)) {
+
+ recv_state.recv_buff = zc_if->get_recv_buff();
+ if (recv_state.recv_buff == NULL)
+ return false;
+
+ recv_state.bytes_read = 0;
+ }
+
+ return true;
+}
+
+size_t usrp1_impl::io_impl::copy_convert_recv_samps(void *buff,
+ size_t num_samps,
+ size_t sample_offset,
+ const io_type_t io_type,
+ otw_type_t otw_type)
+{
+ UHD_ASSERT_THROW(recv_state.bytes_avail() % otw_type.get_sample_size() == 0);
+
+ size_t samps_avail = recv_state.bytes_avail() / otw_type.get_sample_size();
+ size_t copy_samps = std::min(num_samps - sample_offset, samps_avail);
+
+ const boost::uint8_t *otw_mem =
+ recv_state.recv_buff->cast<const boost::uint8_t *>();
+
+ boost::uint8_t *io_mem = reinterpret_cast<boost::uint8_t *>(buff);
+
+ convert_otw_type_to_io_type(otw_mem + recv_state.bytes_read,
+ otw_type,
+ io_mem + sample_offset * io_type.size,
+ io_type,
+ copy_samps);
+
+ recv_state.bytes_read += copy_samps * otw_type.get_sample_size();
+ recv_state.overrun_poll_samp_count += copy_samps;
+
+ return copy_samps;
+}
+
+bool usrp1_impl::io_impl::check_overrun(usrp_ctrl::sptr ctrl_if,
+ size_t poll_interval,
+ bool force)
+{
+ unsigned char overrun = 0;
+
+ bool ready_to_poll = recv_state.overrun_poll_samp_count > poll_interval;
+
+ if (force || ready_to_poll) {
+ int ret = ctrl_if->usrp_control_read(VRQ_GET_STATUS,
+ 0,
+ GS_RX_OVERRUN,
+ &overrun, sizeof(char));
+ if (ret < 0)
+ std::cerr << "USRP: overrrun check failed" << std::endl;
+ if (overrun)
+ std::cerr << "O" << std::flush;
+
+ recv_state.overrun_poll_samp_count = 0;
+ }
+
+ return (bool) overrun;
+}
+
+size_t usrp1_impl::recv(const std::vector<void *> &buffs,
+ size_t num_samps,
+ rx_metadata_t &,
+ const io_type_t &io_type,
+ recv_mode_t,
+ size_t)
+{
+ UHD_ASSERT_THROW(buffs.size() == 1);
+
+ size_t total_samps_recv = 0;
+
+ while (total_samps_recv < num_samps) {
+
+ if (!_io_impl->get_recv_buffer(_data_transport))
+ return 0;
+
+ total_samps_recv += _io_impl->copy_convert_recv_samps(buffs[0],
+ num_samps,
+ total_samps_recv,
+ io_type,
+ _rx_otw_type);
+ _io_impl->check_overrun(_ctrl_transport,
+ _rx_samps_per_poll_interval, false);
+ }
+
+ return total_samps_recv;
+}
diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp
new file mode 100644
index 000000000..a90532cb8
--- /dev/null
+++ b/host/lib/usrp/usrp1/mboard_impl.cpp
@@ -0,0 +1,382 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_impl.hpp"
+#include "usrp_commands.h"
+#include "fpga_regs_standard.h"
+#include "fpga_regs_common.h"
+#include "usrp_i2c_addr.h"
+#include <uhd/usrp/misc_utils.hpp>
+#include <uhd/usrp/mboard_props.hpp>
+#include <uhd/usrp/dboard_props.hpp>
+#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/utils/warning.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/images.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/foreach.hpp>
+#include <boost/bind.hpp>
+#include <boost/thread/thread.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+
+/***********************************************************************
+ * Calculate the RX mux value:
+ * The I and Q mux values are intentionally reversed to flip I and Q
+ * to account for the reversal in the type conversion routines.
+ **********************************************************************/
+static int calc_rx_mux_pair(int adc_for_i, int adc_for_q){
+ return (adc_for_i << 2) | (adc_for_q << 0); //shift reversal here
+}
+
+/*!
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-----------------------+-------+-------+-------+-------+-+-----+
+ * | must be zero | Q3| I3| Q2| I2| Q1| I1| Q0| I0|Z| NCH |
+ * +-----------------------+-------+-------+-------+-------+-+-----+
+ */
+static boost::uint32_t calc_rx_mux(
+ const subdev_spec_t &subdev_spec, wax::obj mboard
+){
+ //create look-up-table for mapping dboard name and connection type to ADC flags
+ static const int ADC0 = 0, ADC1 = 1, ADC2 = 2, ADC3 = 3;
+ static const uhd::dict<std::string, uhd::dict<subdev_conn_t, int> > name_to_conn_to_flag = boost::assign::map_list_of
+ ("A", boost::assign::map_list_of
+ (SUBDEV_CONN_COMPLEX_IQ, calc_rx_mux_pair(ADC0, ADC1)) //I and Q
+ (SUBDEV_CONN_COMPLEX_QI, calc_rx_mux_pair(ADC1, ADC0)) //I and Q
+ (SUBDEV_CONN_REAL_I, calc_rx_mux_pair(ADC0, ADC0)) //I and Q (Q identical but ignored Z=1)
+ (SUBDEV_CONN_REAL_Q, calc_rx_mux_pair(ADC1, ADC1)) //I and Q (Q identical but ignored Z=1)
+ )
+ ("B", boost::assign::map_list_of
+ (SUBDEV_CONN_COMPLEX_IQ, calc_rx_mux_pair(ADC2, ADC3)) //I and Q
+ (SUBDEV_CONN_COMPLEX_QI, calc_rx_mux_pair(ADC3, ADC2)) //I and Q
+ (SUBDEV_CONN_REAL_I, calc_rx_mux_pair(ADC2, ADC2)) //I and Q (Q identical but ignored Z=1)
+ (SUBDEV_CONN_REAL_Q, calc_rx_mux_pair(ADC3, ADC3)) //I and Q (Q identical but ignored Z=1)
+ )
+ ;
+
+ //extract the number of channels
+ size_t nchan = subdev_spec.size();
+
+ //calculate the channel flags
+ int channel_flags = 0;
+ size_t num_reals = 0, num_quads = 0;
+ BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){
+ wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_RX_DBOARD, pair.db_name)];
+ wax::obj subdev = dboard[named_prop_t(DBOARD_PROP_SUBDEV, pair.sd_name)];
+ subdev_conn_t conn = subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>();
+ switch(conn){
+ case SUBDEV_CONN_COMPLEX_IQ:
+ case SUBDEV_CONN_COMPLEX_QI: num_quads++; break;
+ case SUBDEV_CONN_REAL_I:
+ case SUBDEV_CONN_REAL_Q: num_reals++; break;
+ }
+ channel_flags = (channel_flags << 4) | name_to_conn_to_flag[pair.db_name][conn];
+ }
+
+ //calculate Z:
+ // for all real sources: Z = 1
+ // for all quadrature sources: Z = 0
+ // for mixed sources: warning + Z = 0
+ int Z = (num_quads > 0)? 0 : 1;
+ if (num_quads != 0 and num_reals != 0) uhd::print_warning(
+ "Mixing real and quadrature rx subdevices is not supported.\n"
+ "The Q input to the real source(s) will be non-zero.\n"
+ );
+
+ //calculate the rx mux value
+ return ((channel_flags & 0xffff) << 4) | ((Z & 0x1) << 3) | ((nchan & 0x7) << 0);
+}
+
+/***********************************************************************
+ * Calculate the TX mux value:
+ * The I and Q mux values are intentionally reversed to flip I and Q
+ * to account for the reversal in the type conversion routines.
+ **********************************************************************/
+static int calc_tx_mux_pair(int chn_for_i, int chn_for_q){
+ return (chn_for_i << 4) | (chn_for_q << 0); //shift reversal here
+}
+
+/*!
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-----------------------+-------+-------+-------+-------+-+-----+
+ * | | DAC1Q | DAC1I | DAC0Q | DAC0I |0| NCH |
+ * +-----------------------------------------------+-------+-+-----+
+ */
+static boost::uint32_t calc_tx_mux(
+ const subdev_spec_t &subdev_spec, wax::obj mboard
+){
+ //create look-up-table for mapping channel number and connection type to flags
+ static const int ENB = 1 << 3, CHAN_I0 = 0, CHAN_Q0 = 1, CHAN_I1 = 2, CHAN_Q1 = 3;
+ static const uhd::dict<size_t, uhd::dict<subdev_conn_t, int> > chan_to_conn_to_flag = boost::assign::map_list_of
+ (0, boost::assign::map_list_of
+ (SUBDEV_CONN_COMPLEX_IQ, calc_tx_mux_pair(CHAN_I0 | ENB, CHAN_Q0 | ENB))
+ (SUBDEV_CONN_COMPLEX_QI, calc_tx_mux_pair(CHAN_Q0 | ENB, CHAN_I0 | ENB))
+ (SUBDEV_CONN_REAL_I, calc_tx_mux_pair(CHAN_I0 | ENB, 0 ))
+ (SUBDEV_CONN_REAL_Q, calc_tx_mux_pair(0, CHAN_I0 | ENB))
+ )
+ (1, boost::assign::map_list_of
+ (SUBDEV_CONN_COMPLEX_IQ, calc_tx_mux_pair(CHAN_I1 | ENB, CHAN_Q1 | ENB))
+ (SUBDEV_CONN_COMPLEX_QI, calc_tx_mux_pair(CHAN_Q1 | ENB, CHAN_I1 | ENB))
+ (SUBDEV_CONN_REAL_I, calc_tx_mux_pair(CHAN_I1 | ENB, 0 ))
+ (SUBDEV_CONN_REAL_Q, calc_tx_mux_pair(0, CHAN_I1 | ENB))
+ )
+ ;
+
+ //extract the number of channels
+ size_t nchan = subdev_spec.size();
+
+ //calculate the channel flags
+ int channel_flags = 0, chan = 0;
+ BOOST_FOREACH(const subdev_spec_pair_t &pair, subdev_spec){
+ wax::obj dboard = mboard[named_prop_t(MBOARD_PROP_TX_DBOARD, pair.db_name)];
+ wax::obj subdev = dboard[named_prop_t(DBOARD_PROP_SUBDEV, pair.sd_name)];
+ subdev_conn_t conn = subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>();
+
+ //combine the channel flags: shift for slot A vs B
+ if (pair.db_name == "A") channel_flags |= chan_to_conn_to_flag[chan][conn] << 0;
+ if (pair.db_name == "B") channel_flags |= chan_to_conn_to_flag[chan][conn] << 8;
+
+ //increment for the next channel
+ chan++;
+ }
+
+ //calculate the tx mux value
+ return ((channel_flags & 0xffff) << 4) | ((nchan & 0x7) << 0);
+}
+
+/*!
+ * Capabilities Register
+ *
+ * 3 2 1 0
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-----------------------------------------------+-+-----+-+-----+
+ * | Reserved |T|DUCs |R|DDCs |
+ * +-----------------------------------------------+-+-----+-+-----+
+ */
+static int num_ddcs(boost::uint32_t regval)
+{
+ return (regval >> 0) & 0x0007;
+}
+
+static int num_ducs(boost::uint32_t regval)
+{
+ return (regval >> 4) & 0x0007;
+}
+
+static bool has_rx_halfband(boost::uint32_t regval)
+{
+ return (regval >> 3) & 0x0001;
+}
+
+static bool has_tx_halfband(boost::uint32_t regval)
+{
+ return (regval >> 7) & 0x0001;
+}
+
+/***********************************************************************
+ * Mboard Initialization
+ **********************************************************************/
+void usrp1_impl::mboard_init(void)
+{
+ _mboard_proxy = wax_obj_proxy::make(
+ boost::bind(&usrp1_impl::mboard_get, this, _1, _2),
+ boost::bind(&usrp1_impl::mboard_set, this, _1, _2));
+
+ // Normal mode with no loopback or Rx counting
+ _iface->poke32(FR_MODE, 0x00000000);
+ _iface->poke32(FR_DEBUG_EN, 0x00000000);
+ _iface->poke32(FR_RX_SAMPLE_RATE_DIV, 0x00000001);
+ _iface->poke32(FR_TX_SAMPLE_RATE_DIV, 0x00000003);
+ _iface->poke32(FR_DC_OFFSET_CL_EN, 0x0000000f);
+
+ // Reset offset correction registers
+ _iface->poke32(FR_ADC_OFFSET_0, 0x00000000);
+ _iface->poke32(FR_ADC_OFFSET_1, 0x00000000);
+ _iface->poke32(FR_ADC_OFFSET_2, 0x00000000);
+ _iface->poke32(FR_ADC_OFFSET_3, 0x00000000);
+
+ // Set default for RX format to 16-bit I&Q and no half-band filter bypass
+ _iface->poke32(FR_RX_FORMAT, 0x00000300);
+
+ // Set default for TX format to 16-bit I&Q
+ _iface->poke32(FR_TX_FORMAT, 0x00000000);
+
+ // TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
+ //
+ // Do something useful with the capabilities register
+ //
+ boost::uint32_t regval = _iface->peek32(FR_RB_CAPS);
+ std::cout << "USRP1 Capabilities" << std::endl;
+ std::cout << " number of duc's: " << num_ddcs(regval) << std::endl;
+ std::cout << " number of ddc's: " << num_ducs(regval) << std::endl;
+ std::cout << " rx halfband: " << has_rx_halfband(regval) << std::endl;
+ std::cout << " tx halfband: " << has_tx_halfband(regval) << std::endl;
+}
+
+void usrp1_impl::issue_stream_cmd(const stream_cmd_t &stream_cmd)
+{
+ if (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_START_CONTINUOUS) {
+ _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, true, 0, 0, 0);
+ }
+
+ if (stream_cmd.stream_mode == stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS) {
+ _iface->write_firmware_cmd(VRQ_FPGA_SET_RX_ENABLE, false, 0, 0, 0);
+ }
+}
+
+/***********************************************************************
+ * Mboard Get
+ **********************************************************************/
+static prop_names_t dboard_names = boost::assign::list_of("A")("B");
+
+void usrp1_impl::mboard_get(const wax::obj &key_, wax::obj &val)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ if(key_.type() == typeid(std::string)) {
+ if(key.as<std::string>() == "serial") {
+ uhd::byte_vector_t buf;
+ buf.insert(buf.begin(), 248);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ _iface->write_i2c(I2C_DEV_EEPROM, buf);
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ buf = _iface->read_i2c(I2C_DEV_EEPROM, 8);
+ val = std::string(buf.begin(), buf.end());
+ }
+
+ return;
+ }
+
+ //handle the get request conditioned on the key
+ switch(key.as<mboard_prop_t>()){
+ case MBOARD_PROP_NAME:
+ val = std::string("usrp1 mboard");
+ return;
+
+ case MBOARD_PROP_OTHERS:
+ val = prop_names_t();
+ return;
+
+ case MBOARD_PROP_RX_DBOARD:
+ uhd::assert_has(dboard_names, key.name, "dboard name");
+ if (key.name == "A") val = _rx_dboard_proxies[DBOARD_SLOT_A]->get_link();
+ if (key.name == "B") val = _rx_dboard_proxies[DBOARD_SLOT_B]->get_link();
+ return;
+
+ case MBOARD_PROP_RX_DBOARD_NAMES:
+ val = dboard_names;
+ return;
+
+ case MBOARD_PROP_TX_DBOARD:
+ uhd::assert_has(dboard_names, key.name, "dboard name");
+ if (key.name == "A") val = _tx_dboard_proxies[DBOARD_SLOT_A]->get_link();
+ if (key.name == "B") val = _tx_dboard_proxies[DBOARD_SLOT_B]->get_link();
+ return;
+
+ case MBOARD_PROP_TX_DBOARD_NAMES:
+ val = dboard_names;
+ return;
+
+ case MBOARD_PROP_RX_DSP:
+ UHD_ASSERT_THROW(key.name == "");
+ val = _rx_dsp_proxy->get_link();
+ return;
+
+ case MBOARD_PROP_RX_DSP_NAMES:
+ val = prop_names_t(1, "");
+ return;
+
+ case MBOARD_PROP_TX_DSP:
+ UHD_ASSERT_THROW(key.name == "");
+ val = _tx_dsp_proxy->get_link();
+ return;
+
+ case MBOARD_PROP_TX_DSP_NAMES:
+ val = prop_names_t(1, "");
+ return;
+
+ case MBOARD_PROP_CLOCK_CONFIG:
+ val = _clock_config;
+ return;
+
+ case MBOARD_PROP_RX_SUBDEV_SPEC:
+ val = _rx_subdev_spec;
+ return;
+
+ case MBOARD_PROP_TX_SUBDEV_SPEC:
+ val = _tx_subdev_spec;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * Mboard Set
+ **********************************************************************/
+void usrp1_impl::mboard_set(const wax::obj &key, const wax::obj &val)
+{
+ if(key.type() == typeid(std::string)) {
+ if(key.as<std::string>() == "load_eeprom") {
+ std::string usrp1_eeprom_image = val.as<std::string>();
+ std::cout << "USRP1 EEPROM image: " << usrp1_eeprom_image << std::endl;
+ _ctrl_transport->usrp_load_eeprom(val.as<std::string>());
+ }
+
+ if(key.as<std::string>() == "serial") {
+ std::string sernum = val.as<std::string>();
+ uhd::byte_vector_t buf(sernum.begin(), sernum.end());
+ buf.insert(buf.begin(), 248);
+ _iface->write_i2c(I2C_DEV_EEPROM, buf);
+ }
+
+ return;
+ }
+
+ //handle the get request conditioned on the key
+ switch(key.as<mboard_prop_t>()){
+
+ case MBOARD_PROP_STREAM_CMD:
+ issue_stream_cmd(val.as<stream_cmd_t>());
+ return;
+
+ case MBOARD_PROP_RX_SUBDEV_SPEC:
+ _rx_subdev_spec = val.as<subdev_spec_t>();
+ verify_rx_subdev_spec(_rx_subdev_spec, _mboard_proxy->get_link());
+ //sanity check
+ UHD_ASSERT_THROW(_rx_subdev_spec.size() <= 2);
+ //set the mux and set the number of rx channels
+ _iface->poke32(FR_RX_MUX, calc_rx_mux(_rx_subdev_spec, _mboard_proxy->get_link()));
+ return;
+
+ case MBOARD_PROP_TX_SUBDEV_SPEC:
+ _tx_subdev_spec = val.as<subdev_spec_t>();
+ verify_tx_subdev_spec(_tx_subdev_spec, _mboard_proxy->get_link());
+ //sanity check
+ UHD_ASSERT_THROW(_tx_subdev_spec.size() <= 2);
+ //set the mux and set the number of tx channels
+ _iface->poke32(FR_TX_MUX, calc_tx_mux(_tx_subdev_spec, _mboard_proxy->get_link()));
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+}
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.cpp b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
new file mode 100644
index 000000000..451129ef5
--- /dev/null
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.cpp
@@ -0,0 +1,446 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_ctrl.hpp"
+#include "usrp_commands.h"
+#include <uhd/transport/usb_control.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/thread/thread.hpp>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include <cstring>
+
+using namespace uhd;
+
+enum firmware_code {
+ USRP_FPGA_LOAD_SUCCESS,
+ USRP_FPGA_ALREADY_LOADED,
+ USRP_FIRMWARE_LOAD_SUCCESS,
+ USRP_FIRMWARE_ALREADY_LOADED
+};
+
+#define FX2_FIRMWARE_LOAD 0xa0
+
+/***********************************************************************
+ * Helper Functions
+ **********************************************************************/
+/*!
+ * Create a file hash
+ * The hash will be used to identify the loaded firmware and fpga image
+ * \param filename file used to generate hash value
+ * \return hash value in a size_t type
+ */
+static size_t generate_hash(const char *filename)
+{
+ std::ifstream file(filename);
+ if (!file)
+ std::cerr << "error: cannot open input file " << filename << std::endl;
+
+ size_t hash = 0;
+
+ char ch;
+ while (file.get(ch)) {
+ boost::hash_combine(hash, ch);
+ }
+
+ if (!file.eof())
+ std::cerr << "error: file error " << filename << std::endl;
+
+ file.close();
+ return hash;
+}
+
+
+/*!
+ * Verify checksum of a Intel HEX record
+ * \param record a line from an Intel HEX file
+ * \return true if record is valid, false otherwise
+ */
+static bool checksum(std::string *record)
+{
+
+ size_t len = record->length();
+ unsigned int i;
+ unsigned char sum = 0;
+ unsigned int val;
+
+ for (i = 1; i < len; i += 2) {
+ std::istringstream(record->substr(i, 2)) >> std::hex >> val;
+ sum += val;
+ }
+
+ if (sum == 0)
+ return true;
+ else
+ return false;
+}
+
+
+/*!
+ * Parse Intel HEX record
+ *
+ * \param record a line from an Intel HEX file
+ * \param len output length of record
+ * \param addr output address
+ * \param type output type
+ * \param data output data
+ * \return true if record is sucessfully read, false on error
+ */
+bool parse_record(std::string *record, unsigned int &len,
+ unsigned int &addr, unsigned int &type,
+ unsigned char* data)
+{
+ unsigned int i;
+ std::string _data;
+ unsigned int val;
+
+ if (record->substr(0, 1) != ":")
+ return false;
+
+ std::istringstream(record->substr(1, 2)) >> std::hex >> len;
+ std::istringstream(record->substr(3, 4)) >> std::hex >> addr;
+ std::istringstream(record->substr(7, 2)) >> std::hex >> type;
+
+ for (i = 0; i < len; i++) {
+ std::istringstream(record->substr(9 + 2 * i, 2)) >> std::hex >> val;
+ data[i] = (unsigned char) val;
+ }
+
+ return true;
+}
+
+
+/*!
+ * USRP control implementation for device discovery and configuration
+ */
+class usrp_ctrl_impl : public usrp_ctrl {
+public:
+ usrp_ctrl_impl(uhd::transport::usb_control::sptr ctrl_transport)
+ {
+ _ctrl_transport = ctrl_transport;
+ }
+
+
+ ~usrp_ctrl_impl(void)
+ {
+ /* NOP */
+ }
+
+
+ int usrp_load_firmware(std::string filestring, bool force)
+ {
+ const char *filename = filestring.c_str();
+
+ size_t hash = generate_hash(filename);
+
+ size_t loaded_hash;
+ if (usrp_get_firmware_hash(loaded_hash) < 0) {
+ std::cerr << "firmware hash retrieval failed" << std::endl;
+ return -1;
+ }
+
+ if (!force && (hash == loaded_hash))
+ return USRP_FIRMWARE_ALREADY_LOADED;
+
+ //FIXME: verify types
+ unsigned int len;
+ unsigned int addr;
+ unsigned int type;
+ unsigned char data[512];
+
+ int ret;
+ std::ifstream file;
+ file.open(filename, std::ifstream::in);
+
+ if (!file.good()) {
+ std::cerr << "cannot open firmware input file" << std::endl;
+ return -1;
+ }
+
+ unsigned char reset_y = 1;
+ unsigned char reset_n = 0;
+
+ //hit the reset line
+ usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0,
+ &reset_y, 1);
+
+ while (!file.eof()) {
+ std::string record;
+ file >> record;
+
+ //check for valid record
+ if (!checksum(&record) ||
+ !parse_record(&record, len, addr, type, data)) {
+ std::cerr << "error: bad record" << std::endl;
+ file.close();
+ return -1;
+ }
+
+ //type 0x00 is data
+ if (type == 0x00) {
+ ret = usrp_control_write(FX2_FIRMWARE_LOAD, addr, 0,
+ data, len);
+ if (ret < 0) {
+ std::cerr << "error: usrp_control_write failed: ";
+ std::cerr << ret << std::endl;
+ file.close();
+ return -1;
+ }
+ }
+ //type 0x01 is end
+ else if (type == 0x01) {
+ usrp_control_write(FX2_FIRMWARE_LOAD, 0xe600, 0,
+ &reset_n, 1);
+ usrp_set_firmware_hash(hash);
+ file.close();
+
+ //wait for things to settle
+ boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
+
+ return USRP_FIRMWARE_LOAD_SUCCESS;
+ }
+ //type anything else is unhandled
+ else {
+ std::cerr << "error: unsupported record" << std::endl;
+ file.close();
+ return -1;
+ }
+ }
+
+ //file did not end
+ std::cerr << "error: bad record" << std::endl;
+ file.close();
+ return -1;
+ }
+
+
+ int usrp_load_fpga(std::string filestring)
+ {
+ const char *filename = filestring.c_str();
+
+ size_t hash = generate_hash(filename);
+
+ size_t loaded_hash;
+ if (usrp_get_fpga_hash(loaded_hash) < 0) {
+ std::cerr << "fpga hash retrieval failed" << std::endl;
+ return -1;
+ }
+
+ if (hash == loaded_hash)
+ return USRP_FPGA_ALREADY_LOADED;
+ const int ep0_size = 64;
+ unsigned char buf[ep0_size];
+ int ret;
+
+ FILE *fp;
+ if ((fp = fopen(filename, "rb")) == NULL) {
+ std::cerr << "cannot open fpga input file" << std::endl;
+ fclose(fp);
+ return -1;
+ }
+
+ if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_BEGIN) < 0) {
+ std::cerr << "fpga load error" << std::endl;
+ fclose(fp);
+ return -1;
+ }
+
+ ssize_t n;
+ while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
+ ret = usrp_control_write(VRQ_FPGA_LOAD, 0, FL_XFER,
+ buf, n);
+ if (ret != n) {
+ std::cerr << "fpga load error " << ret << std::endl;
+ fclose(fp);
+ return -1;
+ }
+ }
+
+ if (usrp_control_write_cmd(VRQ_FPGA_LOAD, 0, FL_END) < 0) {
+ std::cerr << "fpga load error" << std::endl;
+ fclose(fp);
+ return -1;
+ }
+
+ usrp_set_fpga_hash(hash);
+ fclose(fp);
+ return 0;
+ }
+
+ int usrp_load_eeprom(std::string filestring)
+ {
+ const char *filename = filestring.c_str();
+ const uint16_t i2c_addr = 0x50;
+
+ //FIXME: verify types
+ int len;
+ unsigned int addr;
+ unsigned char data[256];
+ unsigned char sendbuf[17];
+
+ int ret;
+ std::ifstream file;
+ file.open(filename, std::ifstream::in);
+
+ if (!file.good()) {
+ std::cerr << "cannot open EEPROM input file" << std::endl;
+ return -1;
+ }
+
+ file.read((char *)data, 256);
+ len = file.gcount();
+
+ if(len == 256) {
+ std::cerr << "error: image size too large" << std::endl;
+ file.close();
+ return -1;
+ }
+
+ const int pagesize = 16;
+ addr = 0;
+ while(len > 0) {
+ sendbuf[0] = addr;
+ memcpy(sendbuf+1, &data[addr], len > pagesize ? pagesize : len);
+ ret = usrp_i2c_write(i2c_addr, sendbuf, (len > pagesize ? pagesize : len)+1);
+ if (ret < 0) {
+ std::cerr << "error: usrp_i2c_write failed: ";
+ std::cerr << ret << std::endl;
+ file.close();
+ return -1;
+ }
+ addr += pagesize;
+ len -= pagesize;
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+ }
+ file.close();
+ return 0;
+ }
+
+
+ int usrp_set_led(int led_num, bool on)
+ {
+ return usrp_control_write_cmd(VRQ_SET_LED, on, led_num);
+ }
+
+
+ int usrp_get_firmware_hash(size_t &hash)
+ {
+ return usrp_control_read(0xa0, USRP_HASH_SLOT_0_ADDR, 0,
+ (unsigned char*) &hash, sizeof(size_t));
+ }
+
+
+ int usrp_set_firmware_hash(size_t hash)
+ {
+ return usrp_control_write(0xa0, USRP_HASH_SLOT_0_ADDR, 0,
+ (unsigned char*) &hash, sizeof(size_t));
+
+ }
+
+
+ int usrp_get_fpga_hash(size_t &hash)
+ {
+ return usrp_control_read(0xa0, USRP_HASH_SLOT_1_ADDR, 0,
+ (unsigned char*) &hash, sizeof(size_t));
+ }
+
+
+ int usrp_set_fpga_hash(size_t hash)
+ {
+ return usrp_control_write(0xa0, USRP_HASH_SLOT_1_ADDR, 0,
+ (unsigned char*) &hash, sizeof(size_t));
+ }
+
+ int usrp_tx_enable(bool on)
+ {
+ return usrp_control_write_cmd(VRQ_FPGA_SET_TX_ENABLE, on, 0);
+ }
+
+
+ int usrp_rx_enable(bool on)
+ {
+ return usrp_control_write_cmd(VRQ_FPGA_SET_RX_ENABLE, on, 0);
+ }
+
+
+ int usrp_tx_reset(bool on)
+ {
+ return usrp_control_write_cmd(VRQ_FPGA_SET_TX_RESET, on, 0);
+ }
+
+
+ int usrp_control_write(boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length)
+ {
+ return _ctrl_transport->submit(VRT_VENDOR_OUT, // bmReqeustType
+ request, // bRequest
+ value, // wValue
+ index, // wIndex
+ buff, // data
+ length); // wLength
+ }
+
+
+ int usrp_control_read(boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length)
+ {
+ return _ctrl_transport->submit(VRT_VENDOR_IN, // bmReqeustType
+ request, // bRequest
+ value, // wValue
+ index, // wIndex
+ buff, // data
+ length); // wLength
+ }
+
+
+ int usrp_control_write_cmd(uint8_t request, uint16_t value, uint16_t index)
+ {
+ return usrp_control_write(request, value, index, 0, 0);
+ }
+
+ int usrp_i2c_write(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len)
+ {
+ return usrp_control_write(VRQ_I2C_WRITE, i2c_addr, 0, buf, len);
+ }
+
+ int usrp_i2c_read(boost::uint16_t i2c_addr, unsigned char *buf, boost::uint16_t len)
+ {
+ return usrp_control_read(VRQ_I2C_READ, i2c_addr, 0, buf, len);
+ }
+
+
+
+private:
+ uhd::transport::usb_control::sptr _ctrl_transport;
+};
+
+/***********************************************************************
+ * Public make function for usrp_ctrl interface
+ **********************************************************************/
+usrp_ctrl::sptr usrp_ctrl::make(uhd::transport::usb_control::sptr ctrl_transport){
+ return sptr(new usrp_ctrl_impl(ctrl_transport));
+}
+
diff --git a/host/lib/usrp/usrp1/usrp1_ctrl.hpp b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
new file mode 100644
index 000000000..a02d9f96c
--- /dev/null
+++ b/host/lib/usrp/usrp1/usrp1_ctrl.hpp
@@ -0,0 +1,163 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_USRP_CTRL_HPP
+#define INCLUDED_USRP_CTRL_HPP
+
+#include <uhd/transport/usb_control.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+
+class usrp_ctrl : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<usrp_ctrl> sptr;
+
+ /*!
+ * Make a usrp control object from a control transport
+ * \param ctrl_transport a USB control transport
+ * \return a new usrp control object
+ */
+ static sptr make(uhd::transport::usb_control::sptr ctrl_transport);
+
+ /*!
+ * Load firmware in Intel HEX Format onto device
+ * \param filename name of firmware file
+ * \param force reload firmware if already loaded
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_load_firmware(std::string filename,
+ bool force = false) = 0;
+
+ /*!
+ * Load fpga file onto usrp
+ * \param filename name of fpga image
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_load_fpga(std::string filename) = 0;
+
+ /*!
+ * Load USB descriptor file in Intel HEX format into EEPROM
+ * \param filename name of EEPROM image
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_load_eeprom(std::string filestring) = 0;
+
+ /*!
+ * Set led usrp
+ * \param led_num which LED to control (0 or 1)
+ * \param on turn LED on or off
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_set_led(int led_num, bool on) = 0;
+
+ /*!
+ * Get firmware hash
+ * \param hash a size_t hash value
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_get_firmware_hash(size_t &hash) = 0;
+
+ /*!
+ * Set firmware hash
+ * \param hash a size_t hash value
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_set_firmware_hash(size_t hash) = 0;
+
+ /*!
+ * Get fpga hash
+ * \param hash a size_t hash value
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_get_fpga_hash(size_t &hash) = 0;
+
+ /*!
+ * Set fpga hash
+ * \param hash a size_t hash value
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_set_fpga_hash(size_t hash) = 0;
+
+ /*!
+ * Set rx enable or disable
+ * \param on enable or disable value
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_rx_enable(bool on) = 0;
+
+ /*!
+ * Set rx enable or disable
+ * \param on enable or disable value
+ * \return 0 on success, error code otherwise
+ */
+ virtual int usrp_tx_enable(bool on) = 0;
+
+ /*!
+ * Submit an IN transfer
+ * \param request device specific request
+ * \param value device specific field
+ * \param index device specific field
+ * \param buff buffer to place data
+ * \return number of bytes read or error
+ */
+ virtual int usrp_control_read(boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length) = 0;
+
+ /*!
+ * Submit an OUT transfer
+ * \param request device specific request
+ * \param value device specific field
+ * \param index device specific field
+ * \param buff buffer of data to be sent
+ * \return number of bytes written or error
+ */
+ virtual int usrp_control_write(boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length) = 0;
+
+ /*!
+ * Perform an I2C write
+ * \param i2c_addr I2C device address
+ * \param buf data to be written
+ * \param len length of data in bytes
+ * \return number of bytes written or error
+ */
+
+ virtual int usrp_i2c_write(boost::uint16_t i2c_addr,
+ unsigned char *buf,
+ boost::uint16_t len) = 0;
+
+ /*!
+ * Perform an I2C read
+ * \param i2c_addr I2C device address
+ * \param buf data to be read
+ * \param len length of data in bytes
+ * \return number of bytes read or error
+ */
+
+ virtual int usrp_i2c_read(boost::uint16_t i2c_addr,
+ unsigned char *buf,
+ boost::uint16_t len) = 0;
+
+};
+
+#endif /* INCLUDED_USRP_CTRL_HPP */
diff --git a/host/lib/usrp/usrp1/usrp1_iface.cpp b/host/lib/usrp/usrp1/usrp1_iface.cpp
new file mode 100644
index 000000000..4bc18dd16
--- /dev/null
+++ b/host/lib/usrp/usrp1/usrp1_iface.cpp
@@ -0,0 +1,261 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_iface.hpp"
+#include "usrp_commands.h"
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/byteswap.hpp>
+#include <boost/format.hpp>
+#include <stdexcept>
+#include <iostream>
+#include <iomanip>
+
+using namespace uhd;
+using namespace uhd::transport;
+
+static const bool iface_debug = false;
+
+class usrp1_iface_impl : public usrp1_iface{
+public:
+ /*******************************************************************
+ * Structors
+ ******************************************************************/
+ usrp1_iface_impl(usrp_ctrl::sptr ctrl_transport)
+ {
+ _ctrl_transport = ctrl_transport;
+ }
+
+ ~usrp1_iface_impl(void)
+ {
+ /* NOP */
+ }
+
+ /*******************************************************************
+ * Peek and Poke
+ ******************************************************************/
+ void poke32(boost::uint32_t addr, boost::uint32_t value)
+ {
+ boost::uint32_t swapped = byteswap(value);
+
+ if (iface_debug) {
+ std::cout.fill('0');
+ std::cout << "poke32(";
+ std::cout << std::dec << std::setw(2) << addr << ", 0x";
+ std::cout << std::hex << std::setw(8) << value << ")" << std::endl;
+ }
+
+ boost::uint8_t w_index_h = SPI_ENABLE_FPGA & 0xff;
+ boost::uint8_t w_index_l = (SPI_FMT_MSB | SPI_FMT_HDR_1) & 0xff;
+
+ int ret =_ctrl_transport->usrp_control_write(
+ VRQ_SPI_WRITE,
+ addr & 0x7f,
+ (w_index_h << 8) | (w_index_l << 0),
+ (unsigned char*) &swapped,
+ sizeof(boost::uint32_t));
+
+ if (ret < 0)
+ std::cerr << "USRP: failed memory write: " << ret << std::endl;
+ }
+
+ void poke16(boost::uint32_t, boost::uint16_t)
+ {
+ //fpga only handles 32 bit writes
+ std::cerr << "USRP: unsupported operation: poke16()" << std::endl;
+ }
+
+ boost::uint32_t peek32(boost::uint32_t addr)
+ {
+ uint32_t value_out;
+
+ boost::uint8_t w_index_h = SPI_ENABLE_FPGA & 0xff;
+ boost::uint8_t w_index_l = (SPI_FMT_MSB | SPI_FMT_HDR_1) & 0xff;
+
+ int ret = _ctrl_transport->usrp_control_read(
+ VRQ_SPI_READ,
+ 0x80 | (addr & 0x7f),
+ (w_index_h << 8) | (w_index_l << 0),
+ (unsigned char*) &value_out,
+ sizeof(boost::uint32_t));
+
+ if (ret < 0)
+ std::cerr << "USRP: failed memory read: " << ret << std::endl;
+
+ return byteswap(value_out);
+ }
+
+ boost::uint16_t peek16(boost::uint32_t addr)
+ {
+ uint32_t val = peek32(addr);
+ return boost::uint16_t(val & 0xff);
+ }
+
+ /*******************************************************************
+ * I2C
+ ******************************************************************/
+ static const size_t max_i2c_data_bytes = 64;
+
+ //TODO: make this handle EEPROM page sizes. right now you can't write over a 16-byte boundary.
+ //to accomplish this you'll have to have addr offset as a separate parameter.
+
+ void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes)
+ {
+ UHD_ASSERT_THROW(bytes.size() < max_i2c_data_bytes);
+
+ unsigned char buff[max_i2c_data_bytes];
+ std::copy(bytes.begin(), bytes.end(), buff);
+
+ int ret = _ctrl_transport->usrp_i2c_write(addr & 0xff,
+ buff,
+ bytes.size());
+
+ // TODO throw and catch i2c failures during eeprom read
+ if (iface_debug && (ret < 0))
+ std::cerr << "USRP: failed i2c write: " << ret << std::endl;
+ }
+
+ byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes)
+ {
+ UHD_ASSERT_THROW(num_bytes < max_i2c_data_bytes);
+
+ unsigned char buff[max_i2c_data_bytes];
+ int ret = _ctrl_transport->usrp_i2c_read(addr & 0xff,
+ buff,
+ num_bytes);
+
+ // TODO throw and catch i2c failures during eeprom read
+ if (iface_debug && ((ret < 0) || (unsigned)ret < (num_bytes))) {
+ std::cerr << "USRP: failed i2c read: " << ret << std::endl;
+ return byte_vector_t(num_bytes, 0xff);
+ }
+
+ byte_vector_t out_bytes;
+ for (size_t i = 0; i < num_bytes; i++)
+ out_bytes.push_back(buff[i]);
+
+ return out_bytes;
+ }
+
+ /*******************************************************************
+ * SPI
+ *
+ * For non-readback transactions use the SPI_WRITE command, which is
+ * simpler and uses the USB control buffer for OUT data. No data
+ * needs to be returned.
+ *
+ * For readback transactions use SPI_TRANSACT, which places up to
+ * 4 bytes of OUT data in the device request fields and uses the
+ * control buffer for IN data.
+ ******************************************************************/
+ boost::uint32_t transact_spi(int which_slave,
+ const spi_config_t &,
+ boost::uint32_t bits,
+ size_t num_bits,
+ bool readback)
+ {
+ UHD_ASSERT_THROW((num_bits <= 32) && !(num_bits % 8));
+ size_t num_bytes = num_bits / 8;
+
+ // Byteswap on num_bytes
+ unsigned char buff[4] = { 0 };
+ for (size_t i = 1; i <= num_bytes; i++)
+ buff[num_bytes - i] = (bits >> ((i - 1) * 8)) & 0xff;
+
+ if (readback) {
+ boost::uint8_t w_len_h = which_slave & 0xff;
+ boost::uint8_t w_len_l = num_bytes & 0xff;
+
+ int ret = _ctrl_transport->usrp_control_read(
+ VRQ_SPI_TRANSACT,
+ (buff[0] << 8) | (buff[1] << 0),
+ (buff[2] << 8) | (buff[3] << 0),
+ buff,
+ (w_len_h << 8) | (w_len_l << 0));
+
+ if (ret < 0) {
+ std::cout << "USRP: failed SPI readback transaction: "
+ << std::dec << ret << std::endl;
+ }
+
+ boost::uint32_t val = (((boost::uint32_t)buff[0]) << 0) |
+ (((boost::uint32_t)buff[1]) << 8) |
+ (((boost::uint32_t)buff[2]) << 16) |
+ (((boost::uint32_t)buff[3]) << 24);
+ return val;
+ }
+ else {
+ boost::uint8_t w_index_h = which_slave & 0xff;
+ boost::uint8_t w_index_l = (SPI_FMT_MSB | SPI_FMT_HDR_0) & 0xff;
+
+ int ret =_ctrl_transport->usrp_control_write(
+ VRQ_SPI_WRITE,
+ 0x00,
+ (w_index_h << 8) | (w_index_l << 0),
+ buff, num_bytes);
+
+ if (ret < 0) {
+ std::cout << "USRP: failed SPI transaction: "
+ << std::dec << ret << std::endl;
+ }
+
+ return 0;
+ }
+ }
+
+ /*******************************************************************
+ * Firmware
+ *
+ * This call is deprecated.
+ ******************************************************************/
+ void write_firmware_cmd(boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char *buff,
+ boost::uint16_t length)
+ {
+ int ret;
+
+ if (request & 0x80) {
+ ret = _ctrl_transport->usrp_control_read(request,
+ value,
+ index,
+ buff,
+ length);
+ }
+ else {
+ ret = _ctrl_transport->usrp_control_write(request,
+ value,
+ index,
+ buff,
+ length);
+ }
+
+ if (ret < 0)
+ std::cerr << "USRP: failed firmware command: " << ret << std::endl;
+ }
+
+private:
+ usrp_ctrl::sptr _ctrl_transport;
+};
+
+/***********************************************************************
+ * Public Make Function
+ **********************************************************************/
+usrp1_iface::sptr usrp1_iface::make(usrp_ctrl::sptr ctrl_transport)
+{
+ return sptr(new usrp1_iface_impl(ctrl_transport));
+}
diff --git a/host/lib/usrp/usrp1/usrp1_iface.hpp b/host/lib/usrp/usrp1/usrp1_iface.hpp
new file mode 100644
index 000000000..9a3fdd6bc
--- /dev/null
+++ b/host/lib/usrp/usrp1/usrp1_iface.hpp
@@ -0,0 +1,100 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_USRP1_IFACE_HPP
+#define INCLUDED_USRP1_IFACE_HPP
+
+#include <uhd/types/serial.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include "usrp1_ctrl.hpp"
+
+/*!
+ * The usrp1 interface class:
+ * Provides a set of functions to implementation layer.
+ * Including spi, peek, poke, control...
+ */
+class usrp1_iface : boost::noncopyable, public uhd::i2c_iface{
+public:
+ typedef boost::shared_ptr<usrp1_iface> sptr;
+
+ /*!
+ * Make a new usrp1 interface with the control transport.
+ * \param ctrl_transport the usrp controller object
+ * \return a new usrp1 interface object
+ */
+ static sptr make(usrp_ctrl::sptr ctrl_transport);
+
+ /*!
+ * Write a register (32 bits)
+ * \param addr the address
+ * \param data the 32bit data
+ */
+ virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0;
+
+ /*!
+ * Read a register (32 bits)
+ * \param addr the address
+ * \return the 32bit data
+ */
+ virtual boost::uint32_t peek32(boost::uint32_t addr) = 0;
+
+ /*!
+ * Write a register (16 bits)
+ * \param addr the address
+ * \param data the 16bit data
+ */
+ virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0;
+
+ /*!
+ * read a register (16 bits)
+ * \param addr the address
+ * \return the 16bit data
+ */
+ virtual boost::uint16_t peek16(boost::uint32_t addr) = 0;
+
+ /*!
+ * Perform an spi transaction.
+ * \param which_slave the slave device number
+ * \param config spi config args
+ * \param data the bits to write
+ * \param num_bits how many bits in data
+ * \param readback true to readback a value
+ * \return spi data if readback set
+ */
+ virtual boost::uint32_t transact_spi(int which_slave,
+ const uhd::spi_config_t &config,
+ boost::uint32_t data,
+ size_t num_bits,
+ bool readback) = 0;
+
+ /*!
+ * Perform a general USB firmware OUT operation
+ * \param request
+ * \param value
+ * \param index
+ * \param data
+ * \return
+ */
+ virtual void write_firmware_cmd(boost::uint8_t request,
+ boost::uint16_t value,
+ boost::uint16_t index,
+ unsigned char* buff,
+ boost::uint16_t length) = 0;
+};
+
+#endif /* INCLUDED_USRP1_IFACE_HPP */
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
new file mode 100644
index 000000000..a6806dbc3
--- /dev/null
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -0,0 +1,236 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_impl.hpp"
+#include "usrp1_ctrl.hpp"
+#include "fpga_regs_standard.h"
+#include "usrp_spi_defs.h"
+#include <uhd/transport/usb_control.hpp>
+#include <uhd/usrp/device_props.hpp>
+#include <uhd/usrp/mboard_props.hpp>
+#include <uhd/utils/warning.hpp>
+#include <uhd/utils/assert.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/utils/images.hpp>
+#include <boost/format.hpp>
+#include <boost/assign/list_of.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/thread/thread.hpp>
+#include <iostream>
+
+using namespace uhd;
+using namespace uhd::usrp;
+using namespace uhd::transport;
+
+const boost::uint16_t USRP1_VENDOR_ID = 0xfffe;
+const boost::uint16_t USRP1_PRODUCT_ID = 0x0002;
+const boost::uint16_t FX2_VENDOR_ID = 0x04b4;
+const boost::uint16_t FX2_PRODUCT_ID = 0x8613;
+
+const std::vector<usrp1_impl::dboard_slot_t> usrp1_impl::_dboard_slots = boost::assign::list_of
+ (usrp1_impl::DBOARD_SLOT_A)(usrp1_impl::DBOARD_SLOT_B)
+;
+
+/***********************************************************************
+ * Discovery
+ **********************************************************************/
+static device_addrs_t usrp1_find(const device_addr_t &hint)
+{
+ device_addrs_t usrp1_addrs;
+
+ //return an empty list of addresses when type is set to non-usrp1
+ if (hint.has_key("type") and hint["type"] != "usrp1") return usrp1_addrs;
+
+ //extract the firmware path for the USRP1
+ std::string usrp1_fw_image;
+ try{
+ usrp1_fw_image = find_image_path(
+ hint.has_key("fw")? hint["fw"] : "usrp1_fw.ihx"
+ );
+ }
+ catch(const std::exception &e){
+ uhd::print_warning(
+ "Could not locate USRP1 firmware.\n"
+ "Please install the images package.\n"
+ );
+ return usrp1_addrs;
+ }
+ //std::cout << "USRP1 firmware image: " << usrp1_fw_image << std::endl;
+
+ boost::uint16_t vid = hint.has_key("uninit") ? FX2_VENDOR_ID : USRP1_VENDOR_ID;
+ boost::uint16_t pid = hint.has_key("uninit") ? FX2_PRODUCT_ID : USRP1_PRODUCT_ID;
+
+ //see what we got on the USB bus
+ std::vector<usb_device_handle::sptr> device_list =
+ usb_device_handle::get_device_list(vid, pid);
+
+ if(device_list.size() == 0) return usrp1_addrs; //return nothing if no USRPs found
+
+ //find the usrps and load firmware
+ BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
+ usb_control::sptr ctrl_transport = usb_control::make(handle);
+ usrp_ctrl::sptr usrp_ctrl = usrp_ctrl::make(ctrl_transport);
+ usrp_ctrl->usrp_load_firmware(usrp1_fw_image);
+ }
+
+ //get descriptors again with serial number, but using the initialized VID/PID now since we have firmware
+ vid = USRP1_VENDOR_ID;
+ pid = USRP1_PRODUCT_ID;
+ device_list = usb_device_handle::get_device_list(vid, pid);
+
+ BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
+ device_addr_t new_addr;
+ new_addr["type"] = "usrp1";
+ new_addr["serial"] = handle->get_serial();
+ usrp1_addrs.push_back(new_addr);
+ }
+
+ return usrp1_addrs;
+}
+
+/***********************************************************************
+ * Make
+ **********************************************************************/
+static device::sptr usrp1_make(const device_addr_t &device_addr)
+{
+ //extract the FPGA path for the USRP1
+ std::string usrp1_fpga_image = find_image_path(
+ device_addr.has_key("fpga")? device_addr["fpga"] : "usrp1_fpga.rbf"
+ );
+ //std::cout << "USRP1 FPGA image: " << usrp1_fpga_image << std::endl;
+
+ //try to match the given device address with something on the USB bus
+ std::vector<usb_device_handle::sptr> device_list =
+ usb_device_handle::get_device_list(USRP1_VENDOR_ID, USRP1_PRODUCT_ID);
+
+ //create data and control transports
+ usb_zero_copy::sptr data_transport;
+ usrp_ctrl::sptr usrp_ctrl;
+
+
+ BOOST_FOREACH(usb_device_handle::sptr handle, device_list) {
+ if (handle->get_serial() == device_addr["serial"]) {
+ usb_control::sptr ctrl_transport = usb_control::make(handle);
+ usrp_ctrl = usrp_ctrl::make(ctrl_transport);
+ usrp_ctrl->usrp_load_fpga(usrp1_fpga_image);
+
+ data_transport = usb_zero_copy::make(handle, // identifier
+ 6, // IN endpoint
+ 2, // OUT endpoint
+ 2 * (1 << 20), // buffer size
+ 16384); // transfer size
+ break;
+ }
+ }
+
+ //create the usrp1 implementation guts
+ return device::sptr(new usrp1_impl(data_transport, usrp_ctrl));
+}
+
+UHD_STATIC_BLOCK(register_usrp1_device){
+ device::register_device(&usrp1_find, &usrp1_make);
+}
+
+/***********************************************************************
+ * Structors
+ **********************************************************************/
+usrp1_impl::usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport,
+ usrp_ctrl::sptr ctrl_transport)
+ : _data_transport(data_transport), _ctrl_transport(ctrl_transport)
+{
+ _iface = usrp1_iface::make(ctrl_transport);
+
+ //create clock interface
+ _clock_ctrl = usrp1_clock_ctrl::make(_iface);
+
+ //create codec interface
+ _codec_ctrls[DBOARD_SLOT_A] = usrp1_codec_ctrl::make(
+ _iface, _clock_ctrl, SPI_ENABLE_CODEC_A
+ );
+ _codec_ctrls[DBOARD_SLOT_B] = usrp1_codec_ctrl::make(
+ _iface, _clock_ctrl, SPI_ENABLE_CODEC_B
+ );
+
+ //initialize the codecs
+ codec_init();
+
+ //initialize the mboard
+ mboard_init();
+
+ //initialize the dboards
+ dboard_init();
+
+ //initialize the dsps
+ rx_dsp_init();
+
+ //initialize the dsps
+ tx_dsp_init();
+
+ //initialize the send/recv
+ io_init();
+
+ //turn on the transmitter
+ _ctrl_transport->usrp_tx_enable(true);
+
+ //init the subdev specs
+ this->mboard_set(MBOARD_PROP_RX_SUBDEV_SPEC, subdev_spec_t());
+ this->mboard_set(MBOARD_PROP_TX_SUBDEV_SPEC, subdev_spec_t());
+}
+
+usrp1_impl::~usrp1_impl(void){
+ /* NOP */
+}
+
+bool usrp1_impl::recv_async_msg(uhd::async_metadata_t &, size_t timeout_ms){
+ //dummy fill-in for the recv_async_msg
+ boost::this_thread::sleep(boost::posix_time::milliseconds(timeout_ms));
+ return false;
+}
+
+/***********************************************************************
+ * Device Get
+ **********************************************************************/
+void usrp1_impl::get(const wax::obj &key_, wax::obj &val)
+{
+ named_prop_t key = named_prop_t::extract(key_);
+
+ //handle the get request conditioned on the key
+ switch(key.as<device_prop_t>()){
+ case DEVICE_PROP_NAME:
+ val = std::string("usrp1 device");
+ return;
+
+ case DEVICE_PROP_MBOARD:
+ UHD_ASSERT_THROW(key.name == "");
+ val = _mboard_proxy->get_link();
+ return;
+
+ case DEVICE_PROP_MBOARD_NAMES:
+ val = prop_names_t(1, ""); //vector of size 1 with empty string
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+}
+
+/***********************************************************************
+ * Device Set
+ **********************************************************************/
+void usrp1_impl::set(const wax::obj &, const wax::obj &)
+{
+ UHD_THROW_PROP_SET_ERROR();
+}
diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp
new file mode 100644
index 000000000..c2f693eeb
--- /dev/null
+++ b/host/lib/usrp/usrp1/usrp1_impl.hpp
@@ -0,0 +1,197 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include "usrp1_iface.hpp"
+#include "usrp1_ctrl.hpp"
+#include "clock_ctrl.hpp"
+#include "codec_ctrl.hpp"
+#include <uhd/device.hpp>
+#include <uhd/utils/pimpl.hpp>
+#include <uhd/types/dict.hpp>
+#include <uhd/types/otw_type.hpp>
+#include <uhd/types/clock_config.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/usrp/dboard_id.hpp>
+#include <uhd/usrp/subdev_spec.hpp>
+#include <uhd/usrp/dboard_eeprom.hpp>
+#include <uhd/usrp/dboard_manager.hpp>
+#include <uhd/transport/usb_zero_copy.hpp>
+
+#ifndef INCLUDED_USRP1_IMPL_HPP
+#define INCLUDED_USRP1_IMPL_HPP
+
+/*!
+ * Simple wax obj proxy class:
+ * Provides a wax obj interface for a set and a get function.
+ * This allows us to create nested properties structures
+ * while maintaining flattened code within the implementation.
+ */
+class wax_obj_proxy : public wax::obj {
+public:
+ typedef boost::function<void(const wax::obj &, wax::obj &)> get_t;
+ typedef boost::function<void(const wax::obj &, const wax::obj &)> set_t;
+ typedef boost::shared_ptr<wax_obj_proxy> sptr;
+
+ static sptr make(const get_t &get, const set_t &set){
+ return sptr(new wax_obj_proxy(get, set));
+ }
+
+private:
+ get_t _get; set_t _set;
+ wax_obj_proxy(const get_t &get, const set_t &set): _get(get), _set(set) {};
+ void get(const wax::obj &key, wax::obj &val) {return _get(key, val);}
+ void set(const wax::obj &key, const wax::obj &val) {return _set(key, val);}
+};
+
+/*!
+ * USRP1 implementation guts:
+ * The implementation details are encapsulated here.
+ * Handles properties on the mboard, dboard, dsps...
+ */
+class usrp1_impl : public uhd::device {
+public:
+ //! used everywhere to differentiate slots/sides...
+ enum dboard_slot_t{
+ DBOARD_SLOT_A = 'A',
+ DBOARD_SLOT_B = 'B'
+ };
+ //and a way to enumerate through a list of the above...
+ static const std::vector<dboard_slot_t> _dboard_slots;
+
+ //structors
+ usrp1_impl(uhd::transport::usb_zero_copy::sptr data_transport,
+ usrp_ctrl::sptr ctrl_transport);
+
+ ~usrp1_impl(void);
+
+ //the io interface
+ size_t send(const std::vector<const void *> &,
+ size_t,
+ const uhd::tx_metadata_t &,
+ const uhd::io_type_t &,
+ send_mode_t);
+
+ size_t recv(const std::vector<void *> &,
+ size_t, uhd::rx_metadata_t &,
+ const uhd::io_type_t &,
+ recv_mode_t,
+ size_t timeout);
+
+ size_t get_max_send_samps_per_packet(void) const { return 0; }
+ size_t get_max_recv_samps_per_packet(void) const { return 0; }
+ bool recv_async_msg(uhd::async_metadata_t &, size_t);
+
+private:
+ /*!
+ * Make a usrp1 dboard interface.
+ * \param iface the usrp1 interface object
+ * \param clock the clock control interface
+ * \param codec the codec control interface
+ * \param dboard_slot the slot identifier
+ * \param rx_dboard_id the db id for the rx board (used for evil dbsrx purposes)
+ * \return a sptr to a new dboard interface
+ */
+ static uhd::usrp::dboard_iface::sptr make_dboard_iface(
+ usrp1_iface::sptr iface,
+ usrp1_clock_ctrl::sptr clock,
+ usrp1_codec_ctrl::sptr codec,
+ dboard_slot_t dboard_slot,
+ const uhd::usrp::dboard_id_t &rx_dboard_id
+ );
+
+ //interface to ioctls and file descriptor
+ usrp1_iface::sptr _iface;
+
+ //handle io stuff
+ UHD_PIMPL_DECL(io_impl) _io_impl;
+ void io_init(void);
+ void issue_stream_cmd(const uhd::stream_cmd_t &stream_cmd);
+ void handle_overrun(size_t);
+
+ //underrun and overrun poll intervals
+ size_t _rx_samps_per_poll_interval;
+ size_t _tx_samps_per_poll_interval;
+
+ //otw types
+ uhd::otw_type_t _rx_otw_type;
+ uhd::otw_type_t _tx_otw_type;
+
+ //configuration shadows
+ uhd::clock_config_t _clock_config;
+ uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec;
+
+ //clock control
+ usrp1_clock_ctrl::sptr _clock_ctrl;
+
+ //ad9862 codec control interface
+ uhd::dict<dboard_slot_t, usrp1_codec_ctrl::sptr> _codec_ctrls;
+
+ //codec properties interfaces
+ void codec_init(void);
+ void rx_codec_get(const wax::obj &, wax::obj &, dboard_slot_t);
+ void rx_codec_set(const wax::obj &, const wax::obj &, dboard_slot_t);
+ void tx_codec_get(const wax::obj &, wax::obj &, dboard_slot_t);
+ void tx_codec_set(const wax::obj &, const wax::obj &, dboard_slot_t);
+ uhd::dict<dboard_slot_t, wax_obj_proxy::sptr> _rx_codec_proxies, _tx_codec_proxies;
+
+ //device functions and settings
+ void get(const wax::obj &, wax::obj &);
+ void set(const wax::obj &, const wax::obj &);
+
+ //mboard functions and settings
+ void mboard_init(void);
+ void mboard_get(const wax::obj &, wax::obj &);
+ void mboard_set(const wax::obj &, const wax::obj &);
+ wax_obj_proxy::sptr _mboard_proxy;
+
+ //xx dboard functions and settings
+ void dboard_init(void);
+ uhd::dict<dboard_slot_t, uhd::usrp::dboard_manager::sptr> _dboard_managers;
+ uhd::dict<dboard_slot_t, uhd::usrp::dboard_iface::sptr> _dboard_ifaces;
+
+ //rx dboard functions and settings
+ uhd::dict<dboard_slot_t, uhd::usrp::dboard_eeprom_t> _rx_db_eeproms;
+ void rx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t);
+ void rx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t);
+ uhd::dict<dboard_slot_t, wax_obj_proxy::sptr> _rx_dboard_proxies;
+
+ //tx dboard functions and settings
+ uhd::dict<dboard_slot_t, uhd::usrp::dboard_eeprom_t> _tx_db_eeproms;
+ void tx_dboard_get(const wax::obj &, wax::obj &, dboard_slot_t);
+ void tx_dboard_set(const wax::obj &, const wax::obj &, dboard_slot_t);
+ uhd::dict<dboard_slot_t, wax_obj_proxy::sptr> _tx_dboard_proxies;
+
+ //rx dsp functions and settings
+ void rx_dsp_init(void);
+ void rx_dsp_get(const wax::obj &, wax::obj &);
+ void rx_dsp_set(const wax::obj &, const wax::obj &);
+ double _rx_dsp_freq; size_t _rx_dsp_decim;
+ wax_obj_proxy::sptr _rx_dsp_proxy;
+
+ //tx dsp functions and settings
+ void tx_dsp_init(void);
+ void tx_dsp_get(const wax::obj &, wax::obj &);
+ void tx_dsp_set(const wax::obj &, const wax::obj &);
+ double _tx_dsp_freq; size_t _tx_dsp_interp;
+ wax_obj_proxy::sptr _tx_dsp_proxy;
+
+ //transports
+ uhd::transport::usb_zero_copy::sptr _data_transport;
+ usrp_ctrl::sptr _ctrl_transport;
+};
+
+#endif /* INCLUDED_USRP1_IMPL_HPP */
diff --git a/host/lib/usrp/usrp2/CMakeLists.txt b/host/lib/usrp/usrp2/CMakeLists.txt
index 47d74cec8..f7984fce5 100644
--- a/host/lib/usrp/usrp2/CMakeLists.txt
+++ b/host/lib/usrp/usrp2/CMakeLists.txt
@@ -17,25 +17,46 @@
#This file will be included by cmake, use absolute paths!
-LIBUHD_APPEND_SOURCES(
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_impl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.hpp
- ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.cpp
-)
+########################################################################
+# Conditionally configure the USRP2 support
+########################################################################
+MESSAGE(STATUS "Configuring USRP2 support...")
+
+IF(DEFINED ENABLE_USRP2)
+ IF(ENABLE_USRP2)
+ MESSAGE(STATUS "USRP2 support enabled by configure flag")
+ ELSE(ENABLE_USRP2)
+ MESSAGE(STATUS "USRP2 support disabled by configure flag")
+ ENDIF(ENABLE_USRP2)
+ELSE(DEFINED ENABLE_USRP2) #not defined: automatic enabling of component
+ SET(ENABLE_USRP2 TRUE)
+ENDIF(DEFINED ENABLE_USRP2)
+SET(ENABLE_USRP2 ${ENABLE_USRP2} CACHE BOOL "enable USRP2 support")
+
+IF(ENABLE_USRP2)
+ MESSAGE(STATUS " Building USRP2 support.")
+ LIBUHD_APPEND_SOURCES(
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/clock_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/codec_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dboard_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/dsp_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/gps_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/io_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/mboard_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/serdes_ctrl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_iface.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.cpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_impl.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.hpp
+ ${CMAKE_SOURCE_DIR}/lib/usrp/usrp2/usrp2_regs.cpp
+ )
+ELSE(ENABLE_USRP2)
+ MESSAGE(STATUS " Skipping USRP2 support.")
+ENDIF(ENABLE_USRP2)
diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp
index e5be62205..22a892f02 100644
--- a/host/lib/usrp/usrp2/codec_ctrl.cpp
+++ b/host/lib/usrp/usrp2/codec_ctrl.cpp
@@ -66,8 +66,8 @@ public:
this->send_ads62p44_reg(0x00); //issue a reset to the ADC
//everything else should be pretty much default, i think
// _ads62p44_regs.decimation = DECIMATION_DECIMATE_1;
-
-
+ _ads62p44_regs.power_down = ads62p44_regs_t::POWER_DOWN_NORMAL;
+ this->send_ads62p44_reg(0x14);
}
}
diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h
index 4d3b62d6b..12ff1a76f 100644
--- a/host/lib/usrp/usrp2/fw_common.h
+++ b/host/lib/usrp/usrp2/fw_common.h
@@ -33,7 +33,7 @@ extern "C" {
#endif
//fpga and firmware compatibility numbers
-#define USRP2_FPGA_COMPAT_NUM 1
+#define USRP2_FPGA_COMPAT_NUM 2
#define USRP2_FW_COMPAT_NUM 6
//used to differentiate control packets over data port
diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp
index c67bd02fd..94ff5c2ce 100644
--- a/host/lib/usrp/usrp2/io_impl.cpp
+++ b/host/lib/usrp/usrp2/io_impl.cpp
@@ -113,7 +113,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(
metadata.event_code = vrt_packet_handler::get_context_code<async_metadata_t::event_code_t>(vrt_hdr, if_packet_info);
//print the famous U, and push the metadata into the message queue
- if (metadata.event_code & underflow_flags) std::cerr << "U";
+ if (metadata.event_code & underflow_flags) std::cerr << "U" << std::flush;
async_msg_fifo->push_with_pop_on_full(metadata);
continue;
}
@@ -121,7 +121,7 @@ void usrp2_impl::io_impl::recv_pirate_loop(
//handle the packet count / sequence number
if (if_packet_info.packet_count != next_packet_seq){
//std::cerr << "S" << (if_packet_info.packet_count - next_packet_seq)%16;
- std::cerr << "O"; //report overflow (drops in the kernel)
+ std::cerr << "O" << std::flush; //report overflow (drops in the kernel)
}
next_packet_seq = (if_packet_info.packet_count+1)%16;
diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp
index b5a8ebc53..2669df9bc 100644
--- a/host/lib/usrp/usrp2/mboard_impl.cpp
+++ b/host/lib/usrp/usrp2/mboard_impl.cpp
@@ -77,12 +77,16 @@ usrp2_mboard_impl::usrp2_mboard_impl(
_allowed_decim_and_interp_rates.push_back(i);
}
+ //Issue a stop streaming command (in case it was left running).
+ //Since this command is issued before the networking is setup,
+ //most if not all junk packets will never make it to the socket.
+ this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
+
//setup the vrt rx registers
_iface->poke32(_iface->regs.rx_ctrl_nsamps_per_pkt, _io_helper.get_max_recv_samps_per_packet());
_iface->poke32(_iface->regs.rx_ctrl_nchannels, 1);
_iface->poke32(_iface->regs.rx_ctrl_clear_overrun, 1); //reset
_iface->poke32(_iface->regs.rx_ctrl_vrt_header, 0
-
| (0x1 << 28) //if data with stream id
| (0x1 << 26) //has trailer
| (0x3 << 22) //integer time other
@@ -116,11 +120,6 @@ usrp2_mboard_impl::usrp2_mboard_impl(
//set default subdev specs
(*this)[MBOARD_PROP_RX_SUBDEV_SPEC] = subdev_spec_t();
(*this)[MBOARD_PROP_TX_SUBDEV_SPEC] = subdev_spec_t();
-
- //Issue a stop streaming command (in case it was left running).
- //Since this command is issued before the networking is setup,
- //most if not all junk packets will never make it to the socket.
- this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
}
usrp2_mboard_impl::~usrp2_mboard_impl(void){
diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp
index 0a171d20c..f74c78b7b 100644
--- a/host/lib/usrp/usrp2/usrp2_regs.hpp
+++ b/host/lib/usrp/usrp2/usrp2_regs.hpp
@@ -211,6 +211,7 @@ usrp2_regs_t usrp2_get_regs(int hw_rev);
* </pre>
*/
+
/////////////////////////////////////////////////
// DSP RX Regs
////////////////////////////////////////////////
diff --git a/host/test/convert_types_test.cpp b/host/test/convert_types_test.cpp
index 1587be57f..2148302b6 100644
--- a/host/test/convert_types_test.cpp
+++ b/host/test/convert_types_test.cpp
@@ -17,109 +17,226 @@
#include <uhd/transport/convert_types.hpp>
#include <boost/test/unit_test.hpp>
+#include <boost/foreach.hpp>
#include <boost/cstdint.hpp>
+#include <boost/asio/buffer.hpp>
#include <complex>
+#include <vector>
+#include <cstdlib>
using namespace uhd;
-template <typename host_type, typename dev_type, size_t nsamps>
-void loopback(
+//typedefs for complex types
+typedef std::complex<boost::int16_t> sc16_t;
+typedef std::complex<float> fc32_t;
+
+//extract pointer to POD since using &vector.front() throws in MSVC
+template <typename T> void * pod2ptr(T &pod){
+ return boost::asio::buffer_cast<void *>(boost::asio::buffer(pod));
+}
+template <typename T> const void * pod2ptr(const T &pod){
+ return boost::asio::buffer_cast<const void *>(boost::asio::buffer(pod));
+}
+
+/***********************************************************************
+ * Loopback runner:
+ * convert input buffer into intermediate buffer
+ * convert intermediate buffer into output buffer
+ **********************************************************************/
+template <typename Range> static void loopback(
+ size_t nsamps,
const io_type_t &io_type,
const otw_type_t &otw_type,
- const host_type *input,
- host_type *output
+ const Range &input,
+ Range &output
){
- dev_type dev[nsamps];
+ //item32 is largest device type
+ std::vector<boost::uint32_t> dev(nsamps);
//convert to dev type
transport::convert_io_type_to_otw_type(
- input, io_type,
- dev, otw_type,
+ pod2ptr(input), io_type,
+ pod2ptr(dev), otw_type,
nsamps
);
//convert back to host type
transport::convert_otw_type_to_io_type(
- dev, otw_type,
- output, io_type,
+ pod2ptr(dev), otw_type,
+ pod2ptr(output), io_type,
nsamps
);
}
-typedef std::complex<boost::uint16_t> sc16_t;
+/***********************************************************************
+ * Test short conversion
+ **********************************************************************/
+static void test_convert_types_sc16(
+ size_t nsamps,
+ const io_type_t &io_type,
+ const otw_type_t &otw_type
+){
+ //fill the input samples
+ std::vector<sc16_t> input(nsamps), output(nsamps);
+ BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
+ std::rand()-(RAND_MAX/2),
+ std::rand()-(RAND_MAX/2)
+ );
-BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){
- sc16_t in_sc16[] = {
- sc16_t(0, -1234), sc16_t(4321, 1234),
- sc16_t(9876, -4567), sc16_t(8912, 0)
- }, out_sc16[4];
+ //run the loopback and test
+ loopback(nsamps, io_type, otw_type, input, output);
+ BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+}
+BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){
io_type_t io_type(io_type_t::COMPLEX_INT16);
otw_type_t otw_type;
otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
otw_type.width = 16;
- loopback<sc16_t, boost::uint32_t, 4>(io_type, otw_type, in_sc16, out_sc16);
- BOOST_CHECK_EQUAL_COLLECTIONS(in_sc16, in_sc16+4, out_sc16, out_sc16+4);
+ //try various lengths to test edge cases
+ for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ test_convert_types_sc16(nsamps, io_type, otw_type);
+ }
}
BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){
- sc16_t in_sc16[] = {
- sc16_t(0, -1234), sc16_t(4321, 1234),
- sc16_t(9876, -4567), sc16_t(8912, 0)
- }, out_sc16[4];
-
io_type_t io_type(io_type_t::COMPLEX_INT16);
otw_type_t otw_type;
otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
otw_type.width = 16;
- loopback<sc16_t, boost::uint32_t, 4>(io_type, otw_type, in_sc16, out_sc16);
- BOOST_CHECK_EQUAL_COLLECTIONS(in_sc16, in_sc16+4, out_sc16, out_sc16+4);
+ //try various lengths to test edge cases
+ for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ test_convert_types_sc16(nsamps, io_type, otw_type);
+ }
}
-typedef std::complex<float> fc32_t;
-
-#define BOOST_CHECK_CLOSE_COMPLEX(a1, a2, p) \
- BOOST_CHECK_CLOSE(a1.real(), a2.real(), p); \
- BOOST_CHECK_CLOSE(a1.imag(), a2.imag(), p);
+/***********************************************************************
+ * Test float conversion
+ **********************************************************************/
+static void test_convert_types_fc32(
+ size_t nsamps,
+ const io_type_t &io_type,
+ const otw_type_t &otw_type
+){
+ //fill the input samples
+ std::vector<fc32_t> input(nsamps), output(nsamps);
+ BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
+ (std::rand()/float(RAND_MAX/2)) - 1,
+ (std::rand()/float(RAND_MAX/2)) - 1
+ );
-static const float tolerance = float(0.1);
+ //run the loopback and test
+ loopback(nsamps, io_type, otw_type, input, output);
+ for (size_t i = 0; i < nsamps; i++){
+ BOOST_CHECK_CLOSE_FRACTION(input[i].real(), output[i].real(), float(0.01));
+ BOOST_CHECK_CLOSE_FRACTION(input[i].imag(), output[i].imag(), float(0.01));
+ }
+}
BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){
- fc32_t in_fc32[] = {
- fc32_t(float(0), float(-0.2)), fc32_t(float(0.03), float(-0.16)),
- fc32_t(float(1.0), float(.45)), fc32_t(float(0.09), float(0))
- }, out_fc32[4];
-
io_type_t io_type(io_type_t::COMPLEX_FLOAT32);
otw_type_t otw_type;
otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN;
otw_type.width = 16;
- loopback<fc32_t, boost::uint32_t, 4>(io_type, otw_type, in_fc32, out_fc32);
-
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[0], out_fc32[0], tolerance);
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[1], out_fc32[1], tolerance);
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[2], out_fc32[2], tolerance);
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[3], out_fc32[3], tolerance);
+ //try various lengths to test edge cases
+ for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ test_convert_types_fc32(nsamps, io_type, otw_type);
+ }
}
BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){
- fc32_t in_fc32[] = {
- fc32_t(float(0), float(-0.2)), fc32_t(float(0.03), float(-0.16)),
- fc32_t(float(1.0), float(.45)), fc32_t(float(0.09), float(0))
- }, out_fc32[4];
-
io_type_t io_type(io_type_t::COMPLEX_FLOAT32);
otw_type_t otw_type;
otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN;
otw_type.width = 16;
- loopback<fc32_t, boost::uint32_t, 4>(io_type, otw_type, in_fc32, out_fc32);
+ //try various lengths to test edge cases
+ for (size_t nsamps = 0; nsamps < 16; nsamps++){
+ test_convert_types_fc32(nsamps, io_type, otw_type);
+ }
+}
+
+/***********************************************************************
+ * Test float to short conversion loopback
+ **********************************************************************/
+BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){
+ io_type_t io_type_in(io_type_t::COMPLEX_FLOAT32);
+ io_type_t io_type_out(io_type_t::COMPLEX_INT16);
+
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_NATIVE;
+ otw_type.width = 16;
+
+ const size_t nsamps = 13;
+ std::vector<fc32_t> input(nsamps);
+ BOOST_FOREACH(fc32_t &in, input) in = fc32_t(
+ (std::rand()/float(RAND_MAX/2)) - 1,
+ (std::rand()/float(RAND_MAX/2)) - 1
+ );
+
+ //convert float to dev
+ std::vector<boost::uint32_t> tmp(nsamps);
+ transport::convert_io_type_to_otw_type(
+ pod2ptr(input), io_type_in,
+ pod2ptr(tmp), otw_type,
+ nsamps
+ );
+
+ //convert dev to short
+ std::vector<sc16_t> output(nsamps);
+ transport::convert_otw_type_to_io_type(
+ pod2ptr(tmp), otw_type,
+ pod2ptr(output), io_type_out,
+ nsamps
+ );
+
+ //test that the inputs and outputs match
+ for (size_t i = 0; i < nsamps; i++){
+ BOOST_CHECK_CLOSE_FRACTION(input[i].real(), output[i].real()/float(32767), float(0.01));
+ BOOST_CHECK_CLOSE_FRACTION(input[i].imag(), output[i].imag()/float(32767), float(0.01));
+ }
+}
+
+/***********************************************************************
+ * Test short to float conversion loopback
+ **********************************************************************/
+BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){
+ io_type_t io_type_in(io_type_t::COMPLEX_INT16);
+ io_type_t io_type_out(io_type_t::COMPLEX_FLOAT32);
+
+ otw_type_t otw_type;
+ otw_type.byteorder = otw_type_t::BO_NATIVE;
+ otw_type.width = 16;
+
+ const size_t nsamps = 13;
+ std::vector<sc16_t> input(nsamps);
+ BOOST_FOREACH(sc16_t &in, input) in = sc16_t(
+ std::rand()-(RAND_MAX/2),
+ std::rand()-(RAND_MAX/2)
+ );
+
+ //convert short to dev
+ std::vector<boost::uint32_t> tmp(nsamps);
+ transport::convert_io_type_to_otw_type(
+ pod2ptr(input), io_type_in,
+ pod2ptr(tmp), otw_type,
+ nsamps
+ );
+
+ //convert dev to float
+ std::vector<fc32_t> output(nsamps);
+ transport::convert_otw_type_to_io_type(
+ pod2ptr(tmp), otw_type,
+ pod2ptr(output), io_type_out,
+ nsamps
+ );
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[0], out_fc32[0], tolerance);
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[1], out_fc32[1], tolerance);
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[2], out_fc32[2], tolerance);
- BOOST_CHECK_CLOSE_COMPLEX(in_fc32[3], out_fc32[3], tolerance);
+ //test that the inputs and outputs match
+ for (size_t i = 0; i < nsamps; i++){
+ BOOST_CHECK_CLOSE_FRACTION(input[i].real()/float(32767), output[i].real(), float(0.01));
+ BOOST_CHECK_CLOSE_FRACTION(input[i].imag()/float(32767), output[i].imag(), float(0.01));
+ }
}
diff --git a/host/utils/CMakeLists.txt b/host/utils/CMakeLists.txt
index c349a9018..a95864ca7 100644
--- a/host/utils/CMakeLists.txt
+++ b/host/utils/CMakeLists.txt
@@ -39,9 +39,17 @@ TARGET_LINK_LIBRARIES(usrp2_addr_burner uhd)
ADD_EXECUTABLE(usrp_burn_db_eeprom usrp_burn_db_eeprom.cpp)
TARGET_LINK_LIBRARIES(usrp_burn_db_eeprom uhd)
+ADD_EXECUTABLE(usrp1_init_eeprom usrp1_init_eeprom.cpp)
+TARGET_LINK_LIBRARIES(usrp1_init_eeprom uhd)
+
+ADD_EXECUTABLE(usrp1_serial_burner usrp1_serial_burner.cpp)
+TARGET_LINK_LIBRARIES(usrp1_serial_burner uhd)
+
INSTALL(TARGETS
usrp2_addr_burner
usrp_burn_db_eeprom
+ usrp1_init_eeprom
+ usrp1_serial_burner
RUNTIME DESTINATION ${PKG_DATA_DIR}/utils
)
diff --git a/host/utils/usrp1_init_eeprom.cpp b/host/utils/usrp1_init_eeprom.cpp
new file mode 100644
index 000000000..b05e400b1
--- /dev/null
+++ b/host/utils/usrp1_init_eeprom.cpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/device.hpp>
+#include <uhd/usrp/device_props.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("image", po::value<std::string>(), "BIN image file")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("USRP EEPROM initialization %s") % desc << std::endl;
+ return ~0;
+ }
+
+ //load the options into the address
+ uhd::device_addr_t device_addr;
+ device_addr["type"] = "usrp1";
+ device_addr["uninit"] = "yeah"; //tell find to look for an uninitialized FX2
+
+ //find and create a control transport to do the writing.
+
+ uhd::device_addrs_t found_addrs = uhd::device::find(device_addr);
+
+ if (found_addrs.size() == 0){
+ std::cerr << "No uninitialized USRP devices found" << std::endl;
+ return ~0;
+ }
+
+ for (size_t i = 0; i < found_addrs.size(); i++){
+ std::cout << "Writing EEPROM data..." << std::endl;
+ //uhd::device_addrs_t devs = uhd::device::find(found_addrs[i]);
+ uhd::device::sptr dev = uhd::device::make(found_addrs[i]);
+ wax::obj mb = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD];
+ mb[std::string("load_eeprom")] = vm["image"].as<std::string>();
+ }
+
+
+ std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl;
+ return 0;
+}
diff --git a/host/utils/usrp1_serial_burner.cpp b/host/utils/usrp1_serial_burner.cpp
new file mode 100644
index 000000000..bf7d3d3bb
--- /dev/null
+++ b/host/utils/usrp1_serial_burner.cpp
@@ -0,0 +1,75 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// 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 3 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, see <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/device.hpp>
+#include <uhd/usrp/device_props.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <iostream>
+
+namespace po = boost::program_options;
+
+int UHD_SAFE_MAIN(int argc, char *argv[]){
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("old", po::value<std::string>(), "old USRP serial number (optional)")
+ ("new", po::value<std::string>(), "new USRP serial number")
+ ;
+
+ po::variables_map vm;
+ po::store(po::parse_command_line(argc, argv, desc), vm);
+ po::notify(vm);
+
+ //print the help message
+ if (vm.count("help")){
+ std::cout << boost::format("USRP serial burner %s") % desc << std::endl;
+ return ~0;
+ }
+
+ if(vm.count("new") == 0) {
+ std::cout << "error: must input --new arg" << std::endl;
+ return ~0;
+ }
+
+ //load the options into the address
+ uhd::device_addr_t device_addr;
+ device_addr["type"] = "usrp1";
+ if(vm.count("old")) device_addr["serial"] = vm["old"].as<std::string>();
+
+ //find and create a control transport to do the writing.
+
+ uhd::device_addrs_t found_addrs = uhd::device::find(device_addr);
+
+ if (found_addrs.size() == 0){
+ std::cerr << "No USRP devices found" << std::endl;
+ return ~0;
+ }
+
+ for (size_t i = 0; i < found_addrs.size(); i++){
+ uhd::device::sptr dev = uhd::device::make(found_addrs[i]);
+ wax::obj mb = (*dev)[uhd::usrp::DEVICE_PROP_MBOARD];
+ std::cout << "Writing serial number..." << std::endl;
+ mb[std::string("serial")] = vm["new"].as<std::string>();
+ std::cout << "Reading back serial number: " << mb[std::string("serial")].as<std::string>() << std::endl;
+ }
+
+
+ std::cout << "Power-cycle the usrp for the changes to take effect." << std::endl;
+ return 0;
+}
diff --git a/host/utils/usrp_burn_db_eeprom.cpp b/host/utils/usrp_burn_db_eeprom.cpp
index db2981e87..64ecf75d6 100644
--- a/host/utils/usrp_burn_db_eeprom.cpp
+++ b/host/utils/usrp_burn_db_eeprom.cpp
@@ -19,6 +19,7 @@
#include <uhd/utils/safe_main.hpp>
#include <uhd/device.hpp>
#include <uhd/types/dict.hpp>
+#include <uhd/utils/assert.hpp>
#include <uhd/usrp/dboard_id.hpp>
#include <uhd/usrp/device_props.hpp>
#include <uhd/usrp/mboard_props.hpp>
@@ -34,16 +35,19 @@ namespace po = boost::program_options;
int UHD_SAFE_MAIN(int argc, char *argv[]){
//command line variables
- std::string args, db_name, unit;
+ std::string args, slot, unit;
static const uhd::dict<std::string, mboard_prop_t> unit_to_db_prop = boost::assign::map_list_of
("RX", MBOARD_PROP_RX_DBOARD) ("TX", MBOARD_PROP_TX_DBOARD)
;
+ static const uhd::dict<std::string, mboard_prop_t> unit_to_db_names_prop = boost::assign::map_list_of
+ ("RX", MBOARD_PROP_RX_DBOARD_NAMES) ("TX", MBOARD_PROP_TX_DBOARD_NAMES)
+ ;
po::options_description desc("Allowed options");
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""), "device address args [default = \"\"]")
- ("db", po::value<std::string>(&db_name)->default_value(""), "dboard name [default = \"\"]")
+ ("slot", po::value<std::string>(&slot)->default_value(""), "dboard slot name [default is blank for automatic]")
("unit", po::value<std::string>(&unit)->default_value(""), "which unit [RX or TX]")
("id", po::value<std::string>(), "dboard id to burn, omit for readback")
;
@@ -70,8 +74,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//make the device and extract the dboard w/ property
device::sptr dev = device::make(args);
- wax::obj dboard = (*dev)[DEVICE_PROP_MBOARD][named_prop_t(unit_to_db_prop[unit], db_name)];
- std::string prefix = (db_name == "")? unit : (unit + ":" + db_name);
+ uhd::prop_names_t dboard_names = (*dev)[DEVICE_PROP_MBOARD][unit_to_db_names_prop[unit]].as<uhd::prop_names_t>();
+ if (dboard_names.size() == 1 and slot.empty()) slot = dboard_names.front();
+ uhd::assert_has(dboard_names, slot, "dboard slot name");
+ wax::obj dboard = (*dev)[DEVICE_PROP_MBOARD][named_prop_t(unit_to_db_prop[unit], slot)];
+ std::string prefix = unit + ":" + slot;
//read the current dboard id from eeprom
if (vm.count("id") == 0){
diff --git a/images/Makefile b/images/Makefile
index 6ab54e6ac..57277e787 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -31,8 +31,57 @@ CMAKE_BUILD_DIR = $(TOP_DIR)/build
IMAGES_LIST =
########################################################################
+# Utility Checks
+########################################################################
+ifeq ($(shell sdcc --help > /dev/null 2>&1 && echo $$?),0)
+ HAS_SDCC=1
+endif
+
+ifeq ($(shell mb-gcc --help > /dev/null 2>&1 && echo $$?),0)
+ HAS_MB_GCC=1
+endif
+
+ifeq ($(shell xtclsh -h > /dev/null 2>&1 && echo $$?),0)
+ HAS_XTCLSH=1
+endif
+
+########################################################################
+# USRP1 firmware
+########################################################################
+ifdef HAS_SDCC
+
+_usrp1_fw_dir = $(TOP_FW_DIR)/fx2
+_usrp1_fw_ihx = $(BUILT_IMAGES_DIR)/usrp1_fw.ihx
+IMAGES_LIST += $(_usrp1_fw_ihx)
+
+$(_usrp1_fw_ihx):
+ cd $(_usrp1_fw_dir) && ./bootstrap
+ cd $(_usrp1_fw_dir) && ./configure
+ make -C $(_usrp1_fw_dir) clean
+ make -C $(_usrp1_fw_dir) all
+ cp $(_usrp1_fw_dir)/src/usrp1/std.ihx $@
+
+endif
+
+########################################################################
+# USRP1 fpga
+########################################################################
+_usrp1_fpga_dir = $(TOP_FPGA_DIR)/usrp1/rbf/rev4
+_usrp1_fpga_rbf = $(BUILT_IMAGES_DIR)/usrp1_fpga.rbf
+_usrp1_fpga_4rx_rbf = $(BUILT_IMAGES_DIR)/usrp1_fpga_4rx.rbf
+IMAGES_LIST += $(_usrp1_fpga_rbf) $(_usrp1_fpga_4rx_rbf)
+
+$(_usrp1_fpga_rbf):
+ cp $(_usrp1_fpga_dir)/std_2rxhb_2tx.rbf $@
+
+$(_usrp1_fpga_4rx_rbf):
+ cp $(_usrp1_fpga_dir)/std_4rx_0tx.rbf $@
+
+########################################################################
# USRP2 firmware
########################################################################
+ifdef HAS_MB_GCC
+
_usrp2_fw_dir = $(TOP_FW_DIR)/microblaze
_usrp2_fw_bin = $(BUILT_IMAGES_DIR)/usrp2_fw.bin
IMAGES_LIST += $(_usrp2_fw_bin)
@@ -44,9 +93,13 @@ $(_usrp2_fw_bin):
make -C $(_usrp2_fw_dir) all
cp $(_usrp2_fw_dir)/usrp2/usrp2_txrx_uhd.bin $@
+endif
+
########################################################################
# USRP2 fpga
########################################################################
+ifdef HAS_XTCLSH
+
_usrp2_fpga_dir = $(TOP_FPGA_DIR)/usrp2/top/u2_rev3
_usrp2_fpga_bin = $(BUILT_IMAGES_DIR)/usrp2_fpga.bin
IMAGES_LIST += $(_usrp2_fpga_bin)
@@ -56,6 +109,8 @@ $(_usrp2_fpga_bin):
cd $(_usrp2_fpga_dir) && make -f Makefile.udp bin
cp $(_usrp2_fpga_dir)/build-udp/u2_rev3.bin $@
+endif
+
########################################################################
# Build rules
########################################################################
diff --git a/images/README b/images/README
index ec8391826..2f9c6a95e 100644
--- a/images/README
+++ b/images/README
@@ -18,3 +18,8 @@ To build the package (unix):
The package generator types are described here:
http://www.cmake.org/Wiki/CMake:CPackPackageGenerators
+
+Fedora note:
+ The sdcc binaries are prefixed with "sdcc-" which breaks the build.
+ However, /usr/libexec/sdcc contains properly named sdcc binaries.
+ export PATH=${PATH}:/usr/libexec/sdcc