diff options
| author | Philip Balister <philip@opensdr.com> | 2010-09-09 14:08:20 -0400 | 
|---|---|---|
| committer | Philip Balister <philip@opensdr.com> | 2010-09-09 14:08:20 -0400 | 
| commit | 262109bc461139448c816f92644a9f748798c4fc (patch) | |
| tree | b51367352945b08566ff8501d7ef4b91eb86e4d4 | |
| parent | d2d5be27b09faee1481a763ce25e7b95460a46c9 (diff) | |
| parent | 5058145dcc5cb681887773b8245cf89df58399f9 (diff) | |
| download | uhd-262109bc461139448c816f92644a9f748798c4fc.tar.gz uhd-262109bc461139448c816f92644a9f748798c4fc.tar.bz2 uhd-262109bc461139448c816f92644a9f748798c4fc.zip | |
Merge branch 'master' of ettus.sourcerepo.com:ettus/uhdpriv into usrp_e
168 files changed, 17660 insertions, 218 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.gpfBinary files differ new file mode 100755 index 000000000..a954ac193 --- /dev/null +++ b/firmware/fx2/src/common/gpif.gpf 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.gpfBinary files differ new file mode 100755 index 000000000..854e25399 --- /dev/null +++ b/firmware/fx2/src/usrp1/gpif.gpf 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..0f6d1cfeb 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 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..0d48209be 100644 --- a/host/docs/usrp2.rst +++ b/host/docs/usrp2.rst @@ -205,3 +205,18 @@ 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 diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index fea6cb98f..7da31a16b 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -34,6 +34,9 @@ TARGET_LINK_LIBRARIES(tx_from_file uhd)  ADD_EXECUTABLE(tx_waveforms tx_waveforms.cpp)  TARGET_LINK_LIBRARIES(tx_waveforms uhd) +ADD_EXECUTABLE(pps_test pps_test.cpp) +TARGET_LINK_LIBRARIES(pps_test uhd) +  INSTALL(TARGETS      benchmark_rx_rate      rx_timed_samples @@ -41,5 +44,6 @@ INSTALL(TARGETS      tx_from_file      rx_to_file      tx_waveforms +    pps_test      RUNTIME DESTINATION ${PKG_DATA_DIR}/examples  ) diff --git a/host/examples/pps_test.cpp b/host/examples/pps_test.cpp new file mode 100644 index 000000000..c25cbe94f --- /dev/null +++ b/host/examples/pps_test.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 PPS Test %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>(&l)->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..753fd5e85 100644 --- a/host/lib/transport/CMakeLists.txt +++ b/host/lib/transport/CMakeLists.txt @@ -18,6 +18,24 @@  #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) + +########################################################################  # 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 39acd7f2b..8b8c18a8b 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -31,5 +31,6 @@ 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)  INCLUDE(${CMAKE_SOURCE_DIR}/lib/usrp/usrp_e/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..229a4ce63 --- /dev/null +++ b/host/lib/usrp/usrp1/CMakeLists.txt @@ -0,0 +1,57 @@ +# +# 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(HAVE_USB_SUPPORT) +    MESSAGE(STATUS "Has USB support - found") +ELSE(HAVE_USB_SUPPORT) +    MESSAGE(STATUS "Has USB support - not found") +ENDIF(HAVE_USB_SUPPORT) + +#TODO check for usrp1 enable/disable option flag + +IF(HAVE_USB_SUPPORT) +    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(HAVE_USB_SUPPORT) +    MESSAGE(STATUS "  Skipping usrp1 support.") +ENDIF(HAVE_USB_SUPPORT) 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/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index cc6c41ba7..e812e1221 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 9e29edd82..4e883cf81 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 d5785f326..0b9f8ee83 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -69,6 +69,11 @@ 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); +      //init the rx control registers      _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _io_helper.get_max_recv_samps_per_packet());      _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); @@ -107,11 +112,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 9d306090b..064ad4e95 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -124,41 +124,6 @@  #define U2_REG_DSP_TX_FREQ         _SR_ADDR(SR_TX_DSP + 0)  #define U2_REG_DSP_TX_SCALE_IQ     _SR_ADDR(SR_TX_DSP + 1) // {scale_i,scale_q}  #define U2_REG_DSP_TX_INTERP_RATE  _SR_ADDR(SR_TX_DSP + 2) - -  /*! -   * \brief output mux configuration. -   * -   * <pre> -   *     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 -   *  +-------------------------------+-------+-------+-------+-------+ -   *  |                                               | DAC1  |  DAC0 | -   *  +-------------------------------+-------+-------+-------+-------+ -   *  -   *  There are N DUCs (1 now) with complex inputs and outputs. -   *  There are two DACs. -   *  -   *  Each 4-bit DACx field specifies the source for the DAC -   *  Each subfield is coded like this:  -   *  -   *     3 2 1 0 -   *    +-------+ -   *    |   N   | -   *    +-------+ -   *  -   *  N specifies which DUC output is connected to this DAC. -   *  -   *   N   which interp output -   *  ---  ------------------- -   *   0   DUC 0 I -   *   1   DUC 0 Q -   *   2   DUC 1 I -   *   3   DUC 1 Q -   *   F   All Zeros -   *    -   * The default value is 0x10 -   * </pre> -   */  #define U2_REG_DSP_TX_MUX  _SR_ADDR(SR_TX_DSP + 4)  ///////////////////////////////////////////////// @@ -170,27 +135,6 @@  #define U2_REG_DSP_RX_DCOFFSET_I   _SR_ADDR(SR_RX_DSP + 3) // Bit 31 high sets fixed offset mode, using lower 14 bits,                                                         // otherwise it is automatic   #define U2_REG_DSP_RX_DCOFFSET_Q   _SR_ADDR(SR_RX_DSP + 4) // Bit 31 high sets fixed offset mode, using lower 14 bits -  /*! -   * \brief input mux configuration. -   * -   * This determines which ADC (or constant zero) is connected to  -   * each DDC input.  There are N DDCs (1 now).  Each has two inputs. -   * -   * <pre> -   * Mux value: -   * -   *    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 -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * |                                                       |Q0 |I0 | -   * +-------+-------+-------+-------+-------+-------+-------+-------+ -   * -   * Each 2-bit I field is either 00 (A/D A), 01 (A/D B) or 1X (const zero) -   * Each 2-bit Q field is either 00 (A/D A), 01 (A/D B) or 1X (const zero) -   * -   * The default value is 0x4 -   * </pre> -   */  #define U2_REG_DSP_RX_MUX  _SR_ADDR(SR_RX_DSP + 5)         // called adc_mux in dsp_core_rx.v  //////////////////////////////////////////////// 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 ff0ca895a..280c8dfaa 100644 --- a/host/utils/CMakeLists.txt +++ b/host/utils/CMakeLists.txt @@ -63,9 +63,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/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 | 
