diff --git a/.travis.yml b/.travis.yml
index e931e5386..4b7b99874 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,8 +23,10 @@ env:
# - FLAVOR=AR9X
# - FLAVOR=SKY9X
# - FLAVOR=9XRPRO
+ - FLAVOR=X3
- FLAVOR=X7
- FLAVOR=XLITE
+ - FLAVOR=XLITES
- FLAVOR=X9
# - FLAVOR=X9D
# - FLAVOR=X9D+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ 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.
+
+
+ Copyright (C)
+
+ 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 .
+
+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:
+
+ Copyright (C)
+ 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
+.
+
+ 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
+.
diff --git a/companion/src/firmwares/boards.cpp b/companion/src/firmwares/boards.cpp
index 25b33b98d..a51151d4f 100644
--- a/companion/src/firmwares/boards.cpp
+++ b/companion/src/firmwares/boards.cpp
@@ -96,6 +96,7 @@ const int Boards::getEEpromSize(Board::Type board)
case BOARD_9XRPRO:
case BOARD_AR9X:
return EESIZE_9XRPRO;
+ case BOARD_TARANIS_XLITES:
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_X7:
case BOARD_TARANIS_X9D:
@@ -124,6 +125,7 @@ const int Boards::getFlashSize(Type board)
case BOARD_9XRPRO:
case BOARD_AR9X:
return FSIZE_9XRPRO;
+ case BOARD_TARANIS_XLITES:
case BOARD_TARANIS_XLITE:
case BOARD_TARANIS_X7:
case BOARD_TARANIS_X9D:
@@ -145,7 +147,19 @@ const SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < 0)
return {SWITCH_NOT_AVAILABLE, CPN_STR_UNKNOWN_ITEM};
- if (IS_TARANIS_XLITE(board)) {
+ if (IS_TARANIS_XLITES(board)) {
+ const Board::SwitchInfo switches[] = {
+ {SWITCH_3POS, "SA"},
+ {SWITCH_3POS, "SB"},
+ {SWITCH_2POS, "SC"},
+ {SWITCH_2POS, "SD"},
+ {SWITCH_TOGGLE, "SE"},
+ {SWITCH_TOGGLE, "SF"}
+ };
+ if (index < DIM(switches))
+ return switches[index];
+ }
+ else if (IS_TARANIS_XLITE(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@@ -155,7 +169,7 @@ const SwitchInfo Boards::getSwitchInfo(Board::Type board, int index)
if (index < DIM(switches))
return switches[index];
}
- if (IS_TARANIS_X7(board)) {
+ else if (IS_TARANIS_X7(board)) {
const Board::SwitchInfo switches[] = {
{SWITCH_3POS, "SA"},
{SWITCH_3POS, "SB"},
@@ -246,7 +260,7 @@ const int Boards::getCapability(Board::Type board, Board::Capability capability)
return getCapability(board, Board::Sticks) + getCapability(board, Board::Pots) + getCapability(board, Board::Sliders) + getCapability(board, Board::MouseAnalogs);
case MultiposPots:
- return IS_HORUS_OR_TARANIS(board) ? 3 : 0;
+ return IS_HORUS_OR_TARANIS(board) ? getCapability(board, Board::Pots) : 0;
case MultiposPotsPositions:
return IS_HORUS_OR_TARANIS(board) ? 6 : 0;
@@ -256,6 +270,8 @@ const int Boards::getCapability(Board::Type board, Board::Capability capability)
return 18;
else if (IS_TARANIS_X7(board))
return 6;
+ else if (IS_TARANIS_XLITES(board))
+ return 6;
else if (IS_TARANIS_XLITE(board))
return 4;
else if (IS_HORUS_OR_TARANIS(board))
@@ -405,6 +421,8 @@ const QString Boards::getBoardName(Board::Type board)
return "Taranis X7/X7S";
case BOARD_TARANIS_XLITE:
return "Taranis X-Lite";
+ case BOARD_TARANIS_XLITES:
+ return "Taranis X-Lite S";
case BOARD_TARANIS_X9D:
return "Taranis X9D";
case BOARD_TARANIS_X9DP:
diff --git a/companion/src/firmwares/boards.h b/companion/src/firmwares/boards.h
index 885da2fc3..87f9733e0 100644
--- a/companion/src/firmwares/boards.h
+++ b/companion/src/firmwares/boards.h
@@ -46,6 +46,7 @@ namespace Board {
BOARD_X12S,
BOARD_X10,
BOARD_TARANIS_XLITE,
+ BOARD_TARANIS_XLITES,
BOARD_ENUM_COUNT
};
@@ -186,14 +187,15 @@ class Boards
#define IS_2560(board) (board==Board::BOARD_GRUVIN9X || board==Board::BOARD_MEGA2560)
#define IS_SKY9X(board) (board==Board::BOARD_SKY9X || board==Board::BOARD_9XRPRO || board==Board::BOARD_AR9X)
#define IS_9XRPRO(board) (board==Board::BOARD_9XRPRO)
-#define IS_TARANIS_XLITE(board) (board==Board::BOARD_TARANIS_XLITE)
+#define IS_TARANIS_XLITE(board) (board==Board::BOARD_TARANIS_XLITE || board==Board::BOARD_TARANIS_XLITES)
+#define IS_TARANIS_XLITES(board) (board==Board::BOARD_TARANIS_XLITES)
#define IS_TARANIS_X7(board) (board==Board::BOARD_TARANIS_X7)
#define IS_TARANIS_X9(board) (board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9E)
#define IS_TARANIS_X9D(board) (board==Board::BOARD_TARANIS_X9D || board==Board::BOARD_TARANIS_X9DP)
#define IS_TARANIS_PLUS(board) (board==Board::BOARD_TARANIS_X9DP || board==Board::BOARD_TARANIS_X9E)
#define IS_TARANIS_X9E(board) (board==Board::BOARD_TARANIS_X9E)
-#define IS_TARANIS(board) (IS_TARANIS_X9(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board))
-#define IS_TARANIS_SMALL(board) (board==Board::BOARD_TARANIS_X7 || board==Board::BOARD_TARANIS_XLITE)
+#define IS_TARANIS(board) (IS_TARANIS_X9(board) || IS_TARANIS_X7(board) || IS_TARANIS_XLITE(board) || IS_TARANIS_XLITES(board))
+#define IS_TARANIS_SMALL(board) (board==Board::BOARD_TARANIS_X7 || board==Board::BOARD_TARANIS_XLITE || board==Board::BOARD_TARANIS_XLITES)
#define IS_TARANIS_NOT_X9E(board) (IS_TARANIS(board) && !IS_TARANIS_X9E(board))
#define IS_HORUS_X12S(board) (board==Board::BOARD_X12S)
#define IS_HORUS_X10(board) (board==Board::BOARD_X10)
diff --git a/companion/src/firmwares/eepromimportexport.h b/companion/src/firmwares/eepromimportexport.h
index 69944cba7..30cd2a045 100644
--- a/companion/src/firmwares/eepromimportexport.h
+++ b/companion/src/firmwares/eepromimportexport.h
@@ -387,7 +387,7 @@ class CharField: public DataField {
};
static const char specialCharsTab[] = "_-.,";
-static inline int8_t char2idx(char c)
+static inline int8_t char2zchar(char c)
{
if (c==' ') return 0;
if (c>='A' && c<='Z') return 1+c-'A';
@@ -401,7 +401,7 @@ static inline int8_t char2idx(char c)
}
#define ZCHAR_MAX 40
-static inline char idx2char(int8_t idx)
+static inline char zchar2char(int8_t idx)
{
if (idx == 0) return ' ';
if (idx < 0) {
@@ -429,7 +429,7 @@ class ZCharField: public DataField {
int b = 0;
int len = strlen(field);
for (int i=0; i=len ? 0 : char2idx(field[i]);
+ int idx = i>=len ? 0 : char2zchar(field[i]);
for (int j=0; j<8; j++, b++) {
if (idx & (1<(this, generalData.jitterFilter));
internalField.Append(new BoolField<1>(this, generalData.disableRssiPoweroffAlarm));
internalField.Append(new UnsignedField<2>(this, generalData.usbMode));
- internalField.Append(new SpareBitsField<3>(this));
+ internalField.Append(new UnsignedField<2>(this, generalData.jackMode));
+ internalField.Append(new SpareBitsField<1>(this));
}
else {
internalField.Append(new SpareBitsField<7>(this));
diff --git a/companion/src/firmwares/opentx/opentxeeprom.h b/companion/src/firmwares/opentx/opentxeeprom.h
index 35c571787..ee840cc77 100644
--- a/companion/src/firmwares/opentx/opentxeeprom.h
+++ b/companion/src/firmwares/opentx/opentxeeprom.h
@@ -33,6 +33,7 @@
#define TARANIS_X9E_VARIANT 0x8000
#define TARANIS_X7_VARIANT 0x4000
#define TARANIS_XLITE_VARIANT 0x2000
+#define TARANIS_XLITES_VARIANT 0x1000
#define SIMU_STOCK_VARIANTS (GVARS_VARIANT|FRSKY_VARIANT)
#define SIMU_M128_VARIANTS (M128_VARIANT|SIMU_STOCK_VARIANTS)
diff --git a/companion/src/firmwares/opentx/opentxinterface.cpp b/companion/src/firmwares/opentx/opentxinterface.cpp
index c9c35e251..30ee2de1b 100644
--- a/companion/src/firmwares/opentx/opentxinterface.cpp
+++ b/companion/src/firmwares/opentx/opentxinterface.cpp
@@ -317,6 +317,9 @@ int OpenTxEepromInterface::save(uint8_t * eeprom, const RadioData & radioData, u
else if (IS_TARANIS_X7(board)) {
variant |= TARANIS_X7_VARIANT;
}
+ else if (IS_TARANIS_XLITES(board)) {
+ variant |= TARANIS_XLITES_VARIANT;
+ }
else if (IS_TARANIS_XLITE(board)) {
variant |= TARANIS_XLITE_VARIANT;
}
@@ -691,6 +694,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
return TARANIS_X9E_VARIANT;
else if (IS_TARANIS_X7(board))
return TARANIS_X7_VARIANT;
+ else if (IS_TARANIS_XLITES(board))
+ return TARANIS_XLITES_VARIANT;
else if (IS_TARANIS_XLITE(board))
return TARANIS_XLITE_VARIANT;
else
@@ -708,6 +713,8 @@ int OpenTxFirmware::getCapability(::Capability capability)
return id.contains("danger") ? 1 : 0;
case HasModelCategories:
return IS_HORUS(board);
+ case HasSwitchableJack:
+ return IS_TARANIS_XLITES(board);
default:
return 0;
}
@@ -921,6 +928,11 @@ bool OpenTxEepromInterface::checkVariant(unsigned int version, unsigned int vari
variantError = true;
}
}
+ else if (IS_TARANIS_XLITES(board)) {
+ if (variant != TARANIS_XLITES_VARIANT) {
+ variantError = true;
+ }
+ }
else if (IS_TARANIS_XLITE(board)) {
if (variant != TARANIS_XLITE_VARIANT) {
variantError = true;
@@ -1165,6 +1177,12 @@ void registerOpenTxFirmwares()
addOpenTxTaranisOptions(firmware, false);
registerOpenTxFirmware(firmware);
+ /* FrSky X-Lite S board */
+ firmware = new OpenTxFirmware("opentx-xlites", QCoreApplication::translate("Firmware", "FrSky Taranis X-Lite S"), BOARD_TARANIS_XLITES);
+ // firmware->addOption("stdr9m", QCoreApplication::translate("Firmware", "Use JR-sized R9M module"));
+ addOpenTxTaranisOptions(firmware);
+ registerOpenTxFirmware(firmware);
+
/* FrSky X-Lite board */
firmware = new OpenTxFirmware("opentx-xlite", Firmware::tr("FrSky Taranis X-Lite"), BOARD_TARANIS_XLITE);
// firmware->addOption("stdr9m", Firmware::tr("Use JR-sized R9M module"));
diff --git a/companion/src/generaledit/generalsetup.cpp b/companion/src/generaledit/generalsetup.cpp
index d2265a009..b6bf20711 100644
--- a/companion/src/generaledit/generalsetup.cpp
+++ b/companion/src/generaledit/generalsetup.cpp
@@ -151,13 +151,21 @@ ui(new Ui::GeneralSetup)
ui->adjustRTC->hide();
}
- if (IS_STM32(firmware->getBoard())){
+ if (IS_STM32(firmware->getBoard())) {
ui->usbModeCB->setCurrentIndex(generalSettings.usbMode);
}
else {
ui->usbModeLabel->hide();
ui->usbModeCB->hide();
}
+
+ if (firmware->getCapability(HasSwitchableJack)) {
+ ui->jackModeCB->setCurrentIndex(generalSettings.jackMode);
+ }
+ else {
+ ui->jackModeLabel->hide();
+ ui->jackModeCB->hide();
+ }
if (!firmware->getCapability(OptrexDisplay)) {
ui->label_displayType->hide();
@@ -353,6 +361,15 @@ void GeneralSetupPanel::on_usbModeCB_currentIndexChanged(int index)
}
}
+void GeneralSetupPanel::on_jackModeCB_currentIndexChanged(int index)
+{
+ if (!lock) {
+ generalSettings.jackMode = ui->jackModeCB->currentIndex();
+ emit modified();
+ }
+}
+
+
void GeneralSetupPanel::on_backlightColor_SL_valueChanged()
{
if (!lock) {
diff --git a/companion/src/generaledit/generalsetup.h b/companion/src/generaledit/generalsetup.h
index 80a63d027..d3f800714 100644
--- a/companion/src/generaledit/generalsetup.h
+++ b/companion/src/generaledit/generalsetup.h
@@ -60,6 +60,7 @@ class GeneralSetupPanel : public GeneralPanel
void on_hapticLengthCB_currentIndexChanged(int index);
void on_backlightswCB_currentIndexChanged(int index);
void on_usbModeCB_currentIndexChanged(int index);
+ void on_jackModeCB_currentIndexChanged(int index);
void on_backlightColor_SL_valueChanged();
void on_mavbaud_CB_currentIndexChanged(int index);
void on_voiceLang_CB_currentIndexChanged(int index);
diff --git a/companion/src/generaledit/generalsetup.ui b/companion/src/generaledit/generalsetup.ui
index a30bf446f..5537004bc 100644
--- a/companion/src/generaledit/generalsetup.ui
+++ b/companion/src/generaledit/generalsetup.ui
@@ -29,10 +29,10 @@
QLayout::SetMinimumSize
-
+
0
-
+
0
-
@@ -1121,906 +1121,43 @@ p, li { white-space: pre-wrap; }
QLayout::SetDefaultConstraint
-
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Warnings</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These will define startup warnings.</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Throttle warning - will alert if the throttle is not at idle during startup</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
-
+
-
+
-
-
-
- true
+ GPS Coordinates
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- RSSI Poweroff Warning
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
+
-
+
-
- Beeper volume
-
-0 - Quiet. No beeps at all.
-1 - No Keys. Normal beeps but menu keys do not beep.
-2 - Normal.
-3 - Loud.
-4 - Extra loud.
-
-
-
-
- Quiet
-
-
- -
-
- Alarms Only
-
-
- -
-
- No Keys
-
-
- -
-
- All
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Beeper Mode
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
- X-Short
-
-
- -
-
- Short
-
-
- -
-
- Normal
-
-
- -
-
- Long
-
-
- -
-
- X-Long
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Beeper Length
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Haptic Mode
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Measurement Units
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Play Delay (switch mid position)
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
- X-Short
-
-
- -
-
- Short
-
-
- -
-
- Normal
-
-
- -
-
- Long
-
-
- -
-
- X-Long
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
p, li { white-space: pre-wrap; }
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Warnings</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These will define startup warnings.</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Throttle warning - will alert if the throttle is not at idle during startup</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
-
-
-
-
-
- true
-
-
-
- -
-
-
-
-
- hh° (N/S) mm' ss''.dd
-
-
- -
-
- NMEA
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
- 16777215
- 16777215
-
-
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Warnings</span></p>
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These will define startup warnings.</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Throttle warning - will alert if the throttle is not at idle during startup</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
-
-
-
-
-
- true
-
-
-
- -
-
-
-
-
- 4800 Baud
-
-
- -
-
- 9600 Baud
-
-
- -
-
- 14400 Baud
-
-
- -
-
- 19200 Baud
-
-
- -
-
- 38400 Baud
-
-
- -
-
- 57600 Baud
-
-
- -
-
- 76800 Baud
-
-
- -
-
- 115200 Baud
-
-
-
-
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
-
- 16777215
- 16777215
-
-
-
- Show splash screen on startup
-
-
- Show splash screen on startup
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
- ---
-
-
- -
-
- 2s
-
-
- -
-
- 3s
-
-
- -
-
- 4s
-
-
- -
-
- 6s
-
-
- -
-
- 8s
-
-
- -
-
- 10s
-
-
- -
-
- 15s
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
-
-
-
-
- If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes.
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html>
- min
-
-
- 120
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
- Standard
-
-
- -
-
- Optrex
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
-
-
-
-
- Battery warning voltage.
-This is the threashhold where the battery warning sounds.
-
-Acceptable values are 5v..10v
-
-
-
-
-
- V
-
-
- 1
+ ms
- 4.000000000000000
+ 0
- 12.000000000000000
+ 1000
- 0.100000000000000
-
-
- 9.600000000000000
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
-
-
-
-
-
-
-
10
-
- 45
-
- 25
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
- -2
-
-
- 2
-
-
- 1
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 22
-
-
-
-
-
- Quiet
-
-
- -
-
- Only Alarms
-
-
- -
-
- No Keys
-
-
- -
-
- All
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- MAVLink Baud Rate
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Haptic Length
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 20
- 0
-
-
-
-
-
-
- Battery Warning
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- "No Sound" Warning
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- LCD Display Type
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Haptic Strength
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Battery Meter Range
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
-
-
-
- Contrast
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Show Splash Screen on Startup
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Low EEPROM Warning
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 0
- 0
-
-
-
- Inactivity Timer
+ 0
@@ -2086,8 +1223,8 @@ Acceptable values are 5v..10v
- -
-
+
-
+
@@ -2095,34 +1232,55 @@ Acceptable values are 5v..10v
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">LCD Screen Contrast</span></p>
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Values can be 20-45</span></p></body></html>
+ Mode selection:
+
+Mode 1:
+ Left stick: Elevator, Rudder
+ Right stick: Throttle, Aileron
+
+Mode 2:
+ Left stick: Throttle, Rudder
+ Right stick: Elevator, Aileron
+
+Mode 3:
+ Left stick: Elevator, Aileron
+ Right stick: Throttle, Rudder
+
+Mode 4:
+ Left stick: Throttle, Aileron
+ Right stick: Elevator, Rudder
+
+
-
- ms
-
-
- 0
-
-
- 1000
-
-
- 10
-
-
- 0
+
+ 1
+ -
+
+ Mode 1 (RUD ELE THR AIL)
+
+
+ -
+
+ Mode 2 (RUD THR ELE AIL)
+
+
+ -
+
+ Mode 3 (AIL ELE THR RUD)
+
+
+ -
+
+ Mode 4 (AIL THR ELE RUD)
+
+
- -
-
+
-
+
- GPS Coordinates
+ Stick Mode
@@ -2153,13 +1311,6 @@ p, li { white-space: pre-wrap; }
- -
-
-
- Stick Mode
-
-
-
-
@@ -2296,67 +1447,6 @@ p, li { white-space: pre-wrap; }
- -
-
-
-
-
-
-
-
-
- Mode selection:
-
-Mode 1:
- Left stick: Elevator, Rudder
- Right stick: Throttle, Aileron
-
-Mode 2:
- Left stick: Throttle, Rudder
- Right stick: Elevator, Aileron
-
-Mode 3:
- Left stick: Elevator, Aileron
- Right stick: Throttle, Rudder
-
-Mode 4:
- Left stick: Throttle, Aileron
- Right stick: Elevator, Rudder
-
-
-
-
- 1
-
-
-
-
- Mode 1 (RUD ELE THR AIL)
-
-
- -
-
- Mode 2 (RUD THR ELE AIL)
-
-
- -
-
- Mode 3 (AIL ELE THR RUD)
-
-
- -
-
- Mode 4 (AIL THR ELE RUD)
-
-
-
-
- -
-
-
- USB Mode
-
-
-
-
-
@@ -2381,6 +1471,942 @@ Mode 4:
+ -
+
+
+ USB Mode
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Warnings</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These will define startup warnings.</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Throttle warning - will alert if the throttle is not at idle during startup</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
+
+
+
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ RSSI Poweroff Warning
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Beeper Length
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
+
+
+
+
+
+
+ Beeper volume
+
+0 - Quiet. No beeps at all.
+1 - No Keys. Normal beeps but menu keys do not beep.
+2 - Normal.
+3 - Loud.
+4 - Extra loud.
+
+
-
+
+ Quiet
+
+
+ -
+
+ Alarms Only
+
+
+ -
+
+ No Keys
+
+
+ -
+
+ All
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
-
+
+ X-Short
+
+
+ -
+
+ Short
+
+
+ -
+
+ Normal
+
+
+ -
+
+ Long
+
+
+ -
+
+ X-Long
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Beeper Mode
+
+
+
+ -
+
+
+ Measurement Units
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Haptic Mode
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Play Delay (switch mid position)
+
+
+
+ -
+
+
-
+
+ 4800 Baud
+
+
+ -
+
+ 9600 Baud
+
+
+ -
+
+ 14400 Baud
+
+
+ -
+
+ 19200 Baud
+
+
+ -
+
+ 38400 Baud
+
+
+ -
+
+ 57600 Baud
+
+
+ -
+
+ 76800 Baud
+
+
+ -
+
+ 115200 Baud
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
-
+
+ X-Short
+
+
+ -
+
+ Short
+
+
+ -
+
+ Normal
+
+
+ -
+
+ Long
+
+
+ -
+
+ X-Long
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Warnings</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These will define startup warnings.</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Throttle warning - will alert if the throttle is not at idle during startup</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
+
+
+
+
+
+ true
+
+
+
+ -
+
+
-
+
+ hh° (N/S) mm' ss''.dd
+
+
+ -
+
+ NMEA
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">Warnings</span></p>
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">These will define startup warnings.</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Throttle warning - will alert if the throttle is not at idle during startup</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Switch warning - will alert if switches are not in their defaul position</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Memory warning - will alert if there's not a lot of memory left</p>
+<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Silent mode warning - will alert you if the beeper is set to quiet (0)</p></body></html>
+
+
+
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Show splash screen on startup
+
+
+ Show splash screen on startup
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
-
+
+ ---
+
+
+ -
+
+ 2s
+
+
+ -
+
+ 3s
+
+
+ -
+
+ 4s
+
+
+ -
+
+ 6s
+
+
+ -
+
+ 8s
+
+
+ -
+
+ 10s
+
+
+ -
+
+ 15s
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
+
+
+
+
+
+
+ If not zero will sound beeps if the transmitter has been left without inputs for the specified number of minutes.
+
+
+ min
+
+
+ 120
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
-
+
+ Standard
+
+
+ -
+
+ Optrex
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
+
+
+
+
+
+
+
+
+
+ 10
+
+
+ 45
+
+
+ 25
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
+
+
+
+
+
+
+ Battery warning voltage.
+This is the threashhold where the battery warning sounds.
+
+Acceptable values are 5v..10v
+
+
+
+
+
+ V
+
+
+ 1
+
+
+ 4.000000000000000
+
+
+ 12.000000000000000
+
+
+ 0.100000000000000
+
+
+ 9.600000000000000
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
+ -2
+
+
+ 2
+
+
+ 1
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 22
+
+
+
-
+
+ Quiet
+
+
+ -
+
+ Only Alarms
+
+
+ -
+
+ No Keys
+
+
+ -
+
+ All
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ "No Sound" Warning
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ MAVLink Baud Rate
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 20
+ 0
+
+
+
+
+
+
+ Battery Warning
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Haptic Length
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ LCD Display Type
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Battery Meter Range
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Haptic Strength
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Inactivity Timer
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Low EEPROM Warning
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Show Splash Screen on Startup
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ Contrast
+
+
+
+ -
+
+
+ Jack Mode
+
+
+
+ -
+
+
-
+
+ Ask on Connect
+
+
+ -
+
+ Audio
+
+
+ -
+
+ Trainer
+
+
+
+
-
diff --git a/companion/src/simulation/simulatorwidget.cpp b/companion/src/simulation/simulatorwidget.cpp
index 4ad053c73..5d059f4db 100644
--- a/companion/src/simulation/simulatorwidget.cpp
+++ b/companion/src/simulation/simulatorwidget.cpp
@@ -77,6 +77,7 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
radioUiWidget = new SimulatedUIWidgetX9(simulator, this);
break;
case Board::BOARD_TARANIS_XLITE:
+ case Board::BOARD_TARANIS_XLITES:
radioUiWidget = new SimulatedUIWidgetXLITE(simulator, this);
break;
case Board::BOARD_TARANIS_X9E:
@@ -108,7 +109,7 @@ SimulatorWidget::SimulatorWidget(QWidget * parent, SimulatorInterface * simulato
vJoyLeft = new VirtualJoystickWidget(this, 'L');
ui->leftStickLayout->addWidget(vJoyLeft);
- vJoyRight = new VirtualJoystickWidget(this, 'R', (m_board == Board::BOARD_TARANIS_XLITE ? false : true)); // TODO: maybe remove trims for both joysticks and add a cross in the middle?
+ vJoyRight = new VirtualJoystickWidget(this, 'R', (m_board == Board::BOARD_TARANIS_XLITE || m_board == Board::BOARD_TARANIS_XLITES ? false : true)); // TODO: maybe remove trims for both joysticks and add a cross in the middle?
ui->rightStickLayout->addWidget(vJoyRight);
connect(vJoyLeft, &VirtualJoystickWidget::valueChange, this, &SimulatorWidget::onRadioWidgetValueChange);
diff --git a/radio/src/CMakeLists.txt b/radio/src/CMakeLists.txt
index 713655f44..60646540b 100644
--- a/radio/src/CMakeLists.txt
+++ b/radio/src/CMakeLists.txt
@@ -1,7 +1,7 @@
include(CMakeForceCompiler)
include(Bitmaps)
-set(PCB_TYPES X7 XLITE X9D X9D+ X9E X10 X12S SKY9X 9XRPRO AR9X)
+set(PCB_TYPES X3 X7 XLITE XLITES X9D X9D+ X9E X10 X12S SKY9X 9XRPRO AR9X)
set(GUI_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU NL)
set(TTS_LANGUAGES CZ DE EN ES FR IT PT SK SE PL HU NL RU)
@@ -46,8 +46,6 @@ option(TRACE_LUA_INTERNALS "Turn on traces for Lua internals" OFF)
option(FRSKY_STICKS "Reverse sticks for FrSky sticks" OFF)
option(NANO "Use nano newlib and binalloc")
option(NIGHTLY_BUILD_WARNING "Warn this is a nightly build" OFF)
-option(MODULE_R9M_FLEX_FW "Add R9M options for non certified firmwwares" OFF)
-option(PXX2 "Enable PXX v2 support" OFF)
# since we reset all default CMAKE compiler flags for firmware builds, provide an alternate way for user to specify additional flags.
set(FIRMWARE_C_FLAGS "" CACHE STRING "Additional flags for firmware target c compiler (note: all CMAKE_C_FLAGS[_*] are ignored for firmware/bootloader).")
@@ -82,7 +80,7 @@ set(FATFS_SRC
if(PCB STREQUAL X12S OR PCB STREQUAL X10)
include(targets/horus/CMakeLists.txt)
-elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL XLITE)
+elseif(PCB STREQUAL X9E OR PCB STREQUAL X9D+ OR PCB STREQUAL X9D OR PCB STREQUAL X7 OR PCB STREQUAL X3 OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
include(targets/taranis/CMakeLists.txt)
elseif(PCB STREQUAL SKY9X OR PCB STREQUAL 9XRPRO OR PCB STREQUAL AR9X)
include(targets/sky9x/CMakeLists.txt)
@@ -133,10 +131,7 @@ else()
add_definitions(-DEEPROM -DEEPROM_RAW)
endif()
-if(ARCH STREQUAL ARM AND NOT PCB STREQUAL X12S AND NOT PCB STREQUAL X10 AND NOT PCB STREQUAL XLITE)
- add_definitions(-DEEPROM_CONVERSIONS)
- set(SRC ${SRC} storage/eeprom_conversions.cpp)
-endif()
+include(storage/conversions/CMakeLists.txt)
add_definitions(-DFLAVOUR="${FLAVOUR}")
@@ -313,14 +308,6 @@ if(NIGHTLY_BUILD_WARNING)
add_definitions(-DNIGHTLY_BUILD_WARNING)
endif(NIGHTLY_BUILD_WARNING)
-if(MODULE_R9M_FLEX_FW)
- add_definitions(-DMODULE_R9M_FLEX_FW)
-endif()
-
-if(PXX2)
- add_definitions(-DPXX2)
-endif()
-
set(SRC
${SRC}
opentx.cpp
@@ -458,7 +445,7 @@ if(NOT MSVC)
set(SRC ${SRC} bin_allocator.cpp)
endif()
- if(PCB STREQUAL XLITE OR PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL X10 OR PCB STREQUAL X12S)
+ if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR PCB STREQUAL X9D OR PCB STREQUAL X9D+ OR PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL X3 OR PCB STREQUAL X10 OR PCB STREQUAL X12S)
add_subdirectory(targets/common/arm/stm32/bootloader)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/targets/common/arm/stm32/bootloader)
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} bootloader)
diff --git a/radio/src/audio_arm.cpp b/radio/src/audio.cpp
similarity index 100%
rename from radio/src/audio_arm.cpp
rename to radio/src/audio.cpp
diff --git a/radio/src/audio_arm.h b/radio/src/audio.h
similarity index 100%
rename from radio/src/audio_arm.h
rename to radio/src/audio.h
diff --git a/radio/src/bitfield.h b/radio/src/bitfield.h
new file mode 100644
index 000000000..379d4280f
--- /dev/null
+++ b/radio/src/bitfield.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * This file is based on work published at http://www.coranac.com/documents/working-with-bits-and-bitfields
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef BITFIELD_H
+#define BITFIELD_H
+
+#include
+
+// A set of bitfield handling macros
+
+template
+inline T BF_BIT(uint8_t n)
+{
+ return T(1) << n;
+}
+
+#define BF_BIT_GET(y, mask) ( y & (mask) )
+#define BF_BIT_SET(y, mask) ( y |= (mask) )
+#define BF_BIT_CLEAR(y, mask) ( y &= ~(mask) )
+#define BF_BIT_FLIP(y, mask) ( y ^= (mask) )
+#define BF_SINGLE_BIT_GET(y, i) BF_BIT_GET(y, BF_BIT(i))
+#define BF_SINGLE_BIT_SET(y, i) BF_BIT_SET(y, BF_BIT(i))
+
+//! Create a bitmask of length 'len'.
+template
+inline T BF_BITMASK(uint8_t len)
+{
+ return BF_BIT(len) - 1;
+}
+
+//! Create a bitfield mask of length 'len' starting at bit 'start'.
+template
+inline T BF_MASK(uint8_t start, uint8_t len)
+{
+ return BF_BITMASK(len) << start;
+}
+
+//! Prepare a bitmask for insertion or combining.
+template
+inline T BF_PREP(T x, uint8_t start, uint8_t len)
+{
+ return (x & BF_BITMASK(len)) << start;
+}
+
+//! Extract a bitfield of length 'len' starting at bit 'start' from 'y'.
+#define BF_GET(y, start, len) ( ((y)>>(start)) & BF_BITMASK(len) )
+
+//! Insert 'len' bits of 'x 'into 'y', starting at bit 'start' from 'y'.
+template
+inline T BF_SET(T to, T from, uint8_t start, uint8_t len)
+{
+ return (to & ~BF_MASK(start, len)) | BF_PREP(from, start, len);
+}
+
+#endif //BITFIELD_H
diff --git a/radio/src/bluetooth.cpp b/radio/src/bluetooth.cpp
index 50bc769bd..95245ffcc 100644
--- a/radio/src/bluetooth.cpp
+++ b/radio/src/bluetooth.cpp
@@ -71,32 +71,50 @@ char * bluetoothReadline(bool error_reset)
if (!btRxFifo.pop(byte)) {
#if defined(PCBX9E) && !defined(USEHORUSBT) // X9E BT module can get unresponsive
TRACE("NO RESPONSE FROM BT MODULE");
+#endif
+ return nullptr;
+ }
+
+ TRACE_NOCRLF("%02X ", byte);
+
+#if 0
+ if (error_reset && byte == 'R' && bluetoothBufferIndex == 4 && memcmp(bluetoothBuffer, "ERRO", 4)) {
+#if defined(PCBX9E) // X9E enter BT reset loop if following code is implemented
+ TRACE("BT Error...");
+#else
+ TRACE("BT Reset...");
+ bluetoothBufferIndex = 0;
+ bluetoothDone();
+ bluetoothState = BLUETOOTH_STATE_OFF;
+ bluetoothWakeupTime = get_tmr10ms() + 100; /* 1s */
#endif
return NULL;
}
- TRACE_NOCRLF("%02X ", byte);
+ else
+#endif
+
if (byte == '\n') {
if (bluetoothBufferIndex > 2 && bluetoothBuffer[bluetoothBufferIndex-1] == '\r') {
bluetoothBuffer[bluetoothBufferIndex-1] = '\0';
bluetoothBufferIndex = 0;
TRACE("BT< %s", bluetoothBuffer);
if (error_reset && !strcmp((char *)bluetoothBuffer, "ERROR")) {
-#if defined(PCBX9E) // X9E enter BT reset loop if following code is implemented
- TRACE("BT error...");
+#if defined(PCBX9E) // X9E enter BT reset loop if following code is implemented
+ TRACE("BT Error...");
#else
TRACE("BT Reset...");
bluetoothDone();
bluetoothState = BLUETOOTH_STATE_OFF;
bluetoothWakeupTime = get_tmr10ms() + 100; /* 1s */
#endif
- return NULL;
+ return nullptr;
}
else {
- if (!strncmp((char *)bluetoothBuffer, "Central:", 8))
- strcpy(bluetoothLocalAddr, (char *)bluetoothBuffer+8);
- else if (!strncmp((char *)bluetoothBuffer, "Peripheral:", 11))
- strcpy(bluetoothLocalAddr, (char *)bluetoothBuffer+11);
- return (char *)bluetoothBuffer;
+ if (!memcmp(bluetoothBuffer, "Central:", 8))
+ strcpy(bluetoothLocalAddr, (char *) bluetoothBuffer + 8);
+ else if (!memcmp(bluetoothBuffer, "Peripheral:", 11))
+ strcpy(bluetoothLocalAddr, (char *) bluetoothBuffer + 11);
+ return (char *) bluetoothBuffer;
}
}
else {
@@ -212,7 +230,7 @@ void bluetoothSendTrainer()
{
int16_t PPM_range = g_model.extendedLimits ? 640*2 : 512*2;
- int firstCh = g_model.moduleData[TRAINER_MODULE].channelsStart;
+ int firstCh = g_model.trainerData.channelsStart;
int lastCh = firstCh + 8;
uint8_t * cur = bluetoothBuffer;
@@ -280,7 +298,7 @@ void bluetoothWakeup(void)
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
if (len > 0) {
for (int i = 0; i < len; i++) {
- *cur++ = idx2char(g_eeGeneral.bluetoothName[i]);
+ *cur++ = zchar2char(g_eeGeneral.bluetoothName[i]);
}
}
else {
@@ -361,11 +379,11 @@ void bluetoothWakeup()
bluetoothWakeupTime = now + 10; /* 100ms */
}
else if (bluetoothState == BLUETOOTH_STATE_CONNECTED) {
- if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH) {
+ if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH) {
bluetoothReceiveTrainer();
}
else {
- if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH) {
+ if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH) {
bluetoothSendTrainer();
bluetoothWakeupTime = now + 2; /* 20ms */
}
@@ -374,20 +392,23 @@ void bluetoothWakeup()
}
else {
char * line = bluetoothReadline();
+ if (line) {
+ TRACE("BT %s", line);
+ }
if (bluetoothState == BLUETOOTH_STATE_BAUDRATE_INIT) {
char command[32];
char * cur = strAppend(command, BLUETOOTH_COMMAND_NAME);
uint8_t len = ZLEN(g_eeGeneral.bluetoothName);
if (len > 0) {
for (int i = 0; i < len; i++) {
- *cur++ = idx2char(g_eeGeneral.bluetoothName[i]);
+ *cur++ = zchar2char(g_eeGeneral.bluetoothName[i]);
}
}
else {
#if defined(PCBHORUS)
cur = strAppend(cur, "Horus");
#else
- cur = strAppend(cur, "Taranis");
+ cur = strAppend(cur, "taranis"); // TODO capital letter once allowed by BT module
#endif
}
strAppend(cur, "\r\n");
@@ -395,11 +416,11 @@ void bluetoothWakeup()
bluetoothState = BLUETOOTH_STATE_NAME_SENT;
}
else if (bluetoothState == BLUETOOTH_STATE_NAME_SENT && (!strncmp(line, "OK+", 3) || !strncmp(line, "Central:", 8) || !strncmp(line, "Peripheral:", 11))) {
- bluetoothWriteString("AT+TXPW3\r\n");
+ bluetoothWriteString("AT+TXPW\r\n");
bluetoothState = BLUETOOTH_STATE_POWER_SENT;
}
else if (bluetoothState == BLUETOOTH_STATE_POWER_SENT && (!strncmp(line, "Central:", 8) || !strncmp(line, "Peripheral:", 11))) {
- if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH)
+ if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH)
bluetoothWriteString("AT+ROLE1\r\n");
else
bluetoothWriteString("AT+ROLE0\r\n");
@@ -430,7 +451,7 @@ void bluetoothWakeup()
else if ((bluetoothState == BLUETOOTH_STATE_IDLE || bluetoothState == BLUETOOTH_STATE_DISCONNECTED || bluetoothState == BLUETOOTH_STATE_CONNECT_SENT) && !strncmp(line, "Connected:", 10)) {
strcpy(bluetoothDistantAddr, &line[10]); // TODO quick & dirty
bluetoothState = BLUETOOTH_STATE_CONNECTED;
- if (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH) {
+ if (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH) {
bluetoothWakeupTime += 500; // it seems a 5s delay is needed before sending the 1st frame
}
}
diff --git a/radio/src/bluetooth.h b/radio/src/bluetooth.h
index f0201e431..4be34b8e4 100644
--- a/radio/src/bluetooth.h
+++ b/radio/src/bluetooth.h
@@ -44,13 +44,6 @@ enum BluetoothStates {
#define LEN_BLUETOOTH_ADDR 16
-#if (defined(PCBX7) || defined(PCBXLITE)) && !defined(SIMU)
-extern uint8_t btChipPresent;
-#define IS_BLUETOOTH_CHIP_PRESENT() (btChipPresent)
-#else
-#define IS_BLUETOOTH_CHIP_PRESENT() (true)
-#endif
-
extern volatile uint8_t bluetoothState;
extern char bluetoothLocalAddr[LEN_BLUETOOTH_ADDR+1];
extern char bluetoothDistantAddr[LEN_BLUETOOTH_ADDR+1];
diff --git a/radio/src/cli.h b/radio/src/cli.h
index fdb96d6d1..a590e101c 100644
--- a/radio/src/cli.h
+++ b/radio/src/cli.h
@@ -28,7 +28,7 @@ extern uint8_t cliTracesEnabled;
#ifdef __cplusplus
#include "fifo.h"
extern Fifo cliRxFifo;
-#include "tasks_arm.h"
+#include "tasks.h"
extern RTOS_TASK_HANDLE cliTaskId;
extern RTOS_DEFINE_STACK(cliStack, CLI_STACK_SIZE);
#endif
diff --git a/radio/src/dataconstants.h b/radio/src/dataconstants.h
index c22d85869..b3854cbe0 100644
--- a/radio/src/dataconstants.h
+++ b/radio/src/dataconstants.h
@@ -21,6 +21,8 @@
#ifndef _DATACONSTANTS_H_
#define _DATACONSTANTS_H_
+#include "board.h"
+
#define NUM_STICKS 4
#if defined(EXPORT)
@@ -44,7 +46,7 @@
#define MAX_SCRIPTS 9
#define MAX_INPUTS 32
#define MAX_TRAINER_CHANNELS 16
- #define MAX_TELEMETRY_SENSORS 32
+ #define MAX_TELEMETRY_SENSORS 64
#define MAX_CUSTOM_SCREENS 5
#elif defined(PCBTARANIS)
#define MAX_MODELS 60
@@ -70,20 +72,10 @@
#define MAX_TRAINER_CHANNELS 16
#define MAX_TELEMETRY_SENSORS 32
#else
- #define MAX_MODELS 16
- #define MAX_OUTPUT_CHANNELS 16 // number of real output channels CH1-CH16
- #define MAX_FLIGHT_MODES 5
- #define MAX_MIXERS 32
- #define MAX_EXPOS 14
- #define MAX_LOGICAL_SWITCHES 12
- #define MAX_SPECIAL_FUNCTIONS 16 // number of functions assigned to switches
- #define MAX_TRAINER_CHANNELS 8
- #define MAX_TELEMETRY_SENSORS 0
+ #warning "Unknown board!"
#endif
- #define MAX_TIMERS 3
-
-#define NUM_CYC 3
+#define MAX_TIMERS 3
#define NUM_CAL_PPM 4
enum CurveType {
@@ -92,8 +84,7 @@ enum CurveType {
CURVE_TYPE_LAST = CURVE_TYPE_CUSTOM
};
- #define MIN_POINTS_PER_CURVE 3
-
+#define MIN_POINTS_PER_CURVE 3
#define MAX_POINTS_PER_CURVE 17
#if defined(PCBHORUS)
@@ -133,6 +124,14 @@ enum CurveType {
#define MAX_CURVE_POINTS 512
#endif
+#if defined(PCBHORUS)
+ #define NUM_RECEIVERS 10
+ #define MAX_RECEIVERS_PER_MODULE 5
+#else
+ #define NUM_RECEIVERS 4
+ #define MAX_RECEIVERS_PER_MODULE 4
+#endif
+
#if defined(PCBTARANIS) || defined(PCBSKY9X) || defined(PCBHORUS)
#define NUM_MODULES 2
#else
@@ -191,8 +190,7 @@ enum BeeperMode {
enum ModuleIndex {
INTERNAL_MODULE,
EXTERNAL_MODULE,
- TRAINER_MODULE,
- FLASHING_MODULE,
+ SPORT_MODULE,
};
enum TrainerMode {
TRAINER_MODE_MASTER_TRAINER_JACK,
@@ -211,7 +209,7 @@ enum BeeperMode {
enum ModuleIndex {
EXTERNAL_MODULE,
EXTRA_MODULE,
- TRAINER_MODULE
+ SPORT_MODULE
};
#endif
@@ -224,12 +222,12 @@ enum BeeperMode {
#endif
#if defined(PCBTARANIS) || defined(PCBHORUS)
-#define IS_INTERNAL_MODULE_ENABLED() (g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE)
+ #define IS_INTERNAL_MODULE_ENABLED() (g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE)
#elif defined(PCBSKY9X)
#define IS_INTERNAL_MODULE_ENABLED() (false)
#endif
-#define IS_EXTERNAL_MODULE_ENABLED() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE)
+#define IS_EXTERNAL_MODULE_ENABLED() (g_model.moduleData[EXTERNAL_MODULE].type != MODULE_TYPE_NONE)
enum UartModes {
#if defined(CLI) || defined(DEBUG)
@@ -256,7 +254,7 @@ enum UartModes {
#define LEN_BLUETOOTH_NAME 10
#endif
-#define TELEM_LABEL_LEN 4
+#define TELEM_LABEL_LEN 4
enum TelemetryUnit {
UNIT_RAW,
UNIT_VOLTS,
@@ -358,7 +356,7 @@ enum SwitchSources {
SWSRC_FIRST_SWITCH,
-#if defined(PCBTARANIS) || defined(PCBHORUS)
+#if defined(PCBHORUS) || defined(PCBTARANIS)
SWSRC_SA0 = SWSRC_FIRST_SWITCH,
SWSRC_SA1,
SWSRC_SA2,
@@ -371,22 +369,22 @@ enum SwitchSources {
SWSRC_SD0,
SWSRC_SD1,
SWSRC_SD2,
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#if defined(PCBHORUS) || defined(PCBX9) || defined(PCBXLITES)
SWSRC_SE0,
SWSRC_SE1,
SWSRC_SE2,
#endif
-#if !defined(PCBXLITE)
+#if defined(PCBHORUS) || defined(PCBX9) || defined(PCBX7) || defined(PCBXLITES)
SWSRC_SF0,
SWSRC_SF1,
SWSRC_SF2,
#endif
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#if defined(PCBHORUS) || defined(PCBX9)
SWSRC_SG0,
SWSRC_SG1,
SWSRC_SG2,
#endif
-#if !defined(PCBXLITE)
+#if defined(PCBHORUS) || defined(PCBX9) || defined(PCBX7)
SWSRC_SH0,
SWSRC_SH1,
SWSRC_SH2,
@@ -423,15 +421,11 @@ enum SwitchSources {
SWSRC_SR1,
SWSRC_SR2,
#endif
-#if defined(PCBX9E)
+ SWSRC_LAST_SWITCH = SWSRC_FIRST_SWITCH + NUM_SWITCHES_POSITIONS - 1,
+#if NUM_SWITCHES >= 8
SWSRC_TRAINER = SWSRC_SH2,
- SWSRC_LAST_SWITCH = SWSRC_SR2,
-#elif defined(PCBXLITE)
- SWSRC_TRAINER = SWSRC_SD2,
- SWSRC_LAST_SWITCH = SWSRC_SD2,
#else
- SWSRC_TRAINER = SWSRC_SH2,
- SWSRC_LAST_SWITCH = SWSRC_SH2,
+ SWSRC_TRAINER = SWSRC_LAST_SWITCH,
#endif
#else // neither Taranis nor Horus
SWSRC_ID0 = SWSRC_FIRST_SWITCH,
@@ -560,6 +554,9 @@ enum MixSources {
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2")
MIXSRC_LAST_POT = MIXSRC_POT2,
+#elif defined(PCBX3)
+ MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
+ MIXSRC_LAST_POT = MIXSRC_POT1,
#elif defined(PCBTARANIS)
MIXSRC_POT1 = MIXSRC_FIRST_POT, LUA_EXPORT("s1", "Potentiometer 1")
MIXSRC_POT2, LUA_EXPORT("s2", "Potentiometer 2")
@@ -588,9 +585,9 @@ enum MixSources {
MIXSRC_MAX,
MIXSRC_FIRST_HELI,
- MIXSRC_CYC1 = MIXSRC_FIRST_HELI, LUA_EXPORT("cyc1", "Cyclic 1")
- MIXSRC_CYC2, LUA_EXPORT("cyc2", "Cyclic 2")
- MIXSRC_CYC3, LUA_EXPORT("cyc3", "Cyclic 3")
+ MIXSRC_CYC1 = MIXSRC_FIRST_HELI, LUA_EXPORT("cyc1", "Cyclic 1")
+ MIXSRC_CYC2, LUA_EXPORT("cyc2", "Cyclic 2")
+ MIXSRC_CYC3, LUA_EXPORT("cyc3", "Cyclic 3")
MIXSRC_FIRST_TRIM,
MIXSRC_TrimRud = MIXSRC_FIRST_TRIM, LUA_EXPORT("trim-rud", "Rudder trim")
@@ -607,25 +604,23 @@ enum MixSources {
MIXSRC_FIRST_SWITCH,
-#if defined(PCBXLITE)
+#if defined(PCBHORUS) || defined(PCBTARANIS)
MIXSRC_SA = MIXSRC_FIRST_SWITCH, LUA_EXPORT("sa", "Switch A")
MIXSRC_SB, LUA_EXPORT("sb", "Switch B")
MIXSRC_SC, LUA_EXPORT("sc", "Switch C")
MIXSRC_SD, LUA_EXPORT("sd", "Switch D")
- MIXSRC_LAST_SWITCH = MIXSRC_SD,
-#elif defined(PCBTARANIS) || defined(PCBHORUS)
- MIXSRC_SA = MIXSRC_FIRST_SWITCH, LUA_EXPORT("sa", "Switch A")
- MIXSRC_SB, LUA_EXPORT("sb", "Switch B")
- MIXSRC_SC, LUA_EXPORT("sc", "Switch C")
- MIXSRC_SD, LUA_EXPORT("sd", "Switch D")
-#if !defined(PCBX7)
+#if defined(PCBHORUS) || defined(PCBX9) || defined(PCBXLITES)
MIXSRC_SE, LUA_EXPORT("se", "Switch E")
#endif
+#if defined(PCBHORUS) || defined(PCBX9) || defined(PCBX7) || defined(PCBXLITES)
MIXSRC_SF, LUA_EXPORT("sf", "Switch F")
-#if !defined(PCBX7)
+#endif
+#if defined(PCBHORUS) || defined(PCBX9)
MIXSRC_SG, LUA_EXPORT("sg", "Switch G")
#endif
+#if defined(PCBHORUS) || defined(PCBX9) || defined(PCBX7)
MIXSRC_SH, LUA_EXPORT("sh", "Switch H")
+#endif
#if defined(PCBX9E)
MIXSRC_SI, LUA_EXPORT("si", "Switch I")
MIXSRC_SJ, LUA_EXPORT("sj", "Switch J")
@@ -637,9 +632,6 @@ enum MixSources {
MIXSRC_SP, LUA_EXPORT("sp", "Switch P")
MIXSRC_SQ, LUA_EXPORT("sq", "Switch Q")
MIXSRC_SR, LUA_EXPORT("sr", "Switch R")
- MIXSRC_LAST_SWITCH = MIXSRC_SR,
-#else
- MIXSRC_LAST_SWITCH = MIXSRC_SH,
#endif
#else
MIXSRC_3POS = MIXSRC_FIRST_SWITCH,
@@ -649,7 +641,6 @@ enum MixSources {
MIXSRC_AIL,
MIXSRC_GEA,
MIXSRC_TRN,
- MIXSRC_LAST_SWITCH = MIXSRC_TRN,
#endif
MIXSRC_FIRST_LOGICAL_SWITCH,
MIXSRC_SW1 = MIXSRC_FIRST_LOGICAL_SWITCH, LUA_EXPORT_MULTIPLE("ls", "Logical switch L%d", MAX_LOGICAL_SWITCHES)
@@ -703,10 +694,11 @@ enum MixSources {
MIXSRC_LAST_TELEM = MIXSRC_FIRST_TELEM+3*MAX_TELEMETRY_SENSORS-1
};
-#define MIXSRC_FIRST (MIXSRC_NONE+1)
-#define MIXSRC_LAST MIXSRC_LAST_CH
-#define INPUTSRC_FIRST MIXSRC_Rud
-#define INPUTSRC_LAST MIXSRC_LAST_TELEM
+#define MIXSRC_FIRST (MIXSRC_NONE + 1)
+#define MIXSRC_LAST MIXSRC_LAST_CH
+#define MIXSRC_LAST_SWITCH (MIXSRC_FIRST_SWITCH + NUM_SWITCHES - 1)
+#define INPUTSRC_FIRST MIXSRC_Rud
+#define INPUTSRC_LAST MIXSRC_LAST_TELEM
enum BacklightMode {
e_backlight_mode_off = 0,
@@ -803,4 +795,9 @@ enum BluetoothModes {
BLUETOOTH_TRAINER,
};
+// PXX2 constants
+#define PXX2_LEN_REGISTRATION_ID 8
+#define PXX2_LEN_RX_NAME 8
+#define PXX2_MAX_RECEIVERS_PER_MODULE 3
+
#endif // _DATACONSTANTS_H_
diff --git a/radio/src/datastructs.h b/radio/src/datastructs.h
index 44eb39f6a..f097f90c2 100644
--- a/radio/src/datastructs.h
+++ b/radio/src/datastructs.h
@@ -25,6 +25,7 @@
#include "board.h"
#include "dataconstants.h"
#include "definitions.h"
+#include "bitfield.h"
#if defined(PCBTARANIS)
#define N_TARANIS_FIELD(x)
@@ -385,14 +386,40 @@ PACK(struct TelemetrySensor {
uint32_t param;
};
NOBACKUP(
- void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
- void init(uint16_t id);
- bool isAvailable() const;
- int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
- bool isConfigurable() const;
- bool isPrecConfigurable() const;
- int32_t getPrecMultiplier() const;
- int32_t getPrecDivisor() const);
+ void init(const char *label, uint8_t unit=UNIT_RAW, uint8_t prec=0);
+ void init(uint16_t id);
+ bool isAvailable() const;
+ int32_t getValue(int32_t value, uint8_t unit, uint8_t prec) const;
+ bool isConfigurable() const;
+ bool isPrecConfigurable() const;
+ int32_t getPrecMultiplier() const;
+ int32_t getPrecDivisor() const;
+ );
+});
+
+/*
+ * Trainer module structure
+ */
+
+PACK(struct TrainerModuleData {
+ uint8_t mode:3;
+ uint8_t spare:5;
+ uint8_t channelsStart;
+ int8_t channelsCount; // 0=8 channels
+ int8_t frameLength;
+ int8_t delay:6;
+ uint8_t pulsePol:1;
+});
+
+/*
+ * Receiver structure
+ */
+
+PACK(struct ReceiverData {
+ uint8_t used:1;
+ uint8_t telemetry:1;
+ uint8_t dirty:6;
+ char name[PXX2_LEN_RX_NAME];
});
/*
@@ -406,10 +433,19 @@ PACK(struct ModuleData {
int8_t rfProtocol:4;
uint8_t channelsStart;
int8_t channelsCount; // 0=8 channels
- uint8_t failsafeMode:4; // only 3 bits used
- uint8_t subType:3;
- uint8_t invertedSerial:1; // telemetry serial inverted from standard
- int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
+ union {
+ struct {
+ uint8_t failsafeMode:4; // only 3 bits used
+ uint8_t subType:3;
+ uint8_t invertedSerial:1; // telemetry serial inverted from standard
+ };
+ struct {
+ uint8_t failsafeMode:4; // only 3 bits used
+ uint8_t freq:2;
+ uint8_t region:2;
+ } r9m;
+ };
+
union {
struct {
int8_t delay:6;
@@ -440,6 +476,28 @@ PACK(struct ModuleData {
uint8_t spare2:1;
int8_t refreshRate; // definition as framelength for ppm (* 5 + 225 = time in 1/10 ms)
} sbus);
+ NOBACKUP(PACK(struct {
+ uint8_t power:2; // 0=10 mW, 1=100 mW, 2=500 mW, 3=1W
+ uint8_t external_antenna:1; // false = internal antenna, true = external antenna
+#if defined(PCBHORUS)
+ uint8_t spare:5;
+ uint32_t receivers; // max 5 receivers per module and 10 receivers in total (4bits per receiver with 0 = unused)
+#else
+ uint8_t spare:1;
+ uint16_t receivers:12; // max 4 receivers per module and 4 receivers in total (3bits per receiver with 0 = unused)
+#endif
+ NOBACKUP(inline uint8_t getReceiverSlot(uint8_t receiver) {
+ return (receivers >> (3 * receiver)) & 0b111;
+ })
+
+ NOBACKUP(inline void setReceiverSlot(uint8_t receiver, uint8_t slot) {
+ receivers = BF_SET(receivers, slot, 3 * receiver, 3);
+ })
+
+ NOBACKUP(inline void clearReceiverSlot(uint8_t receiver) {
+ setReceiverSlot(receiver, 0);
+ })
+ }) pxx2);
};
// Helper functions to set both of the rfProto protocol at the same time
@@ -449,12 +507,10 @@ PACK(struct ModuleData {
return ((uint8_t) (rfProtocol & 0x0f)) + (multi.rfProtocolExtra << 4);
})
- NOBACKUP(inline void setMultiProtocol(uint8_t proto)
- {
+ NOBACKUP(inline void setMultiProtocol(uint8_t proto) {
rfProtocol = (uint8_t) (proto & 0x0f);
multi.rfProtocolExtra = (proto & 0x30) >> 4;
})
-
});
/*
@@ -501,10 +557,6 @@ typedef uint8_t swarnenable_t;
swarnenable_t switchWarningEnable;
#endif
- #define MODEL_GVARS_DATA GVarData gvars[MAX_GVARS];
-
- #define TELEMETRY_DATA NOBACKUP(FrSkyTelemetryData frsky); NOBACKUP(RssiAlarmData rssiAlarms);
-
#if defined(PCBHORUS)
#include "gui/480x272/layout.h"
#include "gui/480x272/topbar.h"
@@ -518,23 +570,11 @@ PACK(struct CustomScreenData {
NOBACKUP(Topbar::PersistentData topbarData); \
NOBACKUP(uint8_t view);
#elif defined(PCBTARANIS)
-#define CUSTOM_SCREENS_DATA \
+ #define CUSTOM_SCREENS_DATA \
NOBACKUP(uint8_t view);
#else
-#define CUSTOM_SCREENS_DATA
-// TODO other boards could have their custom screens here as well
-#endif
-
-#if defined(PCBX12S)
- #define MODELDATA_EXTRA NOBACKUP(uint8_t spare:3); NOBACKUP(uint8_t trainerMode:3); NOBACKUP(uint8_t potsWarnMode:2); ModuleData moduleData[NUM_MODULES+1]; NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); NOBACKUP(char inputNames[MAX_INPUTS][LEN_INPUT_NAME]); NOBACKUP(uint8_t potsWarnEnabled); NOBACKUP(int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]);
-#elif defined(PCBX10)
- #define MODELDATA_EXTRA NOBACKUP(uint8_t spare:3); NOBACKUP(uint8_t trainerMode:3); NOBACKUP(uint8_t potsWarnMode:2); ModuleData moduleData[NUM_MODULES+1]; NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]); NOBACKUP(char inputNames[MAX_INPUTS][LEN_INPUT_NAME]); NOBACKUP(uint8_t potsWarnEnabled); NOBACKUP(int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]); NOBACKUP(uint8_t potsWarnSpares[NUM_DUMMY_ANAS]);
-#elif defined(PCBTARANIS)
- #define MODELDATA_EXTRA uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; ScriptData scriptsData[MAX_SCRIPTS]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS];
-#elif defined(PCBSKY9X)
- #define MODELDATA_EXTRA uint8_t spare:6; uint8_t potsWarnMode:2; ModuleData moduleData[NUM_MODULES+1]; char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]; uint8_t rxBattAlarms[2];
-#else
- #define MODELDATA_EXTRA
+ #define CUSTOM_SCREENS_DATA
+ // TODO other boards could have their custom screens here as well
#endif
PACK(struct ModelData {
@@ -568,11 +608,25 @@ PACK(struct ModelData {
SWITCHES_WARNING_DATA
- MODEL_GVARS_DATA
+ GVarData gvars[MAX_GVARS];
- TELEMETRY_DATA
+ NOBACKUP(FrSkyTelemetryData frsky);
+ NOBACKUP(RssiAlarmData rssiAlarms);
- MODELDATA_EXTRA
+ NOBACKUP(uint8_t spare:6);
+ NOBACKUP(uint8_t potsWarnMode:2);
+ ModuleData moduleData[NUM_MODULES];
+ ReceiverData receiverData[NUM_RECEIVERS];
+ int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
+ TrainerModuleData trainerData;
+
+#if defined(PCBHORUS) || defined(PCBTARANIS)
+ NOBACKUP(ScriptData scriptsData[MAX_SCRIPTS]);
+#endif
+
+ NOBACKUP(char inputNames[MAX_INPUTS][LEN_INPUT_NAME]);
+ NOBACKUP(uint8_t potsWarnEnabled);
+ NOBACKUP(int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS+NUM_DUMMY_ANAS]);
NOBACKUP(TelemetrySensor telemetrySensors[MAX_TELEMETRY_SENSORS];)
@@ -580,6 +634,7 @@ PACK(struct ModelData {
CUSTOM_SCREENS_DATA
+ char modelRegistrationID[PXX2_LEN_REGISTRATION_ID];
});
/*
@@ -616,30 +671,8 @@ PACK(struct TrainerData {
#define SPLASH_MODE int8_t splashMode:3
#endif
- #define EXTRA_GENERAL_FIELDS_ARM \
- NOBACKUP(uint8_t backlightBright); \
- NOBACKUP(uint32_t globalTimer); \
- NOBACKUP(uint8_t bluetoothBaudrate:4); \
- NOBACKUP(uint8_t bluetoothMode:4); \
- NOBACKUP(uint8_t countryCode); \
- NOBACKUP(uint8_t imperial:1); \
- NOBACKUP(uint8_t jitterFilter:1); /* 0 - active */\
- NOBACKUP(uint8_t disableRssiPoweroffAlarm:1); \
- NOBACKUP(uint8_t USBMode:2); \
- NOBACKUP(uint8_t spareExtraArm:3); \
- NOBACKUP(char ttsLanguage[2]); \
- NOBACKUP(int8_t beepVolume:4); \
- NOBACKUP(int8_t wavVolume:4); \
- NOBACKUP(int8_t varioVolume:4); \
- NOBACKUP(int8_t backgroundVolume:4); \
- NOBACKUP(int8_t varioPitch); \
- NOBACKUP(int8_t varioRange); \
- NOBACKUP(int8_t varioRepeat); \
- CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
-
#if defined(PCBHORUS)
#define EXTRA_GENERAL_FIELDS \
- EXTRA_GENERAL_FIELDS_ARM \
NOBACKUP(uint8_t serial2Mode:4); \
uint8_t slidersConfig:4; \
uint32_t switchConfig; \
@@ -659,7 +692,6 @@ PACK(struct TrainerData {
#define BLUETOOTH_FIELDS
#endif
#define EXTRA_GENERAL_FIELDS \
- EXTRA_GENERAL_FIELDS_ARM \
uint8_t serial2Mode:4; \
uint8_t slidersConfig:4; \
uint8_t potsConfig; /* two bits per pot */\
@@ -671,7 +703,6 @@ PACK(struct TrainerData {
BLUETOOTH_FIELDS
#elif defined(PCBSKY9X)
#define EXTRA_GENERAL_FIELDS \
- EXTRA_GENERAL_FIELDS_ARM \
int8_t txCurrentCalibration; \
int8_t temperatureWarn; \
uint8_t mAhWarn; \
@@ -683,7 +714,7 @@ PACK(struct TrainerData {
char switchNames[NUM_SWITCHES][LEN_SWITCH_NAME]; \
char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME];
#else
- #define EXTRA_GENERAL_FIELDS EXTRA_GENERAL_FIELDS_ARM
+ #define EXTRA_GENERAL_FIELDS
#endif
#if defined(PCBHORUS)
@@ -697,9 +728,9 @@ PACK(struct TrainerData {
#endif
#if defined(BUZZER)
- #define BUZZER_FIELD NOBACKUP(int8_t buzzerMode:2); // -2=quiet, -1=only alarms, 0=no keys, 1=all (only used on AVR radios without audio hardware)
+ #define BUZZER_FIELD int8_t buzzerMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all (only used on AVR radios without audio hardware)
#else
- #define BUZZER_FIELD NOBACKUP(int8_t spareRadio:2);
+ #define BUZZER_FIELD int8_t spareRadio:2;
#endif
PACK(struct RadioData {
@@ -743,16 +774,39 @@ PACK(struct RadioData {
NOBACKUP(int8_t vBatMin);
NOBACKUP(int8_t vBatMax);
+ NOBACKUP(uint8_t backlightBright);
+ NOBACKUP(uint32_t globalTimer);
+ NOBACKUP(uint8_t bluetoothBaudrate:4);
+ NOBACKUP(uint8_t bluetoothMode:4);
+ NOBACKUP(uint8_t countryCode);
+ NOBACKUP(uint8_t imperial:1);
+ NOBACKUP(uint8_t jitterFilter:1); /* 0 - active */
+ NOBACKUP(uint8_t disableRssiPoweroffAlarm:1);
+ NOBACKUP(uint8_t USBMode:2);
+ NOBACKUP(uint8_t jackMode:2);
+ NOBACKUP(uint8_t spareExtraArm:1);
+ NOBACKUP(char ttsLanguage[2]);
+ NOBACKUP(int8_t beepVolume:4);
+ NOBACKUP(int8_t wavVolume:4);
+ NOBACKUP(int8_t varioVolume:4);
+ NOBACKUP(int8_t backgroundVolume:4);
+ NOBACKUP(int8_t varioPitch);
+ NOBACKUP(int8_t varioRange);
+ NOBACKUP(int8_t varioRepeat);
+
+ CustomFunctionData customFn[MAX_SPECIAL_FUNCTIONS];
+
EXTRA_GENERAL_FIELDS
THEME_DATA
+ char ownerRegistrationID[PXX2_LEN_REGISTRATION_ID];
});
#undef SWITCHES_WARNING_DATA
#undef MODEL_GVARS_DATA
#undef TELEMETRY_DATA
-#undef MODELDATA_EXTRA
+#undef SCRIPTS_DATA
#undef CUSTOM_SCREENS_DATA
#undef SPLASH_MODE
#undef EXTRA_GENERAL_FIELDS
@@ -783,7 +837,7 @@ static inline void check_struct()
/* Difference between Taranis/Horus is LEN_EXPOMIX_NAME */
/* LEN_FUNCTION_NAME is the difference in CustomFunctionData */
-#if defined(PCBX7) || defined(PCBXLITE)
+#if defined(PCBX7) || defined(PCBXLITE) || defined(PCBX3)
CHKSIZE(MixData, 20);
CHKSIZE(ExpoData, 17);
CHKSIZE(LimitData, 11);
@@ -862,31 +916,39 @@ static inline void check_struct()
CHKSIZE(LogicalSwitchData, 9);
CHKSIZE(TelemetrySensor, 13);
- CHKSIZE(ModuleData,70);
+
+#if defined(PCBHORUS)
+ CHKSIZE(ModuleData, 9);
+#else
+ CHKSIZE(ModuleData, 6);
+#endif
CHKSIZE(GVarData, 7);
CHKSIZE(RssiAlarmData, 2);
CHKSIZE(TrainerData, 16);
-#if defined(PCBXLITE)
- CHKSIZE(RadioData, 844);
- CHKSIZE(ModelData, 6025);
+#if defined(PCBXLITES)
+ CHKSIZE(RadioData, 858);
+ CHKSIZE(ModelData, 5940);
+#elif defined(PCBXLITE)
+ CHKSIZE(RadioData, 852);
+ CHKSIZE(ModelData, 5940);
#elif defined(PCBX7)
- CHKSIZE(RadioData, 850);
- CHKSIZE(ModelData, 6025);
+ CHKSIZE(RadioData, 858);
+ CHKSIZE(ModelData, 5940);
#elif defined(PCBX9E)
- CHKSIZE(RadioData, 952);
- CHKSIZE(ModelData, 6520);
+ CHKSIZE(RadioData, 960);
+ CHKSIZE(ModelData, 6435);
#elif defined(PCBX9D)
- CHKSIZE(RadioData, 872);
- CHKSIZE(ModelData, 6507);
+ CHKSIZE(RadioData, 880);
+ CHKSIZE(ModelData, 6422);
#elif defined(PCBSKY9X)
- CHKSIZE(RadioData, 727);
- CHKSIZE(ModelData, 5188);
+ CHKSIZE(RadioData, 735);
+ CHKSIZE(ModelData, 5101);
#elif defined(PCBHORUS)
- CHKSIZE(RadioData, 847);
- CHKSIZE(ModelData, 9380);
+ CHKSIZE(RadioData, 855);
+ CHKSIZE(ModelData, 9771);
#endif
#undef CHKSIZE
diff --git a/radio/src/definitions.h b/radio/src/definitions.h
index e921389f9..8b5f5391e 100644
--- a/radio/src/definitions.h
+++ b/radio/src/definitions.h
@@ -22,6 +22,8 @@
#define _DEFINITIONS_H_
#include
+#include
+#include
#if !defined(UNUSED)
#define UNUSED(x) ((void)(x)) /* to avoid warnings */
diff --git a/radio/src/fifo.h b/radio/src/fifo.h
index e24b9ba80..a61d31839 100644
--- a/radio/src/fifo.h
+++ b/radio/src/fifo.h
@@ -21,6 +21,8 @@
#ifndef _FIFO_H_
#define _FIFO_H_
+#include
+
template
class Fifo
{
@@ -40,13 +42,18 @@ class Fifo
void push(T element)
{
- uint32_t next = (widx+1) & (N-1);
+ uint32_t next = nextIndex(widx);
if (next != ridx) {
fifo[widx] = element;
widx = next;
}
}
+ void skip()
+ {
+ ridx = nextIndex(ridx);
+ }
+
bool pop(T & element)
{
if (isEmpty()) {
@@ -54,7 +61,7 @@ class Fifo
}
else {
element = fifo[ridx];
- ridx = (ridx+1) & (N-1);
+ ridx = nextIndex(ridx);
return true;
}
}
@@ -66,7 +73,7 @@ class Fifo
bool isFull()
{
- uint32_t next = (widx+1) & (N-1);
+ uint32_t next = nextIndex(widx);
return (next == ridx);
}
@@ -77,7 +84,7 @@ class Fifo
uint32_t size() const
{
- return (N + widx - ridx) & (N-1);
+ return (N + widx - ridx) & (N - 1);
}
uint32_t hasSpace(uint32_t n) const
@@ -100,6 +107,11 @@ class Fifo
T fifo[N];
volatile uint32_t widx;
volatile uint32_t ridx;
+
+ inline uint32_t nextIndex(uint32_t idx)
+ {
+ return (idx + 1) & (N - 1);
+ }
};
#endif // _FIFO_H_
diff --git a/radio/src/functions.cpp b/radio/src/functions.cpp
index 5142df59c..ef286f494 100644
--- a/radio/src/functions.cpp
+++ b/radio/src/functions.cpp
@@ -155,8 +155,7 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext
active &= (bool)CFN_ACTIVE(cfn);
}
- if (active || IS_PLAY_BOTH_FUNC(CFN_FUNC(cfn))) {
-
+ if (active) {
switch (CFN_FUNC(cfn)) {
#if defined(OVERRIDE_CHANNEL_FUNCTION)
@@ -233,7 +232,7 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext
{
unsigned int moduleIndex = CFN_PARAM(cfn);
if (moduleIndex < NUM_MODULES) {
- moduleFlag[moduleIndex] = 1 + CFN_FUNC(cfn) - FUNC_RANGECHECK;
+ moduleSettings[moduleIndex].mode = 1 + CFN_FUNC(cfn) - FUNC_RANGECHECK;
}
break;
}
@@ -404,7 +403,7 @@ void evalFunctions(const CustomFunctionData * functions, CustomFunctionsContext
{
unsigned int moduleIndex = CFN_PARAM(cfn);
if (moduleIndex < NUM_MODULES) {
- moduleFlag[moduleIndex] = 0;
+ moduleSettings[moduleIndex].mode = 0;
}
break;
}
diff --git a/radio/src/gui/128x64/gui.h b/radio/src/gui/128x64/gui.h
index 6b814dd46..f557fba48 100644
--- a/radio/src/gui/128x64/gui.h
+++ b/radio/src/gui/128x64/gui.h
@@ -27,7 +27,7 @@
#define MENUS_SCROLLBAR_WIDTH 0
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
#define HEADER_LINE 0
#define HEADER_LINE_COLUMNS
#else
@@ -40,7 +40,6 @@
#define NUM_BODY_LINES (LCD_LINES-1)
#define MENU_HEADER_HEIGHT FH
-#define MENU_INIT_VPOS 0
#define CURVE_SIDE_WIDTH (LCD_H/2)
#define CURVE_CENTER_X (LCD_W-CURVE_SIDE_WIDTH-2)
@@ -53,45 +52,32 @@ extern uint8_t noHighlightCounter;
#define NO_HIGHLIGHT() (noHighlightCounter > 0)
#define START_NO_HIGHLIGHT() do { noHighlightCounter = 25; } while(0)
-
void drawSlider(coord_t x, coord_t y, uint8_t value, uint8_t max, uint8_t attr);
-#if defined(NAVIGATION_POT1)
-extern int16_t p1valdiff;
-#else
- #define p1valdiff 0
-#endif
-
-#if defined(NAVIGATION_POT2)
-extern int8_t p2valdiff;
-#else
- #define p2valdiff 0
-#endif
-
extern int8_t checkIncDec_Ret; // global helper vars
-#define EDIT_SELECT_MENU -1
#define EDIT_SELECT_FIELD 0
#define EDIT_MODIFY_FIELD 1
#define EDIT_MODIFY_STRING 2
extern int8_t s_editMode; // global editmode
// checkIncDec flags
-#define EE_GENERAL 0x01
-#define EE_MODEL 0x02
+
+// we leave room for EE_MODEL and EE_GENERAL
#define NO_INCDEC_MARKS 0x04
#define INCDEC_SWITCH 0x08
#define INCDEC_SOURCE 0x10
#define INCDEC_REP10 0x40
#define NO_DBLKEYS 0x80
- #define INCDEC_DECLARE_VARS(f) uint8_t incdecFlag = (f); IsValueAvailable isValueAvailable = NULL
- #define INCDEC_SET_FLAG(f) incdecFlag = (f)
- #define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn
- #define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable)
+#define INCDEC_DECLARE_VARS(f) uint8_t incdecFlag = (f); IsValueAvailable isValueAvailable = NULL
+#define INCDEC_SET_FLAG(f) incdecFlag = (f)
+#define INCDEC_ENABLE_CHECK(fn) isValueAvailable = fn
+#define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable)
// mawrow special values
-#define TITLE_ROW ((uint8_t)-1)
+#define READONLY_ROW ((uint8_t)-1)
+#define TITLE_ROW READONLY_ROW
#define HIDDEN_ROW ((uint8_t)-2)
struct CheckIncDecStops {
@@ -167,9 +153,9 @@ void check_submenu_simple(event_t event, uint8_t maxrow);
void title(const char * s);
#define TITLE(str) title(str)
- #define MENU_TAB(...) const uint8_t mstate_tab[] = __VA_ARGS__
+#define MENU_TAB(...) const uint8_t mstate_tab[] = __VA_ARGS__
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
#define MENU_CHECK(tab, menu, lines_count) \
check(event, menu, tab, DIM(tab), mstate_tab, DIM(mstate_tab)-1, lines_count)
#else
@@ -182,13 +168,12 @@ void title(const char * s);
MENU_CHECK(tab, menu, lines_count); \
TITLE(title)
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
#define SIMPLE_MENU_NOTITLE(tab, menu, lines_count) \
check_simple(event, menu, tab, DIM(tab), lines_count);
-#define SUBMENU_NOTITLE(lines_count, ...) { \
+#define SUBMENU_NOTITLE(lines_count, ...) \
MENU_TAB(__VA_ARGS__); \
- check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count); \
- }
+ check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count);
#define SUBMENU(title, lines_count, ...) \
MENU_TAB(__VA_ARGS__); \
check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, lines_count); \
@@ -198,10 +183,9 @@ void title(const char * s);
#else
#define SIMPLE_MENU_NOTITLE(tab, menu, lines_count) \
check_simple(event, menu, tab, DIM(tab), (lines_count)-1);
-#define SUBMENU_NOTITLE(lines_count, ...) { \
+#define SUBMENU_NOTITLE(lines_count, ...) \
MENU_TAB(__VA_ARGS__); \
- check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, (lines_count)-1); \
- }
+ check(event, 0, NULL, 0, mstate_tab, DIM(mstate_tab)-1, (lines_count)-1);
#define SUBMENU(title, lines_count, ...) \
MENU_TAB(__VA_ARGS__); \
@@ -211,8 +195,6 @@ void title(const char * s);
#define SIMPLE_SUBMENU_NOTITLE(lines_count) \
check_submenu_simple(event, (lines_count)-1);
-
-
#endif
#define SIMPLE_MENU(title, tab, menu, lines_count) \
@@ -232,32 +214,21 @@ int8_t editSwitch(coord_t x, coord_t y, int8_t value, LcdFlags attr, event_t eve
#define ON_OFF_MENU_ITEM(value, x, y, label, attr, event) value = editCheckBox(value, x, y, label, attr, event)
#if defined(GVARS)
- #define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, editflags, event)
-#else
- #define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, event)
-#endif
-
-#if defined(GVARS)
+#define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, editflags, event)
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, uint8_t editflags, event_t event);
void drawGVarName(coord_t x, coord_t y, int8_t index, LcdFlags flags=0);
void drawGVarValue(coord_t x, coord_t y, uint8_t gvar, gvar_t value, LcdFlags flags=0);
void editGVarValue(coord_t x, coord_t y, event_t event, uint8_t gvar, uint8_t flightMode, LcdFlags flags);
-#elif defined(GVARS)
-int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, event_t event);
+#define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0)
#else
int16_t editGVarFieldValue(coord_t x, coord_t y, int16_t value, int16_t min, int16_t max, LcdFlags attr, event_t event);
+#define GVAR_MENU_ITEM(x, y, v, min, max, attr, editflags, event) editGVarFieldValue(x, y, v, min, max, attr, event)
+#define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v)
#endif
void gvarWeightItem(coord_t x, coord_t y, MixData * md, LcdFlags attr, event_t event);
-#if defined(GVARS)
-#define displayGVar(x, y, v, min, max) GVAR_MENU_ITEM(x, y, v, min, max, 0, 0, 0)
-#else
-#define displayGVar(x, y, v, min, max) lcdDraw8bitsNumber(x, y, v)
-#endif
-
void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, uint8_t active, LcdFlags attr=ZCHAR);
-
void editSingleName(coord_t x, coord_t y, const char * label, char * name, uint8_t size, event_t event, uint8_t active);
uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint8_t delay);
@@ -265,13 +236,7 @@ uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint
#define WARNING_TYPE_ASTERISK 0
#define WARNING_TYPE_CONFIRM 1
-#define WARNING_TYPE_INPUT 2
-
-extern const char * warningText;
-extern const char * warningInfoText;
-extern uint8_t warningInfoLength;
-extern uint8_t warningResult;
-extern uint8_t warningType;
+#define WARNING_TYPE_INFO 2
#define COPY_MODE 1
#define MOVE_MODE 2
@@ -295,11 +260,11 @@ void drawStatusLine();
#endif
#define TEXT_FILENAME_MAXLEN 40
- extern char s_text_file[TEXT_FILENAME_MAXLEN];
- void menuTextView(event_t event);
- void pushMenuTextView(const char *filename);
- void pushModelNotes();
- void readModelNotes();
+extern char s_text_file[TEXT_FILENAME_MAXLEN];
+void menuTextView(event_t event);
+void pushMenuTextView(const char *filename);
+void pushModelNotes();
+void readModelNotes();
#define LABEL(...) (uint8_t)-1
@@ -335,7 +300,7 @@ void drawStatusLine();
#endif
// TODO enum
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
#define EDIT_MODE_INIT 0
#else
#define EDIT_MODE_INIT -1
@@ -357,8 +322,6 @@ void onSourceLongEnterPress(const char *result);
uint8_t switchToMix(uint8_t source);
-void deleteExpoMix(uint8_t expo, uint8_t idx);
-
void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr);
extern const unsigned char sticks[] ;
@@ -370,15 +333,12 @@ void drawStick(coord_t centrex, int16_t xval, int16_t yval);
void drawPotsBars();
void doMainScreenGraphics();
-void drawProgressBar(const char * label, int num, int den);
+void drawProgressScreen(const char * title, const char * message, int num, int den);
void drawSleepBitmap();
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
-#if defined(PCBTARANIS)
void drawAlertBox(const char * title, const char * text, const char * action);
-#endif
-
void showAlertBox(const char * title, const char * text, const char * action , uint8_t sound);
#define SET_SCROLLBAR_X(x)
diff --git a/radio/src/gui/128x64/lcd.cpp b/radio/src/gui/128x64/lcd.cpp
index fa1cd058c..d800521df 100644
--- a/radio/src/gui/128x64/lcd.cpp
+++ b/radio/src/gui/128x64/lcd.cpp
@@ -292,7 +292,7 @@ uint8_t getTextWidth(const char * s, uint8_t len, LcdFlags flags)
{
uint8_t width = 0;
for (int i=0; len==0 || i9 ? c+'A'-10 : c+'0';
+ lcdDrawChar(x, y, c, flags|(c>='A' ? CONDENSED : 0));
+ val >>= 4;
+ }
+}
+
+
void lcdDraw8bitsNumber(coord_t x, coord_t y, int8_t val)
{
lcdDrawNumber(x, y, val);
diff --git a/radio/src/gui/128x64/lcd.h b/radio/src/gui/128x64/lcd.h
index c1a562130..3eb08e861 100644
--- a/radio/src/gui/128x64/lcd.h
+++ b/radio/src/gui/128x64/lcd.h
@@ -124,7 +124,8 @@ void lcdDrawTextAlignedLeft(coord_t y, const char * s);
#define lcdDrawTextAlignedCenter(y, s) lcdDrawText((LCD_W-sizeof(TR_##s)*FW+FW+1)/2, y, STR_##s)
- void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0);
+void lcdDrawHexNumber(coord_t x, coord_t y, uint32_t val, LcdFlags mode=0);
+void lcdDrawHexChar(coord_t x, coord_t y, uint8_t val, LcdFlags flags=0);
void lcdDrawNumber(coord_t x, coord_t y, lcdint_t val, LcdFlags mode, uint8_t len);
void lcdDrawNumber(coord_t x, coord_t y, lcdint_t val, LcdFlags mode=0);
diff --git a/radio/src/gui/128x64/menus.cpp b/radio/src/gui/128x64/menus.cpp
index e153fda4e..e09448460 100644
--- a/radio/src/gui/128x64/menus.cpp
+++ b/radio/src/gui/128x64/menus.cpp
@@ -33,6 +33,13 @@ void popMenu()
TRACE("popMenu(%d)", menuLevel);
}
+void abortPopMenu()
+{
+ menuLevel = menuLevel + 1;
+ menuEvent = 0;
+ TRACE("popMenu(%d) aborted", menuLevel);
+}
+
void chainMenu(MenuHandlerFunc newMenu)
{
menuHandlers[menuLevel] = newMenu;
diff --git a/radio/src/gui/128x64/menus.h b/radio/src/gui/128x64/menus.h
index ee5c9e552..26e9af134 100644
--- a/radio/src/gui/128x64/menus.h
+++ b/radio/src/gui/128x64/menus.h
@@ -56,6 +56,17 @@ extern uint8_t menuEvent;
void chainMenu(MenuHandlerFunc newMenu);
void pushMenu(MenuHandlerFunc newMenu);
void popMenu();
+void abortPopMenu();
+
+inline bool isRadioMenuDisplayed()
+{
+ return menuVerticalPositions[0] == 1;
+}
+
+inline bool isModelMenuDisplayed()
+{
+ return menuVerticalPositions[0] == 0;
+}
inline MenuHandlerFunc lastPopMenu()
{
@@ -63,7 +74,6 @@ inline MenuHandlerFunc lastPopMenu()
}
void onMainViewMenu(const char * result);
-
void menuFirstCalib(event_t event);
void menuMainView(event_t event);
void menuViewTelemetryFrsky(event_t event);
@@ -73,10 +83,11 @@ enum MenuRadioIndexes
{
MENU_RADIO_SETUP,
CASE_SDCARD(MENU_RADIO_SD_MANAGER)
+ MENU_RADIO_TOOLS,
MENU_RADIO_SPECIAL_FUNCTIONS,
MENU_RADIO_TRAINER,
- MENU_RADIO_VERSION,
MENU_RADIO_HARDWARE,
+ MENU_RADIO_VERSION,
MENU_RADIO_PAGES_COUNT
};
@@ -88,15 +99,19 @@ void menuRadioVersion(event_t event);
void menuRadioDiagKeys(event_t event);
void menuRadioDiagAnalogs(event_t event);
void menuRadioHardware(event_t event);
+void menuRadioTools(event_t event);
+void menuRadioSpectrumAnalyser(event_t event);
+void menuRadioPowerMeter(event_t event);
void menuRadioCalibration(event_t event);
static const MenuHandlerFunc menuTabGeneral[] = {
menuRadioSetup,
CASE_SDCARD(menuRadioSdManager)
+ menuRadioTools,
menuRadioSpecialFunctions,
menuRadioTrainer,
- menuRadioVersion,
- menuRadioHardware
+ menuRadioHardware,
+ menuRadioVersion
};
enum MenuModelIndexes {
@@ -120,6 +135,9 @@ enum MenuModelIndexes {
void menuModelSelect(event_t event);
void menuModelSetup(event_t event);
+void menuModelFailsafe(event_t event);
+void menuModelModuleOptions(event_t event);
+void menuModelReceiverOptions(event_t event);
void menuModelHeli(event_t event);
void menuModelFlightModesAll(event_t event);
void menuModelExpoOne(event_t event);
diff --git a/radio/src/gui/128x64/model_curve_edit.cpp b/radio/src/gui/128x64/model_curve_edit.cpp
index 3a0112109..188f4c868 100644
--- a/radio/src/gui/128x64/model_curve_edit.cpp
+++ b/radio/src/gui/128x64/model_curve_edit.cpp
@@ -20,17 +20,39 @@
#include "opentx.h"
-void displayPresetChoice(event_t event)
+void runPopupCurvePreset(event_t event)
{
- runPopupWarning(event);
- lcdDrawNumber(WARNING_LINE_X+FW*7, WARNING_LINE_Y, 45*warningInputValue/4, LEFT|INVERS);
+ warningResult = false;
+
+ drawMessageBox(warningText);
+
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+2*FH, STR_POPUPS_ENTER_EXIT);
+
+ switch (event) {
+ case EVT_KEY_BREAK(KEY_ENTER):
+ warningResult = true;
+ // no break
+
+ case EVT_KEY_BREAK(KEY_EXIT):
+ warningText = NULL;
+ warningType = WARNING_TYPE_ASTERISK;
+ break;
+
+ default:
+ s_editMode = EDIT_MODIFY_FIELD;
+ reusableBuffer.curveEdit.preset = checkIncDec(event, reusableBuffer.curveEdit.preset, -4, 4);
+ s_editMode = EDIT_SELECT_FIELD;
+ break;
+ }
+
+ lcdDrawNumber(WARNING_LINE_X+FW*7, WARNING_LINE_Y, 45 * reusableBuffer.curveEdit.preset / 4, LEFT|INVERS);
lcdDrawChar(lcdLastRightPos, WARNING_LINE_Y, '@', INVERS);
if (warningResult) {
warningResult = 0;
CurveInfo & crv = g_model.curves[s_curveChan];
int8_t * points = curveAddress(s_curveChan);
- int k = 25 * warningInputValue;
+ int k = 25 * reusableBuffer.curveEdit.preset;
int dx = 2000 / (5+crv.points-1);
for (uint8_t i=0; i<5+crv.points; i++) {
int x = -1000 + i * dx;
@@ -45,7 +67,8 @@ void displayPresetChoice(event_t event)
void onCurveOneMenu(const char * result)
{
if (result == STR_CURVE_PRESET) {
- POPUP_INPUT(STR_PRESET, displayPresetChoice, 0, -4, 4);
+ reusableBuffer.curveEdit.preset = 4; // 45°
+ POPUP_INPUT(STR_PRESET, runPopupCurvePreset);
}
else if (result == STR_MIRROR) {
CurveInfo & crv = g_model.curves[s_curveChan];
diff --git a/radio/src/gui/128x64/model_custom_scripts.cpp b/radio/src/gui/128x64/model_custom_scripts.cpp
index e63e57e5f..4ff56e735 100644
--- a/radio/src/gui/128x64/model_custom_scripts.cpp
+++ b/radio/src/gui/128x64/model_custom_scripts.cpp
@@ -37,7 +37,7 @@ void onModelCustomScriptMenu(const char *result)
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a lua file in the list
copySelection(sd.file, result, sizeof(sd.file));
memset(sd.inputs, 0, sizeof(sd.inputs));
diff --git a/radio/src/gui/128x64/model_display.cpp b/radio/src/gui/128x64/model_display.cpp
index cc8db7a72..03cd4c094 100644
--- a/radio/src/gui/128x64/model_display.cpp
+++ b/radio/src/gui/128x64/model_display.cpp
@@ -73,7 +73,7 @@ void onTelemetryScriptFileSelectionMenu(const char *result)
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a file in the list
memcpy(g_model.frsky.screens[screenIndex].script.file, result, sizeof(g_model.frsky.screens[screenIndex].script.file));
storageDirty(EE_MODEL);
diff --git a/radio/src/gui/128x64/model_failsafe.cpp b/radio/src/gui/128x64/model_failsafe.cpp
new file mode 100644
index 000000000..2896e8c95
--- /dev/null
+++ b/radio/src/gui/128x64/model_failsafe.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+
+extern uint8_t g_moduleIdx;
+
+void menuModelFailsafe(event_t event)
+{
+ const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
+ const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
+ uint8_t wbar = LCD_W - FW * 4 - FWNUM * 4;
+#if defined(PPM_UNIT_PERCENT_PREC1)
+ wbar -= 6;
+#endif
+
+ if (event == EVT_KEY_LONG(KEY_ENTER)) {
+ killEvents(event);
+ event = 0;
+
+ if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) {
+ if (s_editMode > 0) {
+ g_model.failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart];
+ s_editMode = 0;
+ }
+ else {
+ int16_t & failsafe = g_model.failsafeChannels[menuVerticalPosition];
+ if (failsafe < FAILSAFE_CHANNEL_HOLD)
+ failsafe = FAILSAFE_CHANNEL_HOLD;
+ else if (failsafe == FAILSAFE_CHANNEL_HOLD)
+ failsafe = FAILSAFE_CHANNEL_NOPULSE;
+ else
+ failsafe = 0;
+ }
+ }
+ else {
+ // "Outputs => Failsafe" menu item
+ setCustomFailsafe(g_moduleIdx);
+ }
+
+ storageDirty(EE_MODEL);
+ AUDIO_WARNING1();
+ SEND_FAILSAFE_NOW(g_moduleIdx);
+ }
+
+ SIMPLE_SUBMENU_NOTITLE(sentModuleChannels(g_moduleIdx) + 1);
+
+ lcdDrawTextAlignedCenter(0, FAILSAFESET);
+ lcdInvertLine(0);
+
+ const coord_t x = 1;
+ coord_t y = FH + 1;
+ uint8_t line = (menuVerticalPosition >= sentModuleChannels(g_moduleIdx) ? 2 : 0);
+ uint8_t ch = (menuVerticalPosition >= 8 ? 8 : 0) + line;
+
+ // Channels
+ for (; line < 8; line++) {
+ const int32_t channelValue = channelOutputs[ch+channelStart];
+ int32_t failsafeValue = g_model.failsafeChannels[ch];
+
+ // Channel
+ putsChn(x+1, y, ch+1, SMLSIZE);
+
+ // Value
+ LcdFlags flags = TINSIZE;
+ if (menuVerticalPosition == ch) {
+ flags |= INVERS;
+ if (s_editMode > 0) {
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ s_editMode = 0;
+ }
+ else {
+ flags |= BLINK;
+ CHECK_INCDEC_MODELVAR(event, g_model.failsafeChannels[ch], -lim, +lim);
+ }
+ }
+ }
+
+ const coord_t xValue = x+LCD_W-4-wbar;
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ lcdDrawText(xValue, y, STR_HOLD, RIGHT|flags);
+ failsafeValue = 0;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ lcdDrawText(xValue, y, STR_NONE, RIGHT|flags);
+ failsafeValue = 0;
+ }
+ else {
+#if defined(PPM_UNIT_US)
+ lcdDrawNumber(xValue, y, PPM_CH_CENTER(ch)+failsafeValue/2, RIGHT|flags);
+#elif defined(PPM_UNIT_PERCENT_PREC1)
+ lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue), RIGHT|PREC1|flags);
+#else
+ lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue)/10, RIGHT|flags);
+#endif
+ }
+
+ // Gauge
+#if !defined(PCBX7) // X7 LCD doesn't like too many horizontal lines
+ lcdDrawRect(x+LCD_W-3-wbar, y, wbar+1, 6);
+#endif
+ const uint8_t lenChannel = limit(1, (abs(channelValue) * wbar/2 + lim/2) / lim, wbar/2);
+ const uint8_t lenFailsafe = limit(1, (abs(failsafeValue) * wbar/2 + lim/2) / lim, wbar/2);
+ const coord_t xChannel = (channelValue>0) ? x+LCD_W-3-wbar/2 : x+LCD_W-2-wbar/2-lenChannel;
+ const coord_t xFailsafe = (failsafeValue>0) ? x+LCD_W-3-wbar/2 : x+LCD_W-2-wbar/2-lenFailsafe;
+ lcdDrawHorizontalLine(xChannel, y+1, lenChannel, DOTTED, 0);
+ lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
+ lcdDrawSolidHorizontalLine(xFailsafe, y+3, lenFailsafe);
+ lcdDrawSolidHorizontalLine(xFailsafe, y+4, lenFailsafe);
+
+ y += FH - 1;
+
+ if (++ch >= sentModuleChannels(g_moduleIdx))
+ break;
+ }
+
+ if (menuVerticalPosition >= sentModuleChannels(g_moduleIdx)) {
+ // Outputs => Failsafe
+ lcdDrawText(CENTER_OFS, LCD_H - (FH + 1), STR_OUTPUTS2FAILSAFE, INVERS);
+ }
+}
diff --git a/radio/src/gui/128x64/model_flightmodes.cpp b/radio/src/gui/128x64/model_flightmodes.cpp
index f6f46800b..a9dd6fa4a 100644
--- a/radio/src/gui/128x64/model_flightmodes.cpp
+++ b/radio/src/gui/128x64/model_flightmodes.cpp
@@ -39,7 +39,7 @@ enum MenuModelFlightModeItems {
IF_ROTARY_ENCODERS(ITEM_MODEL_FLIGHT_MODE_ROTARY_ENCODERS)
ITEM_MODEL_FLIGHT_MODE_FADE_IN,
ITEM_MODEL_FLIGHT_MODE_FADE_OUT,
-#if defined(GVARS) && !defined(PCBSTD)
+#if defined(GVARS)
ITEM_MODEL_FLIGHT_MODE_GVARS_LABEL,
ITEM_MODEL_FLIGHT_MODE_GV1,
ITEM_MODEL_FLIGHT_MODE_GV2,
@@ -87,7 +87,7 @@ void menuModelFlightModeOne(event_t event)
int8_t sub = menuVerticalPosition;
int8_t editMode = s_editMode;
-#if defined(GVARS) && !defined(PCBSTD)
+#if defined(GVARS)
if (s_currIdx == 0 && sub>=ITEM_MODEL_FLIGHT_MODE_SWITCH) sub += VERTICAL_SHIFT;
for (uint8_t k=0; k0) || p1valdiff)) {
+ if (attr && menuHorizontalPosition == t && editMode > 0) {
int16_t v = flightModeAddress(s_currIdx)->rotaryEncoders[t];
if (v < ROTARY_ENCODER_MAX) v = ROTARY_ENCODER_MAX;
v = checkIncDec(event, v, ROTARY_ENCODER_MAX, ROTARY_ENCODER_MAX+MAX_FLIGHT_MODES-1, EE_MODEL);
@@ -147,7 +147,7 @@ void menuModelFlightModeOne(event_t event)
fm->fadeOut = EDIT_DELAY(0, y, event, attr, STR_FADEOUT, fm->fadeOut);
break;
-#if defined(GVARS) && !defined(PCBSTD)
+#if defined(GVARS)
case ITEM_MODEL_FLIGHT_MODE_GVARS_LABEL:
lcdDrawTextAlignedLeft(y, STR_GLOBAL_VARS);
break;
@@ -175,7 +175,7 @@ void menuModelFlightModeOne(event_t event)
else {
lcdDrawText(9*FW, y, STR_OWN, posHorz==1 ? attr : 0);
}
- if (attr && s_currIdx>0 && posHorz==1 && (editMode>0 || p1valdiff)) {
+ if (attr && s_currIdx>0 && posHorz==1 && editMode > 0) {
if (v < GVAR_MAX) v = GVAR_MAX;
v = checkIncDec(event, v, GVAR_MAX, GVAR_MAX+MAX_FLIGHT_MODES-1, EE_MODEL);
if (checkIncDec_Ret) {
diff --git a/radio/src/gui/128x64/model_inputs_mixes.cpp b/radio/src/gui/128x64/model_inputs_mixes.cpp
index 6535b8821..c35954d9d 100644
--- a/radio/src/gui/128x64/model_inputs_mixes.cpp
+++ b/radio/src/gui/128x64/model_inputs_mixes.cpp
@@ -524,7 +524,6 @@ void menuModelMixOne(event_t event)
#define MIX_LINE_SWITCH_POS 16*FW
#define MIX_LINE_DELAY_POS 19*FW+7
-#if defined(NAVIGATION_MENUS)
void onExpoMixMenu(const char *result)
{
bool expo = (menuHandlers[menuLevel] == menuModelExposAll);
@@ -551,7 +550,6 @@ void onExpoMixMenu(const char *result)
deleteExpoMix(expo, s_currIdx);
}
}
-#endif
void displayMixInfos(coord_t y, MixData *md)
{
@@ -672,7 +670,6 @@ void menuModelExpoMix(uint8_t expo, event_t event)
}
else {
if (s_copyMode) s_currCh = 0;
-#if defined(NAVIGATION_MENUS)
if (s_currCh) {
if (reachExpoMixCountLimit(expo)) break;
insertExpoMix(expo, s_currIdx);
@@ -691,15 +688,6 @@ void menuModelExpoMix(uint8_t expo, event_t event)
POPUP_MENU_ADD_ITEM(STR_DELETE);
POPUP_MENU_START(onExpoMixMenu);
}
-#else
- if (s_currCh) {
- if (reachExpoMixCountLimit(expo)) break;
- insertExpoMix(expo, s_currIdx);
- }
- pushMenu(expo ? menuModelExpoOne : menuModelMixOne);
- s_copyMode = 0;
- return;
-#endif
}
}
break;
diff --git a/radio/src/gui/128x64/model_logical_switches.cpp b/radio/src/gui/128x64/model_logical_switches.cpp
index 0d2303bfe..d8cf78c47 100644
--- a/radio/src/gui/128x64/model_logical_switches.cpp
+++ b/radio/src/gui/128x64/model_logical_switches.cpp
@@ -234,8 +234,7 @@ void onLogicalSwitchesMenu(const char *result)
s_currIdx = sub;
pushMenu(menuModelLogicalSwitchOne);
}
-
- if (result == STR_COPY) {
+ else if (result == STR_COPY) {
clipboard.type = CLIPBOARD_TYPE_CUSTOM_SWITCH;
clipboard.data.csw = *cs;
}
@@ -269,8 +268,8 @@ void menuModelLogicalSwitches(event_t event)
POPUP_MENU_ADD_ITEM(STR_PASTE);
if (cs->func || cs->v1 || cs->v2 || cs->delay || cs->duration || cs->andsw)
POPUP_MENU_ADD_ITEM(STR_CLEAR);
- if(popupMenuNoItems == 1) {
- popupMenuNoItems = 0;
+ if(popupMenuItemsCount == 1) {
+ popupMenuItemsCount = 0;
s_currIdx = sub;
pushMenu(menuModelLogicalSwitchOne);
}
diff --git a/radio/src/gui/128x64/model_module_options.cpp b/radio/src/gui/128x64/model_module_options.cpp
new file mode 100644
index 000000000..cc2dec0af
--- /dev/null
+++ b/radio/src/gui/128x64/model_module_options.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+#include
+
+#define RECEIVER_OPTIONS_2ND_COLUMN (11*FW)
+
+extern uint8_t g_moduleIdx;
+
+void onTxOptionsUpdateConfirm(const char * result)
+{
+ if (result == STR_OK) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.state = PXX2_SETTINGS_WRITE;
+ reusableBuffer.hardwareAndSettings.moduleSettings.dirty = 2;
+ reusableBuffer.hardwareAndSettings.moduleSettings.timeout = 0;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_MODULE_SETTINGS;
+ }
+ else {
+ popMenu();
+ }
+}
+
+enum {
+ ITEM_MODULE_SETTINGS_RF_PROTOCOL,
+ ITEM_MODULE_SETTINGS_EXTERNAL_ANTENNA,
+ ITEM_MODULE_SETTINGS_POWER,
+ ITEM_MODULE_SETTINGS_COUNT
+};
+
+/* Options order:
+ * - RF Protocol
+ * - External antenna
+ * - Power
+ */
+const uint8_t moduleOptions[] = {
+ 0b11111111, // None = display all options
+ 0b11111011, // XJT
+ 0b11111011, // IXJT
+ 0b11111011, // IXJT-PRO
+ 0b11111011, // IXJT-S
+ 0b11111100, // R9M
+ 0b11111100, // R9MLite
+ 0b11111100, // R9MLite-PRO
+};
+
+#define IF_MODULE_OPTIONS(option, count) uint8_t((moduleOptions[modelId] & (1 << option)) ? count : HIDDEN_ROW)
+
+void drawPower(coord_t x, coord_t y, int8_t dBm)
+{
+ float power_W_PREC1 = pow(10.0, (dBm - 30.0) / 10.0) * 10;
+ if (dBm >= 30) {
+ lcdDrawNumber(x, y, power_W_PREC1, PREC1);
+ lcdDrawText(lcdNextPos, y, "W");
+ }
+ else if (dBm < 10) {
+ uint16_t power_MW_PREC1 = round(power_W_PREC1 * 1000);
+ lcdDrawNumber(x, y, power_MW_PREC1, PREC1);
+ lcdDrawText(lcdNextPos, y, "mW");
+ }
+ else {
+ uint16_t power_MW = round(power_W_PREC1 * 100);
+ if (power_MW >= 50) {
+ power_MW = (power_MW / 5) * 5;
+ lcdDrawNumber(x, y, power_MW);
+ lcdDrawText(lcdNextPos, y, "mW");
+ }
+ else {
+ lcdDrawNumber(x, y, power_MW);
+ lcdDrawText(lcdNextPos, y, "mW");
+ }
+ }
+}
+
+bool isPowerAvailable(int value)
+{
+// uint8_t modelId = reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].information.modelID;
+// uint8_t variant = reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].information.variant;
+
+ return (value == 10 /* 10 mW */ ||
+ value == 14 /* 25 mW */ ||
+ value == 20 /* 100 mW */ ||
+ value == 23 /* 200 mW */ ||
+ value == 27 /* 500 mW */ ||
+ value == 30 /* 1000 mW */);
+}
+
+void menuModelModuleOptions(event_t event)
+{
+ uint8_t modelId = reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].information.modelID;
+ // uint8_t variant = reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].information.variant;
+
+ SUBMENU_NOTITLE(ITEM_MODULE_SETTINGS_COUNT, {
+ IF_MODULE_OPTIONS(0, 0),
+ IF_MODULE_OPTIONS(1, 0),
+ IF_MODULE_OPTIONS(2, 0),
+ });
+
+ if (event == EVT_ENTRY) {
+#if defined(SIMU)
+ reusableBuffer.hardwareAndSettings.moduleSettings.state = PXX2_SETTINGS_OK;
+#else
+ // no need to initialize reusableBuffer.hardwareAndSettings.moduleSettings.state to PXX2_HARDWARE_INFO
+ reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].current = PXX2_HW_INFO_TX_ID;
+ reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].maximum = PXX2_HW_INFO_TX_ID;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_GET_HARDWARE_INFO;
+#endif
+ }
+
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.state == PXX2_HARDWARE_INFO && moduleSettings[g_moduleIdx].mode == MODULE_MODE_NORMAL) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.state = PXX2_SETTINGS_READ;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_MODULE_SETTINGS;
+ }
+
+ if (menuEvent) {
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_NORMAL;
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.dirty) {
+ abortPopMenu();
+ POPUP_CONFIRMATION("Update TX options?", onTxOptionsUpdateConfirm);
+ }
+ else {
+ return;
+ }
+ }
+
+ if (event == EVT_KEY_LONG(KEY_ENTER) && reusableBuffer.hardwareAndSettings.moduleSettings.dirty) {
+ killEvents(event);
+ reusableBuffer.hardwareAndSettings.moduleSettings.state = PXX2_SETTINGS_WRITE;
+ reusableBuffer.hardwareAndSettings.moduleSettings.dirty = 0;
+ reusableBuffer.hardwareAndSettings.moduleSettings.timeout = 0;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_MODULE_SETTINGS;
+ }
+
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.dirty == 2 && reusableBuffer.hardwareAndSettings.moduleSettings.state == PXX2_SETTINGS_OK) {
+ popMenu();
+ }
+
+ if (modelId != 0 && mstate_tab[menuVerticalPosition] == HIDDEN_ROW) {
+ menuVerticalPosition = 0;
+ while (menuVerticalPosition < ITEM_MODULE_SETTINGS_COUNT && mstate_tab[menuVerticalPosition] == HIDDEN_ROW) {
+ ++menuVerticalPosition;
+ }
+ }
+
+ int8_t sub = menuVerticalPosition;
+ lcdDrawTextAlignedLeft(0, "Module options");
+ lcdInvertLine(0);
+
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.state == PXX2_SETTINGS_OK) {
+ for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0);
+
+ switch (i) {
+ case ITEM_MODULE_SETTINGS_RF_PROTOCOL:
+ lcdDrawText(0, y, "RF Protocol");
+ lcdDrawTextAtIndex(RECEIVER_OPTIONS_2ND_COLUMN, y, STR_XJT_PROTOCOLS, reusableBuffer.hardwareAndSettings.moduleSettings.rfProtocol + 1, attr);
+ if (attr) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.rfProtocol = checkIncDec(event, reusableBuffer.hardwareAndSettings.moduleSettings.rfProtocol, RF_PROTO_X16, RF_PROTO_LAST, 0, nullptr);
+ if (checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.dirty = true;
+ }
+ }
+ break;
+
+ case ITEM_MODULE_SETTINGS_EXTERNAL_ANTENNA:
+ reusableBuffer.hardwareAndSettings.moduleSettings.externalAntenna = editCheckBox(reusableBuffer.hardwareAndSettings.moduleSettings.externalAntenna, RECEIVER_OPTIONS_2ND_COLUMN, y, "Ext. antenna", attr, event);
+ if (attr && checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.dirty = true;
+ }
+ break;
+
+ case ITEM_MODULE_SETTINGS_POWER:
+ lcdDrawText(0, y, "Power");
+ lcdDrawNumber(RECEIVER_OPTIONS_2ND_COLUMN, y, reusableBuffer.hardwareAndSettings.moduleSettings.txPower, attr);
+ lcdDrawText(lcdNextPos, y, "dBm(");
+ drawPower(lcdNextPos, y, reusableBuffer.hardwareAndSettings.moduleSettings.txPower);
+ lcdDrawText(lcdNextPos, y, ")");
+ if (attr) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.txPower = checkIncDec(event, reusableBuffer.hardwareAndSettings.moduleSettings.txPower, 0, 30, 0, &isPowerAvailable);
+ if (checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.moduleSettings.dirty = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else {
+ lcdDrawText(4 * FW, 4 * FH, "Waiting for TX...");
+ }
+}
diff --git a/radio/src/gui/128x64/model_outputs_arm.cpp b/radio/src/gui/128x64/model_outputs_arm.cpp
index e3e27b387..2e1437240 100644
--- a/radio/src/gui/128x64/model_outputs_arm.cpp
+++ b/radio/src/gui/128x64/model_outputs_arm.cpp
@@ -113,7 +113,7 @@ void menuModelLimitsOne(event_t event)
coord_t y = MENU_HEADER_HEIGHT + 1 + k*FH;
uint8_t i = k + menuVerticalOffset;
uint8_t attr = (sub==i ? (s_editMode>0 ? BLINK|INVERS : INVERS) : 0);
- uint8_t active = (attr && (s_editMode>0 || p1valdiff)) ;
+ uint8_t active = (attr && s_editMode > 0) ;
int limit = (g_model.extendedLimits ? LIMIT_EXT_MAX : 1000);
switch (i) {
diff --git a/radio/src/gui/128x64/model_receiver_options.cpp b/radio/src/gui/128x64/model_receiver_options.cpp
new file mode 100644
index 000000000..24cddfe01
--- /dev/null
+++ b/radio/src/gui/128x64/model_receiver_options.cpp
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+
+#define RECEIVER_OPTIONS_2ND_COLUMN 80
+
+extern uint8_t g_moduleIdx;
+extern void drawReceiverName(uint8_t x, uint8_t y, uint8_t receiverSlot);
+
+void onRxOptionsUpdateConfirm(const char * result)
+{
+ if (result == STR_OK) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.state = PXX2_SETTINGS_WRITE;
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = 2;
+ reusableBuffer.hardwareAndSettings.receiverSettings.timeout = 0;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_RECEIVER_SETTINGS;
+ }
+ else {
+ popMenu();
+ }
+}
+
+enum {
+ ITEM_RECEIVER_TELEMETRY,
+ ITEM_RECEIVER_PWM_RATE,
+ ITEM_RECEIVER_PINMAP_FIRST
+};
+
+void menuModelReceiverOptions(event_t event)
+{
+ const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
+ uint8_t wbar = LCD_W / 2 - 20;
+ auto outputsCount = min(16, reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount);
+
+ SIMPLE_SUBMENU_NOTITLE(ITEM_RECEIVER_PINMAP_FIRST + outputsCount);
+
+ if (event == EVT_ENTRY) {
+#if defined(SIMU)
+ reusableBuffer.hardwareAndSettings.receiverSettings.state = PXX2_SETTINGS_OK;
+ reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount = 8;
+#else
+ // no need to initialize reusableBuffer.hardwareAndSettings.receiverSettings.state to PXX2_HARDWARE_INFO
+ reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].current = reusableBuffer.hardwareAndSettings.receiverSettings.receiverId;
+ reusableBuffer.hardwareAndSettings.modules[g_moduleIdx].maximum = reusableBuffer.hardwareAndSettings.receiverSettings.receiverId;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_GET_HARDWARE_INFO;
+#endif
+ }
+
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.state == PXX2_HARDWARE_INFO && moduleSettings[g_moduleIdx].mode == MODULE_MODE_NORMAL) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.state = PXX2_SETTINGS_READ;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_RECEIVER_SETTINGS;
+ }
+
+ if (menuEvent) {
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_NORMAL;
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.dirty) {
+ abortPopMenu();
+ POPUP_CONFIRMATION("Update RX options?", onRxOptionsUpdateConfirm);
+ }
+ else {
+ return;
+ }
+ }
+
+ if (event == EVT_KEY_LONG(KEY_ENTER) && reusableBuffer.hardwareAndSettings.receiverSettings.dirty) {
+ killEvents(event);
+ reusableBuffer.hardwareAndSettings.receiverSettings.state = PXX2_SETTINGS_WRITE;
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = 0;
+ reusableBuffer.hardwareAndSettings.receiverSettings.timeout = 0;
+ moduleSettings[g_moduleIdx].mode = MODULE_MODE_RECEIVER_SETTINGS;
+ }
+
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.dirty == 2 && reusableBuffer.hardwareAndSettings.receiverSettings.state == PXX2_SETTINGS_OK) {
+ popMenu();
+ return;
+ }
+
+ int8_t sub = menuVerticalPosition;
+ lcdDrawTextAlignedLeft(0, STR_RECEIVER_OPTIONS);
+ drawReceiverName(FW * 13, 0, reusableBuffer.hardwareAndSettings.receiverSettings.receiverId);
+ lcdInvertLine(0);
+
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.state == PXX2_SETTINGS_OK) {
+ for (uint8_t k=0; k0 ? BLINK|INVERS : INVERS) : 0);
+
+ switch (i) {
+ case ITEM_RECEIVER_TELEMETRY:
+ reusableBuffer.hardwareAndSettings.receiverSettings.telemetryDisabled = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.telemetryDisabled, RECEIVER_OPTIONS_2ND_COLUMN, y, "Telem. disabled", attr, event);
+ if (attr && checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = true;
+ }
+ break;
+
+ case ITEM_RECEIVER_PWM_RATE:
+ reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate = editCheckBox(reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate, RECEIVER_OPTIONS_2ND_COLUMN, y, "9ms PWM", attr, event);
+ if (attr && checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = true;
+ }
+ break;
+
+ default:
+ // Pin
+ {
+ uint8_t pin = i - ITEM_RECEIVER_PINMAP_FIRST;
+ uint8_t channel = reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin];
+ int32_t channelValue = channelOutputs[channel];
+ lcdDrawText(0, y, "Pin");
+ lcdDrawNumber(lcdLastRightPos + 1, y, pin + 1);
+ putsChn(7 * FW, y, channel + 1, attr);
+
+ // Channel
+ if (attr) {
+ channel = checkIncDec(event, channel, 0, sentModuleChannels(g_moduleIdx) - 1);
+ if (checkIncDec_Ret) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin] = channel;
+ reusableBuffer.hardwareAndSettings.receiverSettings.dirty = true;
+ }
+ }
+
+ // Bargraph
+#if !defined(PCBX7) // X7 LCD doesn't like too many horizontal lines
+ lcdDrawRect(LCD_W - 3 - wbar, y + 1, wbar + 1, 4);
+#endif
+ const uint8_t lenChannel = limit(1, (abs(channelValue) * wbar / 2 + lim / 2) / lim, wbar / 2);
+ const coord_t xChannel = (channelValue > 0) ? LCD_W - 3 - wbar / 2 : LCD_W - 2 - wbar / 2 - lenChannel;
+ lcdDrawHorizontalLine(xChannel, y + 2, lenChannel, SOLID, 0);
+ lcdDrawHorizontalLine(xChannel, y + 3, lenChannel, SOLID, 0);
+ break;
+ }
+ }
+ }
+ }
+ else {
+ lcdDrawText(4 * FW, 4 * FH, "Waiting for RX...");
+ }
+}
diff --git a/radio/src/gui/128x64/model_select.cpp b/radio/src/gui/128x64/model_select.cpp
index e91a3a53b..8b7aa6b33 100644
--- a/radio/src/gui/128x64/model_select.cpp
+++ b/radio/src/gui/128x64/model_select.cpp
@@ -22,7 +22,6 @@
#define MODELSEL_W LCD_W
-#if defined(NAVIGATION_MENUS)
void onModelSelectMenu(const char * result)
{
int8_t sub = menuVerticalPosition;
@@ -53,11 +52,11 @@ void onModelSelectMenu(const char * result)
}
#endif
else if (result == STR_DELETE_MODEL) {
- POPUP_CONFIRMATION(STR_DELETEMODEL);
+ POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr);
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
}
#if defined(SDCARD)
- else {
+ else if (result != STR_EXIT) {
// The user choosed a file on SD to restore
storageCheck(true);
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
@@ -67,7 +66,6 @@ void onModelSelectMenu(const char * result)
}
#endif
}
-#endif
void menuModelSelect(event_t event)
{
@@ -89,12 +87,6 @@ void menuModelSelect(event_t event)
check_submenu_simple(_event_, MAX_MODELS - HEADER_LINE);
-#if defined(NAVIGATION_POT2)
- if (event==0 && p2valdiff<0) {
- event = EVT_KEY_FIRST(KEY_RIGHT);
- }
-#endif
-
if (s_editMode > 0) s_editMode = 0;
@@ -112,7 +104,7 @@ void menuModelSelect(event_t event)
case EVT_KEY_LONG(KEY_EXIT):
killEvents(event);
if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) {
- POPUP_CONFIRMATION(STR_DELETEMODEL);
+ POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr);
SET_WARNING_INFO(modelHeaders[sub].name, sizeof(g_model.header.name), ZCHAR);
}
else {
@@ -200,7 +192,6 @@ void menuModelSelect(event_t event)
else if (event == EVT_KEY_LONG(KEY_ENTER) || IS_ROTARY_BREAK(event)) {
s_copyMode = 0;
killEvents(event);
-#if defined(NAVIGATION_MENUS)
if (g_eeGeneral.currModel != sub) {
if (eeModelExists(sub)) {
POPUP_MENU_ADD_ITEM(STR_SELECT_MODEL);
@@ -224,11 +215,6 @@ void menuModelSelect(event_t event)
POPUP_MENU_ADD_ITEM(STR_MOVE_MODEL);
}
POPUP_MENU_START(onModelSelectMenu);
-#else
- if (g_eeGeneral.currModel != sub) {
- selectModel(sub);
- }
-#endif
}
else if (eeModelExists(sub)) {
s_copyMode = (s_copyMode == COPY_MODE ? MOVE_MODE : COPY_MODE);
@@ -237,7 +223,7 @@ void menuModelSelect(event_t event)
}
break;
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
case EVT_KEY_LONG(KEY_PAGE):
chainMenu(menuTabModel[DIM(menuTabModel)-1]);
killEvents(event);
@@ -269,7 +255,7 @@ void menuModelSelect(event_t event)
#endif
#endif
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
case EVT_ROTARY_LEFT:
case EVT_ROTARY_RIGHT:
#endif
@@ -310,7 +296,7 @@ void menuModelSelect(event_t event)
lcdDrawNumber(17*FW, 0, reusableBuffer.modelsel.eepromfree, RIGHT);
#endif
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
drawScreenIndex(MENU_MODEL_SELECT, DIM(menuTabModel), 0);
#elif defined(ROTARY_ENCODER_NAVIGATION)
drawScreenIndex(MENU_MODEL_SELECT, DIM(menuTabModel), (sub == g_eeGeneral.currModel) ? ((IS_ROTARY_ENCODER_NAVIGATION_ENABLE() && s_editMode < 0) ? INVERS|BLINK : INVERS) : 0);
diff --git a/radio/src/gui/128x64/model_setup.cpp b/radio/src/gui/128x64/model_setup.cpp
index 6b2298f09..e26dd2cc9 100644
--- a/radio/src/gui/128x64/model_setup.cpp
+++ b/radio/src/gui/128x64/model_setup.cpp
@@ -18,10 +18,25 @@
* GNU General Public License for more details.
*/
-#include "opentx.h"
+#include
+// TODO find why we need this (for REGISTER at least)
+#if defined(PCBXLITE)
+ #define EVT_BUTTON_PRESSED() EVT_KEY_FIRST(KEY_ENTER)
+#else
+ #define EVT_BUTTON_PRESSED() EVT_KEY_BREAK(KEY_ENTER)
+#endif
+
+// TODO can be moved to reusableBuffer
uint8_t g_moduleIdx;
-void menuModelFailsafe(event_t event);
+
+void drawReceiverName(uint8_t x, uint8_t y, uint8_t receiverSlot)
+{
+ if (g_model.receiverData[receiverSlot].name[0] != '\0')
+ lcdDrawSizedText(x, y, g_model.receiverData[receiverSlot].name, PXX2_LEN_RX_NAME);
+ else
+ lcdDrawText(x, y, "---");
+}
#if defined(PCBTARANIS)
uint8_t getSwitchWarningsCount()
@@ -70,15 +85,28 @@ enum MenuModelSetupItems {
#endif
ITEM_MODEL_BEEP_CENTER,
ITEM_MODEL_USE_GLOBAL_FUNCTIONS,
+ ITEM_MODEL_REGISTRATION_ID,
#if defined(PCBTARANIS)
ITEM_MODEL_INTERNAL_MODULE_LABEL,
ITEM_MODEL_INTERNAL_MODULE_MODE,
ITEM_MODEL_INTERNAL_MODULE_CHANNELS,
- ITEM_MODEL_INTERNAL_MODULE_BIND,
- ITEM_MODEL_INTERNAL_MODULE_FAILSAFE,
-#if defined(PCBXLITE)
+ ITEM_MODEL_INTERNAL_MODULE_NPXX2_BIND,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_MODEL_NUM,
+#if defined(EXTERNAL_ANTENNA)
ITEM_MODEL_INTERNAL_MODULE_ANTENNA,
#endif
+ ITEM_MODEL_INTERNAL_MODULE_FAILSAFE,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_REGISTER_RANGE,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_OPTIONS,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_LABEL,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_OPTIONS,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_BIND_SHARE,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_LABEL,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_OPTIONS,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_BIND_SHARE,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_LABEL,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_OPTIONS,
+ ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_BIND_SHARE,
#endif
ITEM_MODEL_EXTERNAL_MODULE_LABEL,
ITEM_MODEL_EXTERNAL_MODULE_MODE,
@@ -88,7 +116,8 @@ enum MenuModelSetupItems {
ITEM_MODEL_EXTERNAL_MODULE_SYNCSTATUS,
#endif
ITEM_MODEL_EXTERNAL_MODULE_CHANNELS,
- ITEM_MODEL_EXTERNAL_MODULE_BIND,
+ ITEM_MODEL_EXTERNAL_MODULE_NPXX2_BIND,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_MODEL_NUM,
#if defined(PCBSKY9X) && defined(REVX)
ITEM_MODEL_EXTERNAL_MODULE_OUTPUT_TYPE,
#endif
@@ -97,18 +126,32 @@ enum MenuModelSetupItems {
ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND,
#endif
ITEM_MODEL_EXTERNAL_MODULE_POWER,
+#if !defined(PCBXLITE)
+ ITEM_MODEL_EXTERNAL_MODULE_FREQ,
+#endif
+ ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_REGISTER_RANGE,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_OPTIONS,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_LABEL,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_OPTIONS,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_BIND_SHARE,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_LABEL,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_OPTIONS,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_BIND_SHARE,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_LABEL,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_OPTIONS,
+ ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_BIND_SHARE,
#if defined(PCBSKY9X) && !defined(REVA)
ITEM_MODEL_EXTRA_MODULE_LABEL,
ITEM_MODEL_EXTRA_MODULE_CHANNELS,
ITEM_MODEL_EXTRA_MODULE_BIND,
#endif
- ITEM_MODEL_EXTERNAL_MODULE_FAILSAFE,
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
ITEM_MODEL_TRAINER_LABEL,
ITEM_MODEL_TRAINER_MODE,
-#if defined(BLUETOOTH)
- ITEM_MODEL_TRAINER_BLUETOOTH,
-#endif
+ #if defined(BLUETOOTH)
+ ITEM_MODEL_TRAINER_BLUETOOTH,
+ #endif
ITEM_MODEL_TRAINER_CHANNELS,
ITEM_MODEL_TRAINER_PARAMS,
#elif defined(PCBXLITE)
@@ -116,6 +159,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_TRAINER_MODE,
ITEM_MODEL_TRAINER_BLUETOOTH,
ITEM_MODEL_TRAINER_CHANNELS,
+ ITEM_MODEL_TRAINER_PARAMS,
#endif
ITEM_MODEL_SETUP_MAX
};
@@ -131,10 +175,15 @@ enum MenuModelSetupItems {
#define MODEL_SETUP_RANGE_OFS 4*FW+3
#define MODEL_SETUP_SET_FAILSAFE_OFS 7*FW-2
+#define IF_PXX2_MODULE(module, xxx) (isModulePXX2(module) ? (uint8_t)(xxx) : HIDDEN_ROW)
+#define IF_NOT_PXX2_MODULE(module, xxx) (isModulePXX2(module) ? HIDDEN_ROW : (uint8_t)(xxx))
+#define IF_PXX2_RECEIVER_DISPLAYED(module, idx, xxx) ((isModulePXX2(module) && g_model.moduleData[module].pxx2.getReceiverSlot(idx)) ? (uint8_t)(xxx) : HIDDEN_ROW)
+
#if defined(PCBTARANIS)
- #define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE))
+ #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE)
+ #define CURRENT_RECEIVER_EDITED(k) ((k - (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_LABEL : ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_LABEL)) / (ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_LABEL - ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_LABEL))
#elif defined(PCBSKY9X) && !defined(REVA)
- #define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_EXTRA_MODULE_LABEL ? EXTRA_MODULE : EXTERNAL_MODULE)
+ #define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_EXTRA_MODULE_LABEL ? EXTRA_MODULE : EXTERNAL_MODULE)
#else
#define CURRENT_MODULE_EDITED(k) (EXTERNAL_MODULE)
#endif
@@ -144,59 +193,89 @@ enum MenuModelSetupItems {
#else
#define SW_WARN_ROWS uint8_t(NAVIGATION_LINE_BY_LINE|(getSwitchWarningsCount()-1)), uint8_t(getSwitchWarningsCount() > 5 ? TITLE_ROW : HIDDEN_ROW)
#endif
-#if !defined(TARANIS_INTERNAL_PPM)
- #define INTERNAL_MODULE_MODE_ROWS 0 // (OFF / RF protocols)
-#else
+
+#if defined(TARANIS_INTERNAL_PPM)
#define INTERNAL_MODULE_MODE_ROWS (isModuleXJT(INTERNAL_MODULE) ? (uint8_t)1 : (uint8_t)0) // Module type + RF protocols
+#else
+ #define INTERNAL_MODULE_MODE_ROWS 0 // (OFF / RF protocols)
#endif
- #define IF_INTERNAL_MODULE_ON(x) (IS_INTERNAL_MODULE_ENABLED()? (uint8_t)(x) : HIDDEN_ROW )
- #define IF_EXTERNAL_MODULE_ON(x) (IS_EXTERNAL_MODULE_ENABLED()? (uint8_t)(x) : HIDDEN_ROW)
- #define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1)
- #define EXTERNAL_MODULE_BIND_ROWS() ((isModuleXJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) || isModuleSBUS(EXTERNAL_MODULE)) ? (uint8_t)1 : (isModulePPM(EXTERNAL_MODULE) || isModulePXX(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW
+
+#define IF_INTERNAL_MODULE_ON(x) (IS_INTERNAL_MODULE_ENABLED()? (uint8_t)(x) : HIDDEN_ROW)
+#define IF_EXTERNAL_MODULE_ON(x) (IS_EXTERNAL_MODULE_ENABLED()? (uint8_t)(x) : HIDDEN_ROW)
+#define EXTERNAL_MODULE_BIND_ROWS() ((isModuleXJT(EXTERNAL_MODULE) && IS_D8_RX(EXTERNAL_MODULE)) || isModuleSBUS(EXTERNAL_MODULE)) ? (uint8_t)1 : (isModulePPM(EXTERNAL_MODULE) || isModulePXX(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)2 : HIDDEN_ROW
#if defined(PCBSKY9X) && defined(REVX)
#define OUTPUT_TYPE_ROWS() (isModulePPM(EXTERNAL_MODULE) ? (uint8_t)0 : HIDDEN_ROW) ,
#else
#define OUTPUT_TYPE_ROWS()
#endif
- #define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 0)
+#define PORT_CHANNELS_ROWS(x) (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 0)
+
+#if defined(PCBXLITE)
#define EXTERNAL_MODULE_MODE_ROWS (isModulePXX(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0
+ #define EXTERNAL_MODULE_FREQ_ROW
+#else
+ #define EXTERNAL_MODULE_MODE_ROWS (isModuleXJT(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0
+ #define EXTERNAL_MODULE_FREQ_ROW isR9MMFlex(EXTERNAL_MODULE) ? (uint8_t)1: (uint8_t)HIDDEN_ROW,
+#endif
+
+#define CURSOR_ON_CELL (true)
+#define MODEL_SETUP_MAX_LINES (HEADER_LINE+ITEM_MODEL_SETUP_MAX)
+#define POT_WARN_ITEMS() ((g_model.potsWarnMode) ? (uint8_t)(NUM_POTS+NUM_SLIDERS) : (uint8_t)0)
+#define TIMER_ROWS 2, 0, 0, 0, 0
- #define CURSOR_ON_CELL (true)
- #define MODEL_SETUP_MAX_LINES (HEADER_LINE+ITEM_MODEL_SETUP_MAX)
- #define POT_WARN_ITEMS() ((g_model.potsWarnMode) ? (uint8_t)(NUM_POTS+NUM_SLIDERS) : (uint8_t)0)
- #define TIMER_ROWS 2, 0, 0, 0, 0
#if defined(PCBSKY9X) && !defined(REVA)
#define EXTRA_MODULE_ROWS LABEL(ExtraModule), 1, 2,
#else
#define EXTRA_MODULE_ROWS
#endif
-#if defined(PCBX7)
-#define ANTENNA_ROW
-#if defined(BLUETOOTH)
- #define TRAINER_BLUETOOTH_M_ROW ((bluetoothDistantAddr[0] == '\0' || bluetoothState == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
- #define TRAINER_BLUETOOTH_S_ROW (bluetoothDistantAddr[0] == '\0' ? HIDDEN_ROW : LABEL())
- #define TRAINER_BLUETOOTH_ROW (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW)),
-#else
- #define TRAINER_BLUETOOTH_ROW
-#endif
-#define TRAINER_CHANNELS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)1 : HIDDEN_ROW)
-#define TRAINER_PARAMS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)2 : HIDDEN_ROW)
-#define TRAINER_ROWS LABEL(Trainer), 0, TRAINER_BLUETOOTH_ROW TRAINER_CHANNELS_ROW, TRAINER_PARAMS_ROW
-#elif defined(PCBXLITE)
- #define ANTENNA_ROW IF_INTERNAL_MODULE_ON(0),
+#if defined(PCBX7) || defined(PCBX3)
+ #define ANTENNA_ROW
+ #if defined(BLUETOOTH)
+ #define TRAINER_BLUETOOTH_M_ROW ((bluetoothDistantAddr[0] == '\0' || bluetoothState == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
+ #define TRAINER_BLUETOOTH_S_ROW (bluetoothDistantAddr[0] == '\0' ? HIDDEN_ROW : LABEL())
+ #define TRAINER_BLUETOOTH_ROW (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW)),
+ #else
+ #define TRAINER_BLUETOOTH_ROW
+ #endif
+ #define TRAINER_CHANNELS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)1 : HIDDEN_ROW)
+ #define TRAINER_PARAMS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)2 : HIDDEN_ROW)
+ #define TRAINER_ROWS LABEL(Trainer), 0, TRAINER_BLUETOOTH_ROW TRAINER_CHANNELS_ROW, TRAINER_PARAMS_ROW
+#elif defined(PCBXLITES)
+ #define ANTENNA_ROW IF_NOT_PXX2_MODULE(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(0)),
#define IF_BT_TRAINER_ON(x) (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER ? (uint8_t)(x) : HIDDEN_ROW)
#define TRAINER_BLUETOOTH_M_ROW ((bluetoothDistantAddr[0] == '\0' || bluetoothState == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
#define TRAINER_BLUETOOTH_S_ROW (bluetoothDistantAddr[0] == '\0' ? HIDDEN_ROW : LABEL())
- #define TRAINER_BLUETOOTH_ROW (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW))
+ #define TRAINER_BLUETOOTH_ROW (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW))
+ #define TRAINER_CHANNELS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)1 : HIDDEN_ROW)
+ #define TRAINER_PARAMS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)2 : HIDDEN_ROW)
+ #define TRAINER_ROWS LABEL(Trainer), 0, IF_BT_TRAINER_ON(TRAINER_BLUETOOTH_ROW), TRAINER_CHANNELS_ROW, TRAINER_PARAMS_ROW
+#elif defined(PCBXLITE)
+ #define ANTENNA_ROW IF_NOT_PXX2_MODULE(INTERNAL_MODULE, IF_INTERNAL_MODULE_ON(0)),
+ #define IF_BT_TRAINER_ON(x) (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER ? (uint8_t)(x) : HIDDEN_ROW)
+ #define TRAINER_BLUETOOTH_M_ROW ((bluetoothDistantAddr[0] == '\0' || bluetoothState == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
+ #define TRAINER_BLUETOOTH_S_ROW (bluetoothDistantAddr[0] == '\0' ? HIDDEN_ROW : LABEL())
+ #define TRAINER_BLUETOOTH_ROW (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_BLUETOOTH_M_ROW : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? TRAINER_BLUETOOTH_S_ROW : HIDDEN_ROW))
#define TRAINER_CHANNELS_ROW (IS_SLAVE_TRAINER() ? (uint8_t)1 : HIDDEN_ROW)
#define TRAINER_ROWS IF_BT_TRAINER_ON(LABEL(Trainer)), IF_BT_TRAINER_ON(0), IF_BT_TRAINER_ON(TRAINER_BLUETOOTH_ROW), IF_BT_TRAINER_ON(TRAINER_CHANNELS_ROW)
#else
#define TRAINER_ROWS
#endif
+void onPXX2BindMenu(const char * result)
+{
+ if (result != STR_EXIT) {
+ reusableBuffer.moduleSetup.pxx2.bindSelectedReceiverIndex = (result - reusableBuffer.moduleSetup.pxx2.bindCandidateReceiversNames[0]) / sizeof(reusableBuffer.moduleSetup.pxx2.bindCandidateReceiversNames[0]);
+ reusableBuffer.moduleSetup.pxx2.bindStep = BIND_RX_NAME_SELECTED;
+ }
+ else {
+ // the user pressed [Exit]
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(menuVerticalPosition);
+ moduleSettings[moduleIdx].mode = MODULE_MODE_NORMAL;
+ }
+}
void onBindMenu(const char * result)
{
@@ -222,13 +301,116 @@ void onBindMenu(const char * result)
return;
}
- moduleFlag[moduleIdx] = MODULE_BIND;
+ moduleSettings[moduleIdx].mode = MODULE_MODE_BIND;
}
+enum PopupRegisterItems {
+ ITEM_REGISTER_PASSWORD,
+ ITEM_REGISTER_MODULE_INDEX,
+ ITEM_REGISTER_RECEIVER_NAME,
+ ITEM_REGISTER_BUTTONS
+};
+
+void runPopupRegister(event_t event)
+{
+ uint8_t backupVerticalPosition = menuVerticalPosition;
+ uint8_t backupHorizontalPosition = menuHorizontalPosition;
+ uint8_t backupVerticalOffset = menuVerticalOffset;
+ int8_t backupEditMode = s_editMode;
+
+ menuVerticalPosition = reusableBuffer.moduleSetup.pxx2.registerPopupVerticalPosition;
+ menuHorizontalPosition = reusableBuffer.moduleSetup.pxx2.registerPopupHorizontalPosition;
+ s_editMode = reusableBuffer.moduleSetup.pxx2.registerPopupEditMode;
+
+ switch (event) {
+ case EVT_KEY_BREAK(KEY_ENTER):
+ if (menuVerticalPosition != ITEM_REGISTER_BUTTONS) {
+ break;
+ }
+ else if (reusableBuffer.moduleSetup.pxx2.registerStep >= REGISTER_RX_NAME_RECEIVED && menuHorizontalPosition == 0) {
+ // [Enter] pressed
+ reusableBuffer.moduleSetup.pxx2.registerStep = REGISTER_RX_NAME_SELECTED;
+ backupEditMode = EDIT_MODIFY_FIELD; // so that the [Register] button blinks and the REGISTER process can continue
+ }
+ // no break
+
+ case EVT_KEY_LONG(KEY_EXIT):
+ s_editMode = 0;
+ // no break;
+
+ case EVT_KEY_BREAK(KEY_EXIT):
+ if (s_editMode <= 0) {
+ warningText = nullptr;
+ }
+ break;
+ }
+
+ if (warningText) {
+ const uint8_t dialogRows[] = { 0, 0, uint8_t(reusableBuffer.moduleSetup.pxx2.registerStep < REGISTER_RX_NAME_RECEIVED ? READONLY_ROW : 0), uint8_t(reusableBuffer.moduleSetup.pxx2.registerStep < REGISTER_RX_NAME_RECEIVED ? 0 : 1)};
+ check(event, 0, nullptr, 0, dialogRows, 3, 4 - HEADER_LINE); // TODO add a comment for 3 - HEADER_LINE once understood
+
+ drawMessageBox(warningText);
+
+ // registration password
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y - 4, STR_REG_ID);
+ editName(WARNING_LINE_X + 8*FW, WARNING_LINE_Y - 4, g_model.modelRegistrationID, PXX2_LEN_REGISTRATION_ID, event, menuVerticalPosition == ITEM_REGISTER_PASSWORD);
+
+ // module index
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y - 4 + FH, "UID");
+ lcdDrawNumber(WARNING_LINE_X + 8*FW, WARNING_LINE_Y - 4 + FH, reusableBuffer.moduleSetup.pxx2.registerModuleIndex, menuVerticalPosition == ITEM_REGISTER_MODULE_INDEX ? (s_editMode ? INVERS + BLINK : INVERS) : 0);
+ if (menuVerticalPosition == ITEM_REGISTER_MODULE_INDEX && s_editMode) {
+ CHECK_INCDEC_MODELVAR_ZERO(event, reusableBuffer.moduleSetup.pxx2.registerModuleIndex, 7);
+ }
+
+ // RX name
+ if (reusableBuffer.moduleSetup.pxx2.registerStep < REGISTER_RX_NAME_RECEIVED) {
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y - 4 + 2 * FH, "Waiting ...");
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y - 2 + 3 * FH, TR_EXIT, menuVerticalPosition == ITEM_REGISTER_BUTTONS ? INVERS : 0);
+ }
+ else {
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y - 4 + 2 * FH, STR_RX_NAME);
+ editName(WARNING_LINE_X + 8*FW, WARNING_LINE_Y - 4 + 2 * FH, reusableBuffer.moduleSetup.pxx2.registerRxName, PXX2_LEN_RX_NAME, event, menuVerticalPosition == ITEM_REGISTER_RECEIVER_NAME);
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y - 2 + 3 * FH, TR_ENTER, menuVerticalPosition == ITEM_REGISTER_BUTTONS && menuHorizontalPosition == 0 ? INVERS : 0);
+ lcdDrawText(WARNING_LINE_X + 8*FW, WARNING_LINE_Y - 2 + 3 * FH, TR_EXIT, menuVerticalPosition == ITEM_REGISTER_BUTTONS && menuHorizontalPosition == 1 ? INVERS : 0);
+ }
+
+ reusableBuffer.moduleSetup.pxx2.registerPopupVerticalPosition = menuVerticalPosition;
+ reusableBuffer.moduleSetup.pxx2.registerPopupHorizontalPosition = menuHorizontalPosition;
+ reusableBuffer.moduleSetup.pxx2.registerPopupEditMode = s_editMode;
+ }
+
+ menuVerticalPosition = backupVerticalPosition;
+ menuHorizontalPosition = backupHorizontalPosition;
+ menuVerticalOffset = backupVerticalOffset;
+ s_editMode = backupEditMode;
+}
+
+void startRegisterDialog(uint8_t module)
+{
+ memclear(&reusableBuffer.moduleSetup.pxx2, sizeof(reusableBuffer.moduleSetup.pxx2));
+ moduleSettings[module].mode = MODULE_MODE_REGISTER;
+ s_editMode = 0;
+ POPUP_INPUT("", runPopupRegister);
+}
+
+inline bool isDefaultModelRegistrationID()
+{
+ return memcmp(g_model.modelRegistrationID, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID) == 0;
+}
+
+uint8_t findEmptyReceiverSlot()
+{
+ for (uint8_t slot=0; slot 1
- moduleFlag[1] = 0;
+ moduleSettings[1].mode = 0;
#endif
}
#endif
@@ -307,7 +524,7 @@ void menuModelSetup(event_t event)
TITLE(STR_MENUSETUP);
if (event == EVT_ENTRY) {
- reusableBuffer.modelsetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power;
+ reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power;
}
uint8_t sub = menuVerticalPosition - HEADER_LINE;
@@ -342,7 +559,7 @@ void menuModelSetup(event_t event)
drawStringWithIndex(0*FW, y, STR_TIMER, timerIdx+1);
drawTimerMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, menuHorizontalPosition==0 ? attr : 0);
drawTimer(MODEL_SETUP_2ND_COLUMN+5*FW-2+5*FWNUM+1, y, timer->start, RIGHT | (menuHorizontalPosition==1 ? attr : 0), menuHorizontalPosition==2 ? attr : 0);
- if (attr && (editMode>0 || p1valdiff)) {
+ if (attr && editMode > 0) {
div_t qr = div(timer->start, 60);
switch (menuHorizontalPosition) {
case 0:
@@ -542,7 +759,7 @@ void menuModelSetup(event_t event)
for (int i=0; i= NUM_SWITCHES)) {
lcdDrawFilledRect(MODEL_SETUP_2ND_COLUMN-1, y-1, 8*(2*FW+1), 1+FH*((current+4)/5));
}
-#else //PCBTARANIS
+#else // PCBTARANIS
{
lcdDrawTextAlignedLeft(y, STR_SWITCHWARNING);
swarnstate_t states = g_model.switchWarningState;
@@ -616,6 +833,7 @@ void menuModelSetup(event_t event)
#endif
break;
}
+
#if defined(PCBTARANIS)
case ITEM_MODEL_POTS_WARNING:
lcdDrawTextAlignedLeft(y, STR_POTWARNING);
@@ -673,7 +891,7 @@ void menuModelSetup(event_t event)
lcdDrawTextAtIndex(x, y, STR_RETA123, i, ((menuHorizontalPosition==i) && attr) ? BLINK|INVERS : (((g_model.beepANACenter & ((BeepANACenter)1<0 || p1valdiff)) {
+ if (attr && editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
- g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, IS_TRAINER_EXTERNAL_MODULE() ? MODULE_TYPE_NONE : MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable);
- if (checkIncDec_Ret) {
- g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
- g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
- g_model.moduleData[EXTERNAL_MODULE].channelsCount = defaultModuleChannels_M8(EXTERNAL_MODULE);
- if (isModuleSBUS(EXTERNAL_MODULE))
- g_model.moduleData[EXTERNAL_MODULE].sbus.refreshRate = -31;
- if(isModulePPM(EXTERNAL_MODULE))
- SET_DEFAULT_PPM_FRAME_LENGTH(EXTERNAL_MODULE);
+ {
+ uint8_t moduleType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type,
+ MODULE_TYPE_NONE,
+ IS_TRAINER_EXTERNAL_MODULE() ? MODULE_TYPE_NONE :
+ MODULE_TYPE_COUNT - 1, EE_MODEL,
+ isExternalModuleAvailable);
+ if (checkIncDec_Ret) {
+ // TODO this code should be common, in module.h (X10_new_UI branch)
+ memclear(&g_model.moduleData[EXTERNAL_MODULE], sizeof(ModuleData));
+ g_model.moduleData[EXTERNAL_MODULE].type = moduleType;
+ g_model.moduleData[EXTERNAL_MODULE].channelsCount = defaultModuleChannels_M8(EXTERNAL_MODULE);
+ if (isModuleSBUS(EXTERNAL_MODULE))
+ g_model.moduleData[EXTERNAL_MODULE].sbus.refreshRate = -31;
+ if (isModulePPM(EXTERNAL_MODULE))
+ SET_DEFAULT_PPM_FRAME_LENGTH(EXTERNAL_MODULE);
+ }
}
break;
case 1:
if (isModuleDSM2(EXTERNAL_MODULE))
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
+#if defined(PCBXLITE)
else if (isModuleR9M(EXTERNAL_MODULE)) {
uint8_t newR9MType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].subType, MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_LAST, EE_MODEL, isR9MModeAvailable);
if (newR9MType != g_model.moduleData[EXTERNAL_MODULE].subType && newR9MType > MODULE_SUBTYPE_R9M_EU) {
@@ -764,7 +994,7 @@ void menuModelSetup(event_t event)
}
g_model.moduleData[EXTERNAL_MODULE].subType = newR9MType;
}
-
+#endif
#if defined(MULTIMODULE)
else if (isModuleMultimodule(EXTERNAL_MODULE)) {
int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].multi.customProto == 1 ? MM_RF_PROTO_CUSTOM : g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false);
@@ -811,7 +1041,7 @@ void menuModelSetup(event_t event)
if (pdef->subTypeString != nullptr)
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, pdef->subTypeString, g_model.moduleData[EXTERNAL_MODULE].subType, attr);
}
- if (attr && (editMode > 0 || p1valdiff)) {
+ if (attr && editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
if (multi_rfProto == MM_RF_CUSTOM_SELECTED)
@@ -836,9 +1066,9 @@ void menuModelSetup(event_t event)
case ITEM_MODEL_TRAINER_MODE:
lcdDrawTextAlignedLeft(y, STR_MODE);
- lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerMode, attr);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr);
if (attr) {
- g_model.trainerMode = checkIncDec(event, g_model.trainerMode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable);
+ g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable);
#if defined(BLUETOOTH)
if (checkIncDec_Ret) {
bluetoothState = BLUETOOTH_STATE_OFF;
@@ -851,7 +1081,7 @@ void menuModelSetup(event_t event)
#if defined(PCBTARANIS) && defined(BLUETOOTH)
case ITEM_MODEL_TRAINER_BLUETOOTH:
- if (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH) {
+ if (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH) {
if (attr) {
s_editMode = 0;
}
@@ -900,6 +1130,25 @@ void menuModelSetup(event_t event)
#if defined(PCBTARANIS)
case ITEM_MODEL_TRAINER_CHANNELS:
+ lcdDrawTextAlignedLeft(y, STR_CHANNELRANGE);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_CH, menuHorizontalPosition==0 ? attr : 0);
+ lcdDrawNumber(lcdLastRightPos, y, g_model.trainerData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0));
+ lcdDrawChar(lcdLastRightPos, y, '-');
+ lcdDrawNumber(lcdLastRightPos + FW+1, y, g_model.trainerData.channelsStart + 8 + g_model.trainerData.channelsCount, LEFT | (menuHorizontalPosition==1 ? attr : 0));
+ if (attr && editMode > 0) {
+ switch (menuHorizontalPosition) {
+ case 0:
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.trainerData.channelsStart, 32-8-g_model.trainerData.channelsCount);
+ break;
+ case 1:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.channelsCount, -4, min(MAX_TRAINER_CHANNELS_M8, 32-8-g_model.trainerData.channelsStart));
+ break;
+ }
+ }
+ break;
+#endif
+
+#if defined(PCBTARANIS)
case ITEM_MODEL_INTERNAL_MODULE_CHANNELS:
#endif
#if defined(PCBSKY9X)
@@ -915,13 +1164,13 @@ void menuModelSetup(event_t event)
lcdDrawNumber(lcdLastRightPos, y, moduleData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0));
lcdDrawChar(lcdLastRightPos, y, '-');
lcdDrawNumber(lcdLastRightPos + FW+1, y, moduleData.channelsStart+sentModuleChannels(moduleIdx), LEFT | (menuHorizontalPosition==1 ? attr : 0));
- if (attr && (editMode>0 || p1valdiff)) {
+ if (attr && editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.channelsStart, 32-8-moduleData.channelsCount);
break;
case 1:
- CHECK_INCDEC_MODELVAR(event, moduleData.channelsCount, -4, min(maxModuleChannels_M8(moduleIdx), 32-8-moduleData.channelsStart));
+ CHECK_INCDEC_MODELVAR_CHECK(event, moduleData.channelsCount, -4, min(maxModuleChannels_M8(moduleIdx), 32-8-moduleData.channelsStart), moduleData.type == MODULE_TYPE_XJT2 ? isPXX2ChannelsCountAllowed : nullptr);
if ((k == ITEM_MODEL_EXTERNAL_MODULE_CHANNELS && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM)) {
SET_DEFAULT_PPM_FRAME_LENGTH(moduleIdx);
}
@@ -932,16 +1181,213 @@ void menuModelSetup(event_t event)
break;
}
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
case ITEM_MODEL_TRAINER_PARAMS:
+ lcdDrawTextAlignedLeft(y, STR_PPMFRAME);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN+3*FW, y, STR_MS);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.trainerData.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT);
+ lcdDrawChar(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u');
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.trainerData.delay*50)+300, RIGHT | ((CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0));
+ lcdDrawChar(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.trainerData.pulsePol ? '+' : '-', (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0);
+ if (attr && editMode > 0) {
+ switch (menuHorizontalPosition) {
+ case 0:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.frameLength, -20, 35);
+ break;
+ case 1:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.delay, -4, 10);
+ break;
+ case 2:
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.trainerData.pulsePol, 1);
+ break;
+ }
+ }
+ break;
#endif
+
#if defined(PCBTARANIS)
- case ITEM_MODEL_INTERNAL_MODULE_BIND:
+ case ITEM_MODEL_REGISTRATION_ID:
+ lcdDrawTextAlignedLeft(y, STR_REG_ID);
+ if (isDefaultModelRegistrationID())
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, "");
+ else
+ lcdDrawSizedText(MODEL_SETUP_2ND_COLUMN, y, g_model.modelRegistrationID, sizeof(g_model.modelRegistrationID), ZCHAR);
+ break;
+
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_MODEL_NUM:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_MODEL_NUM:
+ {
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ lcdDrawTextAlignedLeft(y, STR_RECEIVER_NUM);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], attr | LEADING0 | LEFT, 2);
+ if (attr) {
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], MAX_RX_NUM(moduleIdx));
+ if (checkIncDec_Ret) {
+ modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
+ }
+ }
+ }
+ break;
+
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_REGISTER_RANGE:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_REGISTER_RANGE:
+ {
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ lcdDrawTextAlignedLeft(y, STR_MODULE);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_REGISTER_BUTTON, (menuHorizontalPosition == 0 ? attr : 0));
+ lcdDrawText(lcdLastRightPos + 3, y, STR_MODULE_RANGE, (menuHorizontalPosition == 1 ? attr : 0));
+ if (attr) {
+ if (moduleSettings[moduleIdx].mode == MODULE_MODE_NORMAL && s_editMode > 0) {
+ if (menuHorizontalPosition == 0 && event == EVT_BUTTON_PRESSED()) {
+ startRegisterDialog(moduleIdx);
+ }
+ else if (menuHorizontalPosition == 1) {
+ moduleSettings[moduleIdx].mode = MODULE_MODE_RANGECHECK;
+ }
+ }
+ if (s_editMode == 0 && !warningText) {
+ moduleSettings[moduleIdx].mode = MODULE_MODE_NORMAL;
+ }
+ if (moduleSettings[moduleIdx].mode == MODULE_MODE_NORMAL) {
+ // REGISTER finished
+ s_editMode = 0;
+ }
+ }
+ }
+ break;
+
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_LABEL:
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_LABEL:
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_LABEL:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_LABEL:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_LABEL:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_LABEL:
+ {
+ uint8_t receiverIdx = CURRENT_RECEIVER_EDITED(k);
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ uint8_t receiverSlot = g_model.moduleData[moduleIdx].pxx2.getReceiverSlot(receiverIdx);
+
+ lcdDrawTextAlignedLeft(y, STR_RECEIVER);
+ lcdDrawNumber(lcdLastRightPos + 1, y, receiverIdx + 1);
+
+ if (receiverSlot) {
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DEL_BUTTON, attr);
+ if (attr && s_editMode > 0) {
+ g_model.moduleData[moduleIdx].pxx2.receivers = (g_model.moduleData[moduleIdx].pxx2.receivers & BF_MASK(0, receiverIdx * 3)) | ((g_model.moduleData[moduleIdx].pxx2.receivers & BF_MASK((receiverIdx + 1) * 3, (MAX_RECEIVERS_PER_MODULE - 1 - receiverIdx) * 3)) >> 3);
+ memclear(&g_model.receiverData[receiverSlot - 1], sizeof(ReceiverData));
+ s_editMode = 0;
+ killEvents(event);
+ storageDirty(EE_MODEL);
+ }
+ }
+ else {
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_RXADD_BUTTON, attr);
+ if (attr && s_editMode > 0) {
+ s_editMode = 0;
+ killEvents(event);
+ uint8_t slot = findEmptyReceiverSlot();
+ if (slot > 0) {
+ g_model.moduleData[moduleIdx].pxx2.receivers |= (slot << (receiverIdx * 3));
+ --slot;
+ g_model.receiverData[slot].used = 1;
+ storageDirty(EE_MODEL);
+ }
+ }
+ }
+ }
+ break;
+
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_OPTIONS:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_OPTIONS:
+ lcdDrawText(INDENT_WIDTH, y, STR_OPTIONS);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_SET, attr);
+ if (event == EVT_KEY_BREAK(KEY_ENTER) && attr) {
+ g_moduleIdx = CURRENT_MODULE_EDITED(k);
+ memclear(&reusableBuffer.hardwareAndSettings, sizeof(reusableBuffer.hardwareAndSettings));
+ pushMenu(menuModelModuleOptions);
+ }
+ break;
+
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_OPTIONS:
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_OPTIONS:
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_OPTIONS:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_OPTIONS:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_OPTIONS:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_OPTIONS:
+ lcdDrawText(INDENT_WIDTH * 2, y, STR_OPTIONS);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_SET, attr);
+ if (event == EVT_KEY_BREAK(KEY_ENTER) && attr) {
+ g_moduleIdx = CURRENT_MODULE_EDITED(k);
+ uint8_t receiverIdx = CURRENT_RECEIVER_EDITED(k);
+ uint8_t receiverSlot = g_model.moduleData[g_moduleIdx].pxx2.getReceiverSlot(receiverIdx) - 1;
+ memclear(&reusableBuffer.hardwareAndSettings, sizeof(reusableBuffer.hardwareAndSettings));
+ reusableBuffer.hardwareAndSettings.receiverSettings.receiverId = receiverSlot;
+ pushMenu(menuModelReceiverOptions);
+ }
+ break;
+
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_1_BIND_SHARE:
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_2_BIND_SHARE:
+ case ITEM_MODEL_INTERNAL_MODULE_PXX2_RECEIVER_3_BIND_SHARE:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_1_BIND_SHARE:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_2_BIND_SHARE:
+ case ITEM_MODEL_EXTERNAL_MODULE_PXX2_RECEIVER_3_BIND_SHARE:
+ {
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ uint8_t receiverIdx = CURRENT_RECEIVER_EDITED(k);
+ uint8_t receiverSlot = g_model.moduleData[moduleIdx].pxx2.getReceiverSlot(receiverIdx) - 1;
+
+ drawReceiverName(INDENT_WIDTH * 2, y, receiverSlot);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_BIND, menuHorizontalPosition==0 ? attr : 0);
+ lcdDrawText(lcdLastRightPos + FW/2, y, STR_BUTTON_SHARE, menuHorizontalPosition==1 ? attr : 0);
+
+ if (attr) {
+ if (menuHorizontalPosition == 0) {
+ if (event == EVT_KEY_BREAK(KEY_ENTER)) {
+ // TODO this will go to module.cpp
+ memclear(&reusableBuffer.moduleSetup.pxx2, sizeof(reusableBuffer.moduleSetup.pxx2));
+ reusableBuffer.moduleSetup.pxx2.bindReceiverId = receiverSlot;
+ moduleSettings[moduleIdx].mode ^= MODULE_MODE_BIND;
+ }
+ else if (event == EVT_KEY_BREAK(KEY_EXIT)) {
+ moduleSettings[moduleIdx].mode &= ~MODULE_MODE_BIND;
+ }
+ if (moduleSettings[moduleIdx].mode == MODULE_MODE_BIND) {
+ s_editMode = 1;
+ if (reusableBuffer.moduleSetup.pxx2.bindStep == BIND_START && reusableBuffer.moduleSetup.pxx2.bindCandidateReceiversCount > 0) {
+ popupMenuItemsCount = min(reusableBuffer.moduleSetup.pxx2.bindCandidateReceiversCount, PXX2_MAX_RECEIVERS_PER_MODULE);
+ for (uint8_t i=0; i0 || p1valdiff)) {
+ if (attr && editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, moduleData.ppm.frameLength, -20, 35);
@@ -998,7 +1444,7 @@ void menuModelSetup(event_t event)
if (xOffsetBind)
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, g_model.header.modelId[moduleIdx], (l_posHorz==0 ? attr : 0) | LEADING0|LEFT, 2);
if (attr && l_posHorz == 0) {
- if (editMode>0 || p1valdiff) {
+ if (editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.header.modelId[moduleIdx], MAX_RX_NUM(moduleIdx));
if (checkIncDec_Ret) {
modelHeaders[g_eeGeneral.currModel].modelId[moduleIdx] = g_model.header.modelId[moduleIdx];
@@ -1058,36 +1504,36 @@ void menuModelSetup(event_t event)
POPUP_MENU_START(onBindMenu);
continue;
}
- if (moduleFlag[moduleIdx] == MODULE_BIND) {
- newFlag = MODULE_BIND;
+ if (moduleSettings[moduleIdx].mode == MODULE_MODE_BIND) {
+ newFlag = MODULE_MODE_BIND;
}
else {
- if (!popupMenuNoItems) {
+ if (!popupMenuItemsCount) {
s_editMode = 0; // this is when popup is exited before a choice is made
}
}
}
else {
- newFlag = MODULE_BIND;
+ newFlag = MODULE_MODE_BIND;
}
}
else if (l_posHorz == 2) {
- newFlag = MODULE_RANGECHECK;
+ newFlag = MODULE_MODE_RANGECHECK;
}
}
}
#else
if (attr && l_posHorz>0 && s_editMode>0) {
if (l_posHorz == 1)
- newFlag = MODULE_BIND;
+ newFlag = MODULE_MODE_BIND;
else if (l_posHorz == 2)
- newFlag = MODULE_RANGECHECK;
+ newFlag = MODULE_MODE_RANGECHECK;
}
#endif
- moduleFlag[moduleIdx] = newFlag;
+ moduleSettings[moduleIdx].mode = newFlag;
#if defined(MULTIMODULE)
- if (newFlag == MODULE_BIND) {
+ if (newFlag == MODULE_MODE_BIND) {
multiBindStatus = MULTI_BIND_INITIATED;
}
#endif
@@ -1121,11 +1567,12 @@ void menuModelSetup(event_t event)
if (moduleData.failsafeMode != FAILSAFE_CUSTOM)
menuHorizontalPosition = 0;
if (menuHorizontalPosition == 0) {
- if (editMode > 0 || p1valdiff) {
+ if (editMode > 0) {
CHECK_INCDEC_MODELVAR_ZERO(event, moduleData.failsafeMode, FAILSAFE_LAST);
if (checkIncDec_Ret) SEND_FAILSAFE_NOW(moduleIdx);
}
- } else if (menuHorizontalPosition == 1) {
+ }
+ else if (menuHorizontalPosition == 1) {
s_editMode = 0;
if (moduleData.failsafeMode == FAILSAFE_CUSTOM) {
if (event == EVT_KEY_LONG(KEY_ENTER)) {
@@ -1135,12 +1582,13 @@ void menuModelSetup(event_t event)
AUDIO_WARNING1();
SEND_FAILSAFE_NOW(moduleIdx);
}
- else if (event == EVT_KEY_BREAK(KEY_ENTER)) {
+ else if (event == EVT_KEY_BREAK(KEY_ENTER) && attr) {
g_moduleIdx = moduleIdx;
pushMenu(menuModelFailsafe);
}
}
- } else {
+ }
+ else {
lcdDrawSolidFilledRect(MODEL_SETUP_2ND_COLUMN, y, LCD_W - MODEL_SETUP_2ND_COLUMN, 8);
}
}
@@ -1152,7 +1600,7 @@ void menuModelSetup(event_t event)
{
uint8_t newAntennaSel = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_ANTENNASELECTION, STR_VANTENNATYPES, g_model.moduleData[INTERNAL_MODULE].pxx.external_antenna, 0, 1, attr, event);
if (newAntennaSel != g_model.moduleData[INTERNAL_MODULE].pxx.external_antenna && newAntennaSel == XJT_EXTERNAL_ANTENNA) {
- POPUP_CONFIRMATION(STR_ANTENNACONFIRM1);
+ POPUP_CONFIRMATION(STR_ANTENNACONFIRM1, nullptr);
const char * w = STR_ANTENNACONFIRM2;
SET_WARNING_INFO(w, strlen(w), 0);
}
@@ -1191,6 +1639,7 @@ void menuModelSetup(event_t event)
}
}
#endif
+#if defined(PCBXLITE)
if (isModuleR9M(moduleIdx)) {
lcdDrawTextAlignedLeft(y, STR_MODULE_TELEMETRY);
if (IS_TELEMETRY_INTERNAL_MODULE()) {
@@ -1201,6 +1650,9 @@ void menuModelSetup(event_t event)
}
}
else if (isModuleSBUS(moduleIdx)) {
+#else
+ if (isModuleSBUS(moduleIdx)) {
+#endif
lcdDrawTextAlignedLeft(y, STR_WARN_BATTVOLTAGE);
putsVolts(lcdLastRightPos, y, getBatteryVoltage(), attr | PREC2 | LEFT);
}
@@ -1230,11 +1682,11 @@ void menuModelSetup(event_t event)
if (attr) {
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[moduleIdx].pxx.power, R9M_LBT_POWER_MAX);
}
- if (attr && editMode == 0 && reusableBuffer.modelsetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) {
- if((reusableBuffer.modelsetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) { //switching between mode 2 and 3 does not require rebind
+ if (attr && editMode == 0 && reusableBuffer.moduleSetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) {
+ if((reusableBuffer.moduleSetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) { //switching between mode 2 and 3 does not require rebind
POPUP_WARNING(STR_REBIND);
}
- reusableBuffer.modelsetup.r9mPower = g_model.moduleData[moduleIdx].pxx.power;
+ reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[moduleIdx].pxx.power;
}
}
}
@@ -1247,6 +1699,20 @@ void menuModelSetup(event_t event)
}
break;
+#if !defined(PCBXLITE)
+ case ITEM_MODEL_EXTERNAL_MODULE_FREQ:
+ {
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ lcdDrawTextAlignedLeft(y, STR_FREQUENCY);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9MFLEX_FREQ, g_model.moduleData[moduleIdx].r9m.freq, LEFT | attr);
+ if (attr)
+ {
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[moduleIdx].r9m.freq, 1);
+ }
+ }
+ break;
+#endif
+
#if defined(MULTIMODULE)
case ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND:
if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MM_RF_PROTO_DSM2)
@@ -1283,7 +1749,7 @@ void menuModelSetup(event_t event)
lcdDrawNumber(lcdLastRightPos, y, g_model.moduleData[1].channelsStart+1, LEFT | (menuHorizontalPosition<=0 ? attr : 0));
lcdDrawChar(lcdLastRightPos, y, '-');
lcdDrawNumber(lcdLastRightPos + FW+1, y, g_model.moduleData[1].channelsStart+8+g_model.moduleData[1].channelsCount, LEFT | (menuHorizontalPosition!=0 ? attr : 0));
- if (attr && (editMode>0 || p1valdiff)) {
+ if (attr && editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[1].channelsStart, 32-8-g_model.moduleData[1].channelsCount);
@@ -1304,7 +1770,7 @@ void menuModelSetup(event_t event)
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, 'u');
lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+8*FW+2, y, (g_model.moduleData[1].ppmDelay*50)+300, RIGHT | ((menuHorizontalPosition < 0 || menuHorizontalPosition==1) ? attr : 0));
lcdDrawChar(MODEL_SETUP_2ND_COLUMN+10*FW, y, g_model.moduleData[1].ppmPulsePol ? '+' : '-', (menuHorizontalPosition < 0 || menuHorizontalPosition==2) ? attr : 0);
- if (attr && (editMode>0 || p1valdiff)) {
+ if (attr && editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[1].ppmFrameLength, -20, 35);
@@ -1326,7 +1792,7 @@ void menuModelSetup(event_t event)
#if defined(PXX)
if (IS_RANGECHECK_ENABLE()) {
showMessageBox("RSSI: ");
- lcdDrawNumber(16+4*FW, 5*FH, TELEMETRY_RSSI(), BOLD);
+ lcdDrawNumber(WARNING_LINE_X, 5*FH, TELEMETRY_RSSI(), BOLD);
}
#endif
@@ -1334,7 +1800,7 @@ void menuModelSetup(event_t event)
if (old_editMode > 0 && s_editMode == 0) {
switch(menuVerticalPosition) {
#if defined(PCBTARANIS)
- case ITEM_MODEL_INTERNAL_MODULE_BIND:
+ case ITEM_MODEL_INTERNAL_MODULE_NPXX2_BIND:
if (menuHorizontalPosition == 0)
checkModelIdUnique(g_eeGeneral.currModel, INTERNAL_MODULE);
break;
@@ -1345,125 +1811,10 @@ void menuModelSetup(event_t event)
checkModelIdUnique(g_eeGeneral.currModel, EXTRA_MODULE);
break;
#endif
- case ITEM_MODEL_EXTERNAL_MODULE_BIND:
+ case ITEM_MODEL_EXTERNAL_MODULE_NPXX2_BIND:
if (menuHorizontalPosition == 0)
checkModelIdUnique(g_eeGeneral.currModel, EXTERNAL_MODULE);
break;
}
}
}
-
-void menuModelFailsafe(event_t event)
-{
- const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
- const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
- uint8_t wbar = LCD_W - FW * 4 - FWNUM * 4;
-#if defined(PPM_UNIT_PERCENT_PREC1)
- wbar -= 6;
-#endif
-
- if (event == EVT_KEY_LONG(KEY_ENTER)) {
- killEvents(event);
- event = 0;
-
- if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) {
- if (s_editMode) {
- g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart];
- s_editMode = 0;
- }
- else {
- int16_t & failsafe = g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition];
- if (failsafe < FAILSAFE_CHANNEL_HOLD)
- failsafe = FAILSAFE_CHANNEL_HOLD;
- else if (failsafe == FAILSAFE_CHANNEL_HOLD)
- failsafe = FAILSAFE_CHANNEL_NOPULSE;
- else
- failsafe = 0;
- }
- }
- else {
- // "Outputs => Failsafe" menu item
- setCustomFailsafe(g_moduleIdx);
- }
-
- storageDirty(EE_MODEL);
- AUDIO_WARNING1();
- SEND_FAILSAFE_NOW(g_moduleIdx);
- }
-
- SIMPLE_SUBMENU_NOTITLE(sentModuleChannels(g_moduleIdx) + 1);
-
- lcdDrawTextAlignedCenter(0, FAILSAFESET);
- lcdInvertLine(0);
-
- const coord_t x = 1;
- coord_t y = FH + 1;
- uint8_t line = (menuVerticalPosition >= sentModuleChannels(g_moduleIdx) ? 2 : 0);
- uint8_t ch = (menuVerticalPosition >= 8 ? 8 : 0) + line;
-
- // Channels
- for (; line < 8; line++) {
- const int32_t channelValue = channelOutputs[ch+channelStart];
- int32_t failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[ch];
-
- //Channel
- putsChn(x+1, y, ch+1, SMLSIZE);
-
- // Value
- LcdFlags flags = TINSIZE;
- if (menuVerticalPosition == ch) {
- flags |= INVERS;
- if (s_editMode) {
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- s_editMode = 0;
- }
- else {
- flags |= BLINK;
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[ch], -lim, +lim);
- }
- }
- }
-
- uint8_t xValue = x+LCD_W-4-wbar;
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
- lcdDrawText(xValue, y, STR_HOLD, RIGHT|flags);
- failsafeValue = 0;
- }
- else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- lcdDrawText(xValue, y, STR_NONE, RIGHT|flags);
- failsafeValue = 0;
- }
- else {
-#if defined(PPM_UNIT_US)
- lcdDrawNumber(xValue, y, PPM_CH_CENTER(ch)+failsafeValue/2, RIGHT|flags);
-#elif defined(PPM_UNIT_PERCENT_PREC1)
- lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue), RIGHT|PREC1|flags);
-#else
- lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue)/10, RIGHT|flags);
-#endif
- }
-
- // Gauge
-#if !defined(PCBX7) // X7 LCD doesn't like too many horizontal lines
- lcdDrawRect(x+LCD_W-3-wbar, y, wbar+1, 6);
-#endif
- const uint8_t lenChannel = limit(1, (abs(channelValue) * wbar/2 + lim/2) / lim, wbar/2);
- const uint8_t lenFailsafe = limit(1, (abs(failsafeValue) * wbar/2 + lim/2) / lim, wbar/2);
- const coord_t xChannel = (channelValue>0) ? x+LCD_W-3-wbar/2 : x+LCD_W-2-wbar/2-lenChannel;
- const coord_t xFailsafe = (failsafeValue>0) ? x+LCD_W-3-wbar/2 : x+LCD_W-2-wbar/2-lenFailsafe;
- lcdDrawHorizontalLine(xChannel, y+1, lenChannel, DOTTED, 0);
- lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
- lcdDrawSolidHorizontalLine(xFailsafe, y+3, lenFailsafe);
- lcdDrawSolidHorizontalLine(xFailsafe, y+4, lenFailsafe);
-
- y += FH - 1;
-
- if (++ch >= sentModuleChannels(g_moduleIdx))
- break;
- }
-
- if (menuVerticalPosition >= sentModuleChannels(g_moduleIdx)) {
- // Outputs => Failsafe
- lcdDrawText(CENTER_OFS, LCD_H - (FH + 1), STR_OUTPUTS2FAILSAFE, INVERS);
- }
-}
diff --git a/radio/src/gui/128x64/model_special_functions.cpp b/radio/src/gui/128x64/model_special_functions.cpp
index f8163d0a0..46f1b5d53 100644
--- a/radio/src/gui/128x64/model_special_functions.cpp
+++ b/radio/src/gui/128x64/model_special_functions.cpp
@@ -57,12 +57,12 @@ void onCustomFunctionsFileSelectionMenu(const char * result)
strcpy(directory, SOUNDS_PATH);
strncpy(directory+SOUNDS_PATH_LNG_OFS, currentLanguagePack->id, 2);
}
- if (!sdListFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), NULL)) {
+ if (!sdListFiles(directory, func==FUNC_PLAY_SCRIPT ? SCRIPTS_EXT : SOUNDS_EXT, sizeof(cfn->play.name), nullptr)) {
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
POPUP_MENU_UNSET_BSS_FLAG();
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a file in the list
memcpy(cfn->play.name, result, sizeof(cfn->play.name));
storageDirty(eeFlags);
@@ -96,7 +96,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result)
CFN_PARAM(cfn) = 0;
storageDirty(EE_MODEL);
}
- else {
+ else if (result != STR_EXIT) {
onSourceLongEnterPress(result);
}
}
@@ -186,7 +186,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
uint8_t func = CFN_FUNC(cfn);
for (uint8_t j=0; j<5; j++) {
uint8_t attr = ((sub==k && menuHorizontalPosition==j) ? ((s_editMode>0) ? BLINK|INVERS : INVERS) : 0);
- uint8_t active = (attr && (s_editMode>0 || p1valdiff));
+ uint8_t active = (attr && s_editMode > 0);
switch (j) {
case 0:
if (sub==k && menuHorizontalPosition < 1 && CFN_SWITCH(cfn) == SWSRC_NONE) {
@@ -390,7 +390,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
else if (attr) {
REPEAT_LAST_CURSOR_MOVE();
}
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
if (active || event==EVT_KEY_LONG(KEY_ENTER)) {
CFN_PARAM(cfn) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max);
if (func == FUNC_ADJUST_GVAR && attr && event==EVT_KEY_LONG(KEY_ENTER)) {
@@ -409,7 +409,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
#else
if (active) {
CFN_PARAM(cfn) = CHECK_INCDEC_PARAM(event, val_displayed, val_min, val_max);
-#endif // PCBX7
+#endif
}
break;
}
@@ -437,7 +437,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
break;
}
}
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
if (sub==k && menuHorizontalPosition<0 && CFN_SWITCH(cfn)) {
lcdInvertLine(i+1);
}
@@ -447,7 +447,7 @@ void menuSpecialFunctions(event_t event, CustomFunctionData * functions, CustomF
void menuModelSpecialFunctions(event_t event)
{
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
const CustomFunctionData * cfn = &g_model.customFn[menuVerticalPosition];
if (!CFN_SWITCH(cfn) && menuHorizontalPosition < 0 && event==EVT_KEY_BREAK(KEY_ENTER)) {
menuHorizontalPosition = 0;
@@ -457,7 +457,7 @@ void menuModelSpecialFunctions(event_t event)
menuSpecialFunctions(event, g_model.customFn, &modelFunctionsContext);
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
if (!CFN_SWITCH(cfn) && menuHorizontalPosition == 0 && s_editMode <= 0) {
menuHorizontalPosition = -1;
}
diff --git a/radio/src/gui/128x64/model_telemetry.cpp b/radio/src/gui/128x64/model_telemetry.cpp
index 5e763fd5c..1231e3f37 100644
--- a/radio/src/gui/128x64/model_telemetry.cpp
+++ b/radio/src/gui/128x64/model_telemetry.cpp
@@ -423,7 +423,7 @@ void menuModelTelemetryFrsky(event_t event)
switch (event) {
case EVT_KEY_BREAK(KEY_DOWN):
case EVT_KEY_BREAK(KEY_UP):
-#if !defined(PCBX7)
+#if !defined(PCBX7) && !defined(PCBX3)
case EVT_KEY_BREAK(KEY_LEFT):
case EVT_KEY_BREAK(KEY_RIGHT):
#endif
@@ -531,7 +531,7 @@ void menuModelTelemetryFrsky(event_t event)
s_editMode = 0;
if (event==EVT_KEY_LONG(KEY_ENTER)) {
killEvents(KEY_ENTER);
- POPUP_CONFIRMATION(STR_CONFIRMDELETE);
+ POPUP_CONFIRMATION(STR_CONFIRMDELETE, nullptr);
}
}
break;
@@ -543,7 +543,7 @@ void menuModelTelemetryFrsky(event_t event)
case ITEM_TELEMETRY_RSSI_LABEL:
#if defined(MULTIMODULE)
- if (telemetryProtocol == PROTOCOL_MULTIMODULE &&
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE &&
g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false) == MM_RF_PROTO_FS_AFHDS2A)
lcdDrawTextAlignedLeft(y, "RSNR");
else
@@ -588,7 +588,7 @@ void menuModelTelemetryFrsky(event_t event)
}
lcdDrawNumber(TELEM_COL2, y, -10+g_model.frsky.varioMin, ((CURSOR_ON_LINE() || menuHorizontalPosition==0) ? attr : 0)|LEFT);
lcdDrawNumber(TELEM_COL2+4*FW, y, 10+g_model.frsky.varioMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0)|LEFT);
- if (attr && (s_editMode>0 || p1valdiff)) {
+ if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioMin, -7, 7);
@@ -605,7 +605,7 @@ void menuModelTelemetryFrsky(event_t event)
lcdDrawNumber(TELEM_COL2, y, -5+g_model.frsky.varioCenterMin, ((CURSOR_ON_LINE() || menuHorizontalPosition==0) ? attr : 0)|PREC1|LEFT);
lcdDrawNumber(TELEM_COL2+4*FW, y, 5+g_model.frsky.varioCenterMax, ((CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0)|PREC1|LEFT);
lcdDrawTextAtIndex(TELEM_COL2+8*FW, y, STR_VVARIOCENTER, g_model.frsky.varioCenterSilent, (menuHorizontalPosition==2 ? attr : 0));
- if (attr && (s_editMode>0 || p1valdiff)) {
+ if (attr && s_editMode > 0) {
switch (menuHorizontalPosition) {
case 0:
CHECK_INCDEC_MODELVAR(event, g_model.frsky.varioCenterMin, -16, 5+min(10, g_model.frsky.varioCenterMax+5));
diff --git a/radio/src/gui/128x64/model_templates.cpp b/radio/src/gui/128x64/model_templates.cpp
index b03c24151..95693eb3e 100644
--- a/radio/src/gui/128x64/model_templates.cpp
+++ b/radio/src/gui/128x64/model_templates.cpp
@@ -33,7 +33,7 @@ void menuModelTemplates(event_t event)
AUDIO_WARNING2();
}
if (event==EVT_KEY_BREAK(KEY_ENTER)) {
- POPUP_CONFIRMATION(STR_VTEMPLATES+1 + (sub * LEN2_VTEMPLATES));
+ POPUP_CONFIRMATION(STR_VTEMPLATES+1 + (sub * LEN2_VTEMPLATES), nullptr);
s_editMode = 0;
}
}
diff --git a/radio/src/gui/128x64/popups.cpp b/radio/src/gui/128x64/popups.cpp
index 25b9e28a3..977aa801c 100644
--- a/radio/src/gui/128x64/popups.cpp
+++ b/radio/src/gui/128x64/popups.cpp
@@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
- * th9x - http://code.google.com/p/th9x
+ * th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@@ -20,33 +20,6 @@
#include "opentx.h"
-const char * warningText = NULL;
-const char * warningInfoText;
-uint8_t warningInfoLength;
-uint8_t warningType;
-uint8_t warningResult = 0;
-
-uint8_t warningInfoFlags = ZCHAR;
-int16_t warningInputValue;
-int16_t warningInputValueMin;
-int16_t warningInputValueMax;
-
-void drawMessageBox()
-{
- lcdDrawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE);
- lcdDrawRect(10, 16, LCD_W-20, 40);
- lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y, warningText, WARNING_LINE_LEN);
- // could be a place for a warningInfoText
-}
-
-void showMessageBox(const char * str)
-{
- warningText = str;
- drawMessageBox();
- warningText = NULL;
- lcdRefresh();
-}
-
const unsigned char ASTERISK_BITMAP[] = {
#include "asterisk.lbm"
};
@@ -65,54 +38,16 @@ void drawAlertBox(const char * title, const char * text, const char * action)
lcdDrawText(MESSAGE_LCD_OFFSET, 0, title, DBLSIZE);
lcdDrawText(MESSAGE_LCD_OFFSET, 2*FH, STR_WARNING, DBLSIZE);
#endif
-
+
lcdDrawSolidFilledRect(0, 0, LCD_W, 32);
+
if (text) {
lcdDrawTextAlignedLeft(5*FH, text);
}
+
if (action) {
lcdDrawTextAlignedLeft(7*FH, action);
}
-
+
#undef MESSAGE_LCD_OFFSET
}
-
-void showAlertBox(const char * title, const char * text, const char * action , uint8_t sound)
-{
- drawAlertBox(title, text, action);
-
- AUDIO_ERROR_MESSAGE(sound);
-
- lcdRefresh();
- lcdSetContrast();
- clearKeyEvents();
- backlightOn();
- checkBacklight();
-}
-
-void runPopupWarning(event_t event)
-{
- warningResult = false;
- drawMessageBox();
- if (warningInfoText) {
- lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+FH, warningInfoText, warningInfoLength, WARNING_INFO_FLAGS);
- }
- lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+2*FH, warningType == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS);
- switch (event) {
- case EVT_KEY_BREAK(KEY_ENTER):
- if (warningType == WARNING_TYPE_ASTERISK)
- break;
- warningResult = true;
- // no break
- case EVT_KEY_BREAK(KEY_EXIT):
- warningText = NULL;
- warningType = WARNING_TYPE_ASTERISK;
- break;
- default:
- if (warningType != WARNING_TYPE_INPUT) break;
- s_editMode = EDIT_MODIFY_FIELD;
- warningInputValue = checkIncDec(event, warningInputValue, warningInputValueMin, warningInputValueMax);
- s_editMode = EDIT_SELECT_FIELD;
- break;
- }
-}
diff --git a/radio/src/gui/128x64/popups.h b/radio/src/gui/128x64/popups.h
index bc413305e..73edb0a84 100644
--- a/radio/src/gui/128x64/popups.h
+++ b/radio/src/gui/128x64/popups.h
@@ -21,25 +21,20 @@
#ifndef _POPUPS_H_
#define _POPUPS_H_
-#define MENU_X 10
-#define MENU_Y 16
-#define MENU_W LCD_W-(2*MENU_X)
+#include
+
+#define MESSAGEBOX_X 10
+#define MESSAGEBOX_Y 16
+#define MESSAGEBOX_W (LCD_W - 19)
+
+#define MENU_X MESSAGEBOX_X
+#define MENU_Y MESSAGEBOX_Y
+#define MENU_W MESSAGEBOX_W
+
#define WARNING_LINE_LEN 20
#define WARNING_LINE_X 16
#define WARNING_LINE_Y 3*FH
-void drawMessageBox();
-void showMessageBox(const char * title);
-void runPopupWarning(event_t event);
-
-#define DRAW_MESSAGE_BOX(title) (warningText = title, drawMessageBox(), warningText = NULL)
-
-extern void (*popupFunc)(event_t event);
-extern int16_t warningInputValue;
-extern int16_t warningInputValueMin;
-extern int16_t warningInputValueMax;
-extern uint8_t warningInfoFlags;
-
#if !defined(GUI)
#define DISPLAY_WARNING(...)
#define POPUP_WARNING(...)
@@ -49,9 +44,10 @@ extern uint8_t warningInfoFlags;
#define SET_WARNING_INFO(...)
#else
#define DISPLAY_WARNING (*popupFunc)
+ #define POPUP_INFORMATION(s) (warningText = s, warningType = WARNING_TYPE_INFO, warningInfoText = nullptr, popupFunc = runPopupWarning)
#define POPUP_WARNING(s) (warningText = s, warningInfoText = 0, popupFunc = runPopupWarning)
- #define POPUP_CONFIRMATION(s) (warningText = s, warningType = WARNING_TYPE_CONFIRM, warningInfoText = 0, popupFunc = runPopupWarning)
- #define POPUP_INPUT(s, func, start, min, max) (warningText = s, warningType = WARNING_TYPE_INPUT, popupFunc = func, warningInputValue = start, warningInputValueMin = min, warningInputValueMax = max)
+ #define POPUP_CONFIRMATION(s, func) (warningText = s, warningType = WARNING_TYPE_CONFIRM, warningInfoText = nullptr, popupFunc = runPopupWarning, popupMenuHandler = func)
+ #define POPUP_INPUT(s, func) (warningText = s, popupFunc = func)
#define WARNING_INFO_FLAGS warningInfoFlags
#define SET_WARNING_INFO(info, len, flags) (warningInfoText = info, warningInfoLength = len, warningInfoFlags = flags)
#endif
@@ -62,28 +58,19 @@ extern uint8_t warningInfoFlags;
#define POPUP_MENU_ADD_SD_ITEM(s)
#endif
- #define NAVIGATION_MENUS
- #define POPUP_MENU_ADD_ITEM(s) do { popupMenuOffsetType = MENU_OFFSET_INTERNAL; if (popupMenuNoItems < POPUP_MENU_MAX_LINES) popupMenuItems[popupMenuNoItems++] = s; } while (0)
- #define POPUP_MENU_SELECT_ITEM(s) s_menu_item = (s > 0 ? (s < popupMenuNoItems ? s : popupMenuNoItems) : 0)
- #define POPUP_MENU_START(func) do { popupMenuHandler = (func); AUDIO_KEY_PRESS(); } while (0)
- #define POPUP_MENU_MAX_LINES 12
- #define MENU_MAX_DISPLAY_LINES 6
- #define MENU_LINE_LENGTH (LEN_MODEL_NAME+12)
- #define POPUP_MENU_SET_BSS_FLAG()
- #define POPUP_MENU_UNSET_BSS_FLAG()
- enum {
- MENU_OFFSET_INTERNAL,
- MENU_OFFSET_EXTERNAL
- };
- extern uint8_t popupMenuOffsetType;
- extern uint8_t s_menu_item;
+#define POPUP_MENU_ADD_ITEM(s) do { popupMenuOffsetType = MENU_OFFSET_INTERNAL; if (popupMenuItemsCount < POPUP_MENU_MAX_LINES) popupMenuItems[popupMenuItemsCount++] = s; } while (0)
+#define POPUP_MENU_SELECT_ITEM(s) s_menu_item = (s > 0 ? (s < popupMenuItemsCount ? s : popupMenuItemsCount) : 0)
+#define POPUP_MENU_START(func) do { popupMenuHandler = (func); AUDIO_KEY_PRESS(); } while (0)
+#define POPUP_MENU_MAX_LINES 12
+#define MENU_MAX_DISPLAY_LINES 6
+#define MENU_LINE_LENGTH (LEN_MODEL_NAME+12)
+#define POPUP_MENU_SET_BSS_FLAG()
+#define POPUP_MENU_UNSET_BSS_FLAG()
+enum {
+ MENU_OFFSET_INTERNAL,
+ MENU_OFFSET_EXTERNAL
+};
-#if defined(NAVIGATION_MENUS)
- extern uint16_t popupMenuOffset;
- extern const char * popupMenuItems[POPUP_MENU_MAX_LINES];
- extern uint16_t popupMenuNoItems;
- const char * runPopupMenu(event_t event);
- extern void (*popupMenuHandler)(const char * result);
-#endif
+#include "../common/stdlcd/popups.h"
#endif // _POPUPS_H_
diff --git a/radio/src/gui/128x64/radio_diaganas.cpp b/radio/src/gui/128x64/radio_diaganas.cpp
index 7665f7ca4..dc30519ac 100644
--- a/radio/src/gui/128x64/radio_diaganas.cpp
+++ b/radio/src/gui/128x64/radio_diaganas.cpp
@@ -67,48 +67,6 @@ void menuRadioDiagAnalogs(event_t event)
}
#endif
-
-#if defined(PCBTARANIS)
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH + 2, STR_BATT_CALIB);
- putsVolts(LEN_CALIB_FIELDS*FW+FW, MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH + 2, getBatteryVoltage(), (menuVerticalPosition==HEADER_LINE ? INVERS | (s_editMode > 0 ? BLINK : 0) : 0) | PREC2 | LEFT);
-#elif defined(PCBSKY9X)
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+1+4*FH, STR_BATT_CALIB);
- static int32_t adcBatt;
- // TODO board.cpp
- adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8;
- uint32_t batCalV = (adcBatt + adcBatt*(g_eeGeneral.txVoltageCalibration)/128) * 4191;
- batCalV /= 55296;
- putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_HEADER_HEIGHT+1+4*FH, batCalV, (menuVerticalPosition==HEADER_LINE ? INVERS : 0));
-#else
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH, STR_BATT_CALIB);
- putsVolts(LEN_CALIB_FIELDS*FW+4*FW, MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH, g_vbat100mV, (menuVerticalPosition==HEADER_LINE ? INVERS : 0));
-#endif
-
- if (menuVerticalPosition == HEADER_LINE) {
- CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127);
- }
-
-#if defined(TX_CAPACITY_MEASUREMENT)
- lcdDrawTextAlignedLeft(6*FH+1, STR_CURRENT_CALIB);
- drawValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, 6*FH+1, getCurrent(), UNIT_MILLIAMPS, (menuVerticalPosition==2 ? INVERS : 0)) ;
- if (menuVerticalPosition==2) CHECK_INCDEC_GENVAR(event, g_eeGeneral.txCurrentCalibration, -49, 49);
-#endif
-
-#if defined(PCBSKY9X)
- #if defined(TX_CAPACITY_MEASUREMENT)
- #define TEMP_CALIB_POS 7*FH+1
- #define TEMP_CALIB_MENU_POS 3
- #else
- #define TEMP_CALIB_POS 6*FH+1
- #define TEMP_CALIB_MENU_POS 2
- #endif
-
- lcdDrawTextAlignedLeft(TEMP_CALIB_POS, STR_TEMP_CALIB);
- drawValueWithUnit(LEN_CALIB_FIELDS*FW+4*FW, TEMP_CALIB_POS, getTemperature(), UNIT_TEMPERATURE, (menuVerticalPosition==TEMP_CALIB_MENU_POS ? INVERS : 0)) ;
- if (menuVerticalPosition==TEMP_CALIB_MENU_POS)
- CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureCalib, -100, 100);
-#endif
-
#if (NUM_PWMSTICKS > 0) && !defined(SIMU)
lcdDrawTextAlignedLeft(7*FH, STICKS_PWM_ENABLED() ? "Sticks: PWM" : "Sticks: ANA");
#endif
diff --git a/radio/src/gui/128x64/radio_diagkeys.cpp b/radio/src/gui/128x64/radio_diagkeys.cpp
index 35a3d73fa..214d14726 100644
--- a/radio/src/gui/128x64/radio_diagkeys.cpp
+++ b/radio/src/gui/128x64/radio_diagkeys.cpp
@@ -50,7 +50,7 @@ void menuRadioDiagKeys(event_t event)
}
if (i < TRM_BASE) {
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
y = MENU_HEADER_HEIGHT + FH + FH*i;
if (i >= 2) {
// hide PLUS and MINUS virtual buttons
diff --git a/radio/src/gui/128x64/radio_hardware.cpp b/radio/src/gui/128x64/radio_hardware.cpp
index 6025a9b6e..9203b40ea 100644
--- a/radio/src/gui/128x64/radio_hardware.cpp
+++ b/radio/src/gui/128x64/radio_hardware.cpp
@@ -103,17 +103,33 @@ enum MenuRadioHardwareItems {
ITEM_RADIO_HARDWARE_STICK4,
ITEM_RADIO_HARDWARE_LABEL_POTS,
ITEM_RADIO_HARDWARE_POT1,
+#if !defined(PCBX3)
ITEM_RADIO_HARDWARE_POT2,
+#endif
ITEM_RADIO_HARDWARE_LABEL_SWITCHES,
ITEM_RADIO_HARDWARE_SA,
ITEM_RADIO_HARDWARE_SB,
ITEM_RADIO_HARDWARE_SC,
ITEM_RADIO_HARDWARE_SD,
-#if NUM_SWITCHES > 4
+#if NUM_SWITCHES >= 5
ITEM_RADIO_HARDWARE_SF,
+#endif
+#if NUM_SWITCHES >= 6
ITEM_RADIO_HARDWARE_SH,
#endif
+ ITEM_RADIO_HARDWARE_BATTERY_CALIB,
+#if defined(STM32)
+ ITEM_RADIO_HARDWARE_RTC_BATTERY,
+#endif
+#if defined(TX_CAPACITY_MEASUREMENT)
+ ITEM_RADIO_HARDWARE_CAPACITY_CALIB,
+#endif
+#if defined(PCBSKY9X)
+ ITEM_RADIO_HARDWARE_TEMPERATURE_CALIB,
+#endif
+#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE,
+#endif
#if defined(BLUETOOTH)
ITEM_RADIO_HARDWARE_BLUETOOTH_MODE,
ITEM_RADIO_HARDWARE_BLUETOOTH_PAIRING_CODE,
@@ -126,25 +142,38 @@ enum MenuRadioHardwareItems {
ITEM_RADIO_HARDWARE_MAX
};
-#define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
-
-#if NUM_SWITCHES > 4
-#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
+#if defined(PCBX3)
+#define POTS_ROWS NAVIGATION_LINE_BY_LINE|1
#else
+#define POTS_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
+#endif
+
+#if NUM_SWITCHES == 6
+#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
+#elif NUM_SWITCHES == 5
+#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
+#elif NUM_SWITCHES == 4
#define SWITCHES_ROWS NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1, NAVIGATION_LINE_BY_LINE|1
#endif
-#if defined(PCBTARANIS)
-#define BLUETOOTH_ROWS uint8_t(IS_BLUETOOTH_CHIP_PRESENT() ? 0 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY ? -1 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0),
+#if defined(PCBX3)
+ #define BLUETOOTH_ROWS
+#elif defined(PCBTARANIS)
+ #define BLUETOOTH_ROWS uint8_t(IS_BLUETOOTH_CHIP_PRESENT() ? 0 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_TELEMETRY ? -1 : HIDDEN_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0),
#elif defined(BLUETOOTH)
-#define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : -1), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0),
+ #define BLUETOOTH_ROWS 0, uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : READONLY_ROW), uint8_t(g_eeGeneral.bluetoothMode == BLUETOOTH_OFF ? HIDDEN_ROW : 0),
#else
-#define BLUETOOTH_ROWS
+ #define BLUETOOTH_ROWS
#endif
-#if defined(PCBXLITE)
-#define SWITCH_TYPE_MAX(sw) (SWITCH_3POS)
+
+#if defined(PCBX3)
+ #define SWITCH_TYPE_MAX(sw) (sw == MIXSRC_SD-MIXSRC_FIRST_SWITCH ? SWITCH_2POS : SWITCH_3POS)
+#elif defined(PCBXLITES)
+ #define SWITCH_TYPE_MAX(sw) (sw >= MIXSRC_SE-MIXSRC_FIRST_SWITCH ? SWITCH_2POS : SWITCH_3POS)
+#elif defined(PCBXLITE)
+ #define SWITCH_TYPE_MAX(sw) (SWITCH_3POS)
#else
-#define SWITCH_TYPE_MAX(sw) ((MIXSRC_SF-MIXSRC_FIRST_SWITCH == sw || MIXSRC_SH-MIXSRC_FIRST_SWITCH == sw) ? SWITCH_2POS : SWITCH_3POS)
+ #define SWITCH_TYPE_MAX(sw) ((MIXSRC_SF-MIXSRC_FIRST_SWITCH == sw || MIXSRC_SH-MIXSRC_FIRST_SWITCH == sw) ? SWITCH_2POS : SWITCH_3POS)
#endif
#define HW_SETTINGS_COLUMN1 30
@@ -152,16 +181,44 @@ enum MenuRadioHardwareItems {
void menuRadioHardware(event_t event)
{
- MENU(STR_HARDWARE, menuTabGeneral, MENU_RADIO_HARDWARE, HEADER_LINE+ITEM_RADIO_HARDWARE_MAX, { HEADER_LINE_COLUMNS 0, 0, 0, 0, 0, LABEL(Pots), POTS_ROWS, LABEL(Switches), SWITCHES_ROWS, 0/*max bauds*/, BLUETOOTH_ROWS 0/*jitter filter*/, 1 /* debugs */ });
+ MENU(STR_HARDWARE, menuTabGeneral, MENU_RADIO_HARDWARE, HEADER_LINE + ITEM_RADIO_HARDWARE_MAX, {
+ HEADER_LINE_COLUMNS
+ 0 /* calibration button */,
+ 0 /* stick 1 */,
+ 0 /* stick 2 */,
+ 0 /* stick 3 */,
+ 0 /* stick 4 */,
+ LABEL(Pots),
+ POTS_ROWS,
+ LABEL(Switches),
+ SWITCHES_ROWS,
+ 0 /* battery calib */,
+#if defined(STM32)
+ READONLY_ROW,
+#endif
+#if defined(TX_CAPACITY_MEASUREMENT)
+ 0,
+#endif
+#if defined(PCBSKY9X)
+ 0,
+#endif
+#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
+ 0 /* max bauds */,
+#endif
+ BLUETOOTH_ROWS
+ 0 /* jitter filter */,
+ 1 /* debugs */,
+ });
uint8_t sub = menuVerticalPosition - HEADER_LINE;
- for (uint8_t i=0; i0) ? BLINK|INVERS : INVERS);
uint8_t attr = (sub == k ? blink : 0);
@@ -186,7 +243,9 @@ void menuRadioHardware(event_t event)
break;
case ITEM_RADIO_HARDWARE_POT1:
+#if !defined(PCBX3)
case ITEM_RADIO_HARDWARE_POT2:
+#endif
{
int idx = k - ITEM_RADIO_HARDWARE_POT1;
uint8_t shift = (2*idx);
@@ -211,8 +270,10 @@ void menuRadioHardware(event_t event)
case ITEM_RADIO_HARDWARE_SB:
case ITEM_RADIO_HARDWARE_SC:
case ITEM_RADIO_HARDWARE_SD:
-#if NUM_SWITCHES > 4
+#if NUM_SWITCHES >= 5
case ITEM_RADIO_HARDWARE_SF:
+#endif
+#if NUM_SWITCHES >= 6
case ITEM_RADIO_HARDWARE_SH:
#endif
{
@@ -231,6 +292,55 @@ void menuRadioHardware(event_t event)
break;
}
+ case ITEM_RADIO_HARDWARE_BATTERY_CALIB:
+#if defined(PCBTARANIS)
+ lcdDrawTextAlignedLeft(y, STR_BATT_CALIB);
+ putsVolts(HW_SETTINGS_COLUMN2, y, getBatteryVoltage(), attr|PREC2|LEFT);
+#elif defined(PCBSKY9X)
+ lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+1+4*FH, STR_BATT_CALIB);
+ static int32_t adcBatt;
+ // TODO board.cpp
+ adcBatt = ((adcBatt * 7) + anaIn(TX_VOLTAGE)) / 8;
+ uint32_t batCalV = (adcBatt + adcBatt*(g_eeGeneral.txVoltageCalibration)/128) * 4191;
+ batCalV /= 55296;
+ putsVolts(HW_SETTINGS_COLUMN2, y, batCalV, (menuVerticalPosition==HEADER_LINE ? INVERS : 0));
+#else
+ lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT + 1 + (NUM_STICKS+NUM_POTS+NUM_SLIDERS+1)/2 * FH, STR_BATT_CALIB);
+ putsVolts(HW_SETTINGS_COLUMN2, y, g_vbat100mV, attr|LEFT);
+#endif
+ if (attr) {
+ CHECK_INCDEC_GENVAR(event, g_eeGeneral.txVoltageCalibration, -127, 127);
+ }
+ break;
+
+#if defined(STM32)
+ case ITEM_RADIO_HARDWARE_RTC_BATTERY:
+ lcdDrawTextAlignedLeft(y, "RTC Batt");
+ putsVolts(HW_SETTINGS_COLUMN2, y, vbattRTC, PREC2|LEFT);
+ break;
+#endif
+
+#if defined(TX_CAPACITY_MEASUREMENT)
+ case ITEM_RADIO_HARDWARE_CAPACITY_CALIB:
+ lcdDrawTextAlignedLeft(y, STR_CURRENT_CALIB);
+ drawValueWithUnit(HW_SETTINGS_COLUMN2, y, getCurrent(), UNIT_MILLIAMPS, attr);
+ if (attr) {
+ CHECK_INCDEC_GENVAR(event, g_eeGeneral.txCurrentCalibration, -49, 49);
+ }
+ break;
+#endif
+
+#if defined(PCBSKY9X)
+ case ITEM_RADIO_HARDWARE_TEMPERATURE_CALIB:
+ lcdDrawTextAlignedLeft(y, STR_TEMP_CALIB);
+ drawValueWithUnit(HW_SETTINGS_COLUMN2, y, getTemperature(), UNIT_TEMPERATURE, attr) ;
+ if (attr) {
+ CHECK_INCDEC_GENVAR(event, g_eeGeneral.temperatureCalib, -100, 100);
+ }
+ break;
+#endif
+
+#if defined(CROSSFIRE) && SPORT_MAX_BAUDRATE < 400000
case ITEM_RADIO_HARDWARE_SERIAL_BAUDRATE:
lcdDrawTextAlignedLeft(y, STR_MAXBAUDRATE);
lcdDrawNumber(HW_SETTINGS_COLUMN2, y, CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate], attr|LEFT);
@@ -248,6 +358,7 @@ void menuRadioHardware(event_t event)
}
}
break;
+#endif
#if defined(BLUETOOTH)
case ITEM_RADIO_HARDWARE_BLUETOOTH_MODE:
@@ -289,7 +400,7 @@ void menuRadioHardware(event_t event)
case ITEM_RADIO_HARDWARE_DEBUG:
lcdDrawTextAlignedLeft(y, STR_DEBUG);
lcdDrawText(HW_SETTINGS_COLUMN2, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0);
- lcdDrawText(lcdLastRightPos + 2, y, STR_SWITCHES_BTN, menuHorizontalPosition == 1 ? attr : 0);
+ lcdDrawText(lcdLastRightPos + 2, y, STR_KEYS_BTN, menuHorizontalPosition == 1 ? attr : 0);
if (attr && event == EVT_KEY_FIRST(KEY_ENTER)) {
if (menuHorizontalPosition == 0)
pushMenu(menuRadioDiagAnalogs);
diff --git a/radio/src/gui/128x64/radio_setup.cpp b/radio/src/gui/128x64/radio_setup.cpp
index ca8199462..2334fd44e 100644
--- a/radio/src/gui/128x64/radio_setup.cpp
+++ b/radio/src/gui/128x64/radio_setup.cpp
@@ -26,9 +26,9 @@ const unsigned char sticks[] = {
#include "sticks.lbm"
};
-#define RADIO_SETUP_2ND_COLUMN (LCD_W-6*FW-3)
+#define RADIO_SETUP_2ND_COLUMN (LCD_W-7*FW-3)
#define RADIO_SETUP_DATE_COLUMN (FW*15+7)
-#define RADIO_SETUP_TIME_COLUMN (FW*15+9)
+#define RADIO_SETUP_TIME_COLUMN (RADIO_SETUP_2ND_COLUMN + 2 * FWNUM)
#define SLIDER_5POS(y, value, label, event, attr) { \
int8_t tmp = value; \
@@ -88,6 +88,9 @@ enum MenuRadioSetupItems {
CASE_PWM_BACKLIGHT(ITEM_SETUP_BACKLIGHT_BRIGHTNESS_ON)
ITEM_SETUP_FLASH_BEEP,
CASE_SPLASH_PARAM(ITEM_SETUP_DISABLE_SPLASH)
+#if defined(PXX2)
+ ITEM_RADIO_OWNER_ID,
+#endif
CASE_GPS(ITEM_SETUP_TIMEZONE)
ITEM_SETUP_ADJUST_RTC,
CASE_GPS(ITEM_SETUP_GPSFORMAT)
@@ -97,6 +100,7 @@ enum MenuRadioSetupItems {
IF_FAI_CHOICE(ITEM_SETUP_FAI)
ITEM_SETUP_SWITCHES_DELAY,
CASE_STM32(ITEM_SETUP_USB_MODE)
+ CASE_JACK_DETECT(ITEM_SETUP_JACK_MODE)
ITEM_SETUP_RX_CHANNEL_ORD,
ITEM_SETUP_STICK_MODE_LABELS,
ITEM_SETUP_STICK_MODE,
@@ -131,7 +135,38 @@ void menuRadioSetup(event_t event)
}
#endif
- MENU(STR_MENURADIOSETUP, menuTabGeneral, MENU_RADIO_SETUP, HEADER_LINE+ITEM_SETUP_MAX, { HEADER_LINE_COLUMNS CASE_RTCLOCK(2) CASE_RTCLOCK(2) CASE_BATTGRAPH(1) LABEL(SOUND), CASE_AUDIO(0) CASE_BUZZER(0) 0, 0, 0, 0, 0, CASE_AUDIO(0) CASE_VARIO(LABEL(VARIO)) CASE_VARIO(0) CASE_VARIO(0) CASE_VARIO(0) CASE_VARIO(0) CASE_HAPTIC(LABEL(HAPTIC)) CASE_HAPTIC(0) CASE_HAPTIC(0) CASE_HAPTIC(0) 0, LABEL(ALARMS), 0, CASE_CAPACITY(0) CASE_PCBSKY9X(0) 0, 0, 0, 0, IF_ROTARY_ENCODERS(0) LABEL(BACKLIGHT), 0, 0, 0, CASE_PWM_BACKLIGHT(0) CASE_PWM_BACKLIGHT(0) 0, CASE_SPLASH_PARAM(0) CASE_GPS(0) 0, CASE_GPS(0) CASE_PXX(0) 0, 0, IF_FAI_CHOICE(0) 0, CASE_STM32(0) 0, COL_TX_MODE, 0, 1/*to force edit mode*/});
+ MENU(STR_MENURADIOSETUP, menuTabGeneral, MENU_RADIO_SETUP, HEADER_LINE+ITEM_SETUP_MAX, {
+ HEADER_LINE_COLUMNS CASE_RTCLOCK(2) CASE_RTCLOCK(2) CASE_BATTGRAPH(1)
+ LABEL(SOUND), CASE_AUDIO(0)
+ CASE_BUZZER(0)
+ 0, 0, 0, 0, 0, CASE_AUDIO(0)
+ CASE_VARIO(LABEL(VARIO))
+ CASE_VARIO(0)
+ CASE_VARIO(0)
+ CASE_VARIO(0)
+ CASE_VARIO(0)
+ CASE_HAPTIC(LABEL(HAPTIC))
+ CASE_HAPTIC(0)
+ CASE_HAPTIC(0)
+ CASE_HAPTIC(0)
+ 0, LABEL(ALARMS), 0, CASE_CAPACITY(0)
+ CASE_PCBSKY9X(0)
+ 0, 0, 0, 0, IF_ROTARY_ENCODERS(0)
+ LABEL(BACKLIGHT), 0, 0, 0, CASE_PWM_BACKLIGHT(0)
+ CASE_PWM_BACKLIGHT(0)
+ 0,
+ CASE_SPLASH_PARAM(0)
+#if defined(PXX2)
+ 0 /* owner registration ID */,
+#endif
+ CASE_GPS(0)
+ 0, CASE_GPS(0)
+ CASE_PXX(0)
+ 0, 0, IF_FAI_CHOICE(0)
+ 0,
+ CASE_STM32(0) // USB mode
+ CASE_JACK_DETECT(0) // Jack mode
+ 0, COL_TX_MODE, 0, 1/*to force edit mode*/});
if (event == EVT_ENTRY) {
reusableBuffer.generalSettings.stickMode = g_eeGeneral.stickMode;
@@ -156,11 +191,11 @@ void menuRadioSetup(event_t event)
switch (j) {
case 0:
lcdDrawNumber(RADIO_SETUP_DATE_COLUMN, y, t.tm_year+TM_YEAR_BASE, rowattr|RIGHT);
- if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0);
+ if (rowattr && s_editMode > 0) t.tm_year = checkIncDec(event, t.tm_year, 112, 200, 0);
break;
case 1:
lcdDrawNumber(RADIO_SETUP_DATE_COLUMN+3*FW-2, y, t.tm_mon+1, rowattr|LEADING0|RIGHT, 2);
- if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mon = checkIncDec(event, t.tm_mon, 0, 11, 0);
+ if (rowattr && s_editMode > 0) t.tm_mon = checkIncDec(event, t.tm_mon, 0, 11, 0);
break;
case 2:
{
@@ -169,7 +204,7 @@ void menuRadioSetup(event_t event)
static const uint8_t dmon[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
dlim += dmon[t.tm_mon];
lcdDrawNumber(RADIO_SETUP_DATE_COLUMN+6*FW-4, y, t.tm_mday, rowattr|LEADING0|RIGHT, 2);
- if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_mday = checkIncDec(event, t.tm_mday, 1, dlim, 0);
+ if (rowattr && s_editMode > 0) t.tm_mday = checkIncDec(event, t.tm_mday, 1, dlim, 0);
break;
}
}
@@ -187,15 +222,15 @@ void menuRadioSetup(event_t event)
switch (j) {
case 0:
lcdDrawNumber(RADIO_SETUP_TIME_COLUMN, y, t.tm_hour, rowattr|LEADING0|RIGHT, 2);
- if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_hour = checkIncDec(event, t.tm_hour, 0, 23, 0);
+ if (rowattr && s_editMode > 0) t.tm_hour = checkIncDec(event, t.tm_hour, 0, 23, 0);
break;
case 1:
lcdDrawNumber(RADIO_SETUP_TIME_COLUMN+3*FWNUM, y, t.tm_min, rowattr|LEADING0|RIGHT, 2);
- if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_min = checkIncDec(event, t.tm_min, 0, 59, 0);
+ if (rowattr && s_editMode > 0) t.tm_min = checkIncDec(event, t.tm_min, 0, 59, 0);
break;
case 2:
lcdDrawNumber(RADIO_SETUP_TIME_COLUMN+6*FWNUM, y, t.tm_sec, rowattr|LEADING0|RIGHT, 2);
- if (rowattr && (s_editMode>0 || p1valdiff)) t.tm_sec = checkIncDec(event, t.tm_sec, 0, 59, 0);
+ if (rowattr && s_editMode > 0) t.tm_sec = checkIncDec(event, t.tm_sec, 0, 59, 0);
break;
}
}
@@ -467,6 +502,12 @@ void menuRadioSetup(event_t event)
}
#endif
+#if defined(PXX2)
+ case ITEM_RADIO_OWNER_ID:
+ editSingleName(RADIO_SETUP_2ND_COLUMN, y, STR_OWNER_ID, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID, event, attr);
+ break;
+#endif
+
#if defined(TELEMETRY_FRSKY) && defined(GPS)
case ITEM_SETUP_TIMEZONE:
lcdDrawTextAlignedLeft(y, STR_TIMEZONE);
@@ -512,7 +553,7 @@ void menuRadioSetup(event_t event)
if (g_eeGeneral.fai)
POPUP_WARNING("FAI\001mode blocked!");
else
- POPUP_CONFIRMATION("FAI mode?");
+ POPUP_CONFIRMATION("FAI mode?", nullptr);
}
break;
#endif
@@ -524,11 +565,19 @@ void menuRadioSetup(event_t event)
lcdDrawText(lcdLastRightPos, y, STR_MS, attr);
if (attr) CHECK_INCDEC_GENVAR(event, g_eeGeneral.switchesDelay, -15, 100-15);
break;
+
#if defined(STM32)
case ITEM_SETUP_USB_MODE:
g_eeGeneral.USBMode = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_USBMODE, STR_USBMODES, g_eeGeneral.USBMode, USB_UNSELECTED_MODE, USB_MAX_MODE, attr, event);
break;
#endif
+
+#if defined(JACK_DETECT_GPIO)
+ case ITEM_SETUP_JACK_MODE:
+ g_eeGeneral.jackMode = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_JACKMODE, STR_JACKMODES, g_eeGeneral.jackMode, JACK_UNSELECTED_MODE, JACK_MAX_MODE, attr, event);
+ break;
+#endif
+
case ITEM_SETUP_RX_CHANNEL_ORD:
lcdDrawTextAlignedLeft(y, STR_RXCHANNELORD); // RAET->AETR
for (uint8_t i=1; i<=4; i++) {
diff --git a/radio/src/gui/128x64/radio_version.cpp b/radio/src/gui/128x64/radio_version.cpp
index 66c27cbef..9383f753b 100644
--- a/radio/src/gui/128x64/radio_version.cpp
+++ b/radio/src/gui/128x64/radio_version.cpp
@@ -18,8 +18,217 @@
* GNU General Public License for more details.
*/
+#include
#include "opentx.h"
+// TODO duplicated code
+#if defined(PCBX7) || defined(PCBX9E) || defined(PCBX3)
+#define EVT_KEY_NEXT_LINE EVT_ROTARY_RIGHT
+#define EVT_KEY_PREVIOUS_LINE EVT_ROTARY_LEFT
+#else
+#define EVT_KEY_NEXT_LINE EVT_KEY_FIRST(KEY_DOWN)
+#define EVT_KEY_PREVIOUS_LINE EVT_KEY_FIRST(KEY_UP)
+#endif
+
+#define MENU_BODY_TOP (FH + 1)
+#define MENU_BODY_BOTTOM (LCD_H)
+
+#if defined(PXX2)
+void drawPXX2Version(coord_t x, coord_t y, PXX2Version version)
+{
+ lcdDrawNumber(x, y, version.major, LEFT);
+ lcdDrawChar(lcdNextPos, y, '.');
+ lcdDrawNumber(lcdNextPos, y, version.minor, LEFT);
+ lcdDrawChar(lcdNextPos, y, '.');
+ lcdDrawNumber(lcdNextPos, y, version.revision, LEFT);
+}
+
+void drawPXX2FullVersion(coord_t x, coord_t y, PXX2Version hwVersion, PXX2Version swVersion)
+{
+ drawPXX2Version(x, y, hwVersion);
+ lcdDrawText(lcdNextPos, y, "/");
+ drawPXX2Version(lcdNextPos, y, swVersion);
+}
+
+static const char * const modulesModels[] = {
+ "---",
+ "XJT",
+ "IXJT",
+ "IXJT-PRO",
+ "IXJT-S",
+ "R9M",
+ "R9MLite",
+ "R9MLite-PRO",
+};
+
+static const char * const receiversModels[] = {
+ "---",
+ "X8R",
+ "RX8R",
+ "RX8R-PRO",
+ "RX6R",
+ "RX4R",
+ "G-RX8",
+ "G-RX6",
+ "X6R",
+ "X4R",
+ "X4R-SB",
+ "XSR",
+ "XSR-M",
+ "RXSR",
+ "S6R",
+ "S8R",
+ "XM",
+ "XM+",
+ "XMR",
+ "R9",
+ "R9-SLIM",
+ "R9-SLIM+",
+ "R9-MINI",
+ "R9-MM",
+ "R9-STAB",
+};
+
+void menuRadioModulesVersion(event_t event)
+{
+ if (menuEvent) {
+ moduleSettings[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ moduleSettings[EXTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ return;
+ }
+
+ TITLE("MODULES / RX VERSION");
+
+ if (event == EVT_ENTRY || get_tmr10ms() >= reusableBuffer.hardwareAndSettings.updateTime) {
+ // menuVerticalOffset = 0;
+
+ memclear(&reusableBuffer.hardwareAndSettings.modules, sizeof(reusableBuffer.hardwareAndSettings.modules));
+
+ if (isModulePXX2(INTERNAL_MODULE) && IS_INTERNAL_MODULE_ON()) {
+ reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].current = PXX2_HW_INFO_TX_ID;
+ reusableBuffer.hardwareAndSettings.modules[INTERNAL_MODULE].maximum = MAX_RECEIVERS_PER_MODULE - 1;
+ moduleSettings[INTERNAL_MODULE].mode = MODULE_MODE_GET_HARDWARE_INFO;
+ }
+
+ if (isModulePXX2(EXTERNAL_MODULE) && IS_EXTERNAL_MODULE_ON()) {
+ reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].current = PXX2_HW_INFO_TX_ID;
+ reusableBuffer.hardwareAndSettings.modules[EXTERNAL_MODULE].maximum = MAX_RECEIVERS_PER_MODULE - 1;
+ moduleSettings[EXTERNAL_MODULE].mode = MODULE_MODE_GET_HARDWARE_INFO;
+ }
+
+ reusableBuffer.hardwareAndSettings.updateTime = get_tmr10ms() + 1000 /* 10s*/;
+ }
+
+ coord_t y = (FH + 1) - menuVerticalOffset * FH;
+
+ for (uint8_t module=0; module= MENU_BODY_TOP && y < MENU_BODY_BOTTOM) {
+ if (module == INTERNAL_MODULE)
+ lcdDrawTextAlignedLeft(y, "Internal module");
+ else if (module == EXTERNAL_MODULE)
+ lcdDrawTextAlignedLeft(y, "External module");
+ }
+ y += FH;
+
+ // Module model
+ if (y >= MENU_BODY_TOP && y < MENU_BODY_BOTTOM) {
+ lcdDrawText(INDENT_WIDTH, y, "Model");
+ uint8_t modelId = reusableBuffer.hardwareAndSettings.modules[module].information.modelID;
+ if (modelId >= DIM(modulesModels))
+ modelId = 0;
+ lcdDrawText(12 * FW, y, modulesModels[modelId]);
+ }
+ y += FH;
+
+ // Module version
+ if (y >= MENU_BODY_TOP && y < MENU_BODY_BOTTOM) {
+ lcdDrawText(INDENT_WIDTH, y, "Version");
+ if (reusableBuffer.hardwareAndSettings.modules[module].information.modelID) {
+ drawPXX2FullVersion(12 * FW, y, reusableBuffer.hardwareAndSettings.modules[module].information.hwVersion, reusableBuffer.hardwareAndSettings.modules[module].information.swVersion);
+ }
+ }
+ y += FH;
+
+ for (uint8_t receiver=0; receiver= MENU_BODY_TOP && y < MENU_BODY_BOTTOM) {
+ lcdDrawText(INDENT_WIDTH, y, "Receiver");
+ lcdDrawNumber(lcdLastRightPos + 2, y, receiver + 1);
+ uint8_t modelId = reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.modelID;
+ if (modelId >= DIM(receiversModels))
+ modelId = 0;
+ lcdDrawText(12 * FW, y, receiversModels[modelId]);
+ }
+ y += FH;
+
+ // Receiver version
+ if (y >= MENU_BODY_TOP && y < MENU_BODY_BOTTOM) {
+ drawPXX2FullVersion(12 * FW, y, reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.hwVersion, reusableBuffer.hardwareAndSettings.modules[module].receivers[receiver].information.swVersion);
+ }
+ y += FH;
+ }
+ }
+ }
+
+ uint8_t lines = (y - (FH + 1)) / FH + menuVerticalOffset;
+ if (lines > NUM_BODY_LINES) {
+ drawVerticalScrollbar(LCD_W-1, FH, LCD_H-FH, menuVerticalOffset, lines, NUM_BODY_LINES);
+ }
+ else {
+ menuVerticalOffset = 0;
+ }
+
+ switch(event) {
+ case EVT_KEY_PREVIOUS_LINE:
+ if (lines > NUM_BODY_LINES) {
+ if (menuVerticalOffset-- == 0)
+ menuVerticalOffset = lines - 1;
+ }
+ break;
+
+ case EVT_KEY_NEXT_LINE:
+ if (lines > NUM_BODY_LINES) {
+ if (++menuVerticalOffset + NUM_BODY_LINES > lines)
+ menuVerticalOffset = 0;
+ }
+ break;
+
+ case EVT_KEY_BREAK(KEY_EXIT):
+ if (menuVerticalOffset != 0)
+ menuVerticalOffset = 0;
+ else
+ popMenu();
+ break;
+ }
+}
+#endif
+
+enum MenuRadioVersionItems
+{
+ ITEM_RADIO_VERSION_FIRST = HEADER_LINE - 1,
+#if defined(PXX2)
+ ITEM_RADIO_MODULES_VERSION,
+#endif
+#if defined(EEPROM_RLC)
+ ITEM_RADIO_BACKUP_EEPROM,
+ ITEM_RADIO_FACTORY_RESET,
+#endif
+ ITEM_RADIO_VERSION_COUNT
+};
+
void menuRadioVersion(event_t event)
{
#if defined(EEPROM_RLC)
@@ -31,40 +240,46 @@ void menuRadioVersion(event_t event)
}
#endif
- SIMPLE_MENU(STR_MENUVERSION, menuTabGeneral, MENU_RADIO_VERSION, 1);
+ SIMPLE_MENU(STR_MENUVERSION, menuTabGeneral, MENU_RADIO_VERSION, ITEM_RADIO_VERSION_COUNT);
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+FH, vers_stamp);
+ coord_t y = MENU_HEADER_HEIGHT + 1;
+ lcdDrawTextAlignedLeft(y, vers_stamp);
+ y += 4*FH;
+ // TODO this was good on AVR radios, but horrible now ...
#if defined(COPROCESSOR)
if (Coproc_valid == 1) {
- lcdDrawTextAlignedLeft(6*FH, "CoPr:");
- lcdDraw8bitsNumber(10*FW, 6*FH, Coproc_read);
+ lcdDrawTextAlignedLeft(y, "CoPr:");
+ lcdDraw8bitsNumber(10*FW, y, Coproc_read);
}
else {
- lcdDrawTextAlignedLeft(6*FH, "CoPr: ---");
+ lcdDrawTextAlignedLeft(y, "CoPr: ---");
}
-#elif defined(EEPROM_RLC)
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+5*FH+1, STR_EEBACKUP);
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+6*FH+1, STR_FACTORYRESET);
- lcdDrawFilledRect(0, MENU_HEADER_HEIGHT+5*FH, LCD_W, 2*FH+1, SOLID);
+ y += FH;
+#endif
-#if defined(PCBXLITE)
- if (event == EVT_KEY_LONG(KEY_ENTER)) {
- killEvents(KEY_ENTER);
- if (IS_SHIFT_PRESSED()) {
- POPUP_CONFIRMATION(STR_CONFIRMRESET);
- }
- else {
- eepromBackup();
- }
+#if defined(PXX2)
+ lcdDrawText(INDENT_WIDTH, y, BUTTON("Modules / RX version"), menuVerticalPosition == ITEM_RADIO_MODULES_VERSION ? INVERS : 0);
+ y += FH;
+ if (menuVerticalPosition == ITEM_RADIO_MODULES_VERSION && event == EVT_KEY_BREAK(KEY_ENTER)) {
+ s_editMode = EDIT_SELECT_FIELD;
+ pushMenu(menuRadioModulesVersion);
}
-#else
- if (event == EVT_KEY_LONG(KEY_ENTER)) {
+#endif
+
+#if defined(EEPROM_RLC)
+ lcdDrawText(INDENT_WIDTH, y, BUTTON(STR_EEBACKUP), menuVerticalPosition == ITEM_RADIO_BACKUP_EEPROM ? INVERS : 0);
+ y += FH;
+ if (menuVerticalPosition == ITEM_RADIO_BACKUP_EEPROM && event == EVT_KEY_BREAK(KEY_ENTER)) {
+ s_editMode = EDIT_SELECT_FIELD;
eepromBackup();
}
- else if (event == EVT_KEY_LONG(KEY_MENU)) {
- POPUP_CONFIRMATION(STR_CONFIRMRESET);
+
+ lcdDrawText(INDENT_WIDTH, y, BUTTON(STR_FACTORYRESET), menuVerticalPosition == ITEM_RADIO_FACTORY_RESET ? INVERS : 0);
+ // y += FH;
+ if (menuVerticalPosition == ITEM_RADIO_FACTORY_RESET && event == EVT_KEY_BREAK(KEY_ENTER)) {
+ s_editMode = EDIT_SELECT_FIELD;
+ POPUP_CONFIRMATION(STR_CONFIRMRESET, nullptr);
}
#endif
-#endif
}
diff --git a/radio/src/gui/128x64/view_main.cpp b/radio/src/gui/128x64/view_main.cpp
index 43401c55e..6be26d9e9 100644
--- a/radio/src/gui/128x64/view_main.cpp
+++ b/radio/src/gui/128x64/view_main.cpp
@@ -143,7 +143,7 @@ void displayTrims(uint8_t phase)
}
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && dir != 0) {
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<0 ? 12 : 40, xm-2, -abs(dir/5), TINSIZE|VERTICAL);
+ lcdDrawNumber(dir>0 ? 12 : 40, xm-2, -abs(dir), TINSIZE|VERTICAL);
}
}
}
@@ -165,7 +165,7 @@ void displayTrims(uint8_t phase)
}
if (g_model.displayTrims != DISPLAY_TRIMS_NEVER && dir != 0) {
if (g_model.displayTrims == DISPLAY_TRIMS_ALWAYS || (trimsDisplayTimer > 0 && (trimsDisplayMask & (1<0 ? TRIM_LH_POS : TRIM_LH_NEG) : (dir>0 ? TRIM_RH_POS : TRIM_RH_NEG)), ym-2, -abs(dir/5), TINSIZE);
+ lcdDrawNumber((stickIndex==0 ? (dir>0 ? TRIM_LH_POS : TRIM_LH_NEG) : (dir>0 ? TRIM_RH_POS : TRIM_RH_NEG)), ym-2, -abs(dir), TINSIZE);
}
}
}
@@ -227,7 +227,7 @@ void displayVoltageOrAlarm()
#define displayVoltageOrAlarm() displayBattVoltage()
#endif
-#if defined(PCBX7)
+#if defined(PCBX7) || defined(PCBX3)
#define EVT_KEY_CONTEXT_MENU EVT_KEY_LONG(KEY_ENTER)
#define EVT_KEY_NEXT_VIEW EVT_KEY_BREAK(KEY_PAGE)
#define EVT_KEY_NEXT_PAGE EVT_ROTARY_RIGHT
@@ -258,7 +258,6 @@ void displayVoltageOrAlarm()
#define EVT_KEY_STATISTICS EVT_KEY_LONG(KEY_UP)
#endif
-#if defined(NAVIGATION_MENUS)
void onMainViewMenu(const char *result)
{
if (result == STR_RESET_TIMER1) {
@@ -299,7 +298,6 @@ void onMainViewMenu(const char *result)
chainMenu(menuAboutView);
}
}
-#endif
void menuMainView(event_t event)
{
@@ -334,7 +332,6 @@ void menuMainView(event_t event)
}
break;
-#if defined(NAVIGATION_MENUS)
case EVT_KEY_CONTEXT_MENU:
killEvents(event);
@@ -348,7 +345,6 @@ void menuMainView(event_t event)
POPUP_MENU_ADD_ITEM(STR_ABOUT_US);
POPUP_MENU_START(onMainViewMenu);
break;
-#endif
#if MENUS_LOCK != 2 /*no menus*/
#if defined(EVT_KEY_LAST_MENU)
@@ -403,23 +399,12 @@ void menuMainView(event_t event)
break;
case EVT_KEY_FIRST(KEY_EXIT):
-#if defined(GVARS) && !defined(PCBSTD)
+#if defined(GVARS)
if (gvarDisplayTimer > 0) {
gvarDisplayTimer = 0;
}
-#endif
-#if !defined(NAVIGATION_MENUS)
- if (view == VIEW_TIMER2) {
- timerReset(1);
- }
#endif
break;
-
-#if !defined(NAVIGATION_MENUS)
- case EVT_KEY_LONG(KEY_EXIT):
- flightReset();
- break;
-#endif
}
{
@@ -499,7 +484,17 @@ void menuMainView(event_t event)
doMainScreenGraphics();
// Switches
-#if defined(PCBTARANIS)
+#if defined(PCBX3)
+ static const uint8_t x[NUM_SWITCHES] = {2*FW-2, 2*FW-2, 16*FW+1, 2*FW-2, 16*FW+1};
+ static const uint8_t y[NUM_SWITCHES] = {4*FH+1, 5*FH+1, 5*FH+1, 6*FH+1, 6*FH+1};
+ for (int i=0; i 0) {
gvarDisplayTimer--;
warningText = STR_GLOBAL_VAR;
- drawMessageBox();
+ drawMessageBox(warningText);
lcdDrawSizedText(16, 5*FH, g_model.gvars[gvarLastChanged].name, LEN_GVAR_NAME, ZCHAR);
lcdDrawText(16+6*FW, 5*FH, "[", BOLD);
drawGVarValue(lcdLastRightPos, 5*FH, gvarLastChanged, GVAR_VALUE(gvarLastChanged, getGVarFlightMode(mixerCurrentFlightMode, gvarLastChanged)), LEFT|BOLD);
@@ -573,7 +568,7 @@ void menuMainView(event_t event)
#endif
#if defined(DSM2)
- if (moduleFlag[0] == MODULE_BIND) {
+ if (moduleSettings[0].mode == MODULE_MODE_BIND) {
// Issue 98
lcdDrawText(15*FW, 0, "BIND", 0);
}
diff --git a/radio/src/gui/128x64/widgets.cpp b/radio/src/gui/128x64/widgets.cpp
index cec799981..6ac179599 100644
--- a/radio/src/gui/128x64/widgets.cpp
+++ b/radio/src/gui/128x64/widgets.cpp
@@ -74,7 +74,7 @@ choice_t editChoice(coord_t x, coord_t y, const char * label, const char *values
{
drawFieldLabel(x, y, label);
if (values) lcdDrawTextAtIndex(x, y, values, value-min, attr);
- if (attr & (~RIGHT)) value = checkIncDec(event, value, min, max, (menuVerticalPositions[0] == 0) ? EE_MODEL : EE_GENERAL);
+ if (attr & (~RIGHT)) value = checkIncDec(event, value, min, max, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL);
return value;
}
@@ -230,22 +230,6 @@ void drawStatusLine()
}
#endif
-void drawProgressBar(const char * label, int num, int den)
-{
- lcdClear();
- if (label) {
- lcdDrawTextAlignedLeft(4*FH, label);
- }
- lcdDrawRect(4, 6*FH+4, LCD_W-8, 7);
- if (num > 0 && den > 0) {
- int width = ((LCD_W-12)*num)/den;
- lcdDrawSolidHorizontalLine(6, 6*FH+6, width, FORCE);
- lcdDrawSolidHorizontalLine(6, 6*FH+7, width, FORCE);
- lcdDrawSolidHorizontalLine(6, 6*FH+8, width, FORCE);
- }
- lcdRefresh();
-}
-
const unsigned char SLEEP_BITMAP[] = {
#include "sleep.lbm"
};
diff --git a/radio/src/gui/212x64/gui.h b/radio/src/gui/212x64/gui.h
index 843cc41d9..6922ae328 100644
--- a/radio/src/gui/212x64/gui.h
+++ b/radio/src/gui/212x64/gui.h
@@ -32,7 +32,6 @@
#define DEFAULT_SCROLLBAR_X (LCD_W-1)
#define NUM_BODY_LINES (LCD_LINES-1)
#define MENU_HEADER_HEIGHT FH
-#define MENU_INIT_VPOS 0
#define MODEL_BITMAP_WIDTH 64
#define MODEL_BITMAP_HEIGHT 32
@@ -55,11 +54,6 @@ inline void drawFieldLabel(coord_t x, coord_t y, const char * str)
extern uint8_t modelBitmap[MODEL_BITMAP_SIZE];
bool loadModelBitmap(char * name, uint8_t * bitmap);
-struct MenuItem {
- const char * name;
- const MenuHandlerFunc action;
-};
-
// Temporary no highlight
extern uint8_t noHighlightCounter;
#define NO_HIGHLIGHT() (noHighlightCounter > 0)
@@ -71,8 +65,6 @@ void drawSplash();
void drawSecondSplash();
void drawScreenIndex(uint8_t index, uint8_t count, uint8_t attr);
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
-void displayMenuBar(const MenuItem * menu, int index);
-void drawProgressBar(const char * label, int num, int den);
void drawGauge(coord_t x, coord_t y, coord_t w, coord_t h, int32_t val, int32_t max);
void drawColumnHeader(const char * const * headers, uint8_t index);
void drawStick(coord_t centrex, int16_t xval, int16_t yval);
@@ -86,15 +78,13 @@ typedef uint16_t FlightModesType;
extern int8_t checkIncDec_Ret; // global helper vars
-#define EDIT_SELECT_MENU -1
#define EDIT_SELECT_FIELD 0
#define EDIT_MODIFY_FIELD 1
#define EDIT_MODIFY_STRING 2
extern int8_t s_editMode; // global editmode
// checkIncDec flags
-#define EE_GENERAL 0x01
-#define EE_MODEL 0x02
+// we leave room for EE_MODEL and EE_GENERAL
#define NO_INCDEC_MARKS 0x04
#define INCDEC_SWITCH 0x08
#define INCDEC_SOURCE 0x10
@@ -107,7 +97,8 @@ extern int8_t s_editMode; // global editmode
#define CHECK_INCDEC_PARAM(event, var, min, max) checkIncDec(event, var, min, max, incdecFlag, isValueAvailable)
// mawrow special values
-#define TITLE_ROW ((uint8_t)-1)
+#define READONLY_ROW ((uint8_t)-1)
+#define TITLE_ROW READONLY_ROW
#define HIDDEN_ROW ((uint8_t)-2)
struct CheckIncDecStops
@@ -257,15 +248,10 @@ uint8_t editDelay(coord_t y, event_t event, uint8_t attr, const char * str, uint
#define WARNING_TYPE_ASTERISK 0
#define WARNING_TYPE_CONFIRM 1
#define WARNING_TYPE_INPUT 2
+#define WARNING_TYPE_INFO 4
void copySelection(char * dst, const char * src, uint8_t size);
-extern const char * warningText;
-extern const char * warningInfoText;
-extern uint8_t warningInfoLength;
-extern uint8_t warningResult;
-extern uint8_t warningType;
-
#define COPY_MODE 1
#define MOVE_MODE 2
extern uint8_t s_copyMode;
diff --git a/radio/src/gui/212x64/lcd.cpp b/radio/src/gui/212x64/lcd.cpp
index 104bbcc34..0ba2ef825 100644
--- a/radio/src/gui/212x64/lcd.cpp
+++ b/radio/src/gui/212x64/lcd.cpp
@@ -244,7 +244,7 @@ uint8_t getTextWidth(const char * s, uint8_t len, LcdFlags flags)
{
uint8_t width = 0;
for (int i=0; len==0 || i
+
+extern uint8_t g_moduleIdx;
+
+void menuModelFailsafe(event_t event)
+{
+ static uint8_t maxNameLen = 4;
+ static int8_t lastModel = g_eeGeneral.currModel;
+ const coord_t barH = (LCD_H - FH) / 8 - 1;
+ const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
+ const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
+ uint8_t cols = 1;
+ uint8_t colW = LCD_W;
+
+ if (lastModel != g_eeGeneral.currModel) {
+ lastModel = g_eeGeneral.currModel;
+ maxNameLen = 4;
+ }
+
+ if (event == EVT_KEY_LONG(KEY_ENTER)) {
+ killEvents(event);
+ event = 0;
+
+ if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) {
+ if (s_editMode) {
+ g_model.failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart];
+ s_editMode = 0;
+ }
+ else {
+ int16_t & failsafe = g_model.failsafeChannels[menuVerticalPosition];
+ if (failsafe < FAILSAFE_CHANNEL_HOLD)
+ failsafe = FAILSAFE_CHANNEL_HOLD;
+ else if (failsafe == FAILSAFE_CHANNEL_HOLD)
+ failsafe = FAILSAFE_CHANNEL_NOPULSE;
+ else
+ failsafe = 0;
+ }
+ }
+ else {
+ // "Outputs => Failsafe" menu item
+ setCustomFailsafe(g_moduleIdx);
+ }
+
+ storageDirty(EE_MODEL);
+ AUDIO_WARNING1();
+ SEND_FAILSAFE_NOW(g_moduleIdx);
+ }
+
+ SIMPLE_SUBMENU_NOTITLE(sentModuleChannels(g_moduleIdx) + 1);
+ SET_SCROLLBAR_X(0);
+
+ if (sentModuleChannels(g_moduleIdx) > 8) {
+ cols = 2;
+ colW = LCD_W / cols - 1;
+ // Column separator
+ if (menuVerticalPosition >= sentModuleChannels(g_moduleIdx)) {
+ lcdDrawSolidVerticalLine(colW, FH, LCD_H - (FH*2 + FH/2 + 2));
+ }
+ else {
+ lcdDrawSolidVerticalLine(colW, FH, LCD_H - FH);
+ }
+ }
+
+ lcdDrawTextAlignedCenter(0, FAILSAFESET);
+ lcdInvertLine(0);
+
+ coord_t x = colW;
+ for (uint8_t col = 0; col < cols; col++) {
+
+ coord_t y = FH + 1;
+ uint8_t line = (menuVerticalPosition >= sentModuleChannels(g_moduleIdx) ? 2 : 0);
+ uint8_t ch = line + col*8;
+
+ for (; line < 8; line++) {
+ const int32_t channelValue = channelOutputs[ch+channelStart];
+ int32_t failsafeValue = g_model.failsafeChannels[8*col+line];
+ uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name);
+ uint8_t barW = colW - FW * maxNameLen - FWNUM * 3; // default bar width
+
+#if defined(PPM_UNIT_PERCENT_PREC1)
+ barW -= FWNUM + 1;
+#endif
+ barW += (barW % 2);
+
+ // Channel name if present, number if not
+ if (lenLabel > 0) {
+ if (lenLabel > maxNameLen)
+ maxNameLen = lenLabel;
+ lcdDrawSizedText(x - colW, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE);
+ }
+ else {
+ putsChn(x - colW, y, ch+1, SMLSIZE);
+ }
+
+ // Value
+ LcdFlags flags = TINSIZE;
+ if (menuVerticalPosition == ch) {
+ flags |= INVERS;
+ if (s_editMode) {
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ s_editMode = 0;
+ }
+ else {
+ flags |= BLINK;
+ CHECK_INCDEC_MODELVAR(event, g_model.failsafeChannels[8*col+line], -lim, +lim);
+ }
+ }
+ }
+
+ const coord_t xValue = x - barW;
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ lcdDrawText(xValue, y, STR_HOLD, RIGHT|flags);
+ failsafeValue = 0;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ lcdDrawText(xValue, y, STR_NONE, RIGHT|flags);
+ failsafeValue = 0;
+ }
+ else {
+#if defined(PPM_UNIT_US)
+ lcdDrawNumber(xValue, y, PPM_CH_CENTER(ch)+failsafeValue/2, RIGHT|flags);
+#elif defined(PPM_UNIT_PERCENT_PREC1)
+ lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue), RIGHT|PREC1|flags);
+#else
+ lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue)/10, RIGHT|flags);
+#endif
+ }
+
+ // Gauge
+ lcdDrawRect(x - barW, y, barW - 1, barH);
+ barW = barW / 2 - 1;
+ const coord_t lenChannel = limit(1, (abs(channelValue) * barW + lim / 2) / lim, barW);
+ const coord_t lenFailsafe = limit(1, (abs(failsafeValue) * barW + lim / 2) / lim, barW);
+ const coord_t barX = x - barW - 2;
+ const coord_t xChannel = (channelValue >= 0) ? barX : barX - lenChannel + 1;
+ const coord_t xFailsafe = (failsafeValue > 0) ? barX : barX - lenFailsafe + 1;
+ lcdDrawHorizontalLine(xChannel, y+1, lenChannel, DOTTED, 0);
+ lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
+ lcdDrawSolidHorizontalLine(xFailsafe, y+3, lenFailsafe);
+ lcdDrawSolidHorizontalLine(xFailsafe, y+4, lenFailsafe);
+
+ if (++ch >= sentModuleChannels(g_moduleIdx))
+ break;
+
+ y += barH + 1;
+
+ } // channels
+
+ x += colW + 2;
+
+ } // columns
+
+ if (menuVerticalPosition >= sentModuleChannels(g_moduleIdx)) {
+ // Outputs => Failsafe
+ lcdDrawText(CENTER_OFS, LCD_H - (FH + 1), STR_OUTPUTS2FAILSAFE, INVERS);
+ }
+}
diff --git a/radio/src/io/pxx2.h b/radio/src/gui/212x64/model_module_options.cpp
similarity index 84%
rename from radio/src/io/pxx2.h
rename to radio/src/gui/212x64/model_module_options.cpp
index 3a1506a67..f72d3594f 100644
--- a/radio/src/io/pxx2.h
+++ b/radio/src/gui/212x64/model_module_options.cpp
@@ -18,10 +18,4 @@
* GNU General Public License for more details.
*/
-#ifndef _IO_PXX2_H_
-#define _IO_PXX2_H_
-
-#define PXX2_BAUDRATE 230400
-#define PXX2_PERIOD 4 // 4ms
-
-#endif
+#include
diff --git a/radio/src/gui/212x64/model_receiver_options.cpp b/radio/src/gui/212x64/model_receiver_options.cpp
new file mode 100644
index 000000000..f72d3594f
--- /dev/null
+++ b/radio/src/gui/212x64/model_receiver_options.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
diff --git a/radio/src/gui/212x64/model_select.cpp b/radio/src/gui/212x64/model_select.cpp
index 7eb4bb8a3..758abc31b 100644
--- a/radio/src/gui/212x64/model_select.cpp
+++ b/radio/src/gui/212x64/model_select.cpp
@@ -52,10 +52,10 @@ void onModelSelectMenu(const char * result)
else if (result == STR_DELETE_MODEL) {
char * nametmp = reusableBuffer.modelsel.mainname;
strcat_modelname (nametmp, sub);
- POPUP_CONFIRMATION(STR_DELETEMODEL);
+ POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr);
SET_WARNING_INFO(nametmp, sizeof(g_model.header.name), 0);
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a file on SD to restore
storageCheck(true);
POPUP_WARNING(eeRestoreModel(sub, (char *)result));
@@ -102,7 +102,7 @@ void menuModelSelect(event_t event)
if (s_copyMode && s_copyTgtOfs == 0 && g_eeGeneral.currModel != sub && eeModelExists(sub)) {
char * nametmp = reusableBuffer.modelsel.mainname;
strcat_modelname (nametmp, sub);
- POPUP_CONFIRMATION(STR_DELETEMODEL);
+ POPUP_CONFIRMATION(STR_DELETEMODEL, nullptr);
SET_WARNING_INFO(nametmp, sizeof(g_model.header.name), 0);
killEvents(event);
break;
diff --git a/radio/src/gui/212x64/model_setup.cpp b/radio/src/gui/212x64/model_setup.cpp
index 4f8c5ead2..02626db28 100644
--- a/radio/src/gui/212x64/model_setup.cpp
+++ b/radio/src/gui/212x64/model_setup.cpp
@@ -88,6 +88,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND,
#endif
ITEM_MODEL_EXTERNAL_MODULE_POWER,
+ ITEM_MODEL_EXTERNAL_MODULE_FREQ,
ITEM_MODEL_TRAINER_LABEL,
ITEM_MODEL_TRAINER_MODE,
ITEM_MODEL_TRAINER_LINE1,
@@ -103,7 +104,7 @@ enum MenuModelSetupItems {
#define MODEL_SETUP_RANGE_OFS 7*FW
#define MODEL_SETUP_SET_FAILSAFE_OFS 10*FW-2
-#define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE))
+#define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE)
void onBindMenu(const char * result)
{
@@ -129,7 +130,7 @@ void onBindMenu(const char * result)
return;
}
- moduleFlag[moduleIdx] = MODULE_BIND;
+ moduleSettings[moduleIdx].mode = MODULE_MODE_BIND;
}
void copySelection(char * dst, const char * src, uint8_t size)
@@ -147,7 +148,7 @@ void onModelSetupBitmapMenu(const char * result)
POPUP_WARNING(STR_NO_BITMAPS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a bmp file in the list
copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap));
memcpy(modelHeaders[g_eeGeneral.currModel].bitmap, g_model.header.bitmap, sizeof(g_model.header.bitmap));
@@ -239,21 +240,22 @@ int getSwitchWarningsCount()
#define INTERNAL_MODULE_MODE_ROWS 0 // (OFF / RF protocols)
#endif
#define IF_EXTERNAL_MODULE_ON(x) (IS_EXTERNAL_MODULE_ENABLED() ? (uint8_t)(x) : HIDDEN_ROW)
-#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1)
+
#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 1))
#if defined(BLUETOOTH) && defined(USEHORUSBT)
#define TRAINER_LINE1_BLUETOOTH_M_ROWS ((bluetoothDistantAddr[0] == 0 || bluetoothState == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
- #define TRAINER_LINE1_ROWS (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)1 : (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_LINE1_BLUETOOTH_M_ROWS : (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH ? (uint8_t)1 : HIDDEN_ROW)))
- #define TRAINER_LINE2_ROWS (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
+ #define TRAINER_LINE1_ROWS (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_LINE1_BLUETOOTH_M_ROWS : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? (uint8_t)1 : HIDDEN_ROW)))
+ #define TRAINER_LINE2_ROWS (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
#else
- #define TRAINER_LINE1_ROWS (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)1 : HIDDEN_ROW)
- #define TRAINER_LINE2_ROWS (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
+ #define TRAINER_LINE1_ROWS (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : HIDDEN_ROW)
+ #define TRAINER_LINE2_ROWS (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
#endif
#define TIMER_ROWS(x) 2|NAVIGATION_LINE_BY_LINE, 0, 0, 0, g_model.timers[x].countdownBeep != COUNTDOWN_SILENT ? (uint8_t) 1 : (uint8_t)0
-#define EXTERNAL_MODULE_MODE_ROWS (isModulePXX(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : isModuleMultimodule(EXTERNAL_MODULE) ? MULTIMODULE_MODE_ROWS(EXTERNAL_MODULE) : (uint8_t)0
+#define EXTERNAL_MODULE_MODE_ROWS (isModuleXJT(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0
+#define EXTRA_MODULE_ROWS isR9MMFlex(EXTERNAL_MODULE) ? (uint8_t)1: (uint8_t)HIDDEN_ROW,
#if TIMERS == 1
#define TIMERS_ROWS TIMER_ROWS(0)
@@ -296,18 +298,19 @@ void menuModelSetup(event_t event)
EXTERNAL_MODULE_OPTION_ROW,
MULTIMODULE_MODULE_ROWS
EXTERNAL_MODULE_POWER_ROW,
+ EXTRA_MODULE_ROWS
LABEL(Trainer), 0, TRAINER_LINE1_ROWS, TRAINER_LINE2_ROWS});
MENU_CHECK(STR_MENUSETUP, menuTabModel, MENU_MODEL_SETUP, ITEM_MODEL_SETUP_MAX);
if (event == EVT_ENTRY) {
- reusableBuffer.modelsetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power;
+ reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power;
}
#if (defined(DSM2) || defined(PXX))
if (menuEvent) {
- moduleFlag[0] = 0;
- moduleFlag[1] = 0;
+ moduleSettings[0].mode = 0;
+ moduleSettings[1].mode = 0;
}
#endif
@@ -710,9 +713,9 @@ void menuModelSetup(event_t event)
#endif
case ITEM_MODEL_TRAINER_MODE:
lcdDrawTextAlignedLeft(y, STR_MODE);
- lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerMode, attr);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, attr);
if (attr) {
- g_model.trainerMode = checkIncDec(event, g_model.trainerMode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable);
+ g_model.trainerData.mode = checkIncDec(event, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), EE_MODEL, isTrainerModeAvailable);
}
#if defined(BLUETOOTH) && defined(USEHORUSBT)
if (attr && checkIncDec_Ret) {
@@ -733,8 +736,8 @@ void menuModelSetup(event_t event)
lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
else if (isModuleDSM2(EXTERNAL_MODULE))
lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, menuHorizontalPosition==1 ? attr : 0);
- else if (isModuleR9M(EXTERNAL_MODULE))
- lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0));
+ else if (isR9ModuleRunning(EXTERNAL_MODULE))
+ lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].r9m.region, (menuHorizontalPosition==1 ? attr : 0));
#if defined(MULTIMODULE)
else if (isModuleMultimodule(EXTERNAL_MODULE)) {
uint8_t multi_rfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false);
@@ -757,7 +760,7 @@ void menuModelSetup(event_t event)
if (attr && s_editMode>0) {
switch (menuHorizontalPosition) {
case 0:
- g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, IS_TRAINER_EXTERNAL_MODULE() ? MODULE_TYPE_NONE : MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable);
+ g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, IS_TRAINER_EXTERNAL_MODULE() ? MODULE_TYPE_NONE : MODULE_TYPE_COUNT-1, EE_MODEL, isExternalModuleAvailable);
if (checkIncDec_Ret) {
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
@@ -771,15 +774,6 @@ void menuModelSetup(event_t event)
case 1:
if (isModuleDSM2(EXTERNAL_MODULE))
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
- else if (isModuleR9M(EXTERNAL_MODULE)) {
- uint8_t newR9MType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].subType, MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_LAST, EE_MODEL, isR9MModeAvailable);
- if (newR9MType != g_model.moduleData[EXTERNAL_MODULE].subType && newR9MType > MODULE_SUBTYPE_R9M_EU) {
- POPUP_WARNING(STR_R9MFLEXWARN1);
- const char * w = STR_R9MFLEXWARN2;
- SET_WARNING_INFO(w, strlen(w), 0);
- }
- g_model.moduleData[EXTERNAL_MODULE].subType = newR9MType;
- }
#if defined(MULTIMODULE)
else if (isModuleMultimodule(EXTERNAL_MODULE)) {
int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].multi.customProto == 1 ? MM_RF_PROTO_CUSTOM : g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false);
@@ -835,7 +829,7 @@ void menuModelSetup(event_t event)
#if defined(BLUETOOTH) && defined(USEHORUSBT)
case ITEM_MODEL_TRAINER_LINE1:
- if (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH) {
+ if (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH) {
if (attr) {
s_editMode = 0;
}
@@ -876,7 +870,24 @@ void menuModelSetup(event_t event)
// no break
#else
case ITEM_MODEL_TRAINER_LINE1:
+ lcdDrawTextAlignedLeft(y, STR_CHANNELRANGE);
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_CH, menuHorizontalPosition==0 ? attr : 0);
+ lcdDrawNumber(lcdLastRightPos, y, g_model.trainerData.channelsStart+1, LEFT | (menuHorizontalPosition==0 ? attr : 0));
+ lcdDrawChar(lcdLastRightPos, y, '-');
+ lcdDrawNumber(lcdLastRightPos + FW+1, y, g_model.trainerData.channelsStart+8+g_model.trainerData.channelsCount, LEFT | (menuHorizontalPosition==1 ? attr : 0));
+ if (attr && s_editMode>0) {
+ switch (menuHorizontalPosition) {
+ case 0:
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.trainerData.channelsStart, 32-8-g_model.trainerData.channelsCount);
+ break;
+ case 1:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.channelsCount, -4, min(MAX_TRAINER_CHANNELS_M8, 32-8-g_model.trainerData.channelsStart));
+ break;
+ }
+ }
+ break;
#endif
+
case ITEM_MODEL_INTERNAL_MODULE_CHANNELS:
case ITEM_MODEL_EXTERNAL_MODULE_CHANNELS:
{
@@ -917,9 +928,30 @@ void menuModelSetup(event_t event)
break;
}
+ case ITEM_MODEL_TRAINER_LINE2:
+ lcdDrawTextAlignedLeft(y, STR_PPMFRAME);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.trainerData.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT);
+ lcdDrawText(lcdLastRightPos, y, STR_MS);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+6*FW, y, (g_model.trainerData.delay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr : 0);
+ lcdDrawChar(lcdLastRightPos, y, 'u');
+ lcdDrawChar(MODEL_SETUP_2ND_COLUMN+12*FW, y, g_model.trainerData.pulsePol ? '+' : '-', (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0);
+ if (attr && s_editMode>0) {
+ switch (menuHorizontalPosition) {
+ case 0:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.frameLength, -20, 35);
+ break;
+ case 1:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.delay, -4, 10);
+ break;
+ case 2:
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.trainerData.pulsePol, 1);
+ break;
+ }
+ }
+ break;
+
case ITEM_MODEL_INTERNAL_MODULE_BIND:
case ITEM_MODEL_EXTERNAL_MODULE_BIND:
- case ITEM_MODEL_TRAINER_LINE2:
{
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
ModuleData & moduleData = g_model.moduleData[moduleIdx];
@@ -1029,27 +1061,27 @@ void menuModelSetup(event_t event)
POPUP_MENU_START(onBindMenu);
continue;
}
- if (moduleFlag[moduleIdx] == MODULE_BIND) {
- newFlag = MODULE_BIND;
+ if (moduleSettings[moduleIdx].mode == MODULE_MODE_BIND) {
+ newFlag = MODULE_MODE_BIND;
}
else {
- if (!popupMenuNoItems) {
+ if (!popupMenuItemsCount) {
s_editMode = 0; // this is when popup is exited before a choice is made
}
}
}
else {
- newFlag = MODULE_BIND;
+ newFlag = MODULE_MODE_BIND;
}
}
else if (l_posHorz == 2) {
- newFlag = MODULE_RANGECHECK;
+ newFlag = MODULE_MODE_RANGECHECK;
}
}
}
- moduleFlag[moduleIdx] = newFlag;
+ moduleSettings[moduleIdx].mode = newFlag;
#if defined(MULTIMODULE)
- if (newFlag == MODULE_BIND)
+ if (newFlag == MODULE_MODE_BIND)
multiBindStatus = MULTI_BIND_INITIATED;
#endif
}
@@ -1129,16 +1161,7 @@ void menuModelSetup(event_t event)
}
}
#endif
- if (isModuleR9M(moduleIdx)) {
- lcdDrawTextAlignedLeft(y, STR_MODULE_TELEMETRY);
- if (IS_TELEMETRY_INTERNAL_MODULE()) {
- lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL);
- }
- else {
- lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON);
- }
- }
- else if (isModuleSBUS(moduleIdx)) {
+ if (isModuleSBUS(moduleIdx)) {
lcdDrawTextAlignedLeft(y, STR_WARN_BATTVOLTAGE);
putsVolts(lcdLastRightPos, y, getBatteryVoltage(), attr | PREC2 | LEFT);
}
@@ -1159,10 +1182,10 @@ void menuModelSetup(event_t event)
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9M_LBT_POWER_VALUES, g_model.moduleData[moduleIdx].pxx.power, LEFT | attr);
if (attr)
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].pxx.power, 0, R9M_LBT_POWER_MAX);
- if (attr && s_editMode == 0 && reusableBuffer.modelsetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) {
- if((reusableBuffer.modelsetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) //switching between mode 2 and 3 does not require rebind
+ if (attr && s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) {
+ if((reusableBuffer.moduleSetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) //switching between mode 2 and 3 does not require rebind
POPUP_WARNING(STR_REBIND);
- reusableBuffer.modelsetup.r9mPower = g_model.moduleData[moduleIdx].pxx.power;
+ reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[moduleIdx].pxx.power;
}
}
}
@@ -1174,6 +1197,18 @@ void menuModelSetup(event_t event)
break;
}
+ case ITEM_MODEL_EXTERNAL_MODULE_FREQ:
+ {
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ lcdDrawTextAlignedLeft(y, STR_FREQUENCY);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9MFLEX_FREQ, g_model.moduleData[moduleIdx].r9m.freq, LEFT | attr);
+ if (attr)
+ {
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[moduleIdx].r9m.freq, 1);
+ }
+ }
+ break;
+
#if defined (MULTIMODULE)
case ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND:
if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MM_RF_PROTO_DSM2)
@@ -1205,7 +1240,7 @@ void menuModelSetup(event_t event)
#if defined(PXX)
if (IS_RANGECHECK_ENABLE()) {
showMessageBox("RSSI: ");
- lcdDrawNumber(16+4*FW, 5*FH, TELEMETRY_RSSI(), BOLD);
+ lcdDrawNumber(WARNING_LINE_X, 5*FH, TELEMETRY_RSSI(), BOLD | LEFT);
}
#endif
@@ -1223,157 +1258,3 @@ void menuModelSetup(event_t event)
}
}
}
-
-void menuModelFailsafe(event_t event)
-{
- static uint8_t maxNameLen = 4;
- static int8_t lastModel = g_eeGeneral.currModel;
- const coord_t barH = (LCD_H - FH) / 8 - 1;
- const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
- const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
- uint8_t cols = 1;
- uint8_t colW = LCD_W;
-
- if (lastModel != g_eeGeneral.currModel) {
- lastModel = g_eeGeneral.currModel;
- maxNameLen = 4;
- }
-
- if (event == EVT_KEY_LONG(KEY_ENTER)) {
- killEvents(event);
- event = 0;
-
- if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) {
- if (s_editMode) {
- g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart];
- s_editMode = 0;
- }
- else {
- int16_t & failsafe = g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition];
- if (failsafe < FAILSAFE_CHANNEL_HOLD)
- failsafe = FAILSAFE_CHANNEL_HOLD;
- else if (failsafe == FAILSAFE_CHANNEL_HOLD)
- failsafe = FAILSAFE_CHANNEL_NOPULSE;
- else
- failsafe = 0;
- }
- }
- else {
- // "Outputs => Failsafe" menu item
- setCustomFailsafe(g_moduleIdx);
- }
-
- storageDirty(EE_MODEL);
- AUDIO_WARNING1();
- SEND_FAILSAFE_NOW(g_moduleIdx);
- }
-
- SIMPLE_SUBMENU_NOTITLE(sentModuleChannels(g_moduleIdx)+1);
- SET_SCROLLBAR_X(0);
-
- if (sentModuleChannels(g_moduleIdx) > 8) {
- cols = 2;
- colW = LCD_W / cols - 1;
- // Column separator
- if (menuVerticalPosition >= sentModuleChannels(g_moduleIdx)) {
- lcdDrawSolidVerticalLine(colW, FH, LCD_H - (FH*2 + FH/2 + 2));
- }
- else {
- lcdDrawSolidVerticalLine(colW, FH, LCD_H - FH);
- }
- }
-
- lcdDrawTextAlignedCenter(0, FAILSAFESET);
- lcdInvertLine(0);
-
- coord_t x = colW;
- for (uint8_t col = 0; col < cols; col++) {
-
- coord_t y = FH + 1;
- uint8_t line = (menuVerticalPosition >= sentModuleChannels(g_moduleIdx) ? 2 : 0);
- uint8_t ch = line + col*8;
-
- for (; line < 8; line++) {
- const int32_t channelValue = channelOutputs[ch+channelStart];
- int32_t failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
- uint8_t lenLabel = ZLEN(g_model.limitData[ch+channelStart].name);
- uint8_t barW = colW - FW * maxNameLen - FWNUM * 3; // default bar width
-
-#if defined(PPM_UNIT_PERCENT_PREC1)
- barW -= FWNUM + 1;
-#endif
- barW += (barW % 2);
-
- // Channel name if present, number if not
- if (lenLabel > 0) {
- if (lenLabel > maxNameLen)
- maxNameLen = lenLabel;
- lcdDrawSizedText(x - colW, y, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR | SMLSIZE);
- }
- else {
- putsChn(x - colW, y, ch+1, SMLSIZE);
- }
-
- // Value
- LcdFlags flags = TINSIZE;
- if (menuVerticalPosition == ch) {
- flags |= INVERS;
- if (s_editMode) {
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- s_editMode = 0;
- }
- else {
- flags |= BLINK;
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim);
- }
- }
- }
-
- const coord_t xValue = x - barW;
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
- lcdDrawText(xValue, y, STR_HOLD, RIGHT|flags);
- failsafeValue = 0;
- }
- else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- lcdDrawText(xValue, y, STR_NONE, RIGHT|flags);
- failsafeValue = 0;
- }
- else {
-#if defined(PPM_UNIT_US)
- lcdDrawNumber(xValue, y, PPM_CH_CENTER(ch)+failsafeValue/2, RIGHT|flags);
-#elif defined(PPM_UNIT_PERCENT_PREC1)
- lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue), RIGHT|PREC1|flags);
-#else
- lcdDrawNumber(xValue, y, calcRESXto1000(failsafeValue)/10, RIGHT|flags);
-#endif
- }
-
- // Gauge
- lcdDrawRect(x - barW, y, barW - 1, barH);
- barW = barW / 2 - 1;
- const coord_t lenChannel = limit(1, (abs(channelValue) * barW + lim / 2) / lim, barW);
- const coord_t lenFailsafe = limit(1, (abs(failsafeValue) * barW + lim / 2) / lim, barW);
- const coord_t barX = x - barW - 2;
- const coord_t xChannel = (channelValue >= 0) ? barX : barX - lenChannel + 1;
- const coord_t xFailsafe = (failsafeValue > 0) ? barX : barX - lenFailsafe + 1;
- lcdDrawHorizontalLine(xChannel, y+1, lenChannel, DOTTED, 0);
- lcdDrawHorizontalLine(xChannel, y+2, lenChannel, DOTTED, 0);
- lcdDrawSolidHorizontalLine(xFailsafe, y+3, lenFailsafe);
- lcdDrawSolidHorizontalLine(xFailsafe, y+4, lenFailsafe);
-
- if (++ch >= sentModuleChannels(g_moduleIdx))
- break;
-
- y += barH + 1;
-
- } // channels
-
- x += colW + 2;
-
- } // columns
-
- if (menuVerticalPosition >= sentModuleChannels(g_moduleIdx)) {
- // Outputs => Failsafe
- lcdDrawText(CENTER_OFS, LCD_H - (FH + 1), STR_OUTPUTS2FAILSAFE, INVERS);
- }
-}
diff --git a/radio/src/gui/212x64/model_special_functions.cpp b/radio/src/gui/212x64/model_special_functions.cpp
index 0d911a3bc..3bdbfbc74 100644
--- a/radio/src/gui/212x64/model_special_functions.cpp
+++ b/radio/src/gui/212x64/model_special_functions.cpp
@@ -56,7 +56,7 @@ void onCustomFunctionsFileSelectionMenu(const char * result)
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a file in the list
memcpy(cfn->play.name, result, sizeof(cfn->play.name));
storageDirty(eeFlags);
@@ -129,7 +129,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result)
CFN_PARAM(cfn) = 0;
storageDirty(EE_MODEL);
}
- else {
+ else if (result != STR_EXIT) {
onSourceLongEnterPress(result);
}
}
diff --git a/radio/src/gui/212x64/model_telemetry.cpp b/radio/src/gui/212x64/model_telemetry.cpp
index 13c2f1c21..5c4f5af2d 100644
--- a/radio/src/gui/212x64/model_telemetry.cpp
+++ b/radio/src/gui/212x64/model_telemetry.cpp
@@ -506,7 +506,7 @@ void menuModelTelemetryFrsky(event_t event)
s_editMode = 0;
if (attr && event==EVT_KEY_LONG(KEY_ENTER)) {
killEvents(KEY_ENTER);
- POPUP_CONFIRMATION(STR_CONFIRMDELETE);
+ POPUP_CONFIRMATION(STR_CONFIRMDELETE, nullptr);
}
break;
diff --git a/radio/src/gui/212x64/popups.cpp b/radio/src/gui/212x64/popups.cpp
index dee7c4e72..0802949a5 100644
--- a/radio/src/gui/212x64/popups.cpp
+++ b/radio/src/gui/212x64/popups.cpp
@@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
- * th9x - http://code.google.com/p/th9x
+ * th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@@ -20,30 +20,6 @@
#include "opentx.h"
-const char * warningText = NULL;
-const char * warningInfoText;
-uint8_t warningInfoLength;
-uint8_t warningType;
-uint8_t warningResult = 0;
-uint8_t warningInfoFlags = ZCHAR;
-int16_t warningInputValue;
-int16_t warningInputValueMin;
-int16_t warningInputValueMax;
-
-void drawMessageBox(const char * title)
-{
- lcdDrawFilledRect(10, 16, LCD_W-20, 40, SOLID, ERASE);
- lcdDrawRect(10, 16, LCD_W-20, 40);
- lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y, title, WARNING_LINE_LEN);
- // could be a place for a warningInfoText
-}
-
-void showMessageBox(const char * title)
-{
- drawMessageBox(title);
- lcdRefresh();
-}
-
const unsigned char ASTERISK_BITMAP[] = {
#include "asterisk.lbm"
};
@@ -75,42 +51,3 @@ void drawAlertBox(const char * title, const char * text, const char * action)
#undef MESSAGE_LCD_OFFSET
}
-
-void showAlertBox(const char * title, const char * text, const char * action, uint8_t sound)
-{
- drawAlertBox(title, text, action);
- AUDIO_ERROR_MESSAGE(sound);
- lcdRefresh();
- lcdSetContrast();
- clearKeyEvents();
- backlightOn();
- checkBacklight();
-}
-
-void runPopupWarning(event_t event)
-{
- warningResult = false;
- drawMessageBox(warningText);
- if (warningInfoText) {
- lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+FH, warningInfoText, warningInfoLength, WARNING_INFO_FLAGS);
- }
- lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+2*FH, warningType == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS);
- switch (event) {
- case EVT_KEY_BREAK(KEY_ENTER):
- if (warningType == WARNING_TYPE_ASTERISK)
- break;
- warningResult = true;
- // no break
- case EVT_KEY_BREAK(KEY_EXIT):
- warningText = NULL;
- warningType = WARNING_TYPE_ASTERISK;
- break;
- default:
- if (warningType == WARNING_TYPE_INPUT) {
- s_editMode = EDIT_MODIFY_FIELD;
- warningInputValue = checkIncDec(event, warningInputValue, warningInputValueMin, warningInputValueMax);
- s_editMode = EDIT_SELECT_FIELD;
- }
- break;
- }
-}
diff --git a/radio/src/gui/212x64/popups.h b/radio/src/gui/212x64/popups.h
index 06d1be6d7..295419096 100644
--- a/radio/src/gui/212x64/popups.h
+++ b/radio/src/gui/212x64/popups.h
@@ -21,50 +21,40 @@
#ifndef _POPUPS_H_
#define _POPUPS_H_
+#define MESSAGEBOX_X 10
+#define MESSAGEBOX_Y 16
+#define MESSAGEBOX_W LCD_W - (2 * MESSAGEBOX_X)
+
#define MENU_X 30
#define MENU_Y 16
-#define MENU_W LCD_W-(2*MENU_X)
+#define MENU_W LCD_W - (2 * MENU_X)
+
#define WARNING_LINE_LEN 32
#define WARNING_LINE_X 16
#define WARNING_LINE_Y 3*FH
-void drawMessageBox(const char * title);
-void showMessageBox(const char * title);
-void runPopupWarning(event_t event);
-#define DRAW_MESSAGE_BOX(title) drawMessageBox(title)
-
-extern void (*popupFunc)(event_t event);
-extern int16_t warningInputValue;
-extern int16_t warningInputValueMin;
-extern int16_t warningInputValueMax;
-extern uint8_t warningInfoFlags;
-
#define DISPLAY_WARNING (*popupFunc)
+#define POPUP_INFORMATION(s) (warningText = s, warningType = WARNING_TYPE_INFO, warningInfoText = 0, popupFunc = runPopupWarning)
#define POPUP_WARNING(s) (warningText = s, warningInfoText = 0, popupFunc = runPopupWarning)
-#define POPUP_CONFIRMATION(s) (warningText = s, warningType = WARNING_TYPE_CONFIRM, warningInfoText = 0, popupFunc = runPopupWarning)
-#define POPUP_INPUT(s, func, start, min, max) (warningText = s, warningType = WARNING_TYPE_INPUT, popupFunc = func, warningInputValue = start, warningInputValueMin = min, warningInputValueMax = max)
+#define POPUP_CONFIRMATION(s, func) (warningText = s, warningType = WARNING_TYPE_CONFIRM, warningInfoText = 0, popupFunc = runPopupWarning, popupMenuHandler = func)
+#define POPUP_INPUT(s, func) (warningText = s, popupFunc = func)
#define WARNING_INFO_FLAGS warningInfoFlags
#define SET_WARNING_INFO(info, len, flags) (warningInfoText = info, warningInfoLength = len, warningInfoFlags = flags)
-#define NAVIGATION_MENUS
-#define POPUP_MENU_ADD_ITEM(s) do { popupMenuOffsetType = MENU_OFFSET_INTERNAL; if (popupMenuNoItems < POPUP_MENU_MAX_LINES) popupMenuItems[popupMenuNoItems++] = s; } while (0)
-#define POPUP_MENU_SELECT_ITEM(s) s_menu_item = (s > 0 ? (s < popupMenuNoItems ? s : popupMenuNoItems) : 0)
+#define POPUP_MENU_ADD_ITEM(s) do { popupMenuOffsetType = MENU_OFFSET_INTERNAL; if (popupMenuItemsCount < POPUP_MENU_MAX_LINES) popupMenuItems[popupMenuItemsCount++] = s; } while (0)
+#define POPUP_MENU_SELECT_ITEM(s) s_menu_item = (s > 0 ? (s < popupMenuItemsCount ? s : popupMenuItemsCount) : 0)
#define POPUP_MENU_START(func) do { popupMenuHandler = (func); AUDIO_KEY_PRESS(); } while (0)
#define POPUP_MENU_MAX_LINES 12
#define MENU_MAX_DISPLAY_LINES 6
#define POPUP_MENU_ADD_SD_ITEM(s) POPUP_MENU_ADD_ITEM(s)
#define MENU_LINE_LENGTH (LEN_MODEL_NAME+12)
#define POPUP_MENU_SET_BSS_FLAG()
-extern const char * popupMenuItems[POPUP_MENU_MAX_LINES];
-extern uint16_t popupMenuNoItems;
-extern uint16_t popupMenuOffset;
+
enum {
MENU_OFFSET_INTERNAL,
MENU_OFFSET_EXTERNAL
};
-extern uint8_t popupMenuOffsetType;
-extern uint8_t s_menu_item;
-const char * runPopupMenu(event_t event);
-extern void (*popupMenuHandler)(const char * result);
+
+#include "../common/stdlcd/popups.h"
#endif // _POPUPS_H_
diff --git a/radio/src/gui/212x64/radio_hardware.cpp b/radio/src/gui/212x64/radio_hardware.cpp
index c67501d18..d3e86a989 100644
--- a/radio/src/gui/212x64/radio_hardware.cpp
+++ b/radio/src/gui/212x64/radio_hardware.cpp
@@ -243,7 +243,7 @@ void menuRadioHardware(event_t event)
lcdDrawTextAlignedLeft(y, STR_DEBUG);
lcdDrawText(HW_SETTINGS_COLUMN
, y, STR_ANALOGS_BTN, menuHorizontalPosition == 0 ? attr : 0);
- lcdDrawText(lcdLastRightPos + 2, y, STR_SWITCHES_BTN, menuHorizontalPosition == 1 ? attr : 0);
+ lcdDrawText(lcdLastRightPos + 2, y, STR_KEYS_BTN, menuHorizontalPosition == 1 ? attr : 0);
if (attr && event == EVT_KEY_FIRST(KEY_ENTER)) {
if (menuHorizontalPosition == 0)
pushMenu(menuRadioDiagAnalogs);
diff --git a/radio/src/gui/212x64/radio_setup.cpp b/radio/src/gui/212x64/radio_setup.cpp
index cce07e5cf..684ba39af 100644
--- a/radio/src/gui/212x64/radio_setup.cpp
+++ b/radio/src/gui/212x64/radio_setup.cpp
@@ -460,7 +460,7 @@ void menuRadioSetup(event_t event)
if (g_eeGeneral.fai)
POPUP_WARNING("FAI\001mode blocked!");
else
- POPUP_CONFIRMATION("FAI mode?");
+ POPUP_CONFIRMATION("FAI mode?", nullptr);
}
break;
#endif
diff --git a/radio/src/gui/212x64/radio_version.cpp b/radio/src/gui/212x64/radio_version.cpp
index fb864c11a..b3fbaca32 100644
--- a/radio/src/gui/212x64/radio_version.cpp
+++ b/radio/src/gui/212x64/radio_version.cpp
@@ -38,14 +38,14 @@ void menuRadioVersion(event_t event)
lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+4*FH+1, "UID\037\033:");
lcdDrawText(5*FW+3, MENU_HEADER_HEIGHT+4*FH+1, id);
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+5*FH+1, STR_EEBACKUP);
- lcdDrawTextAlignedLeft(MENU_HEADER_HEIGHT+6*FH+1, STR_FACTORYRESET);
+ lcdDrawText(INDENT_WIDTH, MENU_HEADER_HEIGHT+5*FH+1, "[ENTER Long] " STR_EEBACKUP);
+ lcdDrawText(INDENT_WIDTH, MENU_HEADER_HEIGHT+6*FH+1, "[MENU Long] " STR_FACTORYRESET);
lcdDrawFilledRect(0, MENU_HEADER_HEIGHT+5*FH, LCD_W, 2*FH+1, SOLID);
if (event == EVT_KEY_LONG(KEY_ENTER)) {
eepromBackup();
}
else if (event == EVT_KEY_LONG(KEY_MENU)) {
- POPUP_CONFIRMATION(STR_CONFIRMRESET);
+ POPUP_CONFIRMATION(STR_CONFIRMRESET, nullptr);
}
}
diff --git a/radio/src/gui/212x64/view_statistics.cpp b/radio/src/gui/212x64/view_statistics.cpp
index e980092be..191a4a95b 100644
--- a/radio/src/gui/212x64/view_statistics.cpp
+++ b/radio/src/gui/212x64/view_statistics.cpp
@@ -149,7 +149,7 @@ void menuStatisticsDebug(event_t event)
#if defined(WATCHDOG_TEST)
case EVT_KEY_LONG(KEY_MENU):
{
- POPUP_CONFIRMATION("Test the watchdog?");
+ POPUP_CONFIRMATION("Test the watchdog?", nullptr);
const char * w = "The radio will reset!";
SET_WARNING_INFO(w, strlen(w), 0);
}
diff --git a/radio/src/gui/212x64/widgets.cpp b/radio/src/gui/212x64/widgets.cpp
index 8eb631d09..2cfd11b0b 100644
--- a/radio/src/gui/212x64/widgets.cpp
+++ b/radio/src/gui/212x64/widgets.cpp
@@ -98,22 +98,6 @@ void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uin
lcdDrawVerticalLine(x, y + yofs, yhgt, SOLID, FORCE);
}
-void drawProgressBar(const char * label, int num, int den)
-{
- lcdClear();
- if (label) {
- lcdDrawTextAlignedLeft(4*FH, label);
- }
- lcdDrawRect(4, 6*FH+4, LCD_W-8, 7);
- if (num > 0 && den > 0) {
- int width = ((LCD_W-12)*num)/den;
- lcdDrawSolidHorizontalLine(6, 6*FH+6, width, FORCE);
- lcdDrawSolidHorizontalLine(6, 6*FH+7, width, FORCE);
- lcdDrawSolidHorizontalLine(6, 6*FH+8, width, FORCE);
- }
- lcdRefresh();
-}
-
void drawGauge(coord_t x, coord_t y, coord_t w, coord_t h, int32_t val, int32_t max)
{
lcdDrawRect(x, y, w+1, h);
@@ -134,7 +118,7 @@ choice_t editChoice(coord_t x, coord_t y, const char * label, const char *values
{
drawFieldLabel(x, y, label);
if (values) lcdDrawTextAtIndex(x, y, values, value-min, attr);
- if (attr & (~RIGHT)) value = checkIncDec(event, value, min, max, (menuVerticalPositions[0] == 0) ? EE_MODEL : EE_GENERAL);
+ if (attr & (~RIGHT)) value = checkIncDec(event, value, min, max, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL);
return value;
}
diff --git a/radio/src/gui/480x272/bitmapbuffer.cpp b/radio/src/gui/480x272/bitmapbuffer.cpp
index 67fb457e4..ae38a8500 100644
--- a/radio/src/gui/480x272/bitmapbuffer.cpp
+++ b/radio/src/gui/480x272/bitmapbuffer.cpp
@@ -387,7 +387,7 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t l
#if defined(BOOT)
unsigned char c = *s;
#else
- unsigned char c = (flags & ZCHAR) ? idx2char(*s) : *s;
+ unsigned char c = (flags & ZCHAR) ? zchar2char(*s) : *s;
#endif
if (setpos) {
pos = c;
diff --git a/radio/src/gui/480x272/gui.h b/radio/src/gui/480x272/gui.h
index 7eac8f04d..38e683b22 100644
--- a/radio/src/gui/480x272/gui.h
+++ b/radio/src/gui/480x272/gui.h
@@ -62,7 +62,6 @@
#define DATETIME_MIDDLE (LCD_W+DATETIME_SEPARATOR_X+4)/2
#define MENU_TITLE_NEXT_POS (lcdNextPos + 10)
-#define MENU_INIT_VPOS -1
#if defined(HELI) && defined(GVARS) && defined(LUA_MODEL_SCRIPTS)
#define MENU_ICONS_SPACING 31
diff --git a/radio/src/gui/480x272/lcd.cpp b/radio/src/gui/480x272/lcd.cpp
index 3d5fae358..a9f9075ab 100644
--- a/radio/src/gui/480x272/lcd.cpp
+++ b/radio/src/gui/480x272/lcd.cpp
@@ -130,7 +130,7 @@ int getTextWidth(const char * s, int len, LcdFlags flags)
for (int i=0; len==0 || i 0) {
int8_t c = name[editNameCursorPos];
if (!(flags & ZCHAR)) {
- c = char2idx(c);
+ c = char2zchar(c);
}
int8_t v = c;
@@ -132,15 +132,15 @@ void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, ui
if (c != v) {
if (!(flags & ZCHAR)) {
if (v != '\0' || name[editNameCursorPos+1] != '\0')
- v = idx2char(v);
+ v = zchar2char(v);
}
name[editNameCursorPos] = v;
- storageDirty(menuVerticalPositions[0] == 0 ? EE_MODEL : EE_GENERAL);
+ storageDirty(isModelMenuDisplayed() ? EE_MODEL : EE_GENERAL);
}
lcdDrawSizedText(x, y, name, size, flags);
coord_t left = (editNameCursorPos == 0 ? 0 : getTextWidth(name, editNameCursorPos, flags));
- char s[] = { (flags & ZCHAR) ? idx2char(name[editNameCursorPos]) : name[editNameCursorPos], '\0' };
+ char s[] = { (flags & ZCHAR) ? zchar2char(name[editNameCursorPos]) : name[editNameCursorPos], '\0' };
lcdDrawSolidFilledRect(x+left-1, y, getTextWidth(s, 1)+1, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR);
lcdDrawText(x+left, y, s, TEXT_INVERTED_COLOR);
}
diff --git a/radio/src/gui/480x272/menus.h b/radio/src/gui/480x272/menus.h
index 6aafa5036..a3d3d66f4 100644
--- a/radio/src/gui/480x272/menus.h
+++ b/radio/src/gui/480x272/menus.h
@@ -48,13 +48,20 @@ extern uint8_t menuVerticalPositions[4];
extern uint8_t menuLevel;
extern event_t menuEvent;
-/// goto given Menu, but substitute current menu in menuStack
void chainMenu(MenuHandlerFunc newMenu);
-/// goto given Menu, store current menu in menuStack
void pushMenu(MenuHandlerFunc newMenu);
-/// return to last menu in menuStack
void popMenu();
+inline bool isRadioMenuDisplayed()
+{
+ return menuVerticalPositions[0] == 1;
+}
+
+inline bool isModelMenuDisplayed()
+{
+ return menuVerticalPositions[0] == 0;
+}
+
enum MenuIcons {
ICON_OPENTX,
ICON_RADIO,
@@ -258,7 +265,6 @@ typedef uint16_t FlightModesType;
extern int8_t checkIncDec_Ret; // global helper vars
-#define EDIT_SELECT_MENU -1
#define EDIT_SELECT_FIELD 0
#define EDIT_MODIFY_FIELD 1
#define EDIT_MODIFY_STRING 2
@@ -274,7 +280,8 @@ extern int8_t s_editMode; // global editmode
#define NO_DBLKEYS 0x80
// mawrow special values
-#define TITLE_ROW ((uint8_t)-1)
+#define READONLY_ROW ((uint8_t)-1)
+#define TITLE_ROW READONLY_ROW
#define ORPHAN_ROW ((uint8_t)-2)
#define HIDDEN_ROW ((uint8_t)-3)
#define NAVIGATION_LINE_BY_LINE 0x40
@@ -469,28 +476,25 @@ void showMessageBox(const char * title);
void runPopupWarning(event_t event);
extern void (* popupFunc)(event_t event);
-extern int16_t warningInputValue;
-extern int16_t warningInputValueMin;
-extern int16_t warningInputValueMax;
extern uint8_t warningInfoFlags;
#define DISPLAY_WARNING (*popupFunc)
+
+#define POPUP_INFORMATION(s) (warningText = s, warningType = WARNING_TYPE_INFO, warningInfoText = 0, popupFunc = runPopupWarning)
#define POPUP_WARNING(s) (warningType = WARNING_TYPE_ASTERISK, warningText = s, warningInfoText = 0, popupFunc = runPopupWarning)
-#define POPUP_CONFIRMATION(s) (warningText = s, warningType = WARNING_TYPE_CONFIRM, warningInfoText = 0, popupFunc = runPopupWarning)
-#define POPUP_INPUT(s, func, start, min, max) (warningText = s, warningType = WARNING_TYPE_INPUT, popupFunc = func, warningInputValue = start, warningInputValueMin = min, warningInputValueMax = max)
+#define POPUP_INPUT(s, func) (warningText = s, popupFunc = func)
#define WARNING_INFO_FLAGS warningInfoFlags
#define SET_WARNING_INFO(info, len, flags) (warningInfoText = info, warningInfoLength = len, warningInfoFlags = flags)
-#define NAVIGATION_MENUS
-#define POPUP_MENU_ADD_ITEM(s) do { popupMenuOffsetType = MENU_OFFSET_INTERNAL; if (popupMenuNoItems < POPUP_MENU_MAX_LINES) popupMenuItems[popupMenuNoItems++] = s; } while (0)
-#define POPUP_MENU_SELECT_ITEM(s) s_menu_item = (s > 0 ? (s < popupMenuNoItems ? s : popupMenuNoItems) : 0)
+#define POPUP_MENU_ADD_ITEM(s) do { popupMenuOffsetType = MENU_OFFSET_INTERNAL; if (popupMenuItemsCount < POPUP_MENU_MAX_LINES) popupMenuItems[popupMenuItemsCount++] = s; } while (0)
+#define POPUP_MENU_SELECT_ITEM(s) s_menu_item = (s > 0 ? (s < popupMenuItemsCount ? s : popupMenuItemsCount) : 0)
#define POPUP_MENU_START(func) do { popupMenuHandler = (func); AUDIO_KEY_PRESS(); } while(0)
#define POPUP_MENU_MAX_LINES 12
#define MENU_MAX_DISPLAY_LINES 9
#define MENU_LINE_LENGTH (LEN_MODEL_NAME+12)
#define POPUP_MENU_SET_BSS_FLAG()
extern const char * popupMenuItems[POPUP_MENU_MAX_LINES];
-extern uint16_t popupMenuNoItems;
+extern uint16_t popupMenuItemsCount;
extern uint16_t popupMenuOffset;
enum {
MENU_OFFSET_INTERNAL,
@@ -501,6 +505,15 @@ extern uint8_t s_menu_item;
const char * runPopupMenu(event_t event);
extern void (*popupMenuHandler)(const char * result);
+inline void POPUP_CONFIRMATION(const char *s, void (* confirmHandler)(const char *) = nullptr)
+{
+ warningText = s;
+ warningType = WARNING_TYPE_CONFIRM;
+ warningInfoText = nullptr;
+ popupFunc = runPopupWarning;
+ popupMenuHandler = confirmHandler;
+}
+
#define TEXT_FILENAME_MAXLEN 40
extern char s_text_file[TEXT_FILENAME_MAXLEN];
void pushMenuTextView(const char * filename);
diff --git a/radio/src/gui/480x272/model_curves.cpp b/radio/src/gui/480x272/model_curves.cpp
index a918585bf..7d15edcaf 100644
--- a/radio/src/gui/480x272/model_curves.cpp
+++ b/radio/src/gui/480x272/model_curves.cpp
@@ -25,16 +25,36 @@ void drawCurve(int x, int y, int width)
drawFunction(applyCurrentCurve, x, y, width);
}
-void displayPresetChoice(event_t event)
+void runPopupCurvePreset(event_t event)
{
- runPopupWarning(event);
- lcdDrawNumber(WARNING_LINE_X, WARNING_INFOLINE_Y-10, 45*warningInputValue/4, LEFT|INVERS, 0, NULL, "@");
+ warningResult = false;
+
+ theme->drawMessageBox(warningText, warningInfoText, STR_POPUPS_ENTER_EXIT, warningType);
+
+ switch (event) {
+ case EVT_KEY_BREAK(KEY_ENTER):
+ warningResult = true;
+ // no break
+
+ case EVT_KEY_BREAK(KEY_EXIT):
+ warningText = NULL;
+ warningType = WARNING_TYPE_ASTERISK;
+ break;
+
+ default:
+ s_editMode = EDIT_MODIFY_FIELD;
+ reusableBuffer.curveEdit.preset = checkIncDec(event, reusableBuffer.curveEdit.preset, -4, +4);
+ s_editMode = EDIT_SELECT_FIELD;
+ break;
+ }
+
+ lcdDrawNumber(WARNING_LINE_X, WARNING_INFOLINE_Y-10, 45 * reusableBuffer.curveEdit.preset / 4, LEFT|INVERS, 0, NULL, "@");
if (warningResult) {
warningResult = 0;
CurveInfo & crv = g_model.curves[s_curveChan];
int8_t * points = curveAddress(s_curveChan);
- int k = 25 * warningInputValue;
+ int k = 25 * reusableBuffer.curveEdit.preset;
int dx = 2000 / (5+crv.points-1);
for (uint8_t i=0; i<5+crv.points; i++) {
int x = -1000 + i * dx;
@@ -49,7 +69,8 @@ void displayPresetChoice(event_t event)
void onCurveOneMenu(const char * result)
{
if (result == STR_CURVE_PRESET) {
- POPUP_INPUT(STR_PRESET, displayPresetChoice, 0, -4, 4);
+ reusableBuffer.curveEdit.preset = 4; // 45°
+ POPUP_INPUT(STR_PRESET, runPopupCurvePreset);
}
else if (result == STR_MIRROR) {
CurveInfo & crv = g_model.curves[s_curveChan];
diff --git a/radio/src/gui/480x272/model_custom_scripts.cpp b/radio/src/gui/480x272/model_custom_scripts.cpp
index b2c0a08b8..96ab0b6ca 100644
--- a/radio/src/gui/480x272/model_custom_scripts.cpp
+++ b/radio/src/gui/480x272/model_custom_scripts.cpp
@@ -29,7 +29,7 @@ void onModelCustomScriptMenu(const char *result)
POPUP_WARNING(STR_NO_SCRIPTS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a lua file in the list
copySelection(sd.file, result, sizeof(sd.file));
memset(sd.inputs, 0, sizeof(sd.inputs));
diff --git a/radio/src/gui/480x272/model_failsafe.cpp b/radio/src/gui/480x272/model_failsafe.cpp
new file mode 100644
index 000000000..bcc04d7a5
--- /dev/null
+++ b/radio/src/gui/480x272/model_failsafe.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+
+extern uint8_t g_moduleIdx;
+
+bool menuModelFailsafe(event_t event)
+{
+ uint8_t ch = 0;
+ const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
+ const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
+ const uint8_t SLIDER_W = 128;
+ const uint8_t cols = sentModuleChannels(g_moduleIdx) > 8 ? 2 : 1;
+
+ if (event == EVT_KEY_LONG(KEY_ENTER)) {
+ killEvents(event);
+ event = 0;
+
+ if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) {
+ if (s_editMode) {
+ g_model.failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart];
+ s_editMode = 0;
+ }
+ else {
+ int16_t & failsafe = g_model.failsafeChannels[menuVerticalPosition];
+ if (failsafe < FAILSAFE_CHANNEL_HOLD)
+ failsafe = FAILSAFE_CHANNEL_HOLD;
+ else if (failsafe == FAILSAFE_CHANNEL_HOLD)
+ failsafe = FAILSAFE_CHANNEL_NOPULSE;
+ else
+ failsafe = 0;
+ }
+ }
+ else {
+ // "Outputs => Failsafe" menu item
+ setCustomFailsafe(g_moduleIdx);
+ }
+
+ storageDirty(EE_MODEL);
+ AUDIO_WARNING1();
+ SEND_FAILSAFE_NOW(g_moduleIdx);
+ }
+
+ SIMPLE_SUBMENU_WITH_OPTIONS("FAILSAFE", ICON_STATS_ANALOGS, sentModuleChannels(g_moduleIdx)+1, OPTION_MENU_NO_SCROLLBAR);
+ drawStringWithIndex(50, 3+FH, "Module", g_moduleIdx+1, MENU_TITLE_COLOR);
+
+ for (uint8_t col=0; col < cols; col++) {
+ for (uint8_t line=0; line < 8; line++) {
+ coord_t x = col*(LCD_W/2);
+ const coord_t y = MENU_CONTENT_TOP - FH + line*(FH+2);
+ const int32_t channelValue = channelOutputs[ch+channelStart];
+ int32_t failsafeValue = g_model.failsafeChannels[8*col+line];
+
+ // Channel name if present, number if not
+ if (g_model.limitData[ch+channelStart].name[0] != '\0') {
+ putsChn(x+MENUS_MARGIN_LEFT, y-3, ch+1, TINSIZE);
+ lcdDrawSizedText(x+MENUS_MARGIN_LEFT, y+5, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR|SMLSIZE);
+ }
+ else {
+ putsChn(x+MENUS_MARGIN_LEFT, y, ch+1, 0);
+ }
+
+ // Value
+ LcdFlags flags = RIGHT;
+ if (menuVerticalPosition == ch) {
+ flags |= INVERS;
+ if (s_editMode) {
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ s_editMode = 0;
+ }
+ else {
+ flags |= BLINK;
+ CHECK_INCDEC_MODELVAR(event, g_model.failsafeChannels[8*col+line], -lim, +lim);
+ }
+ }
+ }
+
+ x += (LCD_W/2)-4-MENUS_MARGIN_LEFT-SLIDER_W;
+
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ lcdDrawText(x, y+2, "HOLD", flags|SMLSIZE);
+ failsafeValue = 0;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ lcdDrawText(x, y+2, "NONE", flags|SMLSIZE);
+ failsafeValue = 0;
+ }
+ else {
+#if defined(PPM_UNIT_US)
+ lcdDrawNumber(x, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags);
+#elif defined(PPM_UNIT_PERCENT_PREC1)
+ lcdDrawNumber(x, y, calcRESXto1000(failsafeValue), PREC1|flags);
+#else
+ lcdDrawNumber(x, y, calcRESXto1000(failsafeValue)/10, flags);
+#endif
+ }
+
+ // Gauge
+ x += 4;
+ lcdDrawRect(x, y+3, SLIDER_W+1, 12);
+ const coord_t lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * SLIDER_W/2 + lim/2) / lim), uint8_t(SLIDER_W/2));
+ const coord_t lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * SLIDER_W/2 + lim/2) / lim), uint8_t(SLIDER_W/2));
+ x += SLIDER_W/2;
+ const coord_t xChannel = (channelValue>0) ? x : x+1-lenChannel;
+ const coord_t xFailsafe = (failsafeValue>0) ? x : x+1-lenFailsafe;
+ lcdDrawSolidFilledRect(xChannel, y+4, lenChannel, 5, TEXT_COLOR);
+ lcdDrawSolidFilledRect(xFailsafe, y+9, lenFailsafe, 5, ALARM_COLOR);
+
+ if (++ch >= sentModuleChannels(g_moduleIdx)) {
+
+ // draw that menu at the bottom center
+ flags = CENTERED | (menuVerticalPosition == ch ? INVERS : 0);
+ lcdDrawSizedText(LCD_W/2, MENU_CONTENT_TOP - FH + 8*(FH+2), STR_OUTPUTS2FAILSAFE, 20, flags);
+ break;
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/radio/src/gui/480x272/model_module_options.cpp b/radio/src/gui/480x272/model_module_options.cpp
new file mode 100644
index 000000000..f72d3594f
--- /dev/null
+++ b/radio/src/gui/480x272/model_module_options.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
diff --git a/radio/src/gui/480x272/model_receiver_options.cpp b/radio/src/gui/480x272/model_receiver_options.cpp
new file mode 100644
index 000000000..f72d3594f
--- /dev/null
+++ b/radio/src/gui/480x272/model_receiver_options.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
diff --git a/radio/src/gui/480x272/model_setup.cpp b/radio/src/gui/480x272/model_setup.cpp
index 0931e475b..1311235ea 100644
--- a/radio/src/gui/480x272/model_setup.cpp
+++ b/radio/src/gui/480x272/model_setup.cpp
@@ -82,6 +82,7 @@ enum MenuModelSetupItems {
ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND,
#endif
ITEM_MODEL_EXTERNAL_MODULE_POWER,
+ ITEM_MODEL_EXTERNAL_MODULE_FREQ,
ITEM_MODEL_TRAINER_LABEL,
ITEM_MODEL_TRAINER_MODE,
ITEM_MODEL_TRAINER_LINE1,
@@ -97,18 +98,21 @@ enum MenuModelSetupItems {
#define MODEL_SETUP_SET_FAILSAFE_OFS 100
#define MODEL_SETUP_SLIDPOT_SPACING 45
-#define CURRENT_MODULE_EDITED(k) (k>=ITEM_MODEL_TRAINER_LABEL ? TRAINER_MODULE : (k>=ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE))
+#define CURRENT_MODULE_EDITED(k) (k >= ITEM_MODEL_EXTERNAL_MODULE_LABEL ? EXTERNAL_MODULE : INTERNAL_MODULE)
void checkModelIdUnique(uint8_t moduleIdx)
{
- char* warn_buf = reusableBuffer.modelsetup.msg;
+ if(isModulePXX(moduleIdx) && IS_D8_RX(moduleIdx))
+ return;
+
+ char* warn_buf = reusableBuffer.moduleSetup.msg;
// cannot rely exactly on WARNING_LINE_LEN so using WARNING_LINE_LEN-2
- size_t warn_buf_len = sizeof(reusableBuffer.modelsetup.msg) - WARNING_LINE_LEN - 2;
+ size_t warn_buf_len = sizeof(reusableBuffer.moduleSetup.msg) - WARNING_LINE_LEN - 2;
if (!modelslist.isModelIdUnique(moduleIdx,warn_buf,warn_buf_len)) {
if (warn_buf[0] != 0) {
POPUP_WARNING(STR_MODELIDUSED);
- SET_WARNING_INFO(warn_buf, sizeof(reusableBuffer.modelsetup.msg), 0);
+ SET_WARNING_INFO(warn_buf, sizeof(reusableBuffer.moduleSetup.msg), 0);
}
}
}
@@ -137,7 +141,7 @@ void onBindMenu(const char * result)
return;
}
- moduleFlag[moduleIdx] = MODULE_BIND;
+ moduleSettings[moduleIdx].mode = MODULE_MODE_BIND;
}
void onModelSetupBitmapMenu(const char * result)
@@ -147,7 +151,7 @@ void onModelSetupBitmapMenu(const char * result)
POPUP_WARNING(STR_NO_BITMAPS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a bmp file in the list
copySelection(g_model.header.bitmap, result, sizeof(g_model.header.bitmap));
storageDirty(EE_MODEL);
@@ -231,12 +235,12 @@ int getSwitchWarningsCount()
#define IF_EXTERNAL_MODULE_ON(x) (IS_EXTERNAL_MODULE_ENABLED() ? (uint8_t)(x) : HIDDEN_ROW)
#define INTERNAL_MODULE_MODE_ROWS (uint8_t)0
-#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON(1)
#define PORT_CHANNELS_ROWS(x) (x==INTERNAL_MODULE ? INTERNAL_MODULE_CHANNELS_ROWS : (x==EXTERNAL_MODULE ? EXTERNAL_MODULE_CHANNELS_ROWS : 1))
#define TIMER_ROWS(x) NAVIGATION_LINE_BY_LINE|1, 0, 0, 0, g_model.timers[x].countdownBeep != COUNTDOWN_SILENT ? (uint8_t)1 : (uint8_t)0
-#define EXTERNAL_MODULE_MODE_ROWS (isModulePXX(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE)) ? (uint8_t)1 : isModuleMultimodule(EXTERNAL_MODULE) ? MULTIMODULE_MODE_ROWS(EXTERNAL_MODULE) : (uint8_t)0
+#define EXTERNAL_MODULE_MODE_ROWS (isModuleXJT(EXTERNAL_MODULE) || isModuleDSM2(EXTERNAL_MODULE) || isModuleMultimodule(EXTERNAL_MODULE)) ? (uint8_t)1 : (uint8_t)0
+#define EXTRA_MODULE_ROWS isR9MMFlex(EXTERNAL_MODULE) ? (uint8_t)1: (uint8_t)HIDDEN_ROW,
#if TIMERS == 1
#define TIMERS_ROWS TIMER_ROWS(0)
@@ -252,8 +256,8 @@ int getSwitchWarningsCount()
#define SLIDER_WARN_ITEMS() ((g_model.potsWarnMode) ? uint8_t(NAVIGATION_LINE_BY_LINE|(NUM_SLIDERS-1)) : (uint8_t)0)
#define TRAINER_LINE1_BLUETOOTH_M_ROWS ((bluetoothDistantAddr[0] == 0 || bluetoothState == BLUETOOTH_STATE_CONNECTED) ? (uint8_t)0 : (uint8_t)1)
-#define TRAINER_LINE1_ROWS (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)1 : (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_LINE1_BLUETOOTH_M_ROWS : (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH ? (uint8_t)1 : HIDDEN_ROW)))
-#define TRAINER_LINE2_ROWS (g_model.trainerMode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
+#define TRAINER_LINE1_ROWS (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)1 : (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH ? TRAINER_LINE1_BLUETOOTH_M_ROWS : (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH ? (uint8_t)1 : HIDDEN_ROW)))
+#define TRAINER_LINE2_ROWS (g_model.trainerData.mode == TRAINER_MODE_SLAVE ? (uint8_t)2 : HIDDEN_ROW)
bool menuModelSetup(event_t event)
{
@@ -285,18 +289,19 @@ bool menuModelSetup(event_t event)
EXTERNAL_MODULE_OPTION_ROW,
MULTIMODULE_MODULE_ROWS
EXTERNAL_MODULE_POWER_ROW,
+ EXTRA_MODULE_ROWS
LABEL(Trainer),
0,
TRAINER_LINE1_ROWS,
TRAINER_LINE2_ROWS });
if (event == EVT_ENTRY) {
- reusableBuffer.modelsetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power;
+ reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[EXTERNAL_MODULE].pxx.power;
}
if (menuEvent) {
- moduleFlag[0] = 0;
- moduleFlag[1] = 0;
+ moduleSettings[0].mode = 0;
+ moduleSettings[1].mode = 0;
}
int sub = menuVerticalPosition;
@@ -675,7 +680,7 @@ bool menuModelSetup(event_t event)
case ITEM_MODEL_TRAINER_MODE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODE);
- g_model.trainerMode = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerMode, 0, TRAINER_MODE_MAX(), attr, event);
+ g_model.trainerData.mode = editChoice(MODEL_SETUP_2ND_COLUMN, y, STR_VTRAINERMODES, g_model.trainerData.mode, 0, TRAINER_MODE_MAX(), attr, event);
if (attr && checkIncDec_Ret) {
bluetoothState = BLUETOOTH_STATE_OFF;
bluetoothDistantAddr[0] = 0;
@@ -693,8 +698,8 @@ bool menuModelSetup(event_t event)
lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_XJT_PROTOCOLS, 1+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0));
else if (isModuleDSM2(EXTERNAL_MODULE))
lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_DSM_PROTOCOLS, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, (menuHorizontalPosition==1 ? attr : 0));
- else if (isModuleR9M(EXTERNAL_MODULE))
- lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].subType, (menuHorizontalPosition==1 ? attr : 0));
+ else if (isR9ModuleRunning(EXTERNAL_MODULE))
+ lcdDrawTextAtIndex(MODEL_SETUP_3RD_COLUMN, y, STR_R9M_REGION, g_model.moduleData[EXTERNAL_MODULE].r9m.region, (menuHorizontalPosition==1 ? attr : 0));
#if defined(MULTIMODULE)
else if (isModuleMultimodule(EXTERNAL_MODULE)) {
int multi_rfProto = g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false);
@@ -714,7 +719,9 @@ bool menuModelSetup(event_t event)
if (attr && s_editMode>0) {
switch (menuHorizontalPosition) {
case 0:
- g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type, MODULE_TYPE_NONE, MODULE_TYPE_COUNT-1, EE_MODEL, isModuleAvailable);
+ g_model.moduleData[EXTERNAL_MODULE].type = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].type,
+ MODULE_TYPE_NONE, MODULE_TYPE_COUNT - 1, EE_MODEL,
+ isExternalModuleAvailable);
if (checkIncDec_Ret) {
g_model.moduleData[EXTERNAL_MODULE].rfProtocol = 0;
g_model.moduleData[EXTERNAL_MODULE].channelsStart = 0;
@@ -728,15 +735,6 @@ bool menuModelSetup(event_t event)
case 1:
if (isModuleDSM2(EXTERNAL_MODULE))
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[EXTERNAL_MODULE].rfProtocol, DSM2_PROTO_LP45, DSM2_PROTO_DSMX);
- else if (isModuleR9M(EXTERNAL_MODULE)) {
- uint8_t newR9MType = checkIncDec(event, g_model.moduleData[EXTERNAL_MODULE].subType, MODULE_SUBTYPE_R9M_FCC, MODULE_SUBTYPE_R9M_LAST, EE_MODEL, isR9MModeAvailable);
- if (newR9MType != g_model.moduleData[EXTERNAL_MODULE].subType && newR9MType > MODULE_SUBTYPE_R9M_EU) {
- POPUP_WARNING(STR_R9MFLEXWARN1);
- const char * w = STR_R9MFLEXWARN2;
- SET_WARNING_INFO(w, strlen(w), 0);
- }
- g_model.moduleData[EXTERNAL_MODULE].subType = newR9MType;
- }
#if defined(MULTIMODULE)
else if (isModuleMultimodule(EXTERNAL_MODULE)) {
int multiRfProto = g_model.moduleData[EXTERNAL_MODULE].multi.customProto == 1 ? MM_RF_PROTO_CUSTOM : g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false);
@@ -790,7 +788,7 @@ bool menuModelSetup(event_t event)
break;
case ITEM_MODEL_TRAINER_LINE1:
- if (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH) {
+ if (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH) {
if (attr) {
s_editMode = 0;
}
@@ -864,9 +862,28 @@ bool menuModelSetup(event_t event)
break;
}
+ case ITEM_MODEL_TRAINER_LINE2:
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_PPMFRAME);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN, y, (int16_t)g_model.trainerData.frameLength*5 + 225, (menuHorizontalPosition<=0 ? attr : 0) | PREC1|LEFT, 0, NULL, STR_MS);
+ lcdDrawNumber(MODEL_SETUP_2ND_COLUMN+80, y, (g_model.trainerData.delay*50)+300, (CURSOR_ON_LINE() || menuHorizontalPosition==1) ? attr|LEFT : LEFT, 0, NULL, "us");
+ lcdDrawText(MODEL_SETUP_2ND_COLUMN+160, y, g_model.trainerData.pulsePol ? "+" : "-", (CURSOR_ON_LINE() || menuHorizontalPosition==2) ? attr : 0);
+ if (attr && s_editMode>0) {
+ switch (menuHorizontalPosition) {
+ case 0:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.frameLength, -20, 35);
+ break;
+ case 1:
+ CHECK_INCDEC_MODELVAR(event, g_model.trainerData.delay, -4, 10);
+ break;
+ case 2:
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.trainerData.pulsePol, 1);
+ break;
+ }
+ }
+ break;
+
case ITEM_MODEL_INTERNAL_MODULE_BIND:
case ITEM_MODEL_EXTERNAL_MODULE_BIND:
- case ITEM_MODEL_TRAINER_LINE2:
{
uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
ModuleData & moduleData = g_model.moduleData[moduleIdx];
@@ -932,8 +949,8 @@ bool menuModelSetup(event_t event)
}
}
}
- drawButton(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, (moduleFlag[moduleIdx] == MODULE_BIND ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==1 ? attr : 0));
- drawButton(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, (moduleFlag[moduleIdx] == MODULE_RANGECHECK ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==2 ? attr : 0));
+ drawButton(MODEL_SETUP_2ND_COLUMN+xOffsetBind, y, STR_MODULE_BIND, (moduleSettings[moduleIdx].mode == MODULE_MODE_BIND ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==1 ? attr : 0));
+ drawButton(MODEL_SETUP_2ND_COLUMN+MODEL_SETUP_RANGE_OFS+xOffsetBind, y, STR_MODULE_RANGE, (moduleSettings[moduleIdx].mode == MODULE_MODE_RANGECHECK ? BUTTON_ON : BUTTON_OFF) | (l_posHorz==2 ? attr : 0));
uint8_t newFlag = 0;
#if defined(MULTIMODULE)
if (multiBindStatus == MULTI_BIND_FINISHED) {
@@ -969,27 +986,27 @@ bool menuModelSetup(event_t event)
POPUP_MENU_START(onBindMenu);
continue;
}
- if (moduleFlag[moduleIdx] == MODULE_BIND) {
- newFlag = MODULE_BIND;
+ if (moduleSettings[moduleIdx].mode == MODULE_MODE_BIND) {
+ newFlag = MODULE_MODE_BIND;
}
else {
- if (!popupMenuNoItems) {
+ if (!popupMenuItemsCount) {
s_editMode = 0; // this is when popup is exited before a choice is made
}
}
}
else {
- newFlag = MODULE_BIND;
+ newFlag = MODULE_MODE_BIND;
}
}
else if (l_posHorz == 2) {
- newFlag = MODULE_RANGECHECK;
+ newFlag = MODULE_MODE_RANGECHECK;
}
}
}
- moduleFlag[moduleIdx] = newFlag;
+ moduleSettings[moduleIdx].mode = newFlag;
#if defined(MULTIMODULE)
- if (newFlag == MODULE_BIND)
+ if (newFlag == MODULE_MODE_BIND)
multiBindStatus = MULTI_BIND_INITIATED;
#endif
}
@@ -1068,16 +1085,7 @@ bool menuModelSetup(event_t event)
}
}
#endif
- if (isModuleR9M(moduleIdx)) {
- lcdDrawText(MENUS_MARGIN_LEFT, y, STR_MODULE_TELEMETRY);
- if (IS_TELEMETRY_INTERNAL_MODULE()) {
- lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_DISABLE_INTERNAL);
- }
- else {
- lcdDrawText(MODEL_SETUP_2ND_COLUMN, y, STR_MODULE_TELEM_ON);
- }
- }
- else if (isModuleSBUS(moduleIdx)) {
+ if (isModuleSBUS(moduleIdx)) {
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_WARN_BATTVOLTAGE);
drawValueWithUnit(MODEL_SETUP_4TH_COLUMN, y, getBatteryVoltage(), UNIT_VOLTS, attr|PREC2|LEFT);
}
@@ -1098,12 +1106,12 @@ bool menuModelSetup(event_t event)
lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9M_LBT_POWER_VALUES, g_model.moduleData[moduleIdx].pxx.power, LEFT | attr);
if (attr)
CHECK_INCDEC_MODELVAR(event, g_model.moduleData[moduleIdx].pxx.power, 0, R9M_LBT_POWER_MAX);
- if (attr && s_editMode == 0 && reusableBuffer.modelsetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) {
- if((reusableBuffer.modelsetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) { //switching between mode 2 and 3 does not require rebind
+ if (attr && s_editMode == 0 && reusableBuffer.moduleSetup.r9mPower != g_model.moduleData[moduleIdx].pxx.power) {
+ if((reusableBuffer.moduleSetup.r9mPower + g_model.moduleData[moduleIdx].pxx.power) < 5) { //switching between mode 2 and 3 does not require rebind
POPUP_WARNING(STR_WARNING);
SET_WARNING_INFO(STR_REBIND, sizeof(TR_REBIND), 0);
}
- reusableBuffer.modelsetup.r9mPower = g_model.moduleData[moduleIdx].pxx.power;
+ reusableBuffer.moduleSetup.r9mPower = g_model.moduleData[moduleIdx].pxx.power;
}
}
}
@@ -1116,6 +1124,18 @@ bool menuModelSetup(event_t event)
}
break;
+ case ITEM_MODEL_EXTERNAL_MODULE_FREQ:
+ {
+ uint8_t moduleIdx = CURRENT_MODULE_EDITED(k);
+ lcdDrawText(MENUS_MARGIN_LEFT, y, STR_FREQUENCY);
+ lcdDrawTextAtIndex(MODEL_SETUP_2ND_COLUMN, y, STR_R9MFLEX_FREQ, g_model.moduleData[moduleIdx].r9m.freq, LEFT | attr);
+ if (attr)
+ {
+ CHECK_INCDEC_MODELVAR_ZERO(event, g_model.moduleData[moduleIdx].r9m.freq, 1);
+ }
+ }
+ break;
+
#if defined(MULTIMODULE)
case ITEM_MODEL_EXTERNAL_MODULE_AUTOBIND:
if (g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MM_RF_PROTO_DSM2)
@@ -1180,118 +1200,3 @@ bool menuModelSetup(event_t event)
return true;
}
-
-bool menuModelFailsafe(event_t event)
-{
- uint8_t ch = 0;
- const uint8_t channelStart = g_model.moduleData[g_moduleIdx].channelsStart;
- const int lim = (g_model.extendedLimits ? (512 * LIMIT_EXT_PERCENT / 100) : 512) * 2;
- const uint8_t SLIDER_W = 128;
- const uint8_t cols = sentModuleChannels(g_moduleIdx) > 8 ? 2 : 1;
-
- if (event == EVT_KEY_LONG(KEY_ENTER)) {
- killEvents(event);
- event = 0;
-
- if (menuVerticalPosition < sentModuleChannels(g_moduleIdx)) {
- if (s_editMode) {
- g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition] = channelOutputs[menuVerticalPosition+channelStart];
- s_editMode = 0;
- }
- else {
- int16_t & failsafe = g_model.moduleData[g_moduleIdx].failsafeChannels[menuVerticalPosition];
- if (failsafe < FAILSAFE_CHANNEL_HOLD)
- failsafe = FAILSAFE_CHANNEL_HOLD;
- else if (failsafe == FAILSAFE_CHANNEL_HOLD)
- failsafe = FAILSAFE_CHANNEL_NOPULSE;
- else
- failsafe = 0;
- }
- }
- else {
- // "Outputs => Failsafe" menu item
- setCustomFailsafe(g_moduleIdx);
- }
-
- storageDirty(EE_MODEL);
- AUDIO_WARNING1();
- SEND_FAILSAFE_NOW(g_moduleIdx);
- }
-
- SIMPLE_SUBMENU_WITH_OPTIONS("FAILSAFE", ICON_STATS_ANALOGS, sentModuleChannels(g_moduleIdx)+1, OPTION_MENU_NO_SCROLLBAR);
- drawStringWithIndex(50, 3+FH, "Module", g_moduleIdx+1, MENU_TITLE_COLOR);
-
- for (uint8_t col=0; col < cols; col++) {
- for (uint8_t line=0; line < 8; line++) {
- coord_t x = col*(LCD_W/2);
- const coord_t y = MENU_CONTENT_TOP - FH + line*(FH+2);
- const int32_t channelValue = channelOutputs[ch+channelStart];
- int32_t failsafeValue = g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line];
-
- // Channel name if present, number if not
- if (g_model.limitData[ch+channelStart].name[0] != '\0') {
- putsChn(x+MENUS_MARGIN_LEFT, y-3, ch+1, TINSIZE);
- lcdDrawSizedText(x+MENUS_MARGIN_LEFT, y+5, g_model.limitData[ch+channelStart].name, sizeof(g_model.limitData[ch+channelStart].name), ZCHAR|SMLSIZE);
- }
- else {
- putsChn(x+MENUS_MARGIN_LEFT, y, ch+1, 0);
- }
-
- // Value
- LcdFlags flags = RIGHT;
- if (menuVerticalPosition == ch) {
- flags |= INVERS;
- if (s_editMode) {
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD || failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- s_editMode = 0;
- }
- else {
- flags |= BLINK;
- CHECK_INCDEC_MODELVAR(event, g_model.moduleData[g_moduleIdx].failsafeChannels[8*col+line], -lim, +lim);
- }
- }
- }
-
- x += (LCD_W/2)-4-MENUS_MARGIN_LEFT-SLIDER_W;
-
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
- lcdDrawText(x, y+2, "HOLD", flags|SMLSIZE);
- failsafeValue = 0;
- }
- else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- lcdDrawText(x, y+2, "NONE", flags|SMLSIZE);
- failsafeValue = 0;
- }
- else {
-#if defined(PPM_UNIT_US)
- lcdDrawNumber(x, y, PPM_CH_CENTER(ch)+failsafeValue/2, flags);
-#elif defined(PPM_UNIT_PERCENT_PREC1)
- lcdDrawNumber(x, y, calcRESXto1000(failsafeValue), PREC1|flags);
-#else
- lcdDrawNumber(x, y, calcRESXto1000(failsafeValue)/10, flags);
-#endif
- }
-
- // Gauge
- x += 4;
- lcdDrawRect(x, y+3, SLIDER_W+1, 12);
- const coord_t lenChannel = limit((uint8_t)1, uint8_t((abs(channelValue) * SLIDER_W/2 + lim/2) / lim), uint8_t(SLIDER_W/2));
- const coord_t lenFailsafe = limit((uint8_t)1, uint8_t((abs(failsafeValue) * SLIDER_W/2 + lim/2) / lim), uint8_t(SLIDER_W/2));
- x += SLIDER_W/2;
- const coord_t xChannel = (channelValue>0) ? x : x+1-lenChannel;
- const coord_t xFailsafe = (failsafeValue>0) ? x : x+1-lenFailsafe;
- lcdDrawSolidFilledRect(xChannel, y+4, lenChannel, 5, TEXT_COLOR);
- lcdDrawSolidFilledRect(xFailsafe, y+9, lenFailsafe, 5, ALARM_COLOR);
-
- if (++ch >= sentModuleChannels(g_moduleIdx)) {
-
- // draw that menu at the bottom center
- flags = CENTERED | (menuVerticalPosition == ch ? INVERS : 0);
- lcdDrawSizedText(LCD_W/2, MENU_CONTENT_TOP - FH + 8*(FH+2), STR_OUTPUTS2FAILSAFE, 20, flags);
- break;
- }
- }
- }
-
- return true;
-}
diff --git a/radio/src/gui/480x272/model_special_functions.cpp b/radio/src/gui/480x272/model_special_functions.cpp
index 1ed3528d2..7d4d6c46c 100644
--- a/radio/src/gui/480x272/model_special_functions.cpp
+++ b/radio/src/gui/480x272/model_special_functions.cpp
@@ -56,7 +56,7 @@ void onCustomFunctionsFileSelectionMenu(const char * result)
POPUP_WARNING(func==FUNC_PLAY_SCRIPT ? STR_NO_SCRIPTS_ON_SD : STR_NO_SOUNDS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
// The user choosed a file in the list
memcpy(cf->play.name, result, sizeof(cf->play.name));
storageDirty(eeFlags);
@@ -128,7 +128,7 @@ void onAdjustGvarSourceLongEnterPress(const char * result)
CFN_PARAM(cfn) = 0;
storageDirty(EE_MODEL);
}
- else {
+ else if (result != STR_EXIT) {
onSourceLongEnterPress(result);
}
}
diff --git a/radio/src/gui/480x272/model_telemetry.cpp b/radio/src/gui/480x272/model_telemetry.cpp
index 5b5b10cbf..e31e6af37 100644
--- a/radio/src/gui/480x272/model_telemetry.cpp
+++ b/radio/src/gui/480x272/model_telemetry.cpp
@@ -59,6 +59,38 @@ enum MenuModelTelemetryFrskyItems {
ITEM_TELEMETRY_SENSOR30,
ITEM_TELEMETRY_SENSOR31,
ITEM_TELEMETRY_SENSOR32,
+ ITEM_TELEMETRY_SENSOR33,
+ ITEM_TELEMETRY_SENSOR34,
+ ITEM_TELEMETRY_SENSOR35,
+ ITEM_TELEMETRY_SENSOR36,
+ ITEM_TELEMETRY_SENSOR37,
+ ITEM_TELEMETRY_SENSOR38,
+ ITEM_TELEMETRY_SENSOR39,
+ ITEM_TELEMETRY_SENSOR40,
+ ITEM_TELEMETRY_SENSOR41,
+ ITEM_TELEMETRY_SENSOR42,
+ ITEM_TELEMETRY_SENSOR43,
+ ITEM_TELEMETRY_SENSOR44,
+ ITEM_TELEMETRY_SENSOR45,
+ ITEM_TELEMETRY_SENSOR46,
+ ITEM_TELEMETRY_SENSOR47,
+ ITEM_TELEMETRY_SENSOR48,
+ ITEM_TELEMETRY_SENSOR49,
+ ITEM_TELEMETRY_SENSOR50,
+ ITEM_TELEMETRY_SENSOR51,
+ ITEM_TELEMETRY_SENSOR52,
+ ITEM_TELEMETRY_SENSOR53,
+ ITEM_TELEMETRY_SENSOR54,
+ ITEM_TELEMETRY_SENSOR55,
+ ITEM_TELEMETRY_SENSOR56,
+ ITEM_TELEMETRY_SENSOR57,
+ ITEM_TELEMETRY_SENSOR58,
+ ITEM_TELEMETRY_SENSOR59,
+ ITEM_TELEMETRY_SENSOR60,
+ ITEM_TELEMETRY_SENSOR61,
+ ITEM_TELEMETRY_SENSOR62,
+ ITEM_TELEMETRY_SENSOR63,
+ ITEM_TELEMETRY_SENSOR64,
ITEM_TELEMETRY_DISCOVER_SENSORS,
ITEM_TELEMETRY_NEW_SENSOR,
ITEM_TELEMETRY_DELETE_ALL_SENSORS,
@@ -82,7 +114,8 @@ enum MenuModelTelemetryFrskyItems {
#define IS_RANGE_DEFINED(k) (g_model.frsky.channels[k].ratio > 0)
#define SENSOR_ROWS(x) (isTelemetryFieldAvailable(x) ? (uint8_t)0 : HIDDEN_ROW)
-#define SENSORS_ROWS LABEL(Sensors), SENSOR_ROWS(0), SENSOR_ROWS(1), SENSOR_ROWS(2), SENSOR_ROWS(3), SENSOR_ROWS(4), SENSOR_ROWS(5), SENSOR_ROWS(6), SENSOR_ROWS(7), SENSOR_ROWS(8), SENSOR_ROWS(9), SENSOR_ROWS(10), SENSOR_ROWS(11), SENSOR_ROWS(12), SENSOR_ROWS(13), SENSOR_ROWS(14), SENSOR_ROWS(15), SENSOR_ROWS(16), SENSOR_ROWS(17), SENSOR_ROWS(18), SENSOR_ROWS(19), SENSOR_ROWS(20), SENSOR_ROWS(21), SENSOR_ROWS(22), SENSOR_ROWS(23), SENSOR_ROWS(24), SENSOR_ROWS(25), SENSOR_ROWS(26), SENSOR_ROWS(27), SENSOR_ROWS(28), SENSOR_ROWS(29), SENSOR_ROWS(30), SENSOR_ROWS(31), 0, 0, 0, 0,
+#define SENSORS_ROWS LABEL(Sensors), SENSOR_ROWS(0), SENSOR_ROWS(1), SENSOR_ROWS(2), SENSOR_ROWS(3), SENSOR_ROWS(4), SENSOR_ROWS(5), SENSOR_ROWS(6), SENSOR_ROWS(7), SENSOR_ROWS(8), SENSOR_ROWS(9), SENSOR_ROWS(10), SENSOR_ROWS(11), SENSOR_ROWS(12), SENSOR_ROWS(13), SENSOR_ROWS(14), SENSOR_ROWS(15), SENSOR_ROWS(16), SENSOR_ROWS(17), SENSOR_ROWS(18), SENSOR_ROWS(19), SENSOR_ROWS(20), SENSOR_ROWS(21), SENSOR_ROWS(22), SENSOR_ROWS(23), SENSOR_ROWS(24), SENSOR_ROWS(25), SENSOR_ROWS(26), SENSOR_ROWS(27), SENSOR_ROWS(28), SENSOR_ROWS(29), SENSOR_ROWS(30), \
+ SENSOR_ROWS(31), SENSOR_ROWS(32), SENSOR_ROWS(33), SENSOR_ROWS(34), SENSOR_ROWS(35), SENSOR_ROWS(36), SENSOR_ROWS(37), SENSOR_ROWS(38), SENSOR_ROWS(39), SENSOR_ROWS(40),SENSOR_ROWS(41), SENSOR_ROWS(42), SENSOR_ROWS(43), SENSOR_ROWS(44), SENSOR_ROWS(45), SENSOR_ROWS(46), SENSOR_ROWS(47), SENSOR_ROWS(48), SENSOR_ROWS(49), SENSOR_ROWS(50),SENSOR_ROWS(51), SENSOR_ROWS(52), SENSOR_ROWS(53), SENSOR_ROWS(54), SENSOR_ROWS(55), SENSOR_ROWS(56), SENSOR_ROWS(57), SENSOR_ROWS(58), SENSOR_ROWS(59),SENSOR_ROWS(60),SENSOR_ROWS(61), SENSOR_ROWS(62), SENSOR_ROWS(63), 0, 0, 0, 0,
#if defined(VARIO)
#define VARIO_ROWS LABEL(Vario), 0, 1, 2,
#else
diff --git a/radio/src/gui/480x272/popups.cpp b/radio/src/gui/480x272/popups.cpp
index d26ccff61..147592d3c 100644
--- a/radio/src/gui/480x272/popups.cpp
+++ b/radio/src/gui/480x272/popups.cpp
@@ -26,13 +26,10 @@ uint8_t warningInfoLength;
uint8_t warningType;
uint8_t warningResult = 0;
uint8_t warningInfoFlags = ZCHAR;
-int16_t warningInputValue;
-int16_t warningInputValueMin;
-int16_t warningInputValueMax;
void (*popupFunc)(event_t event) = NULL;
const char *popupMenuItems[POPUP_MENU_MAX_LINES];
uint8_t s_menu_item = 0;
-uint16_t popupMenuNoItems = 0;
+uint16_t popupMenuItemsCount = 0;
uint16_t popupMenuOffset = 0;
uint8_t popupMenuOffsetType = MENU_OFFSET_INTERNAL;
void (*popupMenuHandler)(const char * result);
@@ -80,24 +77,20 @@ void runPopupWarning(event_t event)
{
warningResult = false;
- theme->drawMessageBox(warningText, warningInfoText, warningType == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS, warningType);
+ theme->drawMessageBox(warningText, warningInfoText, WARNING_TYPE_INFO ? STR_OK : (warningType == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS_ENTER_EXIT), warningType);
switch (event) {
case EVT_KEY_BREAK(KEY_ENTER):
if (warningType == WARNING_TYPE_ASTERISK)
break;
- warningResult = true;
+ if (warningType != WARNING_TYPE_INFO)
+ warningResult = true;
// no break
+
case EVT_KEY_BREAK(KEY_EXIT):
warningText = NULL;
warningType = WARNING_TYPE_ASTERISK;
break;
- default:
- if (warningType != WARNING_TYPE_INPUT) break;
- s_editMode = EDIT_MODIFY_FIELD;
- warningInputValue = checkIncDec(event, warningInputValue, warningInputValueMin, warningInputValueMax);
- s_editMode = EDIT_SELECT_FIELD;
- break;
}
}
@@ -105,7 +98,7 @@ const char * runPopupMenu(event_t event)
{
const char * result = NULL;
- uint8_t display_count = min(popupMenuNoItems, MENU_MAX_DISPLAY_LINES);
+ uint8_t display_count = min(popupMenuItemsCount, MENU_MAX_DISPLAY_LINES);
switch (event) {
case EVT_ROTARY_LEFT:
@@ -118,18 +111,18 @@ const char * runPopupMenu(event_t event)
}
else {
s_menu_item = min(display_count, MENU_MAX_DISPLAY_LINES) - 1;
- if (popupMenuNoItems > MENU_MAX_DISPLAY_LINES) {
- popupMenuOffset = popupMenuNoItems - MENU_MAX_DISPLAY_LINES;
+ if (popupMenuItemsCount > MENU_MAX_DISPLAY_LINES) {
+ popupMenuOffset = popupMenuItemsCount - MENU_MAX_DISPLAY_LINES;
result = STR_UPDATE_LIST;
}
}
break;
case EVT_ROTARY_RIGHT:
- if (s_menu_item < display_count - 1 && popupMenuOffset + s_menu_item + 1 < popupMenuNoItems) {
+ if (s_menu_item < display_count - 1 && popupMenuOffset + s_menu_item + 1 < popupMenuItemsCount) {
s_menu_item++;
}
- else if (popupMenuNoItems > popupMenuOffset + display_count) {
+ else if (popupMenuItemsCount > popupMenuOffset + display_count) {
popupMenuOffset++;
result = STR_UPDATE_LIST;
}
@@ -147,7 +140,7 @@ const char * runPopupMenu(event_t event)
// no break
case EVT_KEY_BREAK(KEY_EXIT):
- popupMenuNoItems = 0;
+ popupMenuItemsCount = 0;
s_menu_item = 0;
popupMenuOffset = 0;
break;
@@ -168,8 +161,8 @@ const char * runPopupMenu(event_t event)
}
}
- if (popupMenuNoItems > display_count) {
- drawVerticalScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_DISPLAY_LINES * (FH+1), popupMenuOffset, popupMenuNoItems, MENU_MAX_DISPLAY_LINES);
+ if (popupMenuItemsCount > display_count) {
+ drawVerticalScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_DISPLAY_LINES * (FH+1), popupMenuOffset, popupMenuItemsCount, MENU_MAX_DISPLAY_LINES);
}
return result;
diff --git a/radio/src/gui/480x272/radio_sdmanager.cpp b/radio/src/gui/480x272/radio_sdmanager.cpp
index 7206687b2..711ffdfb0 100644
--- a/radio/src/gui/480x272/radio_sdmanager.cpp
+++ b/radio/src/gui/480x272/radio_sdmanager.cpp
@@ -19,6 +19,7 @@
*/
#include
+#include
#include "opentx.h"
#include "storage/modelslist.h"
@@ -141,15 +142,18 @@ void onSdManagerMenu(const char * result)
}
else if (result == STR_FLASH_INTERNAL_MODULE) {
getSelectionFullPath(lfn);
- sportFlashDevice(INTERNAL_MODULE, lfn);
+ DeviceFirmwareUpdate device(INTERNAL_MODULE);
+ device.flashFile(lfn);
}
else if (result == STR_FLASH_EXTERNAL_MODULE) {
getSelectionFullPath(lfn);
- sportFlashDevice(EXTERNAL_MODULE, lfn);
+ DeviceFirmwareUpdate device(EXTERNAL_MODULE);
+ device.flashFile(lfn);
}
else if (result == STR_FLASH_EXTERNAL_DEVICE) {
getSelectionFullPath(lfn);
- sportFlashDevice(FLASHING_MODULE, lfn);
+ DeviceFirmwareUpdate device(SPORT_MODULE);
+ device.flashFile(lfn);
}
#if defined(LUA)
else if (result == STR_EXECUTE_FILE) {
diff --git a/radio/src/gui/480x272/radio_setup.cpp b/radio/src/gui/480x272/radio_setup.cpp
index a4e86b44e..9f921fe94 100644
--- a/radio/src/gui/480x272/radio_setup.cpp
+++ b/radio/src/gui/480x272/radio_setup.cpp
@@ -403,10 +403,12 @@ bool menuRadioSetup(event_t event)
g_eeGeneral.gpsFormat = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_GPSFORMAT, g_eeGeneral.gpsFormat, 0, 1, attr, event);
break;
+#if defined(PXX)
case ITEM_SETUP_COUNTRYCODE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_COUNTRYCODE);
g_eeGeneral.countryCode = editChoice(RADIO_SETUP_2ND_COLUMN, y, STR_COUNTRYCODES, g_eeGeneral.countryCode, 0, 2, attr, event);
break;
+#endif
case ITEM_SETUP_LANGUAGE:
lcdDrawText(MENUS_MARGIN_LEFT, y, STR_VOICELANG);
diff --git a/radio/src/gui/480x272/screens_setup.cpp b/radio/src/gui/480x272/screens_setup.cpp
index a329a136f..749bd50c2 100644
--- a/radio/src/gui/480x272/screens_setup.cpp
+++ b/radio/src/gui/480x272/screens_setup.cpp
@@ -53,7 +53,7 @@ void onZoneOptionFileSelectionMenu(const char * result)
POPUP_WARNING(STR_NO_BITMAPS_ON_SD);
}
}
- else {
+ else if (result != STR_EXIT) {
fileSelectionDone = true;
memcpy(fileSelection, result, sizeof(fileSelection));
}
diff --git a/radio/src/gui/480x272/themes/darkblue.cpp b/radio/src/gui/480x272/themes/darkblue.cpp
index 24cf4616b..9d2e1cbdb 100644
--- a/radio/src/gui/480x272/themes/darkblue.cpp
+++ b/radio/src/gui/480x272/themes/darkblue.cpp
@@ -136,12 +136,10 @@ class DarkblueTheme: public Theme
delete calibHorus;
#if defined(PCBX10)
- if(STICKS_PWM_ENABLED()) {
+ if (STICKS_PWM_ENABLED())
calibHorus = BitmapBuffer::load(getThemePath("X10S.bmp"));
- }
- else {
+ else
calibHorus = BitmapBuffer::load(getThemePath("X10.bmp"));
- }
#else
calibHorus = BitmapBuffer::load(getThemePath("horus.bmp"));
#endif
diff --git a/radio/src/gui/480x272/widgets.cpp b/radio/src/gui/480x272/widgets.cpp
index 065017c6f..f726b193b 100644
--- a/radio/src/gui/480x272/widgets.cpp
+++ b/radio/src/gui/480x272/widgets.cpp
@@ -108,12 +108,12 @@ void drawHorizontalScrollbar(coord_t x, coord_t y, coord_t w, uint16_t offset, u
}
}
-void drawProgressBar(const char * label, int num, int den)
+void drawProgressScreen(const char * title, const char * message, int num, int den)
{
lcdClear();
lcdSetColor(WHITE);
- if (label) {
- lcdDrawText(MENUS_MARGIN_LEFT, LCD_H-42, label, CUSTOM_COLOR);
+ if (message) {
+ lcdDrawText(MENUS_MARGIN_LEFT, LCD_H-42, message, CUSTOM_COLOR);
}
lcdDrawRect(MENUS_MARGIN_LEFT, LCD_H-22, LCD_W-2*MENUS_MARGIN_LEFT, 15, 1, SOLID, CUSTOM_COLOR);
lcdSetColor(RED);
diff --git a/radio/src/gui/480x272/widgets.h b/radio/src/gui/480x272/widgets.h
index 0e2784421..e8be64672 100644
--- a/radio/src/gui/480x272/widgets.h
+++ b/radio/src/gui/480x272/widgets.h
@@ -49,7 +49,7 @@ void drawButton(coord_t x, coord_t y, const char * label, LcdFlags attr);
void drawCheckBox(coord_t x, coord_t y, uint8_t value, LcdFlags attr);
void drawVerticalScrollbar(coord_t x, coord_t y, coord_t h, uint16_t offset, uint16_t count, uint8_t visible);
void drawHorizontalScrollbar(coord_t x, coord_t y, coord_t w, uint16_t offset, uint16_t count, uint8_t visible);
-void drawProgressBar(const char * label, int num, int den);
+void drawProgressScreen(const char * title, const char * message, int num, int den);
void drawShadow(coord_t x, coord_t y, coord_t w, coord_t h);
void drawTrimSquare(coord_t x, coord_t y);
void drawHorizontalTrimPosition(coord_t x, coord_t y, int16_t dir);
diff --git a/radio/src/gui/CMakeLists.txt b/radio/src/gui/CMakeLists.txt
index 6ec951c20..0dd24c589 100644
--- a/radio/src/gui/CMakeLists.txt
+++ b/radio/src/gui/CMakeLists.txt
@@ -9,6 +9,9 @@ set(GUI_SRC
menu_model.cpp
model_select.cpp
model_setup.cpp
+ model_failsafe.cpp
+ model_module_options.cpp
+ model_receiver_options.cpp
model_logical_switches.cpp
model_special_functions.cpp
model_telemetry.cpp
diff --git a/radio/src/gui/common/colorlcd/widgets.cpp b/radio/src/gui/common/colorlcd/widgets.cpp
index 84f49e67d..0dd0a4a39 100644
--- a/radio/src/gui/common/colorlcd/widgets.cpp
+++ b/radio/src/gui/common/colorlcd/widgets.cpp
@@ -46,7 +46,7 @@ void drawValueWithUnit(coord_t x, coord_t y, int32_t val, uint8_t unit, LcdFlags
int editChoice(coord_t x, coord_t y, const char * values, int value, int min, int max, LcdFlags attr, event_t event)
{
- if (attr & INVERS) value = checkIncDec(event, value, min, max, (menuVerticalPositions[0] == 0) ? EE_MODEL : EE_GENERAL);
+ if (attr & INVERS) value = checkIncDec(event, value, min, max, (isModelMenuDisplayed()) ? EE_MODEL : EE_GENERAL);
if (values) lcdDrawTextAtIndex(x, y, values, value-min, attr);
return value;
}
diff --git a/radio/src/gui/common/stdlcd/CMakeLists.txt b/radio/src/gui/common/stdlcd/CMakeLists.txt
index a9056719f..26e29bbda 100644
--- a/radio/src/gui/common/stdlcd/CMakeLists.txt
+++ b/radio/src/gui/common/stdlcd/CMakeLists.txt
@@ -28,5 +28,15 @@ if(SDCARD)
set(GUI_SRC
${GUI_SRC}
../common/stdlcd/radio_sdmanager.cpp
+ ../common/stdlcd/radio_tools.cpp
)
endif()
+
+if(PXX2)
+ set(GUI_SRC
+ ${GUI_SRC}
+ ../common/stdlcd/radio_spectrum_analyser.cpp
+ ../common/stdlcd/radio_power_meter.cpp
+ )
+endif()
+
diff --git a/radio/src/gui/common/stdlcd/popups.cpp b/radio/src/gui/common/stdlcd/popups.cpp
index abd7890da..e4dfe0e5f 100644
--- a/radio/src/gui/common/stdlcd/popups.cpp
+++ b/radio/src/gui/common/stdlcd/popups.cpp
@@ -20,33 +20,77 @@
#include "opentx.h"
-uint8_t popupMenuOffsetType = MENU_OFFSET_INTERNAL;
-void (*popupFunc)(event_t event) = NULL;
+const char * warningText = NULL;
+const char * warningInfoText;
+uint8_t warningInfoLength;
+uint8_t warningType;
+uint8_t warningResult = 0;
+uint8_t warningInfoFlags = ZCHAR;
+
+uint8_t popupMenuOffsetType = MENU_OFFSET_INTERNAL;
+void (* popupFunc)(event_t event) = NULL;
-#if defined(NAVIGATION_MENUS)
const char * popupMenuItems[POPUP_MENU_MAX_LINES];
-uint8_t s_menu_item = 0;
-uint16_t popupMenuNoItems = 0;
-uint8_t popupMenuFlags = 0;
-uint16_t popupMenuOffset = 0;
-void (*popupMenuHandler)(const char * result);
+uint8_t s_menu_item = 0;
+uint16_t popupMenuItemsCount = 0;
+uint16_t popupMenuOffset = 0;
+void (* popupMenuHandler)(const char * result);
+const char * popupMenuTitle = nullptr;
+
+void drawMessageBoxBackground(coord_t top, coord_t height)
+{
+ // white background
+ lcdDrawFilledRect(MESSAGEBOX_X - 1, top - 1, MESSAGEBOX_W + 2, height + 2, SOLID, ERASE);
+
+ // border
+ lcdDrawRect(MESSAGEBOX_X, top, MESSAGEBOX_W, height, SOLID, FORCE);
+}
+
+void drawMessageBox(const char * title)
+{
+ // background + border
+ drawMessageBoxBackground(MESSAGEBOX_Y, 40);
+
+ // title
+ lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y, title, WARNING_LINE_LEN);
+
+ // could be a place for a warningInfoText
+}
+
+void showMessageBox(const char * title)
+{
+ drawMessageBox(title);
+ lcdRefresh();
+}
const char * runPopupMenu(event_t event)
{
- const char * result = NULL;
+ const char * result = nullptr;
- uint8_t display_count = min(popupMenuNoItems, MENU_MAX_DISPLAY_LINES);
- uint8_t y = (display_count >= 5 ? MENU_Y - FH - 1 : MENU_Y);
- lcdDrawFilledRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2, SOLID, ERASE);
- lcdDrawRect(MENU_X, y, MENU_W, display_count * (FH+1) + 2);
+ uint8_t display_count = min(popupMenuItemsCount, MENU_MAX_DISPLAY_LINES);
+ uint8_t y = LCD_H / 2 - (popupMenuTitle ? 0 : 3) - (display_count * FH / 2);
+ // white background
+ lcdDrawFilledRect(MENU_X - 1, popupMenuTitle ? y - FH - 3 : y - 1, MENU_W + 2, display_count * (FH + 1) + (popupMenuTitle ? FH + 6 : 4), SOLID, ERASE);
+
+ // title
+ if (popupMenuTitle) {
+ lcdDrawText(MENU_X + 2, y - FH, popupMenuTitle, BOLD);
+ lcdDrawRect(MENU_X, y - FH - 2, lcdLastRightPos - MENU_X + 2, FH + 3);
+ }
+
+ // border
+ lcdDrawRect(MENU_X, y, MENU_W, display_count * (FH + 1) + 2, SOLID, FORCE);
+
+ // items
for (uint8_t i=0; i display_count) {
- drawVerticalScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_DISPLAY_LINES * (FH+1), popupMenuOffset, popupMenuNoItems, display_count);
+ // scrollbar
+ if (popupMenuItemsCount > display_count) {
+ drawVerticalScrollbar(MENU_X+MENU_W-1, y+1, MENU_MAX_DISPLAY_LINES * (FH+1), popupMenuOffset, popupMenuItemsCount, display_count);
}
switch (event) {
@@ -67,8 +111,8 @@ const char * runPopupMenu(event_t event)
else {
s_menu_item = min(display_count, MENU_MAX_DISPLAY_LINES) - 1;
#if defined(SDCARD)
- if (popupMenuNoItems > MENU_MAX_DISPLAY_LINES) {
- popupMenuOffset = popupMenuNoItems - display_count;
+ if (popupMenuItemsCount > MENU_MAX_DISPLAY_LINES) {
+ popupMenuOffset = popupMenuItemsCount - display_count;
result = STR_UPDATE_LIST;
}
#endif
@@ -80,11 +124,11 @@ const char * runPopupMenu(event_t event)
#endif
case EVT_KEY_FIRST(KEY_DOWN):
case EVT_KEY_REPT(KEY_DOWN):
- if (s_menu_item < display_count - 1 && popupMenuOffset + s_menu_item + 1 < popupMenuNoItems) {
+ if (s_menu_item < display_count - 1 && popupMenuOffset + s_menu_item + 1 < popupMenuItemsCount) {
s_menu_item++;
}
#if defined(SDCARD)
- else if (popupMenuNoItems > popupMenuOffset + display_count) {
+ else if (popupMenuItemsCount > popupMenuOffset + display_count) {
popupMenuOffset++;
result = STR_UPDATE_LIST;
}
@@ -105,7 +149,11 @@ const char * runPopupMenu(event_t event)
#endif
case EVT_KEY_BREAK(KEY_ENTER):
result = popupMenuItems[s_menu_item + (popupMenuOffsetType == MENU_OFFSET_INTERNAL ? popupMenuOffset : 0)];
- // no break
+ popupMenuItemsCount = 0;
+ s_menu_item = 0;
+ popupMenuOffset = 0;
+ popupMenuTitle = nullptr;
+ break;
#if defined(CASE_EVT_ROTARY_LONG)
CASE_EVT_ROTARY_LONG
@@ -114,13 +162,83 @@ const char * runPopupMenu(event_t event)
#endif
case EVT_KEY_BREAK(KEY_EXIT):
- popupMenuNoItems = 0;
+ result = STR_EXIT;
+ popupMenuItemsCount = 0;
s_menu_item = 0;
- popupMenuFlags = 0;
popupMenuOffset = 0;
+ popupMenuTitle = nullptr;
break;
}
return result;
}
-#endif
+
+void runPopupWarning(event_t event)
+{
+ warningResult = false;
+
+ drawMessageBox(warningText);
+
+ if (warningInfoText) {
+ lcdDrawSizedText(WARNING_LINE_X, WARNING_LINE_Y+FH, warningInfoText, warningInfoLength, WARNING_INFO_FLAGS);
+ }
+
+ lcdDrawText(WARNING_LINE_X, WARNING_LINE_Y+2*FH, warningType == WARNING_TYPE_INFO ? STR_OK : (warningType == WARNING_TYPE_ASTERISK ? STR_EXIT : STR_POPUPS_ENTER_EXIT));
+
+ switch (event) {
+ case EVT_KEY_BREAK(KEY_ENTER):
+ if (warningType == WARNING_TYPE_ASTERISK)
+ // key ignored, the user has to press [EXIT]
+ break;
+
+ if (warningType == WARNING_TYPE_CONFIRM) {
+ warningType = WARNING_TYPE_ASTERISK;
+ warningText = nullptr;
+ if (popupMenuHandler)
+ popupMenuHandler(STR_OK);
+ else
+ warningResult = true;
+ break;
+ }
+ // no break
+
+ case EVT_KEY_BREAK(KEY_EXIT):
+ if (warningType == WARNING_TYPE_CONFIRM) {
+ if (popupMenuHandler)
+ popupMenuHandler(STR_EXIT);
+ }
+ warningText = nullptr;
+ warningType = WARNING_TYPE_ASTERISK;
+ break;
+ }
+}
+
+void showAlertBox(const char * title, const char * text, const char * action , uint8_t sound)
+{
+ drawAlertBox(title, text, action);
+ AUDIO_ERROR_MESSAGE(sound);
+ lcdRefresh();
+ lcdSetContrast();
+ clearKeyEvents();
+ backlightOn();
+ checkBacklight();
+}
+
+void drawProgressScreen(const char * title, const char * message, int num, int den)
+{
+ lcdClear();
+ if (title) {
+ lcdDrawText(LCD_W / 2 - getTextWidth(title) / 2, 2*FH, title);
+ }
+ if (message) {
+ lcdDrawText(4, 5*FH, message);
+ }
+ lcdDrawRect(4, 6*FH+4, LCD_W-8, 7);
+ if (num > 0 && den > 0) {
+ int width = ((LCD_W-12)*num)/den;
+ lcdDrawSolidHorizontalLine(6, 6*FH+6, width, FORCE);
+ lcdDrawSolidHorizontalLine(6, 6*FH+7, width, FORCE);
+ lcdDrawSolidHorizontalLine(6, 6*FH+8, width, FORCE);
+ }
+ lcdRefresh();
+}
diff --git a/radio/src/gui/common/stdlcd/popups.h b/radio/src/gui/common/stdlcd/popups.h
new file mode 100644
index 000000000..17806561c
--- /dev/null
+++ b/radio/src/gui/common/stdlcd/popups.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _STDLCD_POPUPS_H_
+#define _STDLCD_POPUPS_H_
+
+extern const char * warningText;
+extern const char * warningInfoText;
+extern uint8_t warningInfoLength;
+extern uint8_t warningResult;
+extern uint8_t warningType;
+extern uint8_t warningInfoFlags;
+
+extern void (* popupFunc)(event_t event);
+extern uint8_t popupMenuOffsetType;
+
+extern uint16_t popupMenuOffset;
+extern const char * popupMenuItems[POPUP_MENU_MAX_LINES];
+extern uint16_t popupMenuItemsCount;
+extern void (* popupMenuHandler)(const char * result);
+extern const char * popupMenuTitle;
+extern uint8_t s_menu_item;
+
+// Message box
+void drawMessageBoxBackground(coord_t top, coord_t height);
+void drawMessageBox(const char * title);
+void showMessageBox(const char * title);
+
+// Popup menu
+const char * runPopupMenu(event_t event);
+void runPopupWarning(event_t event);
+
+// Full screen with an alert
+void showAlertBox(const char * title, const char * text, const char * action , uint8_t sound);
+
+// Full screen with 2 lines and a progress bar
+void drawProgressScreen(const char * title, const char * message, int num, int den);
+
+#endif // _STDLCD_POPUPS_H_
diff --git a/radio/src/gui/common/stdlcd/radio_power_meter.cpp b/radio/src/gui/common/stdlcd/radio_power_meter.cpp
new file mode 100644
index 000000000..fbe5f96ab
--- /dev/null
+++ b/radio/src/gui/common/stdlcd/radio_power_meter.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+#include "opentx.h"
+
+void menuRadioPowerMeter(event_t event)
+{
+ SIMPLE_SUBMENU("POWER METER", 1);
+
+ if (menuEvent) {
+ pausePulses();
+ moduleSettings[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ /* wait 500ms off */
+ watchdogSuspend(500);
+ RTOS_WAIT_MS(500);
+ resumePulses();
+ }
+ else if (event == EVT_ENTRY) {
+ memclear(&reusableBuffer.powerMeter, sizeof(reusableBuffer.powerMeter));
+ reusableBuffer.powerMeter.freq = 2400;
+ moduleSettings[INTERNAL_MODULE].mode = MODULE_MODE_POWER_METER;
+ }
+
+ coord_t y = MENU_HEADER_HEIGHT + 1 + FH;
+ LcdFlags attr = (menuVerticalPosition == 0 ? INVERS : 0);
+ lcdDrawText(0, y, "Freq.");
+ lcdDrawNumber(8*FW, y, reusableBuffer.powerMeter.freq, LEFT|attr|(s_editMode > 0 ? BLINK : 0));
+ lcdDrawText(lcdNextPos, y, "MHz");
+ if (attr) {
+ CHECK_INCDEC_MODELVAR(event, reusableBuffer.powerMeter.freq, 2300, 2500);
+ if (checkIncDec_Ret) {
+ reusableBuffer.powerMeter.power = 0;
+ reusableBuffer.powerMeter.peak = 0;
+ }
+ }
+
+ y += FH + 1;
+ lcdDrawText(0, y, "Power");
+ if (reusableBuffer.powerMeter.power) {
+ lcdDrawNumber(8 * FW, y, reusableBuffer.powerMeter.power, LEFT | PREC2);
+ lcdDrawText(lcdNextPos, y, "dBm");
+ }
+
+ y += FH + 1;
+ lcdDrawText(0, y, "Peak");
+ if (reusableBuffer.powerMeter.peak) {
+ lcdDrawNumber(8 * FW, y, reusableBuffer.powerMeter.peak, LEFT | PREC2);
+ lcdDrawText(lcdNextPos, y, "dBm");
+ }
+}
diff --git a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
index b89cd74f4..ef652d316 100644
--- a/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
+++ b/radio/src/gui/common/stdlcd/radio_sdmanager.cpp
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
+#include "io/frsky_device_firmware_update.h"
#define REFRESH_FILES() do { reusableBuffer.sdmanager.offset = 65535; menuVerticalPosition = 0; } while(0)
#define NODE_TYPE(fname) fname[SD_SCREEN_FILE_LENGTH+1]
@@ -81,7 +82,7 @@ void onSdManagerMenu(const char * result)
pushMenu(menuRadioSdManagerInfo);
}
else if (result == STR_SD_FORMAT) {
- POPUP_CONFIRMATION(STR_CONFIRM_FORMAT);
+ POPUP_CONFIRMATION(STR_CONFIRM_FORMAT, nullptr);
}
else if (result == STR_COPY_FILE) {
clipboard.type = CLIPBOARD_TYPE_SD_FILE;
@@ -141,16 +142,19 @@ void onSdManagerMenu(const char * result)
}
else if (result == STR_FLASH_INTERNAL_MODULE) {
getSelectionFullPath(lfn);
- sportFlashDevice(INTERNAL_MODULE, lfn);
+ DeviceFirmwareUpdate device(INTERNAL_MODULE);
+ device.flashFile(lfn);
}
else if (result == STR_FLASH_EXTERNAL_MODULE) {
// needed on X-Lite (as the R9M needs 2S while the external device flashing port only provides 5V)
getSelectionFullPath(lfn);
- sportFlashDevice(EXTERNAL_MODULE, lfn);
+ DeviceFirmwareUpdate device(EXTERNAL_MODULE);
+ device.flashFile(lfn);
}
else if (result == STR_FLASH_EXTERNAL_DEVICE) {
getSelectionFullPath(lfn);
- sportFlashDevice(FLASHING_MODULE, lfn);
+ DeviceFirmwareUpdate device(SPORT_MODULE);
+ device.flashFile(lfn);
}
#endif
#if defined(LUA)
@@ -171,7 +175,7 @@ void menuRadioSdManager(event_t _event)
Card_state = SD_ST_DATA;
#endif
audioQueue.stopSD();
- if(sdCardFormat()) {
+ if (sdCardFormat()) {
f_chdir("/");
REFRESH_FILES();
}
@@ -197,9 +201,9 @@ void menuRadioSdManager(event_t _event)
menuVerticalOffset = reusableBuffer.sdmanager.offset;
break;
-#if defined(PCBX9) || defined(PCBX7) // TODO NO_MENU_KEY
+#if defined(PCBX9) || defined(PCBX7) || defined(PCBX3) // TODO NO_MENU_KEY
case EVT_KEY_LONG(KEY_MENU):
- if (!READ_ONLY() && s_editMode == 0) {
+ if (SD_CARD_PRESENT() && !READ_ONLY() && s_editMode == 0) {
killEvents(_event);
POPUP_MENU_ADD_ITEM(STR_SD_INFO);
POPUP_MENU_ADD_ITEM(STR_SD_FORMAT);
@@ -234,7 +238,7 @@ void menuRadioSdManager(event_t _event)
break;
case EVT_KEY_LONG(KEY_ENTER):
-#if !defined(PCBX9) && !defined(PCBX7) // TODO NO_HEADER_LINE
+#if !defined(PCBX9) && !defined(PCBX7) && !defined(PCBX3)// TODO NO_HEADER_LINE
if (menuVerticalPosition < HEADER_LINE) {
killEvents(_event);
POPUP_MENU_ADD_ITEM(STR_SD_INFO);
@@ -243,7 +247,7 @@ void menuRadioSdManager(event_t _event)
break;
}
#endif
- if (s_editMode <= 0) {
+ if (SD_CARD_PRESENT() && s_editMode <= 0) {
killEvents(_event);
int index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset;
char * line = reusableBuffer.sdmanager.lines[index];
@@ -300,132 +304,137 @@ void menuRadioSdManager(event_t _event)
break;
}
- if (reusableBuffer.sdmanager.offset != menuVerticalOffset) {
- FILINFO fno;
- DIR dir;
+ if (SD_CARD_PRESENT()) {
+ if (reusableBuffer.sdmanager.offset != menuVerticalOffset) {
+ FILINFO fno;
+ DIR dir;
- if (menuVerticalOffset == 0) {
- reusableBuffer.sdmanager.offset = 0;
- memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines));
- }
- else if (menuVerticalOffset == reusableBuffer.sdmanager.count-NUM_BODY_LINES) {
- reusableBuffer.sdmanager.offset = menuVerticalOffset;
- memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines));
- }
- else if (menuVerticalOffset > reusableBuffer.sdmanager.offset) {
- memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], (NUM_BODY_LINES-1)*sizeof(reusableBuffer.sdmanager.lines[0]));
- memset(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], 0xff, SD_SCREEN_FILE_LENGTH);
- NODE_TYPE(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1]) = 1;
- }
- else {
- memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], (NUM_BODY_LINES-1)*sizeof(reusableBuffer.sdmanager.lines[0]));
- memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
- }
+ if (menuVerticalOffset == 0) {
+ reusableBuffer.sdmanager.offset = 0;
+ memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines));
+ }
+ else if (menuVerticalOffset == reusableBuffer.sdmanager.count-NUM_BODY_LINES) {
+ reusableBuffer.sdmanager.offset = menuVerticalOffset;
+ memset(reusableBuffer.sdmanager.lines, 0, sizeof(reusableBuffer.sdmanager.lines));
+ }
+ else if (menuVerticalOffset > reusableBuffer.sdmanager.offset) {
+ memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], (NUM_BODY_LINES-1)*sizeof(reusableBuffer.sdmanager.lines[0]));
+ memset(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], 0xff, SD_SCREEN_FILE_LENGTH);
+ NODE_TYPE(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1]) = 1;
+ }
+ else {
+ memmove(reusableBuffer.sdmanager.lines[1], reusableBuffer.sdmanager.lines[0], (NUM_BODY_LINES-1)*sizeof(reusableBuffer.sdmanager.lines[0]));
+ memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
+ }
- reusableBuffer.sdmanager.count = 0;
+ reusableBuffer.sdmanager.count = 0;
- FRESULT res = f_opendir(&dir, "."); // Open the directory
- if (res == FR_OK) {
- bool firstTime = true;
- for (;;) {
- res = sdReadDir(&dir, &fno, firstTime);
- if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
- if (strlen(fno.fname) > SD_SCREEN_FILE_LENGTH) continue;
- if (fno.fattrib & AM_HID) continue; /* Ignore Windows hidden files */
- if (fno.fname[0] == '.' && fno.fname[1] != '.') continue; /* Ignore UNIX hidden files, but not .. */
+ FRESULT res = f_opendir(&dir, "."); // Open the directory
+ if (res == FR_OK) {
+ bool firstTime = true;
+ for (;;) {
+ res = sdReadDir(&dir, &fno, firstTime);
+ if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
+ if (strlen(fno.fname) > SD_SCREEN_FILE_LENGTH) continue;
+ if (fno.fattrib & AM_HID) continue; /* Ignore Windows hidden files */
+ if (fno.fname[0] == '.' && fno.fname[1] != '.') continue; /* Ignore UNIX hidden files, but not .. */
- reusableBuffer.sdmanager.count++;
+ reusableBuffer.sdmanager.count++;
- bool isfile = !(fno.fattrib & AM_DIR);
+ bool isfile = !(fno.fattrib & AM_DIR);
- if (menuVerticalOffset == 0) {
- for (uint8_t i=0; i=0; i--) {
+ char * line = reusableBuffer.sdmanager.lines[i];
+ if (line[0] == '\0' || isFilenameGreater(isfile, fno.fname, line)) {
+ if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i);
+ memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[0]));
+ strcpy(line, fno.fname);
+ NODE_TYPE(line) = isfile;
+ break;
+ }
+ }
+ }
+ else if (menuVerticalOffset > reusableBuffer.sdmanager.offset) {
+ if (isFilenameGreater(isfile, fno.fname, reusableBuffer.sdmanager.lines[NUM_BODY_LINES-2]) && isFilenameLower(isfile, fno.fname, reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1])) {
+ memset(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
+ strcpy(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], fno.fname);
+ NODE_TYPE(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1]) = isfile;
+ }
+ }
+ else {
+ if (isFilenameLower(isfile, fno.fname, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fno.fname, reusableBuffer.sdmanager.lines[0])) {
+ memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
+ strcpy(reusableBuffer.sdmanager.lines[0], fno.fname);
+ NODE_TYPE(reusableBuffer.sdmanager.lines[0]) = isfile;
}
}
}
- else if (reusableBuffer.sdmanager.offset == menuVerticalOffset) {
- for (int8_t i=NUM_BODY_LINES-1; i>=0; i--) {
- char * line = reusableBuffer.sdmanager.lines[i];
- if (line[0] == '\0' || isFilenameGreater(isfile, fno.fname, line)) {
- if (i > 0) memmove(reusableBuffer.sdmanager.lines[0], reusableBuffer.sdmanager.lines[1], sizeof(reusableBuffer.sdmanager.lines[0]) * i);
- memset(line, 0, sizeof(reusableBuffer.sdmanager.lines[0]));
- strcpy(line, fno.fname);
- NODE_TYPE(line) = isfile;
- break;
- }
- }
+ f_closedir(&dir);
+ }
+ }
+
+ reusableBuffer.sdmanager.offset = menuVerticalOffset;
+ int index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset;
+
+ for (uint8_t i=0; i reusableBuffer.sdmanager.offset) {
- if (isFilenameGreater(isfile, fno.fname, reusableBuffer.sdmanager.lines[NUM_BODY_LINES-2]) && isFilenameLower(isfile, fno.fname, reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1])) {
- memset(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
- strcpy(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1], fno.fname);
- NODE_TYPE(reusableBuffer.sdmanager.lines[NUM_BODY_LINES-1]) = isfile;
+ if (s_editMode == EDIT_MODIFY_STRING && attr) {
+ uint8_t extlen, efflen;
+ const char * ext = getFileExtension(reusableBuffer.sdmanager.originalName, 0, 0, NULL, &extlen);
+ editName(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], SD_SCREEN_FILE_LENGTH - extlen, _event, attr, 0);
+ efflen = effectiveLen(reusableBuffer.sdmanager.lines[i], SD_SCREEN_FILE_LENGTH - extlen);
+ if (s_editMode == 0) {
+ if (ext) {
+ strAppend(&reusableBuffer.sdmanager.lines[i][efflen], ext);
+ }
+ else {
+ reusableBuffer.sdmanager.lines[i][efflen] = 0;
+ }
+ f_rename(reusableBuffer.sdmanager.originalName, reusableBuffer.sdmanager.lines[i]);
+ REFRESH_FILES();
}
}
else {
- if (isFilenameLower(isfile, fno.fname, reusableBuffer.sdmanager.lines[1]) && isFilenameGreater(isfile, fno.fname, reusableBuffer.sdmanager.lines[0])) {
- memset(reusableBuffer.sdmanager.lines[0], 0, sizeof(reusableBuffer.sdmanager.lines[0]));
- strcpy(reusableBuffer.sdmanager.lines[0], fno.fname);
- NODE_TYPE(reusableBuffer.sdmanager.lines[0]) = isfile;
- }
+ lcdDrawText(lcdNextPos, y, reusableBuffer.sdmanager.lines[i], attr);
+ }
+ if (IS_DIRECTORY(reusableBuffer.sdmanager.lines[i])) {
+ lcdDrawChar(lcdNextPos, y, ']', s_editMode == EDIT_MODIFY_STRING ? 0 : attr);
}
}
- f_closedir(&dir);
}
- }
-
- reusableBuffer.sdmanager.offset = menuVerticalOffset;
- int index = menuVerticalPosition - HEADER_LINE - menuVerticalOffset;
-
- for (uint8_t i=0; i 1
- const char * ext = getFileExtension(reusableBuffer.sdmanager.lines[index]);
- if (ext && isExtensionMatching(ext, BITMAPS_EXT)) {
- if (lastPos != menuVerticalPosition) {
- if (!lcdLoadBitmap(modelBitmap, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) {
- memcpy(modelBitmap, logo_taranis, MODEL_BITMAP_SIZE);
+ const char * ext = getFileExtension(reusableBuffer.sdmanager.lines[index]);
+ if (ext && isExtensionMatching(ext, BITMAPS_EXT)) {
+ if (lastPos != menuVerticalPosition) {
+ if (!lcdLoadBitmap(modelBitmap, reusableBuffer.sdmanager.lines[index], MODEL_BITMAP_WIDTH, MODEL_BITMAP_HEIGHT)) {
+ memcpy(modelBitmap, logo_taranis, MODEL_BITMAP_SIZE);
+ }
}
+ lcdDrawBitmap(22*FW+2, 2*FH+FH/2, modelBitmap);
}
- lcdDrawBitmap(22*FW+2, 2*FH+FH/2, modelBitmap);
- }
#endif
+ }
+ else {
+ lcdDrawText(6*FW+3, 4*FH, STR_NO_SDCARD);
+ }
}
diff --git a/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp b/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp
new file mode 100644
index 000000000..b8ab58cbf
--- /dev/null
+++ b/radio/src/gui/common/stdlcd/radio_spectrum_analyser.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "opentx.h"
+
+void menuRadioSpectrumAnalyser(event_t event)
+{
+ SIMPLE_SUBMENU("SPECTRUM ANALYSER", 1);
+
+ if (menuEvent) {
+ pausePulses();
+ moduleSettings[INTERNAL_MODULE].mode = MODULE_MODE_NORMAL;
+ /* wait 500ms off */
+ watchdogSuspend(500);
+ RTOS_WAIT_MS(500);
+ resumePulses();
+ }
+ else if (event == EVT_ENTRY) {
+ memclear(reusableBuffer.spectrumAnalyser.bars, sizeof(reusableBuffer.spectrumAnalyser.bars));
+ moduleSettings[INTERNAL_MODULE].mode = MODULE_MODE_SPECTRUM_ANALYSER;
+ }
+
+ uint8_t peak_y = 1;
+ uint8_t peak_x = 0;
+ for (uint8_t i=0; i(reusableBuffer.spectrumAnalyser.bars[i] >> 1, 128);
+ if (h > peak_y) {
+ peak_x = i;
+ peak_y = h;
+ }
+ lcdDrawSolidVerticalLine(i, LCD_H - h, h);
+ }
+
+ lcdDrawText(1, 10, "F:", 0);
+ lcdDrawNumber(lcdLastRightPos + 2, 10, reusableBuffer.spectrumAnalyser.freq / 10000000, PREC2);
+ lcdDrawText(lcdLastRightPos + 2, 10, "GHz", 0);
+
+ lcdDrawText(lcdLastRightPos + 5, 10, "S:", 0);
+ lcdDrawNumber(lcdLastRightPos + 2, 10, reusableBuffer.spectrumAnalyser.span/1000000, 0);
+ lcdDrawText(lcdLastRightPos + 2, 10, "MHz", 0);
+
+ int8_t y = max(FH, LCD_H - peak_y - FH);
+ lcdDrawNumber(min(100, peak_x), y, ((reusableBuffer.spectrumAnalyser.freq - reusableBuffer.spectrumAnalyser.span / 2) + peak_x * (reusableBuffer.spectrumAnalyser.span / 128)) / 1000000, TINSIZE);
+ lcdDrawText(lcdLastRightPos, y, "M", TINSIZE);
+}
diff --git a/radio/src/gui/common/stdlcd/radio_tools.cpp b/radio/src/gui/common/stdlcd/radio_tools.cpp
new file mode 100644
index 000000000..25efb65ed
--- /dev/null
+++ b/radio/src/gui/common/stdlcd/radio_tools.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "opentx.h"
+
+void addRadioTool(uint8_t index, const char * label, void (* tool)(event_t event), event_t event)
+{
+ int8_t sub = menuVerticalPosition - HEADER_LINE;
+ LcdFlags attr = (sub == index ? INVERS : 0);
+ coord_t y = MENU_HEADER_HEIGHT + 1 + index * FH;
+ lcdDrawNumber(3, y, index + 1, LEADING0|LEFT, 2);
+ lcdDrawText(3*FW, y, label, (sub == index ? INVERS : 0));
+ if (attr && s_editMode > 0) {
+ s_editMode = 0;
+ pushMenu(tool);
+ }
+}
+
+void menuRadioTools(event_t event)
+{
+ SIMPLE_MENU("TOOLS", menuTabGeneral, MENU_RADIO_TOOLS, HEADER_LINE + 2);
+
+#if defined(PXX2)
+ addRadioTool(0, "Spectrum Analyser", menuRadioSpectrumAnalyser, event);
+ addRadioTool(1, "Power Meter", menuRadioPowerMeter, event);
+#endif
+}
\ No newline at end of file
diff --git a/radio/src/gui/common/stdlcd/widgets.cpp b/radio/src/gui/common/stdlcd/widgets.cpp
index c1b60ec32..266ec6446 100644
--- a/radio/src/gui/common/stdlcd/widgets.cpp
+++ b/radio/src/gui/common/stdlcd/widgets.cpp
@@ -69,7 +69,7 @@ void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, ui
else
mode = FIXEDWIDTH;
}
-
+
lcdDrawSizedText(x, y, name, size, attr | mode);
coord_t backupNextPos = lcdNextPos;
@@ -156,11 +156,11 @@ void editName(coord_t x, coord_t y, char * name, uint8_t size, event_t event, ui
if (c != v) {
name[cur] = v;
- storageDirty(menuVerticalPositions[0] == 0 ? EE_MODEL : EE_GENERAL);
+ storageDirty(isModelMenuDisplayed() ? EE_MODEL : EE_GENERAL);
}
if (attr == ZCHAR) {
- lcdDrawChar(x+editNameCursorPos*FW, y, idx2char(v), ERASEBG|INVERS|FIXEDWIDTH);
+ lcdDrawChar(x+editNameCursorPos*FW, y, zchar2char(v), ERASEBG|INVERS|FIXEDWIDTH);
}
else {
lcdDrawChar(x+editNameCursorPos*FW, y, v, ERASEBG|INVERS|FIXEDWIDTH);
diff --git a/radio/src/gui/gui_common.h b/radio/src/gui/gui_common.h
index c48ee4463..8a1b5dccd 100644
--- a/radio/src/gui/gui_common.h
+++ b/radio/src/gui/gui_common.h
@@ -54,7 +54,11 @@ bool isSwitchAvailableInCustomFunctions(int swtch);
bool isSwitchAvailableInMixes(int swtch);
bool isSwitchAvailableInTimers(int swtch);
bool isR9MModeAvailable(int mode);
-bool isModuleAvailable(int module);
+bool isR9ModuleRunning(int module);
+bool isR9MMFlex(int module);
+bool isPXX2ChannelsCountAllowed(int channels);
+bool isExternalModuleAvailable(int module);
+bool isInternalModuleAvailable(int module);
bool isRfProtocolAvailable(int protocol);
bool isTelemetryProtocolAvailable(int protocol);
bool isTrainerModeAvailable(int mode);
@@ -112,6 +116,7 @@ void runFatalErrorScreen(const char * message);
void lcdDrawMMM(coord_t x, coord_t y, LcdFlags flags=0);
// model_setup Defines that are used in all uis in the same way
+#define INTERNAL_MODULE_CHANNELS_ROWS IF_INTERNAL_MODULE_ON((uint8_t)1)
#define EXTERNAL_MODULE_CHANNELS_ROWS IF_EXTERNAL_MODULE_ON((isModuleDSM2(EXTERNAL_MODULE) || isModuleCrossfire(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE) || (isModuleMultimodule(EXTERNAL_MODULE) && g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) != MM_RF_PROTO_DSM2)) ? (uint8_t)0 : (uint8_t)1)
@@ -148,23 +153,26 @@ const mm_protocol_definition *getMultiProtocolDefinition (uint8_t protocol);
#define MULTIMODULE_OPTIONS_ROW HIDDEN_ROW
#endif
-
#define MAX_RX_NUM(x) (isModuleDSM2(x) ? 20 : isModuleMultimodule(x) ? MULTI_MAX_RX_NUM(x) : 63)
#define IS_D8_RX(x) (g_model.moduleData[x].rfProtocol == RF_PROTO_D8)
#define IS_R9M_OR_XJTD16(x) ((isModuleXJT(x) && g_model.moduleData[x].rfProtocol== RF_PROTO_X16) || isModuleR9M(x))
-#define FAILSAFE_ROWS(x) ((isModuleXJT(x) && HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol)) || MULTIMODULE_HASFAILSAFE(x) || isModuleR9M(x)) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW
+#define FAILSAFE_ROWS(x) ((isModuleXJTVariant(x) && HAS_RF_PROTOCOL_FAILSAFE(g_model.moduleData[x].rfProtocol)) || MULTIMODULE_HASFAILSAFE(x) || isModuleR9M(x) || isModuleR9M2(x)) ? (g_model.moduleData[x].failsafeMode==FAILSAFE_CUSTOM ? (uint8_t)1 : (uint8_t)0) : HIDDEN_ROW
-#define EXTERNAL_MODULE_OPTION_ROW (isModuleR9M(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW)
+#if defined(PCBXLITE)
+ #define EXTERNAL_MODULE_OPTION_ROW (isModuleR9M(EXTERNAL_MODULE) || isModuleSBUS(EXTERNAL_MODULE) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW)
+#else
+ #define EXTERNAL_MODULE_OPTION_ROW (isR9ModuleRunning(EXTERNAL_MODULE) ? HIDDEN_ROW : isModuleSBUS(EXTERNAL_MODULE) ? TITLE_ROW : MULTIMODULE_OPTIONS_ROW)
+#endif
#if defined(PCBXLITE) && !defined(MODULE_R9M_FULLSIZE)
-#define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9M(EXTERNAL_MODULE)) ? (isModuleR9M_FCC_VARIANT(EXTERNAL_MODULE) ? TITLE_ROW : (uint8_t) 0) : HIDDEN_ROW
+ #define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9M(EXTERNAL_MODULE)) ? (isModuleR9M_FCC_VARIANT(EXTERNAL_MODULE) ? TITLE_ROW : (uint8_t) 0) : HIDDEN_ROW
+#elif defined(PCBXLITE)
+ #define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9M(EXTERNAL_MODULE)) ? (uint8_t) 0 : HIDDEN_ROW
#else
-#define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isModuleR9M(EXTERNAL_MODULE)) ? (uint8_t) 0 : HIDDEN_ROW
+ #define EXTERNAL_MODULE_POWER_ROW (isModuleMultimodule(EXTERNAL_MODULE) || isR9ModuleRunning(EXTERNAL_MODULE)) ? (uint8_t) 0 : HIDDEN_ROW
#endif
void editStickHardwareSettings(coord_t x, coord_t y, int idx, event_t event, LcdFlags flags);
-
-
#endif // _GUI_COMMON_H_
diff --git a/radio/src/gui/gui_common_arm.cpp b/radio/src/gui/gui_common_arm.cpp
index 5d6b1fe0a..49281630c 100644
--- a/radio/src/gui/gui_common_arm.cpp
+++ b/radio/src/gui/gui_common_arm.cpp
@@ -486,6 +486,15 @@ bool isSourceAvailableInResetSpecialFunction(int index)
}
}
+bool isR9ModuleRunning(int module)
+{
+#if defined(SIMU)
+ return g_model.moduleData[module].type == MODULE_TYPE_R9M && TELEMETRY_STREAMING(); // Simu uses telemetry simu to activate/desactivate R9
+#else
+ return g_model.moduleData[module].type == MODULE_TYPE_R9M && R9ModuleStreaming;
+#endif
+}
+#if defined(PCBXLITE)
bool isR9MModeAvailable(int mode)
{
#if defined(MODULE_R9M_FLEX_FW)
@@ -495,8 +504,59 @@ bool isR9MModeAvailable(int mode)
#endif
}
-bool isModuleAvailable(int module)
+#else
+bool isR9MModeAvailable(int mode)
{
+ return mode <= MODULE_SUBTYPE_R9M_EUPLUS;
+}
+#endif
+bool isR9MMFlex(int module)
+{
+ return g_model.moduleData[module].r9m.region == MODULE_R9M_REGION_FLEX;
+}
+
+bool isPXX2ChannelsCountAllowed(int channels)
+{
+ return (channels % 8 == 0);
+}
+
+#if defined(HARDWARE_INTERNAL_MODULE)
+bool isInternalModuleAvailable(int module)
+{
+ if (module == MODULE_TYPE_NONE)
+ return true;
+
+#if defined(PXX1)
+ if (module == MODULE_TYPE_XJT)
+ return IS_PXX1_INTERNAL_ENABLED() && !isModulePXX(EXTERNAL_MODULE);
+#endif
+
+#if defined(PXX2)
+ if (module == MODULE_TYPE_XJT2)
+ return IS_PXX2_INTERNAL_ENABLED();
+#endif
+
+ return false;
+}
+#endif
+
+bool isExternalModuleAvailable(int module)
+{
+#if !defined(PCBXLITE)
+ if (module == MODULE_TYPE_R9M_LITE || module == MODULE_TYPE_R9M_LITE2 || module == MODULE_TYPE_R9M_LITE_PRO2) {
+ return false;
+ }
+#endif
+#if !defined(PXX1)
+ if (module == MODULE_TYPE_XJT || module == MODULE_TYPE_R9M || module == MODULE_TYPE_R9M_LITE) {
+ return false;
+ }
+#endif
+#if !defined(PXX2)
+ if (module == MODULE_TYPE_XJT2 || module == MODULE_TYPE_R9M2 || module == MODULE_TYPE_R9M_LITE2 || module == MODULE_TYPE_R9M_LITE_PRO2) {
+ return false;
+ }
+#endif
#if defined(CROSSFIRE)
if (module == MODULE_TYPE_CROSSFIRE && g_model.moduleData[INTERNAL_MODULE].type != MODULE_TYPE_NONE) {
return false;
@@ -516,6 +576,15 @@ bool isModuleAvailable(int module)
return false;
}
#endif
+#if defined(HARDWARE_INTERNAL_MODULE)
+ if (module == MODULE_TYPE_R9M && g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT) {
+ return false;
+ }
+ if (module == MODULE_TYPE_XJT && g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_XJT) {
+ return false;
+ }
+#endif
+
return true;
}
@@ -531,29 +600,38 @@ bool isRfProtocolAvailable(int protocol)
return false;
}
#endif
+#if defined(PCBTARANIS) || defined(PCBHORUS)
+ if (protocol != RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M) {
+ return false;
+ }
+ if (protocol != RF_PROTO_OFF && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_R9M2) {
+ return false;
+ }
+#endif
+
return true;
}
bool isTelemetryProtocolAvailable(int protocol)
{
#if defined(PCBTARANIS)
- if (protocol == PROTOCOL_FRSKY_D_SECONDARY && g_eeGeneral.serial2Mode != UART_MODE_TELEMETRY) {
+ if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY && g_eeGeneral.serial2Mode != UART_MODE_TELEMETRY) {
return false;
}
#endif
- if (protocol== PROTOCOL_PULSES_CROSSFIRE) {
+ if (protocol== PROTOCOL_TELEMETRY_CROSSFIRE) {
return false;
}
#if !defined(MULTIMODULE)
- if (protocol == PROTOCOL_SPEKTRUM || protocol == PROTOCOL_FLYSKY_IBUS || protocol == PROTOCOL_MULTIMODULE) {
+ if (protocol == PROTOCOL_TELEMETRY_SPEKTRUM || protocol == PROTOCOL_TELEMETRY_FLYSKY_IBUS || protocol == PROTOCOL_TELEMETRY_MULTIMODULE) {
return false;
}
#endif
#if defined(PCBHORUS)
- if (protocol == PROTOCOL_FRSKY_D_SECONDARY) {
+ if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
return false;
}
#endif
@@ -588,7 +666,7 @@ bool isTrainerModeAvailable(int mode)
else
return true;
}
-#elif defined(PCBX7)
+#elif defined(PCBX7) || defined(PCBXLITES) || defined(PCBX3)
bool isTrainerModeAvailable(int mode)
{
if (IS_EXTERNAL_MODULE_ENABLED() && (mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE))
@@ -602,13 +680,23 @@ bool isTrainerModeAvailable(int mode)
else
return true;
}
+#elif defined(PCBXLITES)
+bool isTrainerModeAvailable(int mode)
+{
+ if (mode == TRAINER_MODE_MASTER_TRAINER_JACK || mode == TRAINER_MODE_SLAVE)
+ return true;
+ else if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH))
+ return true;
+ else
+ return false;
+}
#elif defined(PCBXLITE)
bool isTrainerModeAvailable(int mode)
{
if (g_eeGeneral.bluetoothMode == BLUETOOTH_TRAINER && (mode == TRAINER_MODE_MASTER_BLUETOOTH || mode == TRAINER_MODE_SLAVE_BLUETOOTH))
- return true;
+ return true;
else
- return false;
+ return false;
}
#endif
diff --git a/radio/src/gui/navigation/navigation_9x.cpp b/radio/src/gui/navigation/navigation_9x.cpp
index 63569e4b9..f4336e194 100644
--- a/radio/src/gui/navigation/navigation_9x.cpp
+++ b/radio/src/gui/navigation/navigation_9x.cpp
@@ -27,14 +27,6 @@ uint8_t menuCalibrationState;
vertpos_t menuVerticalPosition;
horzpos_t menuHorizontalPosition;
-#if defined(NAVIGATION_POT1)
-int16_t p1valdiff;
-#endif
-
-#if defined(NAVIGATION_POT2)
-int8_t p2valdiff;
-#endif
-
int8_t checkIncDec_Ret;
#define DBLKEYS_PRESSED_RGT_LFT(in) ((in & (KEYS_GPIO_PIN_RIGHT + KEYS_GPIO_PIN_LEFT)) == (KEYS_GPIO_PIN_RIGHT + KEYS_GPIO_PIN_LEFT))
@@ -126,12 +118,6 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
newval = !val;
}
-#if defined(NAVIGATION_POT1)
- // change values based on P1
- newval -= p1valdiff;
- p1valdiff = 0;
-#endif
-
#if defined(AUTOSWITCH)
if (i_flags & INCDEC_SWITCH) {
newval = checkIncDecMovedSwitch(newval);
@@ -172,7 +158,6 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
return newval;
}
-#define SCROLL_TH 64
#define SCROLL_POT1_TH 32
#define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0)
@@ -192,36 +177,6 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
uint8_t maxcol = MAXCOL(l_posVert);
-#if defined(NAVIGATION_POT1)
- // check pot 1 - if changed -> scroll values
- static int16_t p1val;
- static int16_t p1valprev;
- p1valdiff = (p1val-calibratedAnalogs[CALIBRATED_POT1]) / SCROLL_POT1_TH;
- if (p1valdiff) {
- p1valdiff = (p1valprev-calibratedAnalogs[CALIBRATED_POT1]) / 2;
- p1val = calibratedAnalogs[CALIBRATED_POT1];
- }
- p1valprev = calibratedAnalogs[CALIBRATED_POT1];
-#endif
-
-#if defined(NAVIGATION_POT2)
- // check pot 2 - if changed -> scroll menu
- static int16_t p2valprev;
- p2valdiff = (p2valprev-calibratedAnalogs[CALIBRATED_POT2]) / SCROLL_TH;
- if (p2valdiff) p2valprev = calibratedAnalogs[CALIBRATED_POT2];
-#endif
-
-#if defined(NAVIGATION_POT3)
- // check pot 3 if changed -> cursor down/up
- static int16_t p3valprev;
- int8_t scrollUD = (p3valprev-calibratedAnalogs[CALIBRATED_POT3]) / SCROLL_TH;
- if (scrollUD) p3valprev = calibratedAnalogs[CALIBRATED_POT3];
-#else
- #define scrollUD 0
-#endif
-
- if (p2valdiff || scrollUD || p1valdiff) backlightOn(); // on keypress turn the light on
-
if (menuTab) {
uint8_t attr = 0;
@@ -230,10 +185,6 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
int8_t cc = curr;
- if (p2valdiff) {
- cc = limit((int8_t)0, (int8_t)(cc - p2valdiff), (int8_t)(menuTabSize-1));
- }
-
switch (event) {
#if defined(ROTARY_ENCODER_NAVIGATION)
case EVT_ROTARY_BREAK:
@@ -289,19 +240,6 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
}
- DISPLAY_PROGRESS_BAR(menuTab ? lcdLastRightPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
-
- if (s_editMode<=0) {
- if (scrollUD) {
- l_posVert = limit((int8_t)0, (int8_t)(l_posVert - scrollUD), (int8_t)maxrow);
- l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
- }
-
- if (p2valdiff && l_posVert>0) {
- l_posHorz = limit((int8_t)0, (int8_t)((uint8_t)l_posHorz - p2valdiff), (int8_t)maxcol);
- }
- }
-
switch (event)
{
case EVT_ENTRY:
diff --git a/radio/src/gui/navigation/navigation_x7.cpp b/radio/src/gui/navigation/navigation_x7.cpp
index d084b6a60..f5553267b 100644
--- a/radio/src/gui/navigation/navigation_x7.cpp
+++ b/radio/src/gui/navigation/navigation_x7.cpp
@@ -230,7 +230,6 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
return newval;
}
-#define SCROLL_TH 64
#define SCROLL_POT1_TH 32
#define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0)
@@ -285,8 +284,6 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc * menuTab, uint8_t
drawScreenIndex(curr, menuTabSize, 0);
}
- DISPLAY_PROGRESS_BAR(menuTab ? lcdLastRightPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
-
switch (event) {
case EVT_ENTRY:
menuEntryTime = get_tmr10ms();
diff --git a/radio/src/gui/navigation/navigation_x9d.cpp b/radio/src/gui/navigation/navigation_x9d.cpp
index a56ca656a..1cfb7d438 100644
--- a/radio/src/gui/navigation/navigation_x9d.cpp
+++ b/radio/src/gui/navigation/navigation_x9d.cpp
@@ -393,8 +393,6 @@ void check(const char * name, event_t event, uint8_t curr, const MenuHandlerFunc
lcdDrawFilledRect(0, 0, LCD_W, MENU_HEADER_HEIGHT, SOLID, FILL_WHITE|GREY_DEFAULT);
}
- DISPLAY_PROGRESS_BAR(menuTab ? lcdLastRightPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
-
switch (event) {
case EVT_ENTRY:
menuEntryTime = get_tmr10ms();
diff --git a/radio/src/gui/navigation/navigation_xlite.cpp b/radio/src/gui/navigation/navigation_xlite.cpp
index c0210caef..327c3d209 100644
--- a/radio/src/gui/navigation/navigation_xlite.cpp
+++ b/radio/src/gui/navigation/navigation_xlite.cpp
@@ -172,7 +172,7 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
}
}
- if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER) || IS_ROTARY_BREAK(event))) {
+ if (!READ_ONLY() && i_min==0 && i_max==1 && (event==EVT_KEY_BREAK(KEY_ENTER))) {
s_editMode = 0;
newval = !val;
}
@@ -185,7 +185,7 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
#if defined(AUTOSOURCE)
if (i_flags & INCDEC_SOURCE) {
- if (s_editMode>0) {
+ if (s_editMode > 0) {
int8_t source = GET_MOVED_SOURCE(i_min, i_max);
if (source) {
newval = source;
@@ -203,7 +203,7 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
#endif
if (newval != val) {
- if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100) && !IS_ROTARY_EVENT(event)) {
+ if (!(i_flags & NO_INCDEC_MARKS) && (newval != i_max) && (newval != i_min) && (newval==0 || newval==-100 || newval==+100)) {
pauseEvents(event); // delay before auto-repeat continues
}
AUDIO_KEY_PRESS();
@@ -292,7 +292,6 @@ int checkIncDec(event_t event, int val, int i_min, int i_max, unsigned int i_fla
return newval;
}
-#define SCROLL_TH 64
#define SCROLL_POT1_TH 32
#define CURSOR_NOT_ALLOWED_IN_ROW(row) ((int8_t)MAXCOL(row) < 0)
@@ -322,25 +321,6 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
int8_t cc = curr;
switch (event) {
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ROTARY_BREAK:
- if (s_editMode < 0 && maxrow > 0) {
- s_editMode = 0;
- // TODO ? l_posVert = (horTab && horTab[1]==0xff) ? 2 : 1;
- l_posHorz = 0;
- }
- else {
- s_editMode = -1;
- }
- event = 0;
- break;
-#endif
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ROTARY_LEFT:
- if (s_editMode >= 0)
- break;
-#endif
case EVT_KEY_FIRST(KEY_LEFT):
if (curr > 0)
cc = curr - 1;
@@ -348,11 +328,6 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
cc = menuTabSize-1;
break;
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ROTARY_RIGHT:
- if (s_editMode >= 0)
- break;
-#endif
case EVT_KEY_FIRST(KEY_RIGHT):
if (curr < (menuTabSize-1))
cc = curr + 1;
@@ -364,65 +339,29 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
if (cc != curr) {
chainMenu(menuTab[cc]);
}
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- if (IS_ROTARY_ENCODER_NAVIGATION_ENABLE() && s_editMode < 0)
- attr = INVERS|BLINK;
-#endif
}
menuCalibrationState = 0;
drawScreenIndex(curr, menuTabSize, attr);
-
}
- DISPLAY_PROGRESS_BAR(menuTab ? lcdLastRightPos-2*FW-((curr+1)/10*FWNUM)-2 : 20*FW+1);
-
switch (event)
{
case EVT_ENTRY:
menuEntryTime = get_tmr10ms();
l_posVert = 0;
l_posHorz = POS_HORZ_INIT(l_posVert);
-#if defined(ROTARY_ENCODER_NAVIGATION)
- if (menuTab) {
- s_editMode = EDIT_MODE_INIT;
- break;
- }
- // no break
-#else
s_editMode = EDIT_MODE_INIT;
break;
-#endif
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ENTRY_UP:
- s_editMode = 0;
- break;
-
- case EVT_ROTARY_BREAK:
- if (s_editMode > 1) break;
-#endif
case EVT_KEY_FIRST(KEY_ENTER):
- if (!menuTab || l_posVert>0) {
+ if (!menuTab || l_posVert > 0) {
if (READ_ONLY_UNLOCKED()) {
- s_editMode = (s_editMode<=0);
+ s_editMode = (s_editMode <= 0);
}
}
break;
-#if defined(ROTARY_ENCODER_NAVIGATION)
- case EVT_ROTARY_LONG:
- if (s_editMode > 1) break;
- killEvents(event);
- if (l_posVert != 0) {
- l_posVert = 0;
- s_editMode = EDIT_MODE_INIT;
- break;
- }
- // no break
-#endif
case EVT_KEY_LONG(KEY_EXIT):
s_editMode = 0; // TODO needed? we call ENTRY_UP after which does the same
popMenu();
@@ -430,17 +369,12 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
case EVT_KEY_BREAK(KEY_EXIT):
AUDIO_KEY_PRESS();
-#if defined(ROTARY_ENCODER_NAVIGATION)
- if (s_editMode == 0)
- s_editMode = EDIT_MODE_INIT;
- else
-#endif
- if (s_editMode>0) {
+ if (s_editMode > 0) {
s_editMode = 0;
break;
}
- if (l_posVert==0 || !menuTab) {
+ if (l_posVert == 0 || !menuTab) {
popMenu(); // beeps itself
}
else {
@@ -450,43 +384,23 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
break;
case EVT_KEY_REPT(KEY_RIGHT): //inc
- if (l_posHorz==maxcol) break;
+ if (l_posHorz == maxcol) break;
// no break
case EVT_KEY_FIRST(KEY_RIGHT)://inc
- if (!horTab || s_editMode>0) break;
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- CASE_EVT_ROTARY_RIGHT
- if (s_editMode != 0) break;
- if (l_posHorz < maxcol) {
- l_posHorz++;
- break;
- }
- else {
- l_posHorz = 0;
- if (!IS_ROTARY_RIGHT(event))
- break;
- }
-#else
+ if (!horTab || s_editMode > 0) break;
INC(l_posHorz, 0, maxcol);
break;
-#endif
case EVT_KEY_REPT(KEY_DOWN):
- if (!IS_ROTARY_RIGHT(event) && l_posVert==maxrow) break;
+ if (l_posVert == maxrow) break;
// no break
case EVT_KEY_FIRST(KEY_DOWN):
- if (s_editMode>0) break;
+ if (s_editMode > 0) break;
do {
INC(l_posVert, 0, maxrow);
} while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- s_editMode = 0; // if we go down, we must be in this mode
-#endif
-
l_posHorz = min(l_posHorz, MAXCOL(l_posVert));
break;
@@ -495,41 +409,18 @@ void check(event_t event, uint8_t curr, const MenuHandlerFunc *menuTab, uint8_t
// no break
case EVT_KEY_FIRST(KEY_LEFT)://dec
- if (!horTab || s_editMode>0) break;
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- CASE_EVT_ROTARY_LEFT
- if (s_editMode != 0) break;
- if (l_posHorz > 0) {
- l_posHorz--;
- break;
- }
- else if (IS_ROTARY_LEFT(event) && s_editMode == 0) {
- l_posHorz = 0xff;
- }
- else {
- l_posHorz = maxcol;
- break;
- }
-#else
+ if (!horTab || s_editMode > 0) break;
DEC(l_posHorz, 0, maxcol);
break;
-#endif
case EVT_KEY_REPT(KEY_UP):
- if (!IS_ROTARY_LEFT(event) && l_posVert==0) break;
+ if (l_posVert == 0) break;
// no break
case EVT_KEY_FIRST(KEY_UP):
- if (s_editMode>0) break;
-
+ if (s_editMode > 0) break;
do {
DEC(l_posVert, 0, maxrow);
} while (CURSOR_NOT_ALLOWED_IN_ROW(l_posVert));
-
-#if defined(ROTARY_ENCODER_NAVIGATION)
- s_editMode = 0; // if we go up, we must be in this mode
-#endif
-
l_posHorz = min((uint8_t)l_posHorz, MAXCOL(l_posVert));
break;
}
diff --git a/radio/src/io/bootloader_flash.cpp b/radio/src/io/bootloader_flash.cpp
index 612fe4e88..7259b2f6a 100644
--- a/radio/src/io/bootloader_flash.cpp
+++ b/radio/src/io/bootloader_flash.cpp
@@ -60,7 +60,7 @@ void bootloaderFlash(const char * filename)
for (int j=0; j<1024; j+=FLASH_PAGESIZE) {
flashWrite(CONVERT_UINT_PTR(FIRMWARE_ADDRESS+i+j), (uint32_t *)(buffer+j));
}
- drawProgressBar(STR_WRITING, i, BOOTLOADER_SIZE);
+ drawProgressScreen("Bootloader", STR_WRITING, i, BOOTLOADER_SIZE);
#if defined(SIMU)
// add an artificial delay and check for simu quit
if (SIMU_SLEEP_OR_EXIT_MS(30))
diff --git a/radio/src/io/frsky_device_firmware_update.cpp b/radio/src/io/frsky_device_firmware_update.cpp
new file mode 100644
index 000000000..99ab6e30c
--- /dev/null
+++ b/radio/src/io/frsky_device_firmware_update.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "opentx.h"
+#include "frsky_device_firmware_update.h"
+
+#define PRIM_REQ_POWERUP 0
+#define PRIM_REQ_VERSION 1
+#define PRIM_CMD_DOWNLOAD 3
+#define PRIM_DATA_WORD 4
+#define PRIM_DATA_EOF 5
+
+#define PRIM_ACK_POWERUP 0x80
+#define PRIM_ACK_VERSION 0x81
+#define PRIM_REQ_DATA_ADDR 0x82
+#define PRIM_END_DOWNLOAD 0x83
+#define PRIM_DATA_CRC_ERR 0x84
+
+void DeviceFirmwareUpdate::processFrame(const uint8_t * frame)
+{
+ if (frame[0] == 0x5E && frame[1] == 0x50) {
+ switch (frame[2]) {
+ case PRIM_ACK_POWERUP :
+ if (state == SPORT_POWERUP_REQ) {
+ state = SPORT_POWERUP_ACK;
+ }
+ break;
+
+ case PRIM_ACK_VERSION:
+ if (state == SPORT_VERSION_REQ) {
+ state = SPORT_VERSION_ACK;
+ // here we could display the version
+ }
+ break;
+
+ case PRIM_REQ_DATA_ADDR:
+ if (state == SPORT_DATA_TRANSFER) {
+ address = *((uint32_t *)(&frame[3]));
+ state = SPORT_DATA_REQ;
+ }
+ break;
+
+ case PRIM_END_DOWNLOAD :
+ state = SPORT_COMPLETE ;
+ break;
+
+ case PRIM_DATA_CRC_ERR :
+ state = SPORT_FAIL ;
+ break;
+ }
+ }
+}
+
+void DeviceFirmwareUpdate::startup()
+{
+ switch(module) {
+#if defined(INTMODULE_USART)
+ case INTERNAL_MODULE:
+ intmoduleSerialStart(57600, true);
+ break;
+#endif
+
+ default:
+ telemetryInit(PROTOCOL_TELEMETRY_FRSKY_SPORT);
+ break;
+ }
+
+ if (module == INTERNAL_MODULE)
+ INTERNAL_MODULE_ON();
+ else if (module == EXTERNAL_MODULE)
+ EXTERNAL_MODULE_ON();
+ else
+ SPORT_UPDATE_POWER_ON();
+}
+
+const uint8_t * DeviceFirmwareUpdate::readFullDuplexFrame(ModuleFifo & fifo, uint32_t timeout)
+{
+ uint8_t len = 0;
+ bool bytestuff = false;
+ while (len < 10) {
+ uint32_t elapsed = 0;
+ uint8_t byte;
+ while (!fifo.pop(byte)) {
+ RTOS_WAIT_MS(1);
+ if (elapsed++ >= timeout) {
+ return nullptr;
+ }
+ }
+ if (byte == 0x7D) {
+ bytestuff = true;
+ continue;
+ }
+ if (bytestuff) {
+ frame[len] = 0x20 ^ byte;
+ bytestuff = false;
+ }
+ else {
+ frame[len] = byte;
+ }
+ if (len > 0 || byte == 0x7E) {
+ ++len;
+ }
+ }
+ return &frame[1];
+}
+
+const uint8_t * DeviceFirmwareUpdate::readHalfDuplexFrame(uint32_t timeout)
+{
+ for (int i=timeout; i>=0; i--) {
+ uint8_t byte ;
+ while (telemetryGetByte(&byte)) {
+ if (pushFrskyTelemetryData(byte)) {
+ return telemetryRxBuffer;
+ }
+ }
+ RTOS_WAIT_MS(1);
+ }
+ return nullptr;
+}
+
+const uint8_t * DeviceFirmwareUpdate::readFrame(uint32_t timeout)
+{
+ switch(module) {
+#if defined(INTMODULE_USART)
+ case INTERNAL_MODULE:
+ return readFullDuplexFrame(intmoduleFifo, timeout);
+#endif
+
+ default:
+ return readHalfDuplexFrame(timeout);
+ }
+}
+
+bool DeviceFirmwareUpdate::waitState(State newState, uint32_t timeout)
+{
+#if defined(SIMU)
+ UNUSED(state);
+ UNUSED(timeout);
+ static uint8_t pass = 0;
+ if (++pass == 10) {
+ pass = 0;
+ RTOS_WAIT_MS(1);
+ }
+ return true;
+#else
+ watchdogSuspend(timeout / 10);
+
+ const uint8_t * frame = readFrame(timeout);
+ if (!frame) {
+ return false;
+ }
+
+ processFrame(frame);
+ return state == newState;
+#endif
+}
+
+void DeviceFirmwareUpdate::startFrame(uint8_t command)
+{
+ frame[0] = 0x50;
+ frame[1] = command;
+ memset(&frame[2], 0, 6);
+}
+
+// TODO merge this function
+void DeviceFirmwareUpdate::sendFrame()
+{
+ uint8_t * ptr = outputTelemetryBuffer.data;
+ *ptr++ = 0x7E;
+ *ptr++ = 0xFF;
+ frame[7] = crc16(frame, 7);
+ for (int i=0; i<8; i++) {
+ if (frame[i] == 0x7E || frame[i] == 0x7D) {
+ *ptr++ = 0x7D;
+ *ptr++ = 0x20 ^ frame[i];
+ }
+ else {
+ *ptr++ = frame[i];
+ }
+ }
+
+ switch(module) {
+#if defined(INTMODULE_USART)
+ case INTERNAL_MODULE:
+ return intmoduleSendBuffer(outputTelemetryBuffer.data, ptr - outputTelemetryBuffer.data);
+#endif
+
+ default:
+ return sportSendBuffer(outputTelemetryBuffer.data, ptr - outputTelemetryBuffer.data);
+ }
+}
+
+const char * DeviceFirmwareUpdate::sendPowerOn()
+{
+ state = SPORT_POWERUP_REQ;
+ waitState(SPORT_IDLE, 50); // Wait 50ms and clear the fifo
+ for (int i=0; i<10; i++) {
+ // max 10 attempts
+ startFrame(PRIM_REQ_POWERUP);
+ sendFrame();
+ if (waitState(SPORT_POWERUP_ACK, 100))
+ return nullptr;
+ }
+
+ if (telemetryProtocol != PROTOCOL_TELEMETRY_FRSKY_SPORT) {
+ return TR("Not responding", "Not S.Port 1");
+ }
+
+ if (!IS_FRSKY_SPORT_PROTOCOL()) {
+ return TR("Not responding", "Not S.Port 2");
+ }
+#if defined(PCBX7)
+ if (IS_PCBREV_40()) {
+ return TR("Bottom pin no resp", "Bottom pin not responding");
+ }
+ else {
+ return TR("Device pin no resp", "Device pin not responding");
+ }
+#else
+ return TR("Not responding", "Device not responding");
+#endif
+}
+
+const char * DeviceFirmwareUpdate::sendReqVersion()
+{
+ waitState(SPORT_IDLE, 20); // Clear the fifo
+ state = SPORT_VERSION_REQ;
+ for (int i=0; i<10; i++) {
+ // max 10 attempts
+ startFrame(PRIM_REQ_VERSION) ;
+ sendFrame();
+ if (waitState(SPORT_VERSION_ACK, 100))
+ return nullptr;
+ }
+ return "Version request failed";
+}
+
+const char * DeviceFirmwareUpdate::uploadFile(const char *filename)
+{
+ FIL file;
+ uint32_t buffer[1024 / sizeof(uint32_t)];
+ UINT count;
+
+ if (f_open(&file, filename, FA_READ) != FR_OK) {
+ return "Error opening file";
+ }
+
+ waitState(SPORT_IDLE, 200); // Clear the fifo
+ state = SPORT_DATA_TRANSFER;
+ startFrame(PRIM_CMD_DOWNLOAD);
+ sendFrame();
+
+ while (1) {
+ if (f_read(&file, buffer, 1024, &count) != FR_OK) {
+ f_close(&file);
+ return "Error reading file";
+ }
+
+ count >>= 2;
+
+ for (uint32_t i=0; i> 2; // 32 bit word offset into buffer
+ *((uint32_t *)(frame + 2)) = buffer[offset];
+ frame[6] = address & 0x000000FF;
+ state = SPORT_DATA_TRANSFER,
+ sendFrame();
+ if (i == 0) {
+ drawProgressScreen(getBasename(filename), STR_WRITING, file.fptr, file.obj.objsize);
+ }
+ }
+
+ if (count < 256) {
+ f_close(&file);
+ return nullptr;
+ }
+ }
+}
+
+const char * DeviceFirmwareUpdate::endTransfer()
+{
+ if (!waitState(SPORT_DATA_REQ, 2000))
+ return "Device refused data";
+ startFrame(PRIM_DATA_EOF);
+ sendFrame();
+ if (!waitState(SPORT_COMPLETE, 2000)) {
+ return "Device rejected firmware";
+ }
+ return nullptr;
+}
+
+void DeviceFirmwareUpdate::flashFile(const char * filename)
+{
+ pausePulses();
+
+ uint8_t intPwr = IS_INTERNAL_MODULE_ON();
+ uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
+
+ drawProgressScreen(getBasename(filename), "Device reset...", 0, 0);
+
+ INTERNAL_MODULE_OFF();
+ EXTERNAL_MODULE_OFF();
+ SPORT_UPDATE_POWER_OFF();
+
+ /* wait 2s off */
+ watchdogSuspend(2000);
+ RTOS_WAIT_MS(2000);
+
+ startup();
+
+ const char * result = sendPowerOn();
+ if (!result) result = sendReqVersion();
+ if (!result) result = uploadFile(filename);
+ if (!result) result = endTransfer();
+
+ AUDIO_PLAY(AU_SPECIAL_SOUND_BEEP1 );
+ BACKLIGHT_ENABLE();
+
+ if (result) {
+ POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR);
+ SET_WARNING_INFO(result, strlen(result), 0);
+ }
+ else {
+ POPUP_INFORMATION(STR_FIRMWARE_UPDATE_SUCCESS);
+ }
+
+ INTERNAL_MODULE_OFF();
+ EXTERNAL_MODULE_OFF();
+ SPORT_UPDATE_POWER_OFF();
+
+ waitState(SPORT_IDLE, 500); // Clear the fifo
+
+ /* wait 2s off */
+ watchdogSuspend(2000);
+ RTOS_WAIT_MS(2000);
+
+ if (intPwr)
+ INTERNAL_MODULE_ON();
+ if (extPwr)
+ EXTERNAL_MODULE_ON();
+
+ state = SPORT_IDLE;
+
+ resumePulses();
+}
diff --git a/radio/src/io/frsky_device_firmware_update.h b/radio/src/io/frsky_device_firmware_update.h
new file mode 100644
index 000000000..729120895
--- /dev/null
+++ b/radio/src/io/frsky_device_firmware_update.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _FRSKY_DEVICE_FIRMWARE_UPDATE_H_
+#define _FRSKY_DEVICE_FIRMWARE_UPDATE_H_
+
+#include "dataconstants.h"
+#include "frsky_pxx2.h"
+
+class DeviceFirmwareUpdate {
+ enum State {
+ SPORT_IDLE,
+ SPORT_POWERUP_REQ,
+ SPORT_POWERUP_ACK,
+ SPORT_VERSION_REQ,
+ SPORT_VERSION_ACK,
+ SPORT_DATA_TRANSFER,
+ SPORT_DATA_REQ,
+ SPORT_COMPLETE,
+ SPORT_FAIL
+ };
+
+ public:
+ DeviceFirmwareUpdate(ModuleIndex module):
+ module(module) {
+ }
+
+ void flashFile(const char * filename);
+
+ protected:
+ uint8_t state = SPORT_IDLE;
+ uint32_t address = 0;
+ ModuleIndex module;
+ uint8_t frame[12];
+
+ void startup();
+
+ void startFrame(uint8_t command);
+ void sendFrame();
+
+ const uint8_t * readFullDuplexFrame(ModuleFifo & fifo, uint32_t timeout);
+ const uint8_t * readHalfDuplexFrame(uint32_t timeout);
+ const uint8_t * readFrame(uint32_t timeout);
+ bool waitState(State state, uint32_t timeout);
+ void processFrame(const uint8_t * frame);
+
+ const char * sendPowerOn();
+ const char * sendReqVersion();
+ const char * uploadFile(const char * filename);
+ const char * endTransfer();
+};
+
+#endif // _FRSKY_DEVICE_FIRMWARE_UPDATE_H_
diff --git a/radio/src/io/frsky_pxx2.h b/radio/src/io/frsky_pxx2.h
new file mode 100644
index 000000000..9aec8ab3d
--- /dev/null
+++ b/radio/src/io/frsky_pxx2.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#ifndef _IO_PXX2_H_
+#define _IO_PXX2_H_
+
+#include "../fifo.h"
+#include "../pulses/pxx.h"
+
+class ModuleFifo : public Fifo {
+ public:
+ bool getFrame(uint8_t * frame)
+ {
+ while (1) {
+ if (isEmpty()) {
+ return false;
+ }
+ else if (fifo[ridx] != 0x7E) {
+ skip();
+ }
+ else {
+ break;
+ }
+ }
+
+ uint32_t next = nextIndex(ridx);
+ uint8_t len = fifo[next];
+
+ if (len > 40) {
+ clear();
+ return false;
+ }
+
+ if (size() < unsigned(len + 4 /* 2 bytes header + 2 bytes CRC */)) {
+ // frame not fully received
+ return false;
+ }
+
+ for (uint32_t i = 0; i <= len; i++) {
+ frame[i] = fifo[next];
+ next = nextIndex(next);
+ }
+
+ // TODO CRC CHECK
+ next = nextIndex(next);
+ ridx = nextIndex(next);
+ return true;
+ }
+
+ uint32_t errors;
+};
+
+#endif
diff --git a/radio/src/io/frsky_sport.cpp b/radio/src/io/frsky_sport.cpp
index a65de6159..adf249382 100644
--- a/radio/src/io/frsky_sport.cpp
+++ b/radio/src/io/frsky_sport.cpp
@@ -20,51 +20,22 @@
#include "opentx.h"
-#if defined(STM32)
-#define PRIM_REQ_POWERUP (0)
-#define PRIM_REQ_VERSION (1)
-#define PRIM_CMD_DOWNLOAD (3)
-#define PRIM_DATA_WORD (4)
-#define PRIM_DATA_EOF (5)
-
-#define PRIM_ACK_POWERUP (0x80)
-#define PRIM_ACK_VERSION (0x81)
-#define PRIM_REQ_DATA_ADDR (0x82)
-#define PRIM_END_DOWNLOAD (0x83)
-#define PRIM_DATA_CRC_ERR (0x84)
-
-enum SportUpdateState {
- SPORT_IDLE,
- SPORT_POWERUP_REQ,
- SPORT_POWERUP_ACK,
- SPORT_VERSION_REQ,
- SPORT_VERSION_ACK,
- SPORT_DATA_TRANSFER,
- SPORT_DATA_REQ,
- SPORT_COMPLETE,
- SPORT_FAIL
-};
-
-uint8_t sportUpdateState = SPORT_IDLE;
-uint32_t sportUpdateAddr = 0;
+bool isTelemetryOutputBufferAvailable()
+{
+ return (outputTelemetryBuffer.size == 0 && outputTelemetryBuffer.trigger == 0x7E);
+}
void sportOutputPushByte(uint8_t byte)
{
if (byte == 0x7E || byte == 0x7D) {
- telemetryOutputPushByte(0x7D);
- telemetryOutputPushByte(0x20 ^ byte);
+ outputTelemetryBuffer.push(0x7D);
+ outputTelemetryBuffer.push(0x20 ^ byte);
}
else {
- telemetryOutputPushByte(byte);
+ outputTelemetryBuffer.push(byte);
}
}
-bool isSportOutputBufferAvailable()
-{
- return (outputTelemetryBufferSize == 0 && outputTelemetryBufferTrigger == 0x7E);
-}
-
-// TODO merge it with S.PORT update function when finished
void sportOutputPushPacket(SportTelemetryPacket * packet)
{
uint16_t crc = 0;
@@ -77,285 +48,7 @@ void sportOutputPushPacket(SportTelemetryPacket * packet)
crc &= 0x00ff;
}
- telemetryOutputPushByte(0xFF-crc);
- telemetryOutputSetTrigger(packet->raw[0]); // physicalId
-}
-
-void sportProcessUpdatePacket(uint8_t * packet)
-{
- if (packet[0]==0x5E && packet[1]==0x50) {
- switch (packet[2]) {
- case PRIM_ACK_POWERUP :
- if (sportUpdateState == SPORT_POWERUP_REQ) {
- sportUpdateState = SPORT_POWERUP_ACK;
- }
- break;
-
- case PRIM_ACK_VERSION:
- if (sportUpdateState == SPORT_VERSION_REQ) {
- sportUpdateState = SPORT_VERSION_ACK;
- // SportVersion[0] = packet[3] ;
- // SportVersion[1] = packet[4] ;
- // SportVersion[2] = packet[5] ;
- // SportVersion[3] = packet[6] ;
- // SportVerValid = 1 ;
- }
- break;
-
- case PRIM_REQ_DATA_ADDR :
- if (sportUpdateState == SPORT_DATA_TRANSFER) {
- sportUpdateAddr = *((uint32_t *)(&packet[3]));
- sportUpdateState = SPORT_DATA_REQ;
- }
- break;
-
- case PRIM_END_DOWNLOAD :
- sportUpdateState = SPORT_COMPLETE ;
- break;
-
- case PRIM_DATA_CRC_ERR :
- sportUpdateState = SPORT_FAIL ;
- break;
- }
- }
-}
-
-bool sportWaitState(SportUpdateState state, int timeout)
-{
-#if defined(SIMU)
- UNUSED(state);
- UNUSED(timeout);
- return true;
-#else
- watchdogSuspend(timeout / 10);
- for (int i=timeout/2; i>=0; i--) {
- uint8_t byte ;
- while (telemetryGetByte(&byte)) {
- processFrskyTelemetryData(byte);
- }
- if (sportUpdateState == state) {
- return true;
- }
- else if (sportUpdateState == SPORT_FAIL) {
- return false;
- }
- RTOS_WAIT_TICKS(1);
- }
- return false;
-#endif
-}
-
-void sportClearPacket(uint8_t * packet)
-{
- memset(packet+2, 0, 6);
-}
-
-// TODO merge this function
-void sportWritePacket(uint8_t * packet)
-{
- uint8_t * ptr = outputTelemetryBuffer;
- *ptr++ = 0x7E;
- *ptr++ = 0xFF;
- packet[7] = crc16(packet, 7);
- for (int i=0; i<8; i++) {
- if (packet[i] == 0x7E || packet[i] == 0x7D) {
- *ptr++ = 0x7D;
- *ptr++ = 0x20 ^ packet[i];
- }
- else {
- *ptr++ = packet[i];
- }
- }
- sportSendBuffer(outputTelemetryBuffer, ptr-outputTelemetryBuffer);
-}
-
-const char * sportUpdatePowerOn(ModuleIndex module)
-{
- uint8_t packet[8];
-
- sportUpdateState = SPORT_POWERUP_REQ;
- sportWaitState(SPORT_IDLE, 500); // Clear the fifo
-
- telemetryInit(PROTOCOL_FRSKY_SPORT);
-
-#if defined(PCBTARANIS) || defined(PCBHORUS)
- if (module == INTERNAL_MODULE)
- INTERNAL_MODULE_ON();
- else if (module == EXTERNAL_MODULE)
- EXTERNAL_MODULE_ON();
- else
- SPORT_UPDATE_POWER_ON();
-#endif
-
- sportWaitState(SPORT_IDLE, 50); // Clear the fifo
-
- for (int i=0; i<10; i++) {
- // max 10 attempts
- sportClearPacket(packet);
- packet[0] = 0x50 ;
- packet[1] = PRIM_REQ_POWERUP;
- sportWritePacket(packet);
- if (sportWaitState(SPORT_POWERUP_ACK, 100))
- return NULL;
- }
-
- if (telemetryProtocol != PROTOCOL_FRSKY_SPORT) {
- return TR("Not responding", "Not S.Port 1");
- }
-
- if (!IS_FRSKY_SPORT_PROTOCOL()) {
- return TR("Not responding", "Not S.Port 2");
- }
-#if defined(PCBX7)
- if (IS_PCBREV_40()) {
- return TR("Bottom pin no resp", "Bottom pin not responding");
- }
- else {
- return TR("Module pin no resp", "Module pin not responding");
- }
-#else
- return TR("Not responding", "Module not responding");
-#endif
-}
-
-const char * sportUpdateReqVersion()
-{
- uint8_t packet[8];
- sportWaitState(SPORT_IDLE, 20); // Clear the fifo
- sportUpdateState = SPORT_VERSION_REQ;
- for (int i=0; i<10; i++) {
- // max 10 attempts
- sportClearPacket(packet) ;
- packet[0] = 0x50 ;
- packet[1] = PRIM_REQ_VERSION ;
- sportWritePacket(packet);
- if (sportWaitState(SPORT_VERSION_ACK, 200))
- return NULL;
- }
- return "Version request failed";
-}
-
-const char * sportUpdateUploadFile(const char *filename)
-{
- FIL file;
- uint32_t buffer[1024/4];
- UINT count;
- uint8_t packet[8];
-
- if (f_open(&file, filename, FA_READ) != FR_OK) {
- return "Error opening file";
- }
-
- sportWaitState(SPORT_IDLE, 200); // Clear the fifo
- sportUpdateState = SPORT_DATA_TRANSFER;
- sportClearPacket(packet) ;
- packet[0] = 0x50 ;
- packet[1] = PRIM_CMD_DOWNLOAD ;
- // Stop here for testing
- sportWritePacket(packet);
-
- while(1) {
- if (f_read(&file, buffer, 1024, &count) != FR_OK) {
- f_close(&file);
- return "Error reading file";
- }
-
- count >>= 2;
-
- for (UINT i=0; i> 2; // 32 bit word offset into buffer
- uint32_t *data = (uint32_t *)(&packet[2]);
- *data = buffer[offset];
- sportUpdateState = SPORT_DATA_TRANSFER,
- sportWritePacket(packet);
- if (i==0) {
- drawProgressBar(STR_WRITING, file.fptr, file.obj.objsize);
- }
- }
-
- if (count < 256) {
- f_close(&file);
- return NULL;
- }
- }
-}
-
-const char * sportUpdateEnd()
-{
- uint8_t packet[8];
- if (!sportWaitState(SPORT_DATA_REQ, 2000))
- return "Module refused data";
- sportClearPacket(packet);
- packet[0] = 0x50 ;
- packet[1] = PRIM_DATA_EOF;
- sportWritePacket(packet);
- if (!sportWaitState(SPORT_COMPLETE, 2000)) {
- return "Module rejected firmware";
- }
- return NULL;
-}
-
-void sportFlashDevice(ModuleIndex module, const char * filename)
-{
- pausePulses();
-
-#if defined(PCBTARANIS) || defined(PCBHORUS)
- uint8_t intPwr = IS_INTERNAL_MODULE_ON();
- uint8_t extPwr = IS_EXTERNAL_MODULE_ON();
- INTERNAL_MODULE_OFF();
- EXTERNAL_MODULE_OFF();
- SPORT_UPDATE_POWER_OFF();
-
- /* wait 2s off */
- watchdogSuspend(2000);
- RTOS_WAIT_MS(2000);
-#endif
-
- const char * result = sportUpdatePowerOn(module);
- if (!result) result = sportUpdateReqVersion();
- if (!result) result = sportUpdateUploadFile(filename);
- if (!result) result = sportUpdateEnd();
-
- if (result) {
- POPUP_WARNING(STR_FIRMWARE_UPDATE_ERROR);
- SET_WARNING_INFO(result, strlen(result), 0);
- }
-
-#if defined(PCBTARANIS) || defined(PCBHORUS)
- INTERNAL_MODULE_OFF();
- EXTERNAL_MODULE_OFF();
- SPORT_UPDATE_POWER_OFF();
-#endif
-
- sportWaitState(SPORT_IDLE, 500); // Clear the fifo
-
-#if defined(PCBTARANIS) || defined(PCBHORUS)
- if (intPwr)
- INTERNAL_MODULE_ON();
- if (extPwr)
- EXTERNAL_MODULE_ON();
-#endif
-
- sportUpdateState = SPORT_IDLE;
-
- resumePulses();
-}
-#endif
-
-void sportProcessPacket(uint8_t * packet)
-{
-#if defined(STM32)
- if (sportUpdateState != SPORT_IDLE) {
- sportProcessUpdatePacket(packet); // Uses different chksum
- return;
- }
-#endif
-
- sportProcessTelemetryPacket(packet);
+ outputTelemetryBuffer.push(0xFF - crc);
+ outputTelemetryBuffer.setTrigger(packet->raw[0]); // physicalId
+ outputTelemetryBuffer.setDestination(SPORT_MODULE);
}
diff --git a/radio/src/io/io_arm.h b/radio/src/io/frsky_sport.h
similarity index 84%
rename from radio/src/io/io_arm.h
rename to radio/src/io/frsky_sport.h
index d510add9b..57a7dabf7 100644
--- a/radio/src/io/io_arm.h
+++ b/radio/src/io/frsky_sport.h
@@ -18,8 +18,8 @@
* GNU General Public License for more details.
*/
-#ifndef _IO_ARM_H_
-#define _IO_ARM_H_
+#ifndef _IO_FRSKY_SPORT_H_
+#define _IO_FRSKY_SPORT_H_
#include "dataconstants.h"
@@ -35,15 +35,13 @@ PACK(union SportTelemetryPacket
uint8_t raw[8];
});
-void sportProcessPacket(uint8_t * packet);
-bool isSportOutputBufferAvailable();
+bool isTelemetryOutputBufferAvailable();
void sportOutputPushPacket(SportTelemetryPacket * packet);
-void sportFlashDevice(ModuleIndex module, const char * filename);
#endif
#if defined(STM32)
bool isBootloader(const char * filename);
void bootloaderFlash(const char * filename);
#endif
-
-#endif // _IO_ARM_H_
+
+#endif // _IO_FRSKY_SPORT_H_
diff --git a/radio/src/keys.h b/radio/src/keys.h
index 3b78a8475..8c2983637 100644
--- a/radio/src/keys.h
+++ b/radio/src/keys.h
@@ -21,6 +21,9 @@
#ifndef _KEYS_H_
#define _KEYS_H_
+#include
+#include "board.h"
+
#define EVT_KEY_MASK(e) ((e) & 0x1f)
#if defined(PCBHORUS)
diff --git a/radio/src/logs.cpp b/radio/src/logs.cpp
index f5fcda516..8a90c71c1 100644
--- a/radio/src/logs.cpp
+++ b/radio/src/logs.cpp
@@ -71,7 +71,7 @@ const char * logsOpen()
len = i+1;
if (len) {
if (filename[i])
- filename[i] = idx2char(filename[i]);
+ filename[i] = zchar2char(filename[i]);
else
filename[i] = '_';
}
@@ -170,6 +170,10 @@ void writeHeader()
#define STR_SWITCHES_LOG_HEADER "SA,SB,SC,SD,SF,SH"
#elif defined(PCBXLITE)
#define STR_SWITCHES_LOG_HEADER "SA,SB,SC,SD"
+#elif defined(PCBXLITES)
+ #define STR_SWITCHES_LOG_HEADER "SA,SB,SC,SD,SE,SF"
+#elif defined(PCBX3)
+ #define STR_SWITCHES_LOG_HEADER "SA,SB,SC,SE,SF"
#else
#define STR_SWITCHES_LOG_HEADER "SA,SB,SC,SD,SE,SF,SG,SH"
#endif
@@ -270,7 +274,16 @@ void logsWrite()
}
// TODO: use hardware config to populate
-#if defined(PCBXLITE)
+#if defined(PCBX3)
+f_printf(&g_oLogFile, "%d,%d,%d,%d,0x%08X%08X,",
+ GET_3POS_STATE(SA),
+ GET_3POS_STATE(SB),
+ GET_3POS_STATE(SC),
+ GET_2POS_STATE(SE),
+ GET_2POS_STATE(SF),
+ getLogicalSwitchesStates(32),
+ getLogicalSwitchesStates(0));
+#elif defined(PCBXLITE)
f_printf(&g_oLogFile, "%d,%d,%d,%d,0x%08X%08X,",
GET_3POS_STATE(SA),
GET_3POS_STATE(SB),
diff --git a/radio/src/lua/CMakeLists.txt b/radio/src/lua/CMakeLists.txt
index b653aa49e..398063f0d 100644
--- a/radio/src/lua/CMakeLists.txt
+++ b/radio/src/lua/CMakeLists.txt
@@ -40,6 +40,7 @@ set(LUA_INCLUDES_STM32F4
)
if(PYTHONINTERP_FOUND)
+ add_lua_export_target(x3 ${LUA_INCLUDES_STM32F2} -DPCBTARANIS -DPCBX3)
add_lua_export_target(x7 ${LUA_INCLUDES_STM32F2} -DPCBTARANIS -DPCBX7)
add_lua_export_target(xlite ${LUA_INCLUDES_STM32F2} -DPCBTARANIS -DPCBXLITE)
add_lua_export_target(x9d ${LUA_INCLUDES_STM32F2} -DPCBTARANIS -DPCBX9D)
diff --git a/radio/src/lua/api_general.cpp b/radio/src/lua/api_general.cpp
index be543535f..d5dd29919 100644
--- a/radio/src/lua/api_general.cpp
+++ b/radio/src/lua/api_general.cpp
@@ -33,6 +33,8 @@
#include "lua/lua_exports_x9e.inc"
#elif defined(PCBX7)
#include "lua/lua_exports_x7.inc"
+#elif defined(PCBX3)
+ #include "lua/lua_exports_x3.inc"
#elif defined(PCBXLITE)
#include "lua/lua_exports_xlite.inc"
#elif defined(PCBTARANIS)
@@ -420,9 +422,9 @@ When called without parameters, it will only return the status of the output buf
static int luaSportTelemetryPush(lua_State * L)
{
if (lua_gettop(L) == 0) {
- lua_pushboolean(L, isSportOutputBufferAvailable());
+ lua_pushboolean(L, isTelemetryOutputBufferAvailable());
}
- else if (isSportOutputBufferAvailable()) {
+ else if (isTelemetryOutputBufferAvailable()) {
SportTelemetryPacket packet;
packet.physicalId = getDataId(luaL_checkunsigned(L, 1));
packet.primId = luaL_checkunsigned(L, 2);
@@ -437,6 +439,63 @@ static int luaSportTelemetryPush(lua_State * L)
return 1;
}
+#if defined(PXX2)
+/*luadoc
+@function pxx2TelemetryPush()
+
+This functions allows for sending SPORT telemetry data toward the receiver,
+and more generally, to anything connected SPORT bus on the receiver or transmitter.
+
+When called without parameters, it will only return the status of the output buffer without sending anything.
+
+@param module module index
+
+@param receiver receiver index
+
+@param sensorId physical sensor ID
+
+@param frameId frame ID
+
+@param dataId data ID
+
+@param value value
+
+@retval boolean data queued in output buffer or not.
+
+@status current Introduced in 2.3.0
+*/
+static int luaPXX2TelemetryPush(lua_State * L)
+{
+ if (lua_gettop(L) == 0) {
+ lua_pushboolean(L, isTelemetryOutputBufferAvailable());
+ }
+ else if (isTelemetryOutputBufferAvailable()) {
+ SportTelemetryPacket packet;
+ uint8_t module = getDataId(luaL_checkunsigned(L, 1));
+ uint8_t receiver = getDataId(luaL_checkunsigned(L, 2));
+ uint8_t rx_uid = g_model.moduleData[module].pxx2.getReceiverSlot(receiver);
+ if (rx_uid > 0) {
+ // TODO add more controls (module started, module = PXX2, etc.)
+ packet.physicalId = getDataId(luaL_checkunsigned(L, 3));
+ packet.primId = luaL_checkunsigned(L, 4);
+ packet.dataId = luaL_checkunsigned(L, 5);
+ packet.value = luaL_checkunsigned(L, 6);
+ // TODO we could avoid this new copy
+ pushPXX2TelemetryPacket(module, rx_uid - 1, &packet);
+ lua_pushboolean(L, true);
+ }
+ else {
+ lua_pushboolean(L, false);
+ }
+ }
+ else {
+ lua_pushboolean(L, false);
+ }
+ return 1;
+}
+#endif
+
+#if defined(CROSSFIRE)
/*luadoc
@function crossfireTelemetryPop()
@@ -518,6 +577,7 @@ static int luaCrossfireTelemetryPush(lua_State * L)
}
return 1;
}
+#endif
/*luadoc
@function getFieldInfo(name)
@@ -931,55 +991,6 @@ static int luaGetGeneralSettings(lua_State * L)
return 1;
}
-/*luadoc
-@function popupInput(title, event, input, min, max)
-
-Raises a pop-up on screen that allows uses input
-
-@param title (string) text to display
-
-@param event (number) the event variable that is passed in from the
-Run function (key pressed)
-
-@param input (number) value that can be adjusted by the +/- keys
-
-@param min (number) min value that input can reach (by pressing the - key)
-
-@param max (number) max value that input can reach
-
-@retval number result of the input adjustment
-
-@retval "OK" user pushed ENT key
-
-@retval "CANCEL" user pushed EXIT key
-
-@notice Use only from stand-alone and telemetry scripts.
-
-@status current Introduced in 2.0.0
-*/
-static int luaPopupInput(lua_State * L)
-{
- event_t event = luaL_checkinteger(L, 2);
- warningInputValue = luaL_checkinteger(L, 3);
- warningInputValueMin = luaL_checkinteger(L, 4);
- warningInputValueMax = luaL_checkinteger(L, 5);
- warningText = luaL_checkstring(L, 1);
- warningType = WARNING_TYPE_INPUT;
- runPopupWarning(event);
- if (warningResult) {
- warningResult = 0;
- lua_pushstring(L, "OK");
- }
- else if (!warningText) {
- lua_pushstring(L, "CANCEL");
- }
- else {
- lua_pushinteger(L, warningInputValue);
- }
- warningText = NULL;
- return 1;
-}
-
/*luadoc
@function popupWarning(title, event)
@@ -1339,7 +1350,7 @@ const luaL_Reg opentxLib[] = {
{ "playDuration", luaPlayDuration },
{ "playTone", luaPlayTone },
{ "playHaptic", luaPlayHaptic },
- { "popupInput", luaPopupInput },
+ // { "popupInput", luaPopupInput },
{ "popupWarning", luaPopupWarning },
{ "popupConfirmation", luaPopupConfirmation },
{ "defaultStick", luaDefaultStick },
@@ -1355,6 +1366,10 @@ const luaL_Reg opentxLib[] = {
{ "sportTelemetryPop", luaSportTelemetryPop },
{ "sportTelemetryPush", luaSportTelemetryPush },
{ "setTelemetryValue", luaSetTelemetryValue },
+#if defined(PXX2)
+ { "sportTelemetryPop", luaSportTelemetryPop },
+ { "pxx2TelemetryPush", luaPXX2TelemetryPush },
+#endif
#if defined(CROSSFIRE)
{ "crossfireTelemetryPop", luaCrossfireTelemetryPop },
{ "crossfireTelemetryPush", luaCrossfireTelemetryPush },
@@ -1388,11 +1403,11 @@ const luaR_value_entry opentxConstants[] = {
{ "MIXSRC_SB", MIXSRC_SB },
{ "MIXSRC_SC", MIXSRC_SC },
{ "MIXSRC_SD", MIXSRC_SD },
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#if !defined(PCBX7) && !defined(PCBXLITE) && !defined(PCBX3)
{ "MIXSRC_SE", MIXSRC_SE },
{ "MIXSRC_SG", MIXSRC_SG },
#endif
-#if !defined(PCBXLITE)
+#if !defined(PCBXLITE) && !defined(PCBX3)
{ "MIXSRC_SF", MIXSRC_SF },
{ "MIXSRC_SH", MIXSRC_SH },
#endif
diff --git a/radio/src/lua/interface.cpp b/radio/src/lua/interface.cpp
index 235e83afa..cd035720c 100644
--- a/radio/src/lua/interface.cpp
+++ b/radio/src/lua/interface.cpp
@@ -671,10 +671,10 @@ bool luaLoadTelemetryScript(uint8_t index)
ScriptInternalData & sid = scriptInternalData[luaScriptsCount++];
sid.reference = SCRIPT_TELEMETRY_FIRST+index;
sid.state = SCRIPT_NOFILE;
- char filename[sizeof(SCRIPTS_TELEM_PATH)+sizeof(script.file)+sizeof(SCRIPT_EXT)] = SCRIPTS_TELEM_PATH "/";
- strncpy(filename+sizeof(SCRIPTS_TELEM_PATH), script.file, sizeof(script.file));
- filename[sizeof(SCRIPTS_TELEM_PATH)+sizeof(script.file)] = '\0';
- strcat(filename+sizeof(SCRIPTS_TELEM_PATH), SCRIPT_EXT);
+ char filename[sizeof(SCRIPTS_TELEM_PATH) + LEN_SCRIPT_FILENAME + sizeof(SCRIPT_EXT)] = SCRIPTS_TELEM_PATH "/";
+ strncpy(filename + sizeof(SCRIPTS_TELEM_PATH), script.file, LEN_SCRIPT_FILENAME);
+ filename[sizeof(SCRIPTS_TELEM_PATH) + LEN_SCRIPT_FILENAME] = '\0';
+ strcat(filename + sizeof(SCRIPTS_TELEM_PATH), SCRIPT_EXT);
if (luaLoad(lsScripts, filename, sid) == SCRIPT_PANIC) {
return false;
}
@@ -733,7 +733,7 @@ void luaLoadPermanentScripts()
void displayLuaError(const char * title)
{
#if !defined(COLORLCD)
- DRAW_MESSAGE_BOX(title);
+ drawMessageBox(title);
#endif
if (lua_warning_info[0]) {
char * split = strstr(lua_warning_info, ": ");
diff --git a/radio/src/main_arm.cpp b/radio/src/main.cpp
similarity index 87%
rename from radio/src/main_arm.cpp
rename to radio/src/main.cpp
index 5b601ff5a..7a088558e 100644
--- a/radio/src/main_arm.cpp
+++ b/radio/src/main.cpp
@@ -50,7 +50,7 @@ void handleUsbConnection()
}
}
if (!usbStarted() && usbPlugged() && getSelectedUsbMode() == USB_UNSELECTED_MODE) {
- if((g_eeGeneral.USBMode == USB_UNSELECTED_MODE) && (popupMenuNoItems == 0)) {
+ if((g_eeGeneral.USBMode == USB_UNSELECTED_MODE) && (popupMenuItemsCount == 0)) {
POPUP_MENU_ADD_ITEM(STR_USB_JOYSTICK);
POPUP_MENU_ADD_ITEM(STR_USB_MASS_STORAGE);
#if defined(DEBUG)
@@ -74,6 +74,76 @@ void handleUsbConnection()
#endif // defined(STM32) && !defined(SIMU)
}
+#if defined(JACK_DETECT_GPIO) && !defined(SIMU)
+bool isJackPlugged()
+{
+ // debounce
+ static bool debounced_state = 0;
+ static bool last_state = 0;
+
+ if (GPIO_ReadInputDataBit(JACK_DETECT_GPIO, JACK_DETECT_GPIO_PIN)) {
+ if (!last_state) {
+ debounced_state = false;
+ }
+ last_state = false;
+ }
+ else {
+ if (last_state) {
+ debounced_state = true;
+ }
+ last_state = true;
+ }
+ return debounced_state;
+}
+#endif
+
+#if defined(PCBXLITES)
+uint8_t jackState = SPEAKER_ACTIVE;
+
+const char STR_JACK_HEADPHONE[] = "Headphone";
+const char STR_JACK_TRAINER[] = "Trainer";
+
+void onJackConnectMenu(const char * result)
+{
+ if (result == STR_JACK_HEADPHONE) {
+ jackState = HEADPHONE_ACTIVE;
+ disableSpeaker();
+ enableHeadphone();
+ }
+ else if (result == STR_JACK_TRAINER) {
+ jackState = TRAINER_ACTIVE;
+ enableTrainer();
+ }
+}
+
+void handleJackConnection()
+{
+ if (jackState == SPEAKER_ACTIVE && isJackPlugged()) {
+ if (g_eeGeneral.jackMode == JACK_HEADPHONE_MODE) {
+ jackState = HEADPHONE_ACTIVE;
+ disableSpeaker();
+ enableHeadphone();
+ }
+ else if (g_eeGeneral.jackMode == JACK_TRAINER_MODE) {
+ jackState = TRAINER_ACTIVE;
+ enableTrainer();
+ }
+ else if (popupMenuItemsCount == 0) {
+ POPUP_MENU_ADD_ITEM(STR_JACK_HEADPHONE);
+ POPUP_MENU_ADD_ITEM(STR_JACK_TRAINER);
+ POPUP_MENU_START(onJackConnectMenu);
+ }
+ }
+ else if (jackState == SPEAKER_ACTIVE && !isJackPlugged() && popupMenuItemsCount > 0 && popupMenuHandler == onJackConnectMenu) {
+ popupMenuItemsCount = 0;
+ }
+ else if (jackState != SPEAKER_ACTIVE && !isJackPlugged()) {
+ jackState = SPEAKER_ACTIVE;
+ enableSpeaker();
+ }
+}
+#endif
+
void checkSpeakerVolume()
{
if (currentSpeakerVolume != requiredSpeakerVolume) {
@@ -227,7 +297,7 @@ void guiMain(event_t evt)
while (1) {
// normal GUI from menus
const char * warn = warningText;
- uint8_t menu = popupMenuNoItems;
+ uint8_t menu = popupMenuItemsCount;
static bool popupDisplayed = false;
if (warn || menu) {
@@ -243,7 +313,7 @@ void guiMain(event_t evt)
if (warn) DISPLAY_WARNING(evt);
if (menu) {
const char * result = runPopupMenu(evt);
- if (result) {
+ if (popupMenuItemsCount == 0) {
popupMenuHandler(result);
if (menuEvent == 0) {
evt = EVT_REFRESH;
@@ -330,8 +400,6 @@ void handleGui(event_t event) {
}
}
-bool inPopupMenu = false;
-
void guiMain(event_t evt)
{
#if defined(LUA)
@@ -373,13 +441,9 @@ void guiMain(event_t evt)
handleGui(0); // suppress events, they are handled by the warning
DISPLAY_WARNING(evt);
}
- else if (popupMenuNoItems > 0) {
+ else if (popupMenuItemsCount > 0) {
// popup menu is active display it on top of normal menus
handleGui(0); // suppress events, they are handled by the popup
- if (!inPopupMenu) {
- TRACE("Popup Menu started");
- inPopupMenu = true;
- }
const char * result = runPopupMenu(evt);
if (result) {
TRACE("popupMenuHandler(%s)", result);
@@ -388,10 +452,6 @@ void guiMain(event_t evt)
}
else {
// normal menus
- if (inPopupMenu) {
- TRACE("Popup Menu ended");
- inPopupMenu = false;
- }
handleGui(evt);
}
@@ -409,6 +469,9 @@ void perMain()
checkEeprom();
logsWrite();
handleUsbConnection();
+#if defined(PCBXLITES)
+ handleJackConnection();
+#endif
checkTrainerSettings();
periodicTick();
DEBUG_TIMER_STOP(debugTimerPerMain1);
diff --git a/radio/src/mixer.cpp b/radio/src/mixer.cpp
index b94181454..edfa31aca 100644
--- a/radio/src/mixer.cpp
+++ b/radio/src/mixer.cpp
@@ -347,7 +347,7 @@ getvalue_t getValue(mixsrc_t i)
else if ((i >= MIXSRC_FIRST_SWITCH) && (i <= MIXSRC_LAST_SWITCH)) {
mixsrc_t sw = i-MIXSRC_FIRST_SWITCH;
if (SWITCH_EXISTS(sw)) {
- return (switchState(3*sw) ? -1024 : (switchState(3*sw+1) ? 0 : 1024));
+ return (switchState(3*sw) ? -1024 : (IS_CONFIG_3POS(sw) && switchState(3*sw+1) ? 0 : 1024));
}
else {
return 0;
diff --git a/radio/src/myeeprom.h b/radio/src/myeeprom.h
index e21595ce0..34d7e7072 100644
--- a/radio/src/myeeprom.h
+++ b/radio/src/myeeprom.h
@@ -23,40 +23,27 @@
#include "datastructs.h"
-#define WARN_THR_BIT 0x01
-#define WARN_BEP_BIT 0x80
-#define WARN_SW_BIT 0x02
-#define WARN_MEM_BIT 0x04
-#define WARN_BVAL_BIT 0x38
+#define EEPROM_VER 219
+#define FIRST_CONV_EEPROM_VER 216
-#define WARN_THR (!(g_eeGeneral.warnOpts & WARN_THR_BIT))
-#define WARN_BEP (!(g_eeGeneral.warnOpts & WARN_BEP_BIT))
-#define WARN_SW (!(g_eeGeneral.warnOpts & WARN_SW_BIT))
-#define WARN_MEM (!(g_eeGeneral.warnOpts & WARN_MEM_BIT))
-#define BEEP_VAL ( (g_eeGeneral.warnOpts & WARN_BVAL_BIT) >>3 )
-
- #define EEPROM_VER 218
- #define FIRST_CONV_EEPROM_VER 216
-
-#define GET_PPM_POLARITY(idx) g_model.moduleData[idx].ppm.pulsePol
-#define GET_SBUS_POLARITY(idx) g_model.moduleData[idx].sbus.noninverted
-#define GET_PPM_DELAY(idx) (g_model.moduleData[idx].ppm.delay * 50 + 300)
-#define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppm.frameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount)
+#define GET_MODULE_PPM_POLARITY(idx) g_model.moduleData[idx].ppm.pulsePol
+#define GET_TRAINER_PPM_POLARITY() g_model.trainerData.pulsePol
+#define GET_SBUS_POLARITY(idx) g_model.moduleData[idx].sbus.noninverted
+#define GET_MODULE_PPM_DELAY(idx) (g_model.moduleData[idx].ppm.delay * 50 + 300)
+#define GET_TRAINER_PPM_DELAY(idx) (g_model.trainerData.delay * 50 + 300)
+#define SET_DEFAULT_PPM_FRAME_LENGTH(idx) g_model.moduleData[idx].ppm.frameLength = 4 * max((int8_t)0, g_model.moduleData[idx].channelsCount)
#if defined(PCBHORUS)
#define IS_TRAINER_EXTERNAL_MODULE() false
#define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.serial2Mode==UART_MODE_SBUS_TRAINER)
#elif defined(PCBTARANIS)
- #define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerMode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerMode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
- #define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.serial2Mode==UART_MODE_SBUS_TRAINER)
+ #define IS_TRAINER_EXTERNAL_MODULE() (g_model.trainerData.mode == TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE || g_model.trainerData.mode == TRAINER_MODE_MASTER_CPPM_EXTERNAL_MODULE)
+ #define HAS_WIRELESS_TRAINER_HARDWARE() (g_eeGeneral.serial2Mode==UART_MODE_SBUS_TRAINER)
#else
#define IS_TRAINER_EXTERNAL_MODULE() false
#endif
- #define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE)
-
- #define IS_PLAY_BOTH_FUNC(func) (0)
- #define IS_VOLUME_FUNC(func) ((func) == FUNC_VOLUME)
+#define IS_PLAY_FUNC(func) ((func) >= FUNC_PLAY_SOUND && func <= FUNC_PLAY_VALUE)
#if defined(GVARS)
#define IS_ADJUST_GV_FUNC(func) ((func) == FUNC_ADJUST_GVAR)
@@ -141,21 +128,20 @@ enum CurveRefType {
CURVE_REF_CUSTOM
};
-
#define MIN_EXPO_WEIGHT -100
#define EXPO_VALID(ed) ((ed)->mode)
#define EXPO_MODE_ENABLE(ed, v) (((v)<0 && ((ed)->mode&1)) || ((v)>=0 && ((ed)->mode&2)))
- #define limit_min_max_t int16_t
- #define LIMIT_EXT_PERCENT 150
- #define LIMIT_EXT_MAX (LIMIT_EXT_PERCENT*10)
- #define PPM_CENTER_MAX 500
- #define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR_PREC1(lim->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode) : lim->max+1000)
- #define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR_PREC1(lim->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode) : lim->min-1000)
- #define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR_PREC1(lim->offset, -1000, 1000, mixerCurrentFlightMode) : lim->offset)
- #define LIMIT_MAX_RESX(lim) calc1000toRESX(LIMIT_MAX(lim))
- #define LIMIT_MIN_RESX(lim) calc1000toRESX(LIMIT_MIN(lim))
- #define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim))
+#define limit_min_max_t int16_t
+#define LIMIT_EXT_PERCENT 150
+#define LIMIT_EXT_MAX (LIMIT_EXT_PERCENT*10)
+#define PPM_CENTER_MAX 500
+#define LIMIT_MAX(lim) (GV_IS_GV_VALUE(lim->max, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR_PREC1(lim->max, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode) : lim->max+1000)
+#define LIMIT_MIN(lim) (GV_IS_GV_VALUE(lim->min, -GV_RANGELARGE, GV_RANGELARGE) ? GET_GVAR_PREC1(lim->min, -LIMIT_EXT_MAX, LIMIT_EXT_MAX, mixerCurrentFlightMode) : lim->min-1000)
+#define LIMIT_OFS(lim) (GV_IS_GV_VALUE(lim->offset, -1000, 1000) ? GET_GVAR_PREC1(lim->offset, -1000, 1000, mixerCurrentFlightMode) : lim->offset)
+#define LIMIT_MAX_RESX(lim) calc1000toRESX(LIMIT_MAX(lim))
+#define LIMIT_MIN_RESX(lim) calc1000toRESX(LIMIT_MIN(lim))
+#define LIMIT_OFS_RESX(lim) calc1000toRESX(LIMIT_OFS(lim))
#define TRIM_OFF (1)
#define TRIM_ON (0)
@@ -191,8 +177,6 @@ enum CurveRefType {
#define MD_OFFSET(md) (md->offset)
#define MD_OFFSET_TO_UNION(md, var) var.word = md->offset
#define MD_UNION_TO_OFFSET(var, md) md->offset = var.word
-// #define MD_SETOFFSET(md, val) md->offset = val
-
enum LogicalSwitchesFunctions {
LS_FUNC_NONE,
@@ -222,14 +206,6 @@ enum LogicalSwitchesFunctions {
#define MAX_LS_DELAY 250 /*25s*/
#define MAX_LS_ANDSW SWSRC_LAST
-//#define TELEM_FLAG_TIMEOUT 0x01
-#define TELEM_FLAG_LOG 0x02
-//#define TELEM_FLAG_PERSISTENT 0x04
-//#define TELEM_FLAG_SCALE 0x08
-#define TELEM_FLAG_AUTO_OFFSET 0x10
-#define TELEM_FLAG_FILTER 0x20
-#define TELEM_FLAG_LOSS_ALARM 0x40
-
enum TelemetrySensorType
{
TELEM_TYPE_CUSTOM,
@@ -251,16 +227,10 @@ enum TelemetrySensorFormula
};
enum VarioSource {
-#if !defined(TELEMETRY_FRSKY_SPORT)
- VARIO_SOURCE_ALTI,
- VARIO_SOURCE_ALTI_PLUS,
-#endif
VARIO_SOURCE_VSPEED,
VARIO_SOURCE_A1,
VARIO_SOURCE_A2,
-#if defined(TELEMETRY_FRSKY_SPORT)
VARIO_SOURCE_DTE,
-#endif
VARIO_SOURCE_COUNT,
VARIO_SOURCE_LAST = VARIO_SOURCE_COUNT-1
};
@@ -292,8 +262,6 @@ enum FrskyVoltsSource {
FRSKY_VOLTS_SOURCE_LAST=FRSKY_VOLTS_SOURCE_CELLS
};
-
-
enum SwashType {
SWASH_TYPE_NONE,
SWASH_TYPE_120,
@@ -310,8 +278,8 @@ enum SwashType {
#define ROTARY_ENCODER_MAX 1024
- #define TRIMS_ARRAY_SIZE 8
- #define TRIM_MODE_NONE 0x1F // 0b11111
+#define TRIMS_ARRAY_SIZE 8
+#define TRIM_MODE_NONE 0x1F // 0b11111
#define IS_MANUAL_RESET_TIMER(idx) (g_model.timers[idx].persistent == 2)
@@ -321,37 +289,6 @@ enum SwashType {
#define TIMER_COUNTDOWN_START(x) 10
#endif
-enum Protocols {
- PROTO_PPM,
-#if defined(PXX) || defined(DSM2) || defined(IRPROTOS)
- PROTO_PXX,
-#endif
-#if defined(DSM2) || defined(IRPROTOS)
- PROTO_DSM2_LP45,
- PROTO_DSM2_DSM2,
- PROTO_DSM2_DSMX,
-#endif
- PROTO_CROSSFIRE,
-#if defined(IRPROTOS)
- // only used on AVR
- // we will need 4 bits for proto :(
- PROTO_SILV,
- PROTO_TRAC09,
- PROTO_PICZ,
- PROTO_SWIFT,
-#endif
- PROTO_MULTIMODULE,
- PROTO_SBUS,
- PROTO_PXX2,
- PROTO_NONE
-};
-
-#if defined(PXX2)
-#define PROTO_PXX_EXTERNAL_MODULE PROTO_PXX2
-#else
-#define PROTO_PXX_EXTERNAL_MODULE PROTO_PXX
-#endif
-
enum XJTRFProtocols {
RF_PROTO_OFF = -1,
RF_PROTO_X16,
@@ -369,6 +306,21 @@ enum R9MSubTypes
MODULE_SUBTYPE_R9M_LAST=MODULE_SUBTYPE_R9M_AUPLUS
};
+enum R9MRegion
+{
+ MODULE_R9M_REGION_FCC,
+ MODULE_R9M_REGION_EU,
+ MODULE_R9M_REGION_FLEX,
+ MODULE_R9M_REGION_LAST=MODULE_R9M_REGION_FLEX
+};
+
+enum R9MFrenquency
+{
+ MODULE_R9M_FREQ_868MHZ,
+ MODULE_R9M_FREQ_915MHZ,
+ MODULE_R9M_FREQ_LAST=MODULE_R9M_FREQ_915MHZ
+};
+
enum MultiModuleRFProtocols {
MM_RF_PROTO_CUSTOM = -1,
MM_RF_PROTO_FIRST = MM_RF_PROTO_CUSTOM,
@@ -450,11 +402,17 @@ enum ModuleTypes {
MODULE_TYPE_NONE = 0,
MODULE_TYPE_PPM,
MODULE_TYPE_XJT,
+ MODULE_TYPE_XJT2,
MODULE_TYPE_DSM2,
MODULE_TYPE_CROSSFIRE,
MODULE_TYPE_MULTIMODULE,
MODULE_TYPE_R9M,
+ MODULE_TYPE_R9M2,
+ MODULE_TYPE_R9M_LITE,
+ MODULE_TYPE_R9M_LITE2,
+ MODULE_TYPE_R9M_LITE_PRO2,
MODULE_TYPE_SBUS,
+ MODULE_TYPE_MAX = MODULE_TYPE_SBUS,
MODULE_TYPE_COUNT
};
@@ -498,17 +456,18 @@ enum ThrottleSources {
THROTTLE_SOURCE_CH1,
};
-enum TelemetryType
+enum TelemetryProtocols
{
PROTOCOL_TELEMETRY_FIRST,
- PROTOCOL_FRSKY_SPORT = PROTOCOL_TELEMETRY_FIRST,
- PROTOCOL_FRSKY_D,
- PROTOCOL_FRSKY_D_SECONDARY,
- PROTOCOL_PULSES_CROSSFIRE,
- PROTOCOL_SPEKTRUM,
- PROTOCOL_FLYSKY_IBUS,
- PROTOCOL_MULTIMODULE,
- PROTOCOL_TELEMETRY_LAST=PROTOCOL_MULTIMODULE
+ PROTOCOL_TELEMETRY_FRSKY_SPORT = PROTOCOL_TELEMETRY_FIRST,
+ PROTOCOL_TELEMETRY_FRSKY_D,
+ PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY,
+ PROTOCOL_TELEMETRY_CROSSFIRE,
+ PROTOCOL_TELEMETRY_SPEKTRUM,
+ PROTOCOL_TELEMETRY_FLYSKY_IBUS,
+ PROTOCOL_TELEMETRY_MULTIMODULE,
+ PROTOCOL_TELEMETRY_LAST=PROTOCOL_TELEMETRY_MULTIMODULE,
+ PROTOCOL_TELEMETRY_PXX2,
};
enum DisplayTrims
@@ -518,8 +477,6 @@ enum DisplayTrims
DISPLAY_TRIMS_ALWAYS
};
-#define TOTAL_EEPROM_USAGE (sizeof(ModelData)*MAX_MODELS + sizeof(RadioData))
-
extern RadioData g_eeGeneral;
extern ModelData g_model;
@@ -531,4 +488,7 @@ PACK(union u_int8int16_t {
int16_t word;
});
+#define EE_GENERAL 0x01
+#define EE_MODEL 0x02
+
#endif // _MYEEPROM_H_
diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp
index e45eb194c..2aef36ba0 100644
--- a/radio/src/opentx.cpp
+++ b/radio/src/opentx.cpp
@@ -27,14 +27,13 @@ ModelData g_model;
Clipboard clipboard;
#endif
-
uint8_t unexpectedShutdown = 0;
-/* AVR: mixer duration in 1/16ms */
+uint16_t vbattRTC;
+
/* ARM: mixer duration in 0.5us */
uint16_t maxMixerDuration;
-
uint8_t heartbeat;
#if defined(OVERRIDE_CHANNEL_FUNCTION)
@@ -242,16 +241,22 @@ void generalDefault()
#elif defined(PCBXLITE)
g_eeGeneral.potsConfig = 0x0F; // S1 and S2 = pot without detent
#elif defined(PCBX7)
- g_eeGeneral.potsConfig = 0x07; // S1 = pot without detent, S2 = pot with detent
+ g_eeGeneral.potsConfig = (POT_WITHOUT_DETENT << 0) + (POT_WITH_DETENT << 2); // S1 = pot without detent, S2 = pot with detent
+#elif defined(PCBX3)
+ g_eeGeneral.potsConfig = (POT_WITH_DETENT << 0); // S1 = pot with detent
#elif defined(PCBTARANIS)
g_eeGeneral.potsConfig = 0x05; // S1 and S2 = pots with detent
g_eeGeneral.slidersConfig = 0x03; // LS and RS = sliders with detent
#endif
-#if defined(PCBXLITE)
- g_eeGeneral.switchConfig = (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0); // 2x3POS, 2x2POS
+#if defined(PCBXLITES)
+ g_eeGeneral.switchConfig = (SWITCH_TOGGLE << 10) + (SWITCH_TOGGLE << 8) + (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0);
+#elif defined(PCBXLITE)
+ g_eeGeneral.switchConfig = (SWITCH_2POS << 6) + (SWITCH_2POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0);
#elif defined(PCBX7)
g_eeGeneral.switchConfig = 0x000006ff; // 4x3POS, 1x2POS, 1xTOGGLE
+#elif defined(PCBX3)
+ g_eeGeneral.switchConfig = (SWITCH_TOGGLE << 8) + (SWITCH_2POS << 6) + (SWITCH_3POS << 4) + (SWITCH_3POS << 2) + (SWITCH_3POS << 0);
#elif defined(PCBTARANIS) || defined(PCBHORUS)
g_eeGeneral.switchConfig = 0x00007bff; // 6x3POS, 1x2POS, 1xTOGGLE
#endif
@@ -300,6 +305,12 @@ void generalDefault()
theme->init();
#endif
+#if defined(PXX2)
+ for (uint8_t i=0; imode = 3; // TODO constant
#if defined(TRANSLATIONS_CZ)
for (int c=0; c<4; c++) {
- g_model.inputNames[i][c] = char2idx(STR_INPUTNAMES[1+4*(stick_index-1)+c]);
+ g_model.inputNames[i][c] = char2zchar(STR_INPUTNAMES[1+4*(stick_index-1)+c]);
}
#else
for (int c=0; c<3; c++) {
- g_model.inputNames[i][c] = char2idx(STR_VSRCRAW[2+4*stick_index+c]);
+ g_model.inputNames[i][c] = char2zchar(STR_VSRCRAW[2 + 4 * stick_index + c]);
}
#if LEN_INPUT_NAME > 3
g_model.inputNames[i][3] = '\0';
@@ -360,18 +371,21 @@ void applyDefaultTemplate()
#if defined(EEPROM)
void checkModelIdUnique(uint8_t index, uint8_t module)
{
+ if(isModulePXX(module) && IS_D8_RX(module))
+ return;
+
uint8_t modelId = g_model.header.modelId[module];
uint8_t additionalOnes = 0;
- char * name = reusableBuffer.modelsetup.msg;
+ char * name = reusableBuffer.moduleSetup.msg;
- memset(reusableBuffer.modelsetup.msg, 0, sizeof(reusableBuffer.modelsetup.msg));
+ memset(reusableBuffer.moduleSetup.msg, 0, sizeof(reusableBuffer.moduleSetup.msg));
if (modelId != 0) {
for (uint8_t i = 0; i < MAX_MODELS; i++) {
if (i != index) {
if (modelId == modelHeaders[i].modelId[module]) {
- if ((WARNING_LINE_LEN - 4 - (name - reusableBuffer.modelsetup.msg)) > (signed)(modelHeaders[i].name[0] ? zlen(modelHeaders[i].name, LEN_MODEL_NAME) : sizeof(TR_MODEL) + 2)) { // you cannot rely exactly on WARNING_LINE_LEN so using WARNING_LINE_LEN-2 (-2 for the ",")
- if (reusableBuffer.modelsetup.msg[0] != 0) {
+ if ((WARNING_LINE_LEN - 4 - (name - reusableBuffer.moduleSetup.msg)) > (signed)(modelHeaders[i].name[0] ? zlen(modelHeaders[i].name, LEN_MODEL_NAME) : sizeof(TR_MODEL) + 2)) { // you cannot rely exactly on WARNING_LINE_LEN so using WARNING_LINE_LEN-2 (-2 for the ",")
+ if (reusableBuffer.moduleSetup.msg[0] != 0) {
name = strAppend(name, ", ");
}
if (modelHeaders[i].name[0] == 0) {
@@ -396,9 +410,9 @@ void checkModelIdUnique(uint8_t index, uint8_t module)
name = strAppend(name, ")");
}
- if (reusableBuffer.modelsetup.msg[0] != 0) {
+ if (reusableBuffer.moduleSetup.msg[0] != 0) {
POPUP_WARNING(STR_MODELIDUSED);
- SET_WARNING_INFO(reusableBuffer.modelsetup.msg, sizeof(reusableBuffer.modelsetup.msg), 0);
+ SET_WARNING_INFO(reusableBuffer.moduleSetup.msg, sizeof(reusableBuffer.moduleSetup.msg), 0);
}
}
@@ -447,6 +461,8 @@ void modelDefault(uint8_t id)
applyDefaultTemplate();
+ memcpy(g_model.modelRegistrationID, g_eeGeneral.ownerRegistrationID, PXX2_LEN_REGISTRATION_ID);
+
#if defined(LUA) && defined(PCBTARANIS) //Horus uses menuModelWizard() for wizard
if (isFileAvailable(WIZARD_PATH "/" WIZARD_NAME)) {
f_chdir(WIZARD_PATH);
@@ -455,14 +471,14 @@ void modelDefault(uint8_t id)
#endif
#if defined(PCBTARANIS) || defined(PCBHORUS)
- g_model.moduleData[INTERNAL_MODULE].type = MODULE_TYPE_XJT;
+ g_model.moduleData[INTERNAL_MODULE].type = IS_PXX2_INTERNAL_ENABLED() ? MODULE_TYPE_XJT2 : MODULE_TYPE_XJT;
g_model.moduleData[INTERNAL_MODULE].channelsCount = defaultModuleChannels_M8(INTERNAL_MODULE);
#elif defined(PCBSKY9X)
g_model.moduleData[EXTERNAL_MODULE].type = MODULE_TYPE_PPM;
#endif
#if defined(PCBXLITE)
- g_model.trainerMode = TRAINER_MODE_MASTER_BLUETOOTH;
+ g_model.trainerData.mode = TRAINER_MODE_MASTER_BLUETOOTH;
#endif
#if defined(EEPROM)
@@ -702,7 +718,6 @@ void checkBacklight()
{
static uint8_t tmr10ms ;
-
uint8_t x = g_blinkTmr10ms;
if (tmr10ms != x) {
tmr10ms = x;
@@ -713,13 +728,12 @@ void checkBacklight()
}
}
- bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || lightOffCounter || isFunctionActive(FUNCTION_BACKLIGHT));
+ bool backlightOn = (g_eeGeneral.backlightMode == e_backlight_mode_on || (g_eeGeneral.backlightMode != e_backlight_mode_off && lightOffCounter) || isFunctionActive(FUNCTION_BACKLIGHT));
if (flashCounter) backlightOn = !backlightOn;
if (backlightOn)
BACKLIGHT_ENABLE();
else
BACKLIGHT_DISABLE();
-
}
}
@@ -1484,9 +1498,9 @@ void doMixerCalculations()
static uint8_t countRangecheck = 0;
for (uint8_t i=0; i= MODULE_MODE_BEEP_FIRST) {
#endif
if (++countRangecheck >= 250) {
countRangecheck = 0;
@@ -1903,7 +1917,6 @@ void opentxInit(OPENTX_INIT_ARGS)
init_trainer_capture();
#endif
-
startPulses();
wdt_enable(WDTO_500MS);
@@ -1926,10 +1939,6 @@ int main()
boardInit();
-#if defined(PCBX7)
- bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE); //BT is turn on for a brief period to differentiate X7 and X7S
-#endif
-
#if defined(PCBHORUS)
loadFonts();
#endif
@@ -2031,7 +2040,7 @@ uint32_t pwrCheck()
lcdRefreshWait();
lcdClear();
- POPUP_CONFIRMATION(STR_MODEL_SHUTDOWN);
+ POPUP_CONFIRMATION(STR_MODEL_SHUTDOWN, nullptr);
SET_WARNING_INFO(STR_MODEL_STILL_POWERED, sizeof(TR_MODEL_STILL_POWERED), 0);
event_t evt = getEvent(false);
DISPLAY_WARNING(evt);
diff --git a/radio/src/opentx.h b/radio/src/opentx.h
index daf616120..acfc457e4 100644
--- a/radio/src/opentx.h
+++ b/radio/src/opentx.h
@@ -190,16 +190,16 @@
#define IS_FAI_FORBIDDEN(idx) (IS_FAI_ENABLED() && isFaiForbidden(idx))
#if defined(BLUETOOTH)
-#if defined(X9E) && !defined(USEHORUSBT)
- #define IS_BLUETOOTH_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH)
- #define IS_SLAVE_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE)
-#else
- #define IS_BLUETOOTH_TRAINER() (g_model.trainerMode == TRAINER_MODE_MASTER_BLUETOOTH || g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH)
- #define IS_SLAVE_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE || g_model.trainerMode == TRAINER_MODE_SLAVE_BLUETOOTH)
-#endif
+ #if defined(X9E) && !defined(USEHORUSBT)
+ #define IS_BLUETOOTH_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH)
+ #define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
+ #else
+ #define IS_BLUETOOTH_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_MASTER_BLUETOOTH || g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH)
+ #define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE || g_model.trainerData.mode == TRAINER_MODE_SLAVE_BLUETOOTH)
+ #endif
#else
#define IS_BLUETOOTH_TRAINER() false
- #define IS_SLAVE_TRAINER() (g_model.trainerMode == TRAINER_MODE_SLAVE)
+ #define IS_SLAVE_TRAINER() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#endif
// RESX range is used for internal calculation; The menu says -100.0 to 100.0; internally it is -1024 to 1024 to allow some optimizations
@@ -211,6 +211,12 @@
#include "board.h"
+#if defined(JACK_DETECT_GPIO)
+#define CASE_JACK_DETECT(x) x,
+#else
+#define CASE_JACK_DETECT(x)
+#endif
+
#if defined(DISK_CACHE)
#include "disk_cache.h"
#endif
@@ -288,7 +294,7 @@ void memswap(void * a, void * b, uint8_t size);
#endif
#include "fifo.h"
-#include "io/io_arm.h"
+#include "io/frsky_sport.h"
extern volatile tmr10ms_t g_tmr10ms;
static inline tmr10ms_t get_tmr10ms()
@@ -425,10 +431,11 @@ extern struct t_inactivity inactivity;
#endif
char hex2zchar(uint8_t hex);
-char idx2char(int8_t idx);
-int8_t char2idx(char c);
+char zchar2char(int8_t idx);
+int8_t char2zchar(char c);
void str2zchar(char *dest, const char *src, int size);
int zchar2str(char *dest, const char *src, int size);
+bool cmpStrWithZchar(const char * charString, const char * zcharString, int size);
#include "keys.h"
#include "pwr.h"
@@ -565,6 +572,8 @@ void flightReset(uint8_t check=true);
extern uint8_t unexpectedShutdown;
+extern uint16_t vbattRTC;
+
extern uint16_t maxMixerDuration;
#define DURATION_MS_PREC2(x) ((x)/20)
@@ -651,7 +660,7 @@ uint16_t isqrt32(uint32_t n);
#define pauseMixerCalculations()
#define resumeMixerCalculations()
#else
-#include "tasks_arm.h"
+#include "tasks.h"
extern RTOS_MUTEX_HANDLE mixerMutex;
inline void pauseMixerCalculations()
{
@@ -1034,14 +1043,10 @@ enum AUDIO_SOUNDS {
};
#if defined(AUDIO)
-#include "audio_arm.h"
+#include "audio.h"
#endif
#include "buzzer.h"
-
-
-
-
#include "translations.h"
#include "fonts.h"
@@ -1090,6 +1095,7 @@ void opentxResume();
#else
#define SD_SCREEN_FILE_LENGTH 64
#endif
+
union ReusableBuffer
{
// ARM 334 bytes
@@ -1110,11 +1116,31 @@ union ReusableBuffer
struct {
char msg[64];
uint8_t r9mPower;
- } modelsetup;
+ union {
+ struct {
+ union {
+ uint8_t registerStep;
+ uint8_t bindStep;
+ };
+ uint32_t bindWaitTimeout;
+ uint8_t registerPopupVerticalPosition;
+ uint8_t registerPopupHorizontalPosition;
+ int8_t registerPopupEditMode;
+ char registerRxName[PXX2_LEN_RX_NAME];
+ uint8_t registerModuleIndex;
+ char bindCandidateReceiversNames[PXX2_MAX_RECEIVERS_PER_MODULE][PXX2_LEN_RX_NAME + 1];
+ uint8_t bindCandidateReceiversCount;
+ uint8_t bindReceiverId;
+ union {
+ uint8_t bindSelectedReceiverIndex;
+ uint8_t shareReceiverId;
+ };
+ } pxx2;
+ };
+ } moduleSetup;
// 103 bytes
- struct
- {
+ struct {
int16_t midVals[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS];
int16_t loVals[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS];
int16_t hiVals[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS];
@@ -1131,8 +1157,7 @@ union ReusableBuffer
#if defined(SDCARD)
// 274 bytes
- struct
- {
+ struct {
char lines[NUM_BODY_LINES][SD_SCREEN_FILE_LENGTH+1+1]; // the last char is used to store the flags (directory) of the line
uint32_t available;
uint16_t offset;
@@ -1141,11 +1166,67 @@ union ReusableBuffer
} sdmanager;
#endif
- struct
- {
+ struct {
+ struct {
+ int8_t current;
+ int8_t maximum;
+ uint8_t timeout;
+ PXX2HardwareInformation information;
+ struct {
+ PXX2HardwareInformation information;
+ } receivers[PXX2_MAX_RECEIVERS_PER_MODULE];
+ } modules[NUM_MODULES];
+
+ uint32_t updateTime;
+
+ union {
+ struct {
+ uint8_t state; // 0x00 = READ 0x40 = WRITE
+ tmr10ms_t timeout;
+ uint8_t dirty;
+ uint8_t rfProtocol;
+ uint8_t externalAntenna;
+ int8_t txPower;
+ } moduleSettings;
+
+ struct {
+ uint8_t state; // 0x00 = READ 0x40 = WRITE
+ tmr10ms_t timeout;
+ uint8_t receiverId;
+ uint8_t dirty;
+ uint8_t telemetryDisabled;
+ uint8_t pwmRate;
+ uint8_t outputsCount;
+ uint8_t outputsMapping[24];
+ } receiverSettings;
+ };
+
+ } hardwareAndSettings;
+
+ struct {
uint8_t stickMode;
} generalSettings;
+ struct
+ {
+ uint8_t bars[LCD_W];
+ uint32_t freq;
+ uint32_t span;
+ uint32_t step;
+ } spectrumAnalyser;
+
+ struct
+ {
+ uint32_t freq;
+ int16_t power;
+ int16_t peak;
+ } powerMeter;
+
+ struct
+ {
+ int8_t preset;
+ } curveEdit;
+
#if defined(STM32)
// Data for the USB mass storage driver. If USB mass storage runs no menu is not allowed to be displayed
uint8_t MSC_BOT_Data[MSC_MEDIA_PACKET];
@@ -1290,4 +1371,13 @@ extern JitterMeter avgJitter[NUM_ANALOGS];
#include "bluetooth.h"
#endif
+#if defined(JACK_DETECT_GPIO)
+enum JackMode {
+ JACK_UNSELECTED_MODE,
+ JACK_HEADPHONE_MODE,
+ JACK_TRAINER_MODE,
+ JACK_MAX_MODE = JACK_TRAINER_MODE
+};
+#endif
+
#endif // _OPENTX_H_
diff --git a/radio/src/pulses/crossfire.cpp b/radio/src/pulses/crossfire.cpp
index 6f8876913..889bc9140 100644
--- a/radio/src/pulses/crossfire.cpp
+++ b/radio/src/pulses/crossfire.cpp
@@ -46,3 +46,22 @@ uint8_t createCrossfireChannelsFrame(uint8_t * frame, int16_t * pulses)
*buf++ = crc8(crc_start, 23);
return buf - frame;
}
+
+void setupPulsesCrossfire()
+{
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
+ uint8_t * pulses = extmodulePulsesData.crossfire.pulses;
+#if defined(LUA)
+ if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) {
+ memcpy(pulses, outputTelemetryBuffer, outputTelemetryBufferSize);
+ extmodulePulsesData.crossfire.length = outputTelemetryBufferSize;
+ outputTelemetryBufferTrigger = 0x00;
+ outputTelemetryBufferSize = 0;
+ }
+ else
+#endif
+ {
+ extmodulePulsesData.crossfire.length = createCrossfireChannelsFrame(pulses, &channelOutputs[g_model.moduleData[EXTERNAL_MODULE].channelsStart]);
+ }
+ }
+}
diff --git a/radio/src/pulses/dsm2_arm.cpp b/radio/src/pulses/dsm2.cpp
similarity index 65%
rename from radio/src/pulses/dsm2_arm.cpp
rename to radio/src/pulses/dsm2.cpp
index 99b6506b0..306c3b466 100644
--- a/radio/src/pulses/dsm2_arm.cpp
+++ b/radio/src/pulses/dsm2.cpp
@@ -38,13 +38,13 @@ uint8_t dsm2BindTimer = DSM2_BIND_TIMEOUT;
#if defined(PPM_PIN_SERIAL)
void putDsm2SerialBit(uint8_t bit)
{
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte >>= 1;
+ extmodulePulsesData.dsm2.serialByte >>= 1;
if (bit & 1) {
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte |= 0x80;
+ extmodulePulsesData.dsm2.serialByte |= 0x80;
}
- if (++modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount >= 8) {
- *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte;
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0;
+ if (++extmodulePulsesData.dsm2.serialBitCount >= 8) {
+ *extmodulePulsesData.dsm2.ptr++ = extmodulePulsesData.dsm2.serialByte;
+ extmodulePulsesData.dsm2.serialBitCount = 0;
}
}
@@ -69,14 +69,14 @@ void putDsm2Flush()
#else
void _send_1(uint8_t v)
{
- if (modulePulsesData[EXTERNAL_MODULE].dsm2.index & 1)
+ if (extmodulePulsesData.dsm2.index & 1)
v += 2;
else
v -= 2;
- *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = v - 1;
- modulePulsesData[EXTERNAL_MODULE].dsm2.index += 1;
- modulePulsesData[EXTERNAL_MODULE].dsm2.rest -= v;
+ *extmodulePulsesData.dsm2.ptr++ = v - 1;
+ extmodulePulsesData.dsm2.index += 1;
+ extmodulePulsesData.dsm2.rest -= v;
}
void sendByteDsm2(uint8_t b) // max 10 changes 0 10 10 10 10 1
@@ -100,35 +100,35 @@ void sendByteDsm2(uint8_t b) // max 10 changes 0 10 10 10 10 1
void putDsm2Flush()
{
- if (modulePulsesData[EXTERNAL_MODULE].dsm2.index & 1)
- *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = modulePulsesData[EXTERNAL_MODULE].dsm2.rest;
+ if (extmodulePulsesData.dsm2.index & 1)
+ *extmodulePulsesData.dsm2.ptr++ = extmodulePulsesData.dsm2.rest;
else
- *(modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - 1) = modulePulsesData[EXTERNAL_MODULE].dsm2.rest;
+ *(extmodulePulsesData.dsm2.ptr - 1) = extmodulePulsesData.dsm2.rest;
}
#endif
// This is the data stream to send, prepare after 19.5 mS
// Send after 22.5 mS
-void setupPulsesDSM2(uint8_t port)
+void setupPulsesDSM2()
{
uint8_t dsmDat[14];
#if defined(PPM_PIN_SERIAL)
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0 ;
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0 ;
+ extmodulePulsesData.dsm2.serialByte = 0 ;
+ extmodulePulsesData.dsm2.serialBitCount = 0 ;
#else
- modulePulsesData[EXTERNAL_MODULE].dsm2.index = 0;
- modulePulsesData[EXTERNAL_MODULE].dsm2.rest = DSM2_PERIOD * 2000;
+ extmodulePulsesData.dsm2.index = 0;
+ extmodulePulsesData.dsm2.rest = DSM2_PERIOD * 2000;
#endif
- modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
+ extmodulePulsesData.dsm2.ptr = extmodulePulsesData.dsm2.pulses;
- switch (s_current_protocol[port]) {
- case PROTO_DSM2_LP45:
+ switch (moduleSettings[EXTERNAL_MODULE].protocol) {
+ case PROTOCOL_CHANNELS_DSM2_LP45:
dsmDat[0] = 0x00;
break;
- case PROTO_DSM2_DSM2:
+ case PROTOCOL_CHANNELS_DSM2_DSM2:
dsmDat[0] = 0x10;
break;
default: // DSMX
@@ -140,29 +140,29 @@ void setupPulsesDSM2(uint8_t port)
if (dsm2BindTimer > 0) {
dsm2BindTimer--;
if (switchState(SW_DSM2_BIND)) {
- moduleFlag[port] = MODULE_BIND;
+ moduleSettings[EXTERNAL_MODULE].mode = MODULE_MODE_BIND;
dsmDat[0] |= DSM2_SEND_BIND;
}
}
- else if (moduleFlag[port] == MODULE_RANGECHECK) {
+ else if (moduleSettings[EXTERNAL_MODULE].mode == MODULE_MODE_RANGECHECK) {
dsmDat[0] |= DSM2_SEND_RANGECHECK;
}
else {
- moduleFlag[port] = 0;
+ moduleSettings[EXTERNAL_MODULE].mode = 0;
}
#else
- if (moduleFlag[port] == MODULE_BIND) {
+ if (moduleSettings[EXTERNAL_MODULE].mode == MODULE_MODE_BIND) {
dsmDat[0] |= DSM2_SEND_BIND;
}
- else if (moduleFlag[port] == MODULE_RANGECHECK) {
+ else if (moduleSettings[EXTERNAL_MODULE].mode == MODULE_MODE_RANGECHECK) {
dsmDat[0] |= DSM2_SEND_RANGECHECK;
}
#endif
- dsmDat[1] = g_model.header.modelId[port]; // DSM2 Header second byte for model match
+ dsmDat[1] = g_model.header.modelId[EXTERNAL_MODULE]; // DSM2 Header second byte for model match
for (int i=0; i>5)+512, 1023);
dsmDat[2+2*i] = (i<<2) | ((pulse>>8)&0x03);
diff --git a/radio/src/pulses/modules.h b/radio/src/pulses/modules.h
index f15a9968c..d73f367dd 100644
--- a/radio/src/pulses/modules.h
+++ b/radio/src/pulses/modules.h
@@ -22,6 +22,7 @@
#define _MODULES_H_
#include "myeeprom.h"
+#include "bitfield.h"
#define CROSSFIRE_CHANNELS_COUNT 16
@@ -47,17 +48,21 @@ inline bool isModuleMultimoduleDSM2(uint8_t)
}
#endif
-#if defined(PCBHORUS) || defined(PCBTARANIS)
inline bool isModuleXJT(uint8_t idx)
{
return g_model.moduleData[idx].type == MODULE_TYPE_XJT;
}
-#else
-inline bool isModuleXJT(uint8_t idx)
+
+inline bool isModuleXJT2(uint8_t idx)
{
- return idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_XJT;
+ return g_model.moduleData[idx].type == MODULE_TYPE_XJT2;
}
-#endif
+
+inline bool isModuleXJTVariant(uint8_t idx)
+{
+ return g_model.moduleData[idx].type == MODULE_TYPE_XJT || g_model.moduleData[idx].type == MODULE_TYPE_XJT2;
+}
+
#if defined(CROSSFIRE)
inline bool isModuleCrossfire(uint8_t idx)
@@ -86,24 +91,28 @@ inline bool isExtraModule(uint8_t)
#if defined(TARANIS_INTERNAL_PPM)
inline bool isModulePPM(uint8_t idx)
{
- return idx == TRAINER_MODULE ||
- (idx == INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_PPM) ||
- (idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM));
+ return (idx == INTERNAL_MODULE && g_model.moduleData[INTERNAL_MODULE].type == MODULE_TYPE_PPM) ||
+ (idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM);
}
#else
inline bool isModulePPM(uint8_t idx)
{
- return idx == TRAINER_MODULE ||
- isExtraModule(idx) ||
+ return isExtraModule(idx) ||
(idx == EXTERNAL_MODULE && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM);
}
#endif
inline bool isModuleR9M(uint8_t idx)
{
- return g_model.moduleData[idx].type == MODULE_TYPE_R9M;
+ return g_model.moduleData[idx].type == MODULE_TYPE_R9M || g_model.moduleData[idx].type == MODULE_TYPE_R9M_LITE;
}
+inline bool isModuleR9M2(uint8_t idx)
+{
+ return g_model.moduleData[idx].type == MODULE_TYPE_R9M2 || g_model.moduleData[idx].type == MODULE_TYPE_R9M_LITE2 || g_model.moduleData[idx].type == MODULE_TYPE_R9M_LITE_PRO2;
+}
+
+#if defined(PCBXLITE)
inline bool isModuleR9M_FCC(uint8_t idx)
{
return isModuleR9M(idx) && g_model.moduleData[idx].subType == MODULE_SUBTYPE_R9M_FCC;
@@ -128,13 +137,43 @@ inline bool isModuleR9M_AU_PLUS(uint8_t idx)
{
return isModuleR9M(idx) && g_model.moduleData[idx].subType != MODULE_SUBTYPE_R9M_AUPLUS;
}
+#else
+inline bool isModuleR9M_FCC(uint8_t idx)
+{
+ return isModuleR9M(idx) && g_model.moduleData[idx].r9m.region == MODULE_R9M_REGION_FCC;
+}
+inline bool isModuleR9M_LBT(uint8_t idx)
+{
+ return isModuleR9M(idx) && g_model.moduleData[idx].r9m.region == MODULE_R9M_REGION_EU;
+}
+
+inline bool isModuleR9M_FCC_VARIANT(uint8_t idx)
+{
+ return isModuleR9M(idx) && g_model.moduleData[idx].r9m.region != MODULE_R9M_REGION_EU;
+}
+
+inline bool isModuleR9M_EUPLUS(uint8_t idx)
+{
+ return isModuleR9M(idx) && g_model.moduleData[idx].r9m.region == MODULE_R9M_REGION_FLEX && g_model.moduleData[idx].r9m.freq == MODULE_R9M_FREQ_868MHZ;
+}
+
+inline bool isModuleR9M_AU_PLUS(uint8_t idx)
+{
+ return isModuleR9M(idx) && g_model.moduleData[idx].r9m.region == MODULE_R9M_REGION_FLEX && g_model.moduleData[idx].r9m.freq == MODULE_R9M_FREQ_915MHZ;
+}
+#endif
inline bool isModulePXX(uint8_t idx)
{
return isModuleXJT(idx) || isModuleR9M(idx);
}
+inline bool isModulePXX2(uint8_t idx)
+{
+ return isModuleXJT2(idx) || isModuleR9M2(idx);
+}
+
#if defined(DSM2)
inline bool isModuleDSM2(uint8_t idx)
{
@@ -152,8 +191,8 @@ inline bool isModuleDSM2(uint8_t idx)
}
#endif
-// order is the same as in enum Protocols in myeeprom.h (none, ppm, pxx, dsm, crossfire, multi, r9m, sbus)
-static const int8_t maxChannelsModules[] = { 0, 8, 8, -2, 8, 4, 8, 8}; // relative to 8!
+// order is the same as in enum Protocols in myeeprom.h (none, ppm, pxx, pxx2, dsm, crossfire, multi, r9m, r9m2, sbus)
+static const int8_t maxChannelsModules[] = { 0, 8, 8, 16, -2, 8, 4, 8, 16, 8}; // relative to 8!
static const int8_t maxChannelsXJT[] = { 0, 8, 0, 4 }; // relative to 8!
constexpr int8_t MAX_TRAINER_CHANNELS_M8 = MAX_TRAINER_CHANNELS - 8;
@@ -163,27 +202,12 @@ inline int8_t maxModuleChannels_M8(uint8_t idx)
{
if (isExtraModule(idx))
return MAX_EXTRA_MODULE_CHANNELS_M8;
- else if (idx == TRAINER_MODULE)
- return MAX_TRAINER_CHANNELS_M8;
else if (isModuleXJT(idx))
return maxChannelsXJT[1 + g_model.moduleData[idx].rfProtocol];
else
return maxChannelsModules[g_model.moduleData[idx].type];
}
-inline int8_t maxModuleChannels(uint8_t idx)
-{
- return 8 + maxModuleChannels_M8(idx);
-}
-
-inline int8_t minModuleChannels(uint8_t idx)
-{
- if (isModuleCrossfire(idx))
- return 16;
- else
- return 1;
-}
-
inline int8_t defaultModuleChannels_M8(uint8_t idx)
{
if (isModulePPM(idx))
@@ -192,6 +216,8 @@ inline int8_t defaultModuleChannels_M8(uint8_t idx)
return 0; // 8 channels
else if (isModuleMultimoduleDSM2(idx))
return -1; // 7 channels
+ else if (isModulePXX2(idx))
+ return 8; // 16 channels
else
return maxModuleChannels_M8(idx);
}
diff --git a/radio/src/pulses/multi_arm.cpp b/radio/src/pulses/multi.cpp
similarity index 87%
rename from radio/src/pulses/multi_arm.cpp
rename to radio/src/pulses/multi.cpp
index cb15c1e01..4465a9c08 100644
--- a/radio/src/pulses/multi_arm.cpp
+++ b/radio/src/pulses/multi.cpp
@@ -57,7 +57,7 @@ static void sendFailsafeChannels(uint8_t port)
uint8_t bitsavailable = 0;
for (int i = 0; i < MULTI_CHANS; i++) {
- int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[i];
+ int16_t failsafeValue = g_model.failsafeChannels[i];
int pulseValue;
if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD)
failsafeValue = FAILSAFE_CHANNEL_HOLD;
@@ -86,31 +86,31 @@ static void sendFailsafeChannels(uint8_t port)
}
}
-void setupPulsesMultimodule(uint8_t port)
+void setupPulsesMultimodule()
{
static int counter = 0;
#if defined(PPM_PIN_SERIAL)
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0 ;
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0 ;
+ extmodulePulsesData.dsm2.serialByte = 0 ;
+ extmodulePulsesData.dsm2.serialBitCount = 0 ;
#else
- modulePulsesData[EXTERNAL_MODULE].dsm2.rest = multiSyncStatus.getAdjustedRefreshRate();
- modulePulsesData[EXTERNAL_MODULE].dsm2.index = 0;
+ extmodulePulsesData.dsm2.rest = multiSyncStatus.getAdjustedRefreshRate();
+ extmodulePulsesData.dsm2.index = 0;
#endif
- modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
+ extmodulePulsesData.dsm2.ptr = extmodulePulsesData.dsm2.pulses;
// Every 1000 cycles (=9s) send a config packet that configures the multimodule (inversion, telemetry type)
counter++;
if (counter % 1000== 500) {
sendSetupFrame();
- } else if (counter % 1000 == 0 && g_model.moduleData[port].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[port].failsafeMode != FAILSAFE_RECEIVER) {
- sendFrameProtocolHeader(port, true);
- sendFailsafeChannels(port);
+ } else if (counter % 1000 == 0 && g_model.moduleData[EXTERNAL_MODULE].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[EXTERNAL_MODULE].failsafeMode != FAILSAFE_RECEIVER) {
+ sendFrameProtocolHeader(EXTERNAL_MODULE, true);
+ sendFailsafeChannels(EXTERNAL_MODULE);
} else {
// Normal Frame
- sendFrameProtocolHeader(port, false);
- sendChannels(port);
+ sendFrameProtocolHeader(EXTERNAL_MODULE, false);
+ sendChannels(EXTERNAL_MODULE);
}
putDsm2Flush();
@@ -152,16 +152,16 @@ void sendFrameProtocolHeader(uint8_t port, bool failsafe)
int8_t optionValue = g_model.moduleData[port].multi.optionValue;
uint8_t protoByte = 0;
- if (moduleFlag[port] == MODULE_BIND)
+ if (moduleSettings[port].mode == MODULE_MODE_BIND)
protoByte |= MULTI_SEND_BIND;
- else if (moduleFlag[port] == MODULE_RANGECHECK)
+ else if (moduleSettings[port].mode == MODULE_MODE_RANGECHECK)
protoByte |= MULTI_SEND_RANGECHECK;
// rfProtocol
if (g_model.moduleData[port].getMultiProtocol(true) == MM_RF_PROTO_DSM2) {
// Autobinding should always be done in DSMX 11ms
- if (g_model.moduleData[port].multi.autoBindMode && moduleFlag[port] == MODULE_BIND)
+ if (g_model.moduleData[port].multi.autoBindMode && moduleSettings[port].mode == MODULE_MODE_BIND)
subtype = MM_RF_DSM2_SUBTYPE_AUTO;
// Multi module in DSM mode wants the number of channels to be used as option value
diff --git a/radio/src/pulses/ppm_arm.cpp b/radio/src/pulses/ppm.cpp
similarity index 61%
rename from radio/src/pulses/ppm_arm.cpp
rename to radio/src/pulses/ppm.cpp
index 04b8f50c7..561f4ba03 100644
--- a/radio/src/pulses/ppm_arm.cpp
+++ b/radio/src/pulses/ppm.cpp
@@ -21,7 +21,7 @@
#include "opentx.h"
template
-void setupPulsesPPM(uint8_t port, PpmPulsesData * ppmPulsesData)
+void setupPulsesPPM(PpmPulsesData * ppmPulsesData, uint8_t channelsStart, int8_t channelsCount, int8_t frameLength)
{
int16_t PPM_range = g_model.extendedLimits ? (512*LIMIT_EXT_PERCENT/100) * 2 : 512 * 2; // range of 0.7 .. 1.7msec
@@ -29,8 +29,8 @@ void setupPulsesPPM(uint8_t port, PpmPulsesData * ppmPulsesData)
// each pulse is 0.7..1.7ms long with a 0.3ms stop tail
// The pulse ISR is 2mhz that's why everything is multiplied by 2
- uint32_t firstCh = g_model.moduleData[port].channelsStart;
- uint32_t lastCh = min(MAX_OUTPUT_CHANNELS, firstCh + 8 + g_model.moduleData[port].channelsCount);
+ uint8_t firstCh = channelsStart;
+ uint8_t lastCh = min(MAX_OUTPUT_CHANNELS, firstCh + 8 + channelsCount);
#if defined(STM32)
ppmPulsesData->ptr = ppmPulsesData->pulses;
@@ -40,7 +40,7 @@ void setupPulsesPPM(uint8_t port, PpmPulsesData * ppmPulsesData)
#endif
int32_t rest = 22500u * 2;
- rest += (int32_t(g_model.moduleData[port].ppm.frameLength)) * 1000;
+ rest += int32_t(frameLength) * 1000;
for (uint32_t i=firstCh; i * ppmPulsesData)
rest = limit(9000, rest, 65535); /* avoids that CCR2 is bigger than ARR which would cause reboot */
#if defined(STM32)
*ppmPulsesData->ptr++ = rest;
+ *ppmPulsesData->ptr = 0; // it's needed in case PPM is sent without DMA (we stop when we reach this 0)
#else
*ptr = rest;
*(ptr + 1) = 0;
#endif
}
-void setupPulsesPPMModule(uint8_t port)
-{
- setupPulsesPPM(port, &modulePulsesData[port].ppm);
-}
-
void setupPulsesPPMTrainer()
{
- setupPulsesPPM(TRAINER_MODULE, &trainerPulsesData.ppm);
+ setupPulsesPPM(&trainerPulsesData.ppm, g_model.trainerData.channelsStart, g_model.trainerData.channelsCount, g_model.trainerData.frameLength);
}
+
+#if defined(PCBTARANIS) && defined(TARANIS_INTERNAL_PPM)
+void setupPulsesPPMInternalModule()
+{
+ setupPulsesPPM(&intmodulePulsesData.ppm, g_model.moduleData[INTERNAL_MODULE].channelsStart, g_model.moduleData[INTERNAL_MODULE].channelsCount, g_model.moduleData[INTERNAL_MODULE].ppm.frameLength);
+}
+#endif
+
+void setupPulsesPPMExternalModule()
+{
+ setupPulsesPPM(&extmodulePulsesData.ppm, g_model.moduleData[EXTERNAL_MODULE].channelsStart, g_model.moduleData[EXTERNAL_MODULE].channelsCount, g_model.moduleData[EXTERNAL_MODULE].ppm.frameLength);
+}
+
+
diff --git a/radio/src/pulses/pulses.cpp b/radio/src/pulses/pulses.cpp
new file mode 100755
index 000000000..c0679b01b
--- /dev/null
+++ b/radio/src/pulses/pulses.cpp
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "opentx.h"
+#include "io/frsky_pxx2.h"
+#include "pulses/pxx2.h"
+
+uint8_t s_pulses_paused = 0;
+ModuleSettings moduleSettings[NUM_MODULES];
+InternalModulePulsesData intmodulePulsesData __DMA;
+ExternalModulePulsesData extmodulePulsesData __DMA;
+TrainerPulsesData trainerPulsesData __DMA;
+
+uint8_t getModuleType(uint8_t module)
+{
+ uint8_t type = g_model.moduleData[module].type;
+
+#if defined(HARDWARE_INTERNAL_MODULE)
+ if (module == INTERNAL_MODULE && isInternalModuleAvailable(type)) {
+ return type;
+ }
+#endif
+
+ if (module == EXTERNAL_MODULE && isExternalModuleAvailable(type)) {
+ return type;
+ }
+
+ return MODULE_TYPE_NONE;
+}
+
+uint8_t getRequiredProtocol(uint8_t module)
+{
+ uint8_t protocol;
+
+ switch (getModuleType(module)) {
+ case MODULE_TYPE_PPM:
+ protocol = PROTOCOL_CHANNELS_PPM;
+ break;
+
+ case MODULE_TYPE_XJT:
+#if defined(INTMODULE_USART)
+ if (module == INTERNAL_MODULE) {
+ protocol = PROTOCOL_CHANNELS_PXX1_SERIAL;
+ break;
+ }
+#endif
+ // no break
+
+ case MODULE_TYPE_R9M:
+ protocol = PROTOCOL_CHANNELS_PXX1_PULSES;
+ break;
+
+ case MODULE_TYPE_R9M_LITE:
+ protocol = PROTOCOL_CHANNELS_PXX1_SERIAL;
+ break;
+
+ case MODULE_TYPE_XJT2:
+ case MODULE_TYPE_R9M2:
+ case MODULE_TYPE_R9M_LITE2:
+ case MODULE_TYPE_R9M_LITE_PRO2:
+ protocol = PROTOCOL_CHANNELS_PXX2;
+ break;
+
+ case MODULE_TYPE_SBUS:
+ protocol = PROTOCOL_CHANNELS_SBUS;
+ break;
+
+#if defined(MULTIMODULE)
+ case MODULE_TYPE_MULTIMODULE:
+ protocol = PROTOCOL_CHANNELS_MULTIMODULE;
+ break;
+#endif
+
+#if defined(DSM2)
+ case MODULE_TYPE_DSM2:
+ protocol = limit(PROTOCOL_CHANNELS_DSM2_LP45, PROTOCOL_CHANNELS_DSM2_LP45+g_model.moduleData[module].rfProtocol, PROTOCOL_CHANNELS_DSM2_DSMX);
+ // The module is set to OFF during one second before BIND start
+ {
+ static tmr10ms_t bindStartTime = 0;
+ if (moduleSettings[module].mode == MODULE_MODE_BIND) {
+ if (bindStartTime == 0) bindStartTime = get_tmr10ms();
+ if ((tmr10ms_t)(get_tmr10ms() - bindStartTime) < 100) {
+ protocol = PROTOCOL_CHANNELS_NONE;
+ break;
+ }
+ }
+ else {
+ bindStartTime = 0;
+ }
+ }
+ break;
+#endif
+
+#if defined(CROSSFIRE)
+ case MODULE_TYPE_CROSSFIRE:
+ protocol = PROTOCOL_CHANNELS_CROSSFIRE;
+ break;
+#endif
+
+ default:
+ protocol = PROTOCOL_CHANNELS_NONE;
+ break;
+ }
+
+ if (s_pulses_paused) {
+ protocol = PROTOCOL_CHANNELS_NONE;
+ }
+
+#if 0
+ // will need an EEPROM conversion
+ if (moduleSettings[module].mode == MODULE_OFF) {
+ protocol = PROTOCOL_CHANNELS_NONE;
+ }
+#endif
+
+ return protocol;
+}
+
+void disablePulses(uint8_t module, uint8_t protocol)
+{
+ // stop existing protocol hardware
+
+ switch (protocol) {
+#if defined(PXX1)
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
+ disable_pxx1_pulses(module);
+ break;
+
+#if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
+ case PROTOCOL_CHANNELS_PXX1_SERIAL:
+ disable_pxx1_serial(module);
+ break;
+#endif
+#endif
+
+#if defined(DSM2)
+ case PROTOCOL_CHANNELS_DSM2_LP45:
+ case PROTOCOL_CHANNELS_DSM2_DSM2:
+ case PROTOCOL_CHANNELS_DSM2_DSMX:
+ disable_serial(module);
+ break;
+#endif
+
+#if defined(CROSSFIRE)
+ case PROTOCOL_CHANNELS_CROSSFIRE:
+ // TODO disable_module_timer(module);
+ break;
+#endif
+
+#if defined(PXX2)
+ case PROTOCOL_CHANNELS_PXX2:
+ disable_pxx2(module);
+ break;
+#endif
+
+#if defined(MULTIMODULE)
+ case PROTOCOL_CHANNELS_MULTIMODULE:
+#endif
+ case PROTOCOL_CHANNELS_SBUS:
+ disable_serial(module);
+ break;
+
+ case PROTOCOL_CHANNELS_PPM:
+ disable_ppm(module);
+ break;
+ }
+}
+
+void enablePulses(uint8_t module, uint8_t protocol)
+{
+ // start new protocol hardware here
+
+ switch (protocol) {
+#if defined(PXX1)
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
+ init_pxx1_pulses(module);
+ break;
+
+#if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
+ case PROTOCOL_CHANNELS_PXX1_SERIAL:
+ init_pxx1_serial(module);
+ break;
+#endif
+#endif
+
+#if defined(DSM2)
+ case PROTOCOL_CHANNELS_DSM2_LP45:
+ case PROTOCOL_CHANNELS_DSM2_DSM2:
+ case PROTOCOL_CHANNELS_DSM2_DSMX:
+ init_serial(module, DSM2_BAUDRATE, DSM2_PERIOD * 2000);
+ break;
+#endif
+
+#if defined(CROSSFIRE)
+ case PROTOCOL_CHANNELS_CROSSFIRE:
+ // TODO init_module_timer(module, CROSSFIRE_PERIOD, true);
+ break;
+#endif
+
+#if defined(PXX2)
+ case PROTOCOL_CHANNELS_PXX2:
+ init_pxx2(module);
+ break;
+#endif
+
+#if defined(MULTIMODULE)
+ case PROTOCOL_CHANNELS_MULTIMODULE:
+ init_serial(module, MULTIMODULE_BAUDRATE, MULTIMODULE_PERIOD * 2000);
+ break;
+#endif
+
+ case PROTOCOL_CHANNELS_SBUS:
+ init_serial(module, SBUS_BAUDRATE, SBUS_PERIOD_HALF_US);
+ break;
+
+ case PROTOCOL_CHANNELS_PPM:
+ init_ppm(module);
+ break;
+ }
+}
+
+void setupPulsesInternalModule(uint8_t protocol)
+{
+ switch (protocol) {
+#if defined(HARDWARE_INTERNAL_MODULE) && defined(PXX1) && !defined(INTMODULE_USART)
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
+ intmodulePulsesData.pxx.setupFrame(INTERNAL_MODULE);
+ scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX_PERIOD);
+ break;
+#endif
+
+#if defined(PXX1) && defined(INTMODULE_USART)
+ case PROTOCOL_CHANNELS_PXX1_SERIAL:
+ intmodulePulsesData.pxx_uart.setupFrame(INTERNAL_MODULE);
+ scheduleNextMixerCalculation(INTERNAL_MODULE, INTMODULE_PXX_PERIOD);
+ break;
+#endif
+
+#if defined(PXX2)
+ case PROTOCOL_CHANNELS_PXX2:
+ intmodulePulsesData.pxx2.setupFrame(INTERNAL_MODULE);
+ scheduleNextMixerCalculation(INTERNAL_MODULE, moduleSettings[INTERNAL_MODULE].mode == MODULE_MODE_SPECTRUM_ANALYSER || moduleSettings[INTERNAL_MODULE].mode == MODULE_MODE_POWER_METER ? 1 : PXX2_PERIOD);
+ break;
+#endif
+
+#if defined(PCBTARANIS) && defined(TARANIS_INTERNAL_PPM)
+ case PROTOCOL_CHANNELS_PPM:
+ setupPulsesPPM(&extmodulePulsesData.ppm, g_model.moduleData[INTERNAL_MODULE].channelsStart, g_model.moduleData[INTERNAL_MODULE].channelsCount, g_model.moduleData[INTERNAL_MODULE].ppm.frameLength);
+ scheduleNextMixerCalculation(INTERNAL_MODULE, PPM_PERIOD(INTERNAL_MODULE));
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
+
+void setupPulsesExternalModule(uint8_t protocol)
+{
+ switch (protocol) {
+#if defined(PXX1)
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
+ extmodulePulsesData.pxx.setupFrame(EXTERNAL_MODULE);
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX_PULSES_PERIOD);
+ break;
+#endif
+
+#if defined(PXX1) && defined(EXTMODULE_USART)
+ case PROTOCOL_CHANNELS_PXX1_SERIAL:
+ extmodulePulsesData.pxx_uart.setupFrame(EXTERNAL_MODULE);
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, EXTMODULE_PXX_SERIAL_PERIOD);
+ break;
+#endif
+
+#if defined(PXX2)
+ case PROTOCOL_CHANNELS_PXX2:
+ extmodulePulsesData.pxx2.setupFrame(EXTERNAL_MODULE);
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, PXX2_PERIOD);
+ break;
+#endif
+
+ case PROTOCOL_CHANNELS_SBUS:
+ setupPulsesSbus();
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, SBUS_PERIOD);
+ break;
+
+#if defined(DSM2)
+ case PROTOCOL_CHANNELS_DSM2_LP45:
+ case PROTOCOL_CHANNELS_DSM2_DSM2:
+ case PROTOCOL_CHANNELS_DSM2_DSMX:
+ setupPulsesDSM2();
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, DSM2_PERIOD);
+ break;
+#endif
+
+#if defined(CROSSFIRE)
+ case PROTOCOL_CHANNELS_CROSSFIRE:
+ setupPulsesCrossfire();
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, CROSSFIRE_PERIOD);
+ break;
+#endif
+
+#if defined(MULTIMODULE)
+ case PROTOCOL_CHANNELS_MULTIMODULE:
+ setupPulsesMultimodule();
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, MULTIMODULE_PERIOD);
+ break;
+#endif
+
+ case PROTOCOL_CHANNELS_PPM:
+ setupPulsesPPMExternalModule();
+ scheduleNextMixerCalculation(EXTERNAL_MODULE, PPM_PERIOD(EXTERNAL_MODULE));
+ break;
+
+ default:
+ break;
+ }
+}
+
+void setupPulses(uint8_t module, uint8_t protocol)
+{
+ switch (module) {
+#if defined(HARDWARE_INTERNAL_MODULE)
+ case INTERNAL_MODULE:
+ setupPulsesInternalModule(protocol);
+ break;
+#endif
+
+ case EXTERNAL_MODULE:
+ setupPulsesExternalModule(protocol);
+ break;
+ }
+}
+
+bool setupPulses(uint8_t module)
+{
+ uint8_t protocol = getRequiredProtocol(module);
+
+ heartbeat |= (HEART_TIMER_PULSES << module);
+
+ if (moduleSettings[module].protocol != protocol) {
+ disablePulses(module, moduleSettings[module].protocol);
+ moduleSettings[module].protocol = protocol;
+ enablePulses(module, protocol);
+ return false;
+ }
+ else {
+ setupPulses(module, protocol);
+ return true;
+ }
+}
+
+void setCustomFailsafe(uint8_t moduleIndex)
+{
+ if (moduleIndex < NUM_MODULES) {
+ for (int ch=0; ch= sentModuleChannels(moduleIndex) + g_model.moduleData[moduleIndex].channelsStart) {
+ g_model.failsafeChannels[ch] = 0;
+ }
+ else if (g_model.failsafeChannels[ch] < FAILSAFE_CHANNEL_HOLD) {
+ g_model.failsafeChannels[ch] = channelOutputs[ch];
+ }
+ }
+ }
+}
diff --git a/radio/src/pulses/pulses.h b/radio/src/pulses/pulses.h
index 6a0739149..405956259 100644
--- a/radio/src/pulses/pulses.h
+++ b/radio/src/pulses/pulses.h
@@ -21,37 +21,25 @@
#ifndef _PULSES_H_
#define _PULSES_H_
-enum ModuleFlag
-{
- MODULE_NORMAL_MODE,
- MODULE_RANGECHECK,
- MODULE_BIND,
- // MODULE_OFF, // will need an EEPROM conversion
-};
-
- extern uint8_t moduleFlag[NUM_MODULES];
+#include "definitions.h"
+#include "dataconstants.h"
+#include "pulses_common.h"
+#include "pulses/pxx1.h"
+#include "pulses/pxx2.h"
#if NUM_MODULES > 1
- #define IS_RANGECHECK_ENABLE() (moduleFlag[0] == MODULE_RANGECHECK || moduleFlag[1] == MODULE_RANGECHECK)
+ #define IS_RANGECHECK_ENABLE() (moduleSettings[0].mode == MODULE_MODE_RANGECHECK || moduleSettings[1].mode == MODULE_MODE_RANGECHECK)
#else
- #define IS_RANGECHECK_ENABLE() (moduleFlag[0] == MODULE_RANGECHECK)
+ #define IS_RANGECHECK_ENABLE() (moduleSettings[0].mode == MODULE_MODE_RANGECHECK)
#endif
-#if defined(DSM2) && !defined(PCBTARANIS)
+#if defined(PCBSKY9X) && defined(DSM2)
#define DSM2_BIND_TIMEOUT 255 // 255*11ms
extern uint8_t dsm2BindTimer;
#endif
- #define IS_PPM_PROTOCOL(protocol) (protocol==PROTO_PPM)
-
-#if defined(PXX)
- #define IS_PXX_PROTOCOL(protocol) (protocol==PROTO_PXX)
-#else
- #define IS_PXX_PROTOCOL(protocol) (0)
-#endif
-
#if defined(DSM2)
- #define IS_DSM2_PROTOCOL(protocol) (protocol>=PROTO_DSM2_LP45 && protocol<=PROTO_DSM2_DSMX)
+ #define IS_DSM2_PROTOCOL(protocol) (protocol>=PROTOCOL_CHANNELS_DSM2_LP45 && protocol<=PROTOCOL_CHANNELS_DSM2_DSMX)
#else
#define IS_DSM2_PROTOCOL(protocol) (0)
#endif
@@ -63,7 +51,7 @@ enum ModuleFlag
#endif
#if defined(MULTIMODULE)
- #define IS_MULTIMODULE_PROTOCOL(protocol) (protocol==PROTO_MULTIMODULE)
+ #define IS_MULTIMODULE_PROTOCOL(protocol) (protocol==PROTOCOL_CHANNELS_MULTIMODULE)
#if !defined(DSM2)
#error You need to enable DSM2 = PPM for MULTIMODULE support
#endif
@@ -71,9 +59,258 @@ enum ModuleFlag
#define IS_MULTIMODULE_PROTOCOL(protocol) (0)
#endif
- #define IS_SBUS_PROTOCOL(protocol) (protocol == PROTO_SBUS)
+#define IS_SBUS_PROTOCOL(protocol) (protocol == PROTOCOL_CHANNELS_SBUS)
+
+extern uint8_t s_pulses_paused;
+
+enum ModuleSettingsMode
+{
+ MODULE_MODE_NORMAL,
+ MODULE_MODE_SPECTRUM_ANALYSER,
+ MODULE_MODE_POWER_METER,
+ MODULE_MODE_GET_HARDWARE_INFO,
+ MODULE_MODE_MODULE_SETTINGS,
+ MODULE_MODE_RECEIVER_SETTINGS,
+ MODULE_MODE_BEEP_FIRST,
+ MODULE_MODE_REGISTER = MODULE_MODE_BEEP_FIRST,
+ MODULE_MODE_BIND,
+ MODULE_MODE_SHARE,
+ MODULE_MODE_RANGECHECK,
+};
+
+PACK(struct ModuleSettings {
+ uint8_t protocol:4;
+ uint8_t mode:4;
+ uint8_t paused:1;
+ uint8_t spare:7;
+ uint16_t counter;
+});
+
+extern ModuleSettings moduleSettings[NUM_MODULES];
+
+template struct PpmPulsesData {
+ T pulses[20];
+ T * ptr;
+};
+
+#if defined(PPM_PIN_SERIAL)
+PACK(struct Dsm2SerialPulsesData {
+ uint8_t pulses[64];
+ uint8_t * ptr;
+ uint8_t serialByte ;
+ uint8_t serialBitCount;
+ uint16_t _alignment;
+});
+typedef Dsm2SerialPulsesData Dsm2PulsesData;
+#else
+#define MAX_PULSES_TRANSITIONS 300
+PACK(struct Dsm2TimerPulsesData {
+ pulse_duration_t pulses[MAX_PULSES_TRANSITIONS];
+ pulse_duration_t * ptr;
+ uint16_t rest;
+ uint8_t index;
+});
+typedef Dsm2TimerPulsesData Dsm2PulsesData;
+#endif
+
+#define PPM_PERIOD_HALF_US(module) ((g_model.moduleData[module].ppm.frameLength * 5 + 225) * 200) /*half us*/
+#define PPM_PERIOD(module) (PPM_PERIOD_HALF_US(module) / 2000) /*ms*/
+#define DSM2_BAUDRATE 125000
+#define DSM2_PERIOD 22 /*ms*/
+#define SBUS_BAUDRATE 100000
+#define SBUS_PERIOD_HALF_US ((g_model.moduleData[EXTERNAL_MODULE].sbus.refreshRate * 5 + 225) * 200) /*half us*/
+#define SBUS_PERIOD (SBUS_PERIOD_HALF_US / 2000) /*ms*/
+#define MULTIMODULE_BAUDRATE 100000
+#define MULTIMODULE_PERIOD 7 /*ms*/
+
+#define CROSSFIRE_FRAME_MAXLEN 64
+PACK(struct CrossfirePulsesData {
+ uint8_t pulses[CROSSFIRE_FRAME_MAXLEN];
+ uint8_t length;
+});
+
+union InternalModulePulsesData {
+#if defined(PXX1)
+ #if defined(INTMODULE_USART)
+ UartPxx1Pulses pxx_uart;
+ #else
+ PwmPxx1Pulses pxx;
+ #endif
+#endif
+
+#if defined(PXX2)
+ Pxx2Pulses pxx2;
+#endif
+
+#if defined(TARANIS_INTERNAL_PPM)
+ PpmPulsesData ppm;
+#endif
+} __ALIGNED(4);
+
+union ExternalModulePulsesData {
+#if defined(PXX1)
+ #if defined(EXTMODULE_USART)
+ UartPxx1Pulses pxx_uart;
+ #endif
+ #if defined(PPM_PIN_SERIAL)
+ SerialPxx1Pulses pxx;
+ #else
+ PwmPxx1Pulses pxx;
+ #endif
+#endif
+
+#if defined(PXX2)
+ Pxx2Pulses pxx2;
+#endif
+
+#if defined(DSM2) || defined(MULTIMODULE) || defined(SBUS)
+ Dsm2PulsesData dsm2;
+#endif
+
+ PpmPulsesData ppm;
+
+ CrossfirePulsesData crossfire;
+} __ALIGNED(4);
+
+/* The __ALIGNED keyword is required to align the struct inside the modulePulsesData below,
+ * which is also defined to be __DMA (which includes __ALIGNED) aligned.
+ * Arrays in C/C++ are always defined to be *contiguously*. The first byte of the second element is therefore always
+ * sizeof(ModulePulsesData). __ALIGNED is required for sizeof(ModulePulsesData) to be a multiple of the alignment.
+ */
- #include "pulses_arm.h"
+extern InternalModulePulsesData intmodulePulsesData;
+extern ExternalModulePulsesData extmodulePulsesData;
+
+union TrainerPulsesData {
+ PpmPulsesData ppm;
+};
+
+extern TrainerPulsesData trainerPulsesData;
+
+bool setupPulses(uint8_t module);
+void setupPulsesDSM2();
+void setupPulsesCrossfire();
+void setupPulsesMultimodule();
+void setupPulsesSbus();
+void setupPulsesPPMInternalModule();
+void setupPulsesPPMExternalModule();
+void setupPulsesPPMTrainer();
+void sendByteDsm2(uint8_t b);
+void putDsm2Flush();
+void putDsm2SerialBit(uint8_t bit);
+void sendByteSbus(uint8_t b);
+
+#if defined(HUBSAN)
+void Hubsan_Init();
+#endif
+
+inline void startPulses()
+{
+ s_pulses_paused = false;
+
+#if defined(PCBTARANIS) || defined(PCBHORUS)
+ setupPulses(INTERNAL_MODULE);
+ setupPulses(EXTERNAL_MODULE);
+#else
+ setupPulses(EXTERNAL_MODULE);
+#endif
+
+#if defined(HUBSAN)
+ Hubsan_Init();
+#endif
+}
+
+enum ChannelsProtocols {
+ PROTOCOL_CHANNELS_UNINITIALIZED,
+ PROTOCOL_CHANNELS_NONE,
+ PROTOCOL_CHANNELS_PPM,
+#if defined(PXX) || defined(DSM2)
+ PROTOCOL_CHANNELS_PXX1_PULSES,
+ PROTOCOL_CHANNELS_PXX1_SERIAL,
+#endif
+#if defined(DSM2)
+ PROTOCOL_CHANNELS_DSM2_LP45,
+ PROTOCOL_CHANNELS_DSM2_DSM2,
+ PROTOCOL_CHANNELS_DSM2_DSMX,
+#endif
+ PROTOCOL_CHANNELS_CROSSFIRE,
+ PROTOCOL_CHANNELS_MULTIMODULE,
+ PROTOCOL_CHANNELS_SBUS,
+ PROTOCOL_CHANNELS_PXX2
+};
+
+inline bool pulsesStarted() { return moduleSettings[0].protocol != PROTOCOL_CHANNELS_UNINITIALIZED; }
+inline void pausePulses() { s_pulses_paused = true; }
+inline void resumePulses() { s_pulses_paused = false; }
+
+#define SEND_FAILSAFE_NOW(idx) moduleSettings[idx].counter = 1
+
+inline void SEND_FAILSAFE_1S()
+{
+ for (int i=0; i(PROTO_DSM2_LP45, PROTO_DSM2_LP45+g_model.moduleData[EXTERNAL_MODULE].rfProtocol, PROTO_DSM2_DSMX);
- // The module is set to OFF during one second before BIND start
- {
- static tmr10ms_t bindStartTime = 0;
- if (moduleFlag[EXTERNAL_MODULE] == MODULE_BIND) {
- if (bindStartTime == 0) bindStartTime = get_tmr10ms();
- if ((tmr10ms_t)(get_tmr10ms() - bindStartTime) < 100) {
- required_protocol = PROTO_NONE;
- break;
- }
- }
- else {
- bindStartTime = 0;
- }
- }
- break;
-#endif
-#if defined(CROSSFIRE)
- case MODULE_TYPE_CROSSFIRE:
- required_protocol = PROTO_CROSSFIRE;
- break;
-#endif
- default:
- required_protocol = PROTO_NONE;
- break;
- }
- break;
- }
-
- if (s_pulses_paused) {
- required_protocol = PROTO_NONE;
- }
-
-#if 0
- // will need an EEPROM conversion
- if (moduleFlag[port] == MODULE_OFF) {
- required_protocol = PROTO_NONE;
- }
-#endif
-
- return required_protocol;
-}
-
-void setupPulsesPXX(uint8_t port)
-{
-#if defined(INTMODULE_USART) && defined(EXTMODULE_USART)
- modulePulsesData[port].pxx_uart.setupFrame(port);
-#elif !defined(INTMODULE_USART) && !defined(EXTMODULE_USART)
- modulePulsesData[port].pxx.setupFrame(port);
-#else
- if (IS_UART_MODULE(port))
- modulePulsesData[port].pxx_uart.setupFrame(port);
- else
- modulePulsesData[port].pxx.setupFrame(port);
-#endif
-}
-
-void setupPulses(uint8_t port)
-{
- bool init_needed = false;
- uint8_t required_protocol = getRequiredProtocol(port);
-
- heartbeat |= (HEART_TIMER_PULSES << port);
-
- if (s_current_protocol[port] != required_protocol) {
- init_needed = true;
- switch (s_current_protocol[port]) { // stop existing protocol hardware
- case PROTO_PXX:
- disable_pxx(port);
- break;
-
-#if defined(DSM2)
- case PROTO_DSM2_LP45:
- case PROTO_DSM2_DSM2:
- case PROTO_DSM2_DSMX:
- disable_serial(port);
- break;
-#endif
-
-#if defined(CROSSFIRE)
- case PROTO_CROSSFIRE:
- disable_module_timer(port);
- break;
-#endif
-
-#if defined(PXX2)
- case PROTO_PXX2:
- disable_module_timer(port);
- break;
-#endif
-
-#if defined(MULTIMODULE)
- case PROTO_MULTIMODULE:
-#endif
- case PROTO_SBUS:
- disable_serial(port);
- break;
-
- case PROTO_PPM:
- disable_ppm(port);
- break;
-
- default:
- disable_no_pulses(port);
- break;
- }
- s_current_protocol[port] = required_protocol;
- }
-
- // Set up output data here
- switch (required_protocol) {
- case PROTO_PXX:
- setupPulsesPXX(port);
- scheduleNextMixerCalculation(port, PXX_PERIOD);
- break;
-
- case PROTO_SBUS:
- setupPulsesSbus(port);
- scheduleNextMixerCalculation(port, SBUS_PERIOD);
- break;
-
-#if defined(DSM2)
- case PROTO_DSM2_LP45:
- case PROTO_DSM2_DSM2:
- case PROTO_DSM2_DSMX:
- setupPulsesDSM2(port);
- scheduleNextMixerCalculation(port, DSM2_PERIOD);
- break;
-#endif
-
-#if defined(CROSSFIRE)
- case PROTO_CROSSFIRE:
- if (telemetryProtocol == PROTOCOL_PULSES_CROSSFIRE && !init_needed) {
- uint8_t * crossfire = modulePulsesData[port].crossfire.pulses;
- uint8_t len;
-#if defined(LUA)
- if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) {
- memcpy(crossfire, outputTelemetryBuffer, outputTelemetryBufferSize);
- len = outputTelemetryBufferSize;
- outputTelemetryBufferTrigger = 0x00;
- outputTelemetryBufferSize = 0;
- }
- else
-#endif
- {
- len = createCrossfireChannelsFrame(crossfire, &channelOutputs[g_model.moduleData[port].channelsStart]);
- }
- sportSendBuffer(crossfire, len);
- }
- scheduleNextMixerCalculation(port, CROSSFIRE_PERIOD);
- break;
-#endif
-
-#if defined(PXX2)
- case PROTO_PXX2:
- if (telemetryProtocol == PROTOCOL_FRSKY_SPORT && !init_needed) {
- modulePulsesData[port].pxx2.setupFrame(port);
- sportSendBuffer(modulePulsesData[port].pxx2.getData(), modulePulsesData[port].pxx2.getSize());
- }
- scheduleNextMixerCalculation(port, PXX2_PERIOD);
- break;
-#endif
-
-#if defined(MULTIMODULE)
- case PROTO_MULTIMODULE:
- setupPulsesMultimodule(port);
- scheduleNextMixerCalculation(port, MULTIMODULE_PERIOD);
- break;
-#endif
-
- case PROTO_PPM:
-#if defined(PCBSKY9X)
- case PROTO_NONE:
-#endif
- setupPulsesPPMModule(port);
- scheduleNextMixerCalculation(port, PPM_PERIOD(port));
- break;
-
- default:
- break;
- }
-
- if (init_needed) {
- switch (required_protocol) { // Start new protocol hardware here
- case PROTO_PXX:
- init_pxx(port);
- break;
-
-#if defined(DSM2)
- case PROTO_DSM2_LP45:
- case PROTO_DSM2_DSM2:
- case PROTO_DSM2_DSMX:
- init_serial(port, DSM2_BAUDRATE, DSM2_PERIOD * 2000);
- break;
-#endif
-
-#if defined(CROSSFIRE)
- case PROTO_CROSSFIRE:
- init_module_timer(port, CROSSFIRE_PERIOD, true);
- break;
-#endif
-
-#if defined(PXX2)
- case PROTO_PXX2:
- init_module_timer(port, PXX2_PERIOD, true);
- break;
-#endif
-
-#if defined(MULTIMODULE)
- case PROTO_MULTIMODULE:
- init_serial(port, MULTIMODULE_BAUDRATE, MULTIMODULE_PERIOD * 2000);
- break;
-#endif
-
- case PROTO_SBUS:
- init_serial(port, SBUS_BAUDRATE, SBUS_PERIOD_HALF_US);
- break;
-
- case PROTO_PPM:
- init_ppm(port);
- break;
-
- default:
- init_no_pulses(port);
- break;
- }
- }
-}
-
-void setCustomFailsafe(uint8_t moduleIndex)
-{
- if (moduleIndex < NUM_MODULES) {
- for (int ch=0; ch= sentModuleChannels(moduleIndex) + g_model.moduleData[moduleIndex].channelsStart) {
- g_model.moduleData[moduleIndex].failsafeChannels[ch] = 0;
- }
- else if (g_model.moduleData[moduleIndex].failsafeChannels[ch] < FAILSAFE_CHANNEL_HOLD) {
- g_model.moduleData[moduleIndex].failsafeChannels[ch] = channelOutputs[ch];
- }
- }
- }
-}
diff --git a/radio/src/pulses/pulses_arm.h b/radio/src/pulses/pulses_arm.h
deleted file mode 100644
index fb512de85..000000000
--- a/radio/src/pulses/pulses_arm.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * Copyright (C) OpenTX
- *
- * Based on code named
- * th9x - http://code.google.com/p/th9x
- * er9x - http://code.google.com/p/er9x
- * gruvin9x - http://code.google.com/p/gruvin9x
- *
- * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * 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.
- */
-
-#ifndef _PULSES_ARM_H_
-#define _PULSES_ARM_H_
-
-#include "pulses/pxx2.h"
-#include "pulses/pxx1.h"
-
-#if NUM_MODULES == 2
- #define MODULES_INIT(...) __VA_ARGS__, __VA_ARGS__
-#else
- #define MODULES_INIT(...) __VA_ARGS__
-#endif
-
-extern uint8_t s_current_protocol[NUM_MODULES];
-extern uint8_t s_pulses_paused;
-extern uint16_t failsafeCounter[NUM_MODULES];
-
-template struct PpmPulsesData {
- T pulses[20];
- T * ptr;
-};
-
-#if defined(PPM_PIN_SERIAL)
-PACK(struct Dsm2SerialPulsesData {
- uint8_t pulses[64];
- uint8_t * ptr;
- uint8_t serialByte ;
- uint8_t serialBitCount;
- uint16_t _alignment;
-});
-#else
-#define MAX_PULSES_TRANSITIONS 300
-PACK(struct Dsm2TimerPulsesData {
- pulse_duration_t pulses[MAX_PULSES_TRANSITIONS];
- pulse_duration_t * ptr;
- uint16_t rest;
- uint8_t index;
-});
-#endif
-
-#define PPM_PERIOD_HALF_US(module) ((g_model.moduleData[module].ppm.frameLength * 5 + 225) * 200) /*half us*/
-#define PPM_PERIOD(module) (PPM_PERIOD_HALF_US(module) / 2000) /*ms*/
-#define DSM2_BAUDRATE 125000
-#define DSM2_PERIOD 22 /*ms*/
-#define SBUS_BAUDRATE 100000
-#define SBUS_PERIOD_HALF_US ((g_model.moduleData[EXTERNAL_MODULE].sbus.refreshRate * 5 + 225) * 200) /*half us*/
-#define SBUS_PERIOD (SBUS_PERIOD_HALF_US / 2000) /*ms*/
-#define MULTIMODULE_BAUDRATE 100000
-#define MULTIMODULE_PERIOD 7 /*ms*/
-
-#define CROSSFIRE_FRAME_MAXLEN 64
-PACK(struct CrossfirePulsesData {
- uint8_t pulses[CROSSFIRE_FRAME_MAXLEN];
-});
-
-union ModulePulsesData {
-#if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
- UartPxxPulses pxx_uart;
-#endif
-#if defined(PPM_PIN_SERIAL)
- SerialPxxPulses pxx;
-#elif !defined(INTMODULE_USART) || !defined(EXTMODULE_USART)
- PwmPxxPulses pxx;
-#endif
-
-#if defined(PXX2)
- Pxx2Pulses pxx2;
-#endif
-
-#if defined(PPM_PIN_SERIAL)
- Dsm2SerialPulsesData dsm2;
-#else
- Dsm2TimerPulsesData dsm2;
-#endif
-
- PpmPulsesData ppm;
- CrossfirePulsesData crossfire;
-} __ALIGNED(4);
-
-/* The __ALIGNED keyword is required to align the struct inside the modulePulsesData below,
- * which is also defined to be __DMA (which includes __ALIGNED) aligned.
- * Arrays in C/C++ are always defined to be *contiguously*. The first byte of the second element is therefore always
- * sizeof(ModulePulsesData). __ALIGNED is required for sizeof(ModulePulsesData) to be a multiple of the alignment.
- */
-
-/* TODO: internal pulsedata only needs 200 bytes vs 300 bytes for external, both use 300 byte since we have a common struct */
-extern ModulePulsesData modulePulsesData[NUM_MODULES];
-
-union TrainerPulsesData {
- PpmPulsesData ppm;
-};
-
-extern TrainerPulsesData trainerPulsesData;
-extern const uint16_t CRCTable[];
-
-void setupPulses(uint8_t port);
-void setupPulsesDSM2(uint8_t port);
-void setupPulsesMultimodule(uint8_t port);
-void setupPulsesSbus(uint8_t port);
-void setupPulsesPXX(uint8_t port);
-void setupPulsesPPMModule(uint8_t port);
-void setupPulsesPPMTrainer();
-void sendByteDsm2(uint8_t b);
-void putDsm2Flush();
-void putDsm2SerialBit(uint8_t bit);
-void sendByteSbus(uint8_t byte);
-
-#if defined(HUBSAN)
-void Hubsan_Init();
-#endif
-
-inline void startPulses()
-{
- s_pulses_paused = false;
-
-#if defined(PCBTARANIS) || defined(PCBHORUS)
- setupPulses(INTERNAL_MODULE);
- setupPulses(EXTERNAL_MODULE);
-#else
- setupPulses(EXTERNAL_MODULE);
-#endif
-
-#if defined(HUBSAN)
- Hubsan_Init();
-#endif
-}
-
-inline bool pulsesStarted() { return s_current_protocol[0] != 255; }
-inline void pausePulses() { s_pulses_paused = true; }
-inline void resumePulses() { s_pulses_paused = false; }
-
-#define SEND_FAILSAFE_NOW(idx) failsafeCounter[idx] = 1
-
-inline void SEND_FAILSAFE_1S()
-{
- for (int i=0; i
-void PxxPulses::addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels)
-{
- uint16_t pulseValue = 0;
- uint16_t pulseValueLow = 0;
-
- for (int8_t i=0; i<8; i++) {
- if (sendFailsafe) {
- if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) {
- pulseValue = (i < sendUpperChannels ? 4095 : 2047);
- }
- else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) {
- pulseValue = (i < sendUpperChannels ? 2048 : 0);
- }
- else {
- if (i < sendUpperChannels) {
- int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[8+i];
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
- pulseValue = 4095;
- }
- else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- pulseValue = 2048;
- }
- else {
- failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
- pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094);
- }
- }
- else {
- int16_t failsafeValue = g_model.moduleData[port].failsafeChannels[i];
- if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
- pulseValue = 2047;
- }
- else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
- pulseValue = 0;
- }
- else {
- failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
- pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
- }
- }
- }
- }
- else {
- if (i < sendUpperChannels) {
- int channel = 8 + g_model.moduleData[port].channelsStart + i;
- int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
- pulseValue = limit(2049, (value * 512 / 682) + 3072, 4094);
- }
- else if (i < sentModuleChannels(port)) {
- int channel = g_model.moduleData[port].channelsStart + i;
- int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
- pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
- }
- else {
- pulseValue = 1024;
- }
- }
-
- if (i & 1) {
- PxxTransport::addByte(pulseValueLow); // Low byte of channel
- PxxTransport::addByte(((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels
- PxxTransport::addByte(pulseValue >> 4); // High byte of channel
- }
- else {
- pulseValueLow = pulseValue;
- }
- }
-}
-
-template
-uint8_t PxxPulses::addFlag1(uint8_t port)
-{
- uint8_t flag1 = (g_model.moduleData[port].rfProtocol << 6);
- if (moduleFlag[port] == MODULE_BIND) {
- flag1 |= (g_eeGeneral.countryCode << 1) | PXX_SEND_BIND;
- }
- else if (moduleFlag[port] == MODULE_RANGECHECK) {
- flag1 |= PXX_SEND_RANGECHECK;
- }
- else if (g_model.moduleData[port].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[port].failsafeMode != FAILSAFE_RECEIVER) {
- if (failsafeCounter[port]-- == 0) {
- failsafeCounter[port] = 1000;
- flag1 |= PXX_SEND_FAILSAFE;
- }
- if (failsafeCounter[port] == 0 && g_model.moduleData[port].channelsCount > 0) {
- flag1 |= PXX_SEND_FAILSAFE;
- }
- }
- PxxTransport::addByte(flag1);
- return flag1;
-}
-
-template
-void PxxPulses::addExtraFlags(uint8_t port)
-{
- // Ext. flag (holds antenna selection on Horus internal module, 0x00 otherwise)
- uint8_t extra_flags = 0;
-
-#if defined(PCBHORUS) || defined(PCBXLITE)
- if (port == INTERNAL_MODULE) {
- extra_flags |= (g_model.moduleData[port].pxx.external_antenna << 0);
- }
-#endif
-
- extra_flags |= (g_model.moduleData[port].pxx.receiver_telem_off << 1);
- extra_flags |= (g_model.moduleData[port].pxx.receiver_channel_9_16 << 2);
- if (isModuleR9M(port)) {
- extra_flags |= (min(g_model.moduleData[port].pxx.power, isModuleR9M_FCC_VARIANT(port) ? (uint8_t)R9M_FCC_POWER_MAX : (uint8_t)R9M_LBT_POWER_MAX) << 3);
- if(isModuleR9M_EUPLUS(port))
- extra_flags |= (1 << 6);
- }
-
- // Disable S.PORT if internal module is active
- if (IS_TELEMETRY_INTERNAL_MODULE()) {
- extra_flags |= (1 << 5);
- }
- PxxTransport::addByte(extra_flags);
-}
-
-template class PxxPulses >;
-template class PxxPulses >;
-template class PxxPulses;
-template class PxxPulses;
diff --git a/radio/src/pulses/pxx.h b/radio/src/pulses/pxx.h
index 31e7e16fc..e082e18f0 100644
--- a/radio/src/pulses/pxx.h
+++ b/radio/src/pulses/pxx.h
@@ -27,16 +27,24 @@
#define PXX_SEND_FAILSAFE (1 << 4)
#define PXX_SEND_RANGECHECK (1 << 5)
+#define PXX2_ON_SPORT_BAUDRATE 230400
+#define PXX2_PERIOD 4 // 4ms
+#define PXX2_FRAME_MAXLENGTH 64
+
+#define PXX_PULSES_PERIOD 9/*ms*/
+#define EXTMODULE_PXX_SERIAL_PERIOD 4/*ms*/
+#define EXTMODULE_PXX_SERIAL_BAUDRATE 420000
+
#if defined(PXX_FREQUENCY_HIGH)
- #define EXTMODULE_USART_PXX_BAUDRATE 420000
- #define INTMODULE_USART_PXX_BAUDRATE 450000
- #define PXX_PERIOD 4/*ms*/
+ #define INTMODULE_PXX_BAUDRATE 450000
+ #define INTMODULE_PXX_PERIOD 4/*ms*/
#else
- #define EXTMODULE_USART_PXX_BAUDRATE 115200
- #define INTMODULE_USART_PXX_BAUDRATE 115200
- #define PXX_PERIOD 9/*ms*/
+ #define INTMODULE_PXX_BAUDRATE 115200
+ #define INTMODULE_PXX_PERIOD 9/*ms*/
#endif
+#define EXTMODULE_USART_PXX2_BAUDRATE 230400
+
#if defined(PXX_FREQUENCY_HIGH) && (!defined(INTMODULE_USART) || !defined(EXTMODULE_USART))
/* PXX uses 20 bytes (as of Rev 1.1 document) with 8 changes per byte + stop bit ~= 162 max pulses */
/* DSM2 uses 2 header + 12 channel bytes, with max 10 changes (8n2) per byte + 16 bits trailer ~= 156 max pulses */
@@ -47,32 +55,13 @@
#error "Pulses array needs to be increased (PXX_FREQUENCY=HIGH)"
#endif
-
-#define PXX_PERIOD_HALF_US (PXX_PERIOD * 2000)
-
-class PxxCrcMixin {
- protected:
- void initCrc()
- {
- crc = 0;
- }
-
- void addToCrc(uint8_t byte)
- {
- crc = (crc << 8) ^ (CRCTable[((crc >> 8) ^ byte) & 0xFF]);
- }
-
- uint16_t crc;
- static const uint16_t CRCTable[];
-};
-
// Used by the Sky9x family boards
class SerialPxxBitTransport: public DataBuffer {
protected:
uint8_t byte;
uint8_t bits_count;
- void initFrame()
+ void initFrame(uint32_t period)
{
initBuffer();
byte = 0;
@@ -113,10 +102,10 @@ class PwmPxxBitTransport: public PulsesBuffer {
protected:
uint16_t rest;
- void initFrame()
+ void initFrame(uint32_t period)
{
initBuffer();
- rest = PXX_PERIOD_HALF_US;
+ rest = period * 2000; // 0.5uS (2Mhz)
}
void addPart(uint8_t value)
@@ -133,108 +122,10 @@ class PwmPxxBitTransport: public PulsesBuffer {
}
};
-template
-class StandardPxxTransport: public BitTransport, public PxxCrcMixin {
- protected:
- uint8_t ones_count;
-
- void initFrame()
- {
- BitTransport::initFrame();
- ones_count = 0;
- }
-
- void addByte(uint8_t byte)
- {
- PxxCrcMixin::addToCrc(byte);
- addByteWithoutCrc(byte);
- };
-
- void addRawByteWithoutCrc(uint8_t byte)
- {
- for (uint8_t i = 0; i < 8; i++) {
- if (byte & 0x80)
- BitTransport::addPart(1);
- else
- BitTransport::addPart(0);
- byte <<= 1;
- }
- }
-
- void addByteWithoutCrc(uint8_t byte)
- {
- for (uint8_t i = 0; i < 8; i++) {
- addBit(byte & 0x80);
- byte <<= 1;
- }
- }
-
- void addBit(uint8_t bit)
- {
- if (bit) {
- BitTransport::addPart(1);
- if (++ones_count == 5) {
- ones_count = 0;
- BitTransport::addPart(0); // Stuff a 0 bit in
- }
- }
- else {
- BitTransport::addPart(0);
- ones_count = 0;
- }
- }
-};
-
-class UartPxxTransport: public DataBuffer, public PxxCrcMixin {
- protected:
- void initFrame()
- {
- initBuffer();
- }
-
- void addByte(uint8_t byte)
- {
- PxxCrcMixin::addToCrc(byte);
- addWithByteStuffing(byte);
- }
-
- void addRawByteWithoutCrc(uint8_t byte)
- {
- addByteWithoutCrc(byte);
- }
-
- void addByteWithoutCrc(uint8_t byte)
- {
- *ptr++ = byte;
- }
-
- void addWithByteStuffing(uint8_t byte)
- {
- if (0x7E == byte) {
- *ptr++ = 0x7D;
- *ptr++ = 0x5E;
- }
- else if (0x7D == byte) {
- *ptr++ = 0x7D;
- *ptr++ = 0x5D;
- }
- else {
- *ptr++ = byte;
- }
- }
-
- void addTail()
- {
- // nothing
- }
-};
-
template
class PxxPulses: public PxxTransport {
protected:
- uint8_t addFlag1(uint8_t port);
void addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels);
- void addExtraFlags(uint8_t port);
};
#endif
diff --git a/radio/src/pulses/pxx1.cpp b/radio/src/pulses/pxx1.cpp
index 3ab3963d8..e11642b4e 100644
--- a/radio/src/pulses/pxx1.cpp
+++ b/radio/src/pulses/pxx1.cpp
@@ -21,8 +21,167 @@
#include "opentx.h"
#include "pulses/pxx1.h"
+const uint16_t Pxx1CrcMixin::CRCTable[] = {
+ 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf,
+ 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7,
+ 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e,
+ 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876,
+ 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd,
+ 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5,
+ 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c,
+ 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974,
+ 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb,
+ 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3,
+ 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a,
+ 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72,
+ 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9,
+ 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1,
+ 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738,
+ 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70,
+ 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7,
+ 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff,
+ 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036,
+ 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e,
+ 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5,
+ 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd,
+ 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134,
+ 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c,
+ 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3,
+ 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb,
+ 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232,
+ 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a,
+ 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1,
+ 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9,
+ 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330,
+ 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78
+};
+
template
-void Pxx1Pulses::add8ChannelsFrame(uint8_t port, uint8_t sendUpperChannels)
+uint8_t Pxx1Pulses::addFlag1(uint8_t module)
+{
+ uint8_t flag1 = (g_model.moduleData[module].rfProtocol << 6);
+ if (moduleSettings[module].mode == MODULE_MODE_BIND) {
+ flag1 |= (g_eeGeneral.countryCode << 1) | PXX_SEND_BIND;
+ }
+ else if (moduleSettings[module].mode == MODULE_MODE_RANGECHECK) {
+ flag1 |= PXX_SEND_RANGECHECK;
+ }
+ else {
+ bool failsafeNeeded = g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER;
+ if (moduleSettings[module].counter-- == 0) {
+ // counter is also used for knowing if the frame is odd / even
+ moduleSettings[module].counter = 1000;
+ if (failsafeNeeded) {
+ flag1 |= PXX_SEND_FAILSAFE;
+ }
+ }
+ if (failsafeNeeded && moduleSettings[module].counter == 0 && g_model.moduleData[module].channelsCount > 0) {
+ flag1 |= PXX_SEND_FAILSAFE;
+ }
+ }
+ PxxTransport::addByte(flag1);
+ return flag1;
+}
+
+template
+void Pxx1Pulses::addExtraFlags(uint8_t module)
+{
+ // Ext. flag (holds antenna selection on Horus internal module, 0x00 otherwise)
+ uint8_t extra_flags = 0;
+
+#if defined(PCBHORUS) || defined(PCBXLITE)
+ if (module == INTERNAL_MODULE) {
+ extra_flags |= (g_model.moduleData[module].pxx.external_antenna << 0);
+ }
+#endif
+
+ extra_flags |= (g_model.moduleData[module].pxx.receiver_telem_off << 1);
+ extra_flags |= (g_model.moduleData[module].pxx.receiver_channel_9_16 << 2);
+ if (isModuleR9M(module)) {
+ extra_flags |= (min(g_model.moduleData[module].pxx.power, isModuleR9M_FCC_VARIANT(module) ? (uint8_t)R9M_FCC_POWER_MAX : (uint8_t)R9M_LBT_POWER_MAX) << 3);
+ if (isModuleR9M_EUPLUS(module))
+ extra_flags |= (1 << 6);
+ }
+
+ // Disable S.PORT if internal module is active
+ if (IS_TELEMETRY_INTERNAL_MODULE()) {
+ extra_flags |= (1 << 5);
+ }
+ PxxTransport::addByte(extra_flags);
+}
+
+template
+void Pxx1Pulses::addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels)
+{
+ uint16_t pulseValue = 0;
+ uint16_t pulseValueLow = 0;
+
+ for (int8_t i=0; i<8; i++) {
+ if (sendFailsafe) {
+ if (g_model.moduleData[port].failsafeMode == FAILSAFE_HOLD) {
+ pulseValue = (i < sendUpperChannels ? 4095 : 2047);
+ }
+ else if (g_model.moduleData[port].failsafeMode == FAILSAFE_NOPULSES) {
+ pulseValue = (i < sendUpperChannels ? 2048 : 0);
+ }
+ else {
+ if (i < sendUpperChannels) {
+ int16_t failsafeValue = g_model.failsafeChannels[8+i];
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ pulseValue = 4095;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ pulseValue = 2048;
+ }
+ else {
+ failsafeValue += 2*PPM_CH_CENTER(8+g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
+ pulseValue = limit(2049, (failsafeValue * 512 / 682) + 3072, 4094);
+ }
+ }
+ else {
+ int16_t failsafeValue = g_model.failsafeChannels[i];
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ pulseValue = 2047;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ pulseValue = 0;
+ }
+ else {
+ failsafeValue += 2*PPM_CH_CENTER(g_model.moduleData[port].channelsStart+i) - 2*PPM_CENTER;
+ pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
+ }
+ }
+ }
+ }
+ else {
+ if (i < sendUpperChannels) {
+ int channel = 8 + g_model.moduleData[port].channelsStart + i;
+ int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+ pulseValue = limit(2049, (value * 512 / 682) + 3072, 4094);
+ }
+ else if (i < sentModuleChannels(port)) {
+ int channel = g_model.moduleData[port].channelsStart + i;
+ int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+ pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
+ }
+ else {
+ pulseValue = 1024;
+ }
+ }
+
+ if (i & 1) {
+ PxxTransport::addByte(pulseValueLow); // Low byte of channel
+ PxxTransport::addByte(((pulseValueLow >> 8) & 0x0F) | (pulseValue << 4)); // 4 bits each from 2 channels
+ PxxTransport::addByte(pulseValue >> 4); // High byte of channel
+ }
+ else {
+ pulseValueLow = pulseValue;
+ }
+ }
+}
+
+template
+void Pxx1Pulses::add8ChannelsFrame(uint8_t module, uint8_t sendUpperChannels)
{
PxxTransport::initCrc();
@@ -30,19 +189,19 @@ void Pxx1Pulses::add8ChannelsFrame(uint8_t port, uint8_t sendUpper
addHead();
// RX Number
- PxxTransport::addByte(g_model.header.modelId[port]);
+ PxxTransport::addByte(g_model.header.modelId[module]);
// Flag1
- uint8_t flag1 = PxxPulses::addFlag1(port);
+ uint8_t flag1 = addFlag1(module);
// Flag2
PxxTransport::addByte(0);
// Channels
- PxxPulses::addChannels(port, flag1 & PXX_SEND_FAILSAFE, sendUpperChannels);
+ addChannels(module, flag1 & PXX_SEND_FAILSAFE, sendUpperChannels);
// Extra flags
- PxxPulses::addExtraFlags(port);
+ addExtraFlags(module);
// CRC
addCrc();
@@ -55,25 +214,28 @@ void Pxx1Pulses::add8ChannelsFrame(uint8_t port, uint8_t sendUpper
}
template
-void Pxx1Pulses::setupFrame(uint8_t port)
+void Pxx1Pulses::setupFrame(uint8_t module)
{
- PxxTransport::initFrame();
+ PxxTransport::initFrame(PXX_PULSES_PERIOD);
#if defined(PXX_FREQUENCY_HIGH)
- add8ChannelsFrame(port, 0);
- if (sentModuleChannels(port) > 8) {
- add8ChannelsFrame(port, 8);
+ if (moduleSettings[module].protocol == PROTOCOL_CHANNELS_PXX1_SERIAL) {
+ add8ChannelsFrame(module, 0);
+ if (sentModuleChannels(module) > 8) {
+ add8ChannelsFrame(module, 8);
+ }
+ return;
}
-#else
- static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) };
- uint8_t sendUpperChannels = 0;
- if (pass[port]++ & 0x01) {
- sendUpperChannels = g_model.moduleData[port].channelsCount;
- }
- add8ChannelsFrame(port, sendUpperChannels);
#endif
+
+ uint8_t sendUpperChannels = 0;
+ if (moduleSettings[module].counter & 0x01) {
+ sendUpperChannels = g_model.moduleData[module].channelsCount;
+ }
+
+ add8ChannelsFrame(module, sendUpperChannels);
}
-template class Pxx1Pulses >;
-template class Pxx1Pulses >;
-template class Pxx1Pulses;
+template class Pxx1Pulses >;
+template class Pxx1Pulses >;
+template class Pxx1Pulses;
diff --git a/radio/src/pulses/pxx1.h b/radio/src/pulses/pxx1.h
index d7d958b45..600a1cb4d 100644
--- a/radio/src/pulses/pxx1.h
+++ b/radio/src/pulses/pxx1.h
@@ -23,6 +23,118 @@
#include "pxx.h"
+class Pxx1CrcMixin {
+ protected:
+ void initCrc()
+ {
+ crc = 0;
+ }
+
+ void addToCrc(uint8_t byte)
+ {
+ crc = (crc << 8) ^ (CRCTable[((crc >> 8) ^ byte) & 0xFF]);
+ }
+
+ uint16_t crc;
+ static const uint16_t CRCTable[];
+};
+
+template
+class StandardPxx1Transport: public BitTransport, public Pxx1CrcMixin {
+ protected:
+ uint8_t ones_count;
+
+ void initFrame(uint32_t period)
+ {
+ BitTransport::initFrame(period);
+ ones_count = 0;
+ }
+
+ void addByte(uint8_t byte)
+ {
+ Pxx1CrcMixin::addToCrc(byte);
+ addByteWithoutCrc(byte);
+ };
+
+ void addRawByte(uint8_t byte)
+ {
+ for (uint8_t i = 0; i < 8; i++) {
+ if (byte & 0x80)
+ BitTransport::addPart(1);
+ else
+ BitTransport::addPart(0);
+ byte <<= 1;
+ }
+ }
+
+ void addByteWithoutCrc(uint8_t byte)
+ {
+ for (uint8_t i = 0; i < 8; i++) {
+ addBit(byte & 0x80);
+ byte <<= 1;
+ }
+ }
+
+ void addBit(uint8_t bit)
+ {
+ if (bit) {
+ BitTransport::addPart(1);
+ if (++ones_count == 5) {
+ ones_count = 0;
+ BitTransport::addPart(0); // Stuff a 0 bit in
+ }
+ }
+ else {
+ BitTransport::addPart(0);
+ ones_count = 0;
+ }
+ }
+};
+
+class UartPxx1Transport: public DataBuffer, public Pxx1CrcMixin {
+ protected:
+ void initFrame(uint32_t period)
+ {
+ initBuffer();
+ }
+
+ void addByte(uint8_t byte)
+ {
+ Pxx1CrcMixin::addToCrc(byte);
+ addWithByteStuffing(byte);
+ }
+
+ void addRawByte(uint8_t byte)
+ {
+ *ptr++ = byte;
+ }
+
+ void addByteWithoutCrc(uint8_t byte)
+ {
+ addWithByteStuffing(byte);
+ }
+
+ void addWithByteStuffing(uint8_t byte)
+ {
+ if (0x7E == byte) {
+ addRawByte(0x7D);
+ addRawByte(0x5E);
+ }
+ else if (0x7D == byte) {
+ addRawByte(0x7D);
+ addRawByte(0x5D);
+ }
+ else {
+ addRawByte(byte);
+ }
+ }
+
+ void addTail()
+ {
+ // nothing
+ }
+};
+
template
class Pxx1Pulses: public PxxPulses
{
@@ -33,20 +145,23 @@ class Pxx1Pulses: public PxxPulses
void addHead()
{
// send 7E, do not CRC
- PxxTransport::addRawByteWithoutCrc(0x7E);
+ PxxTransport::addRawByte(0x7E);
}
void addCrc()
{
- PxxTransport::addByteWithoutCrc(PxxCrcMixin::crc >> 8);
- PxxTransport::addByteWithoutCrc(PxxCrcMixin::crc);
+ PxxTransport::addByteWithoutCrc(Pxx1CrcMixin::crc >> 8);
+ PxxTransport::addByteWithoutCrc(Pxx1CrcMixin::crc);
}
+ uint8_t addFlag1(uint8_t port);
+ void addExtraFlags(uint8_t port);
+ void addChannels(uint8_t port, uint8_t sendFailsafe, uint8_t sendUpperChannels);
void add8ChannelsFrame(uint8_t port, uint8_t sendUpperChannels);
};
-typedef Pxx1Pulses UartPxxPulses;
-typedef Pxx1Pulses> PwmPxxPulses;
-typedef Pxx1Pulses> SerialPxxPulses;
+typedef Pxx1Pulses UartPxx1Pulses;
+typedef Pxx1Pulses> PwmPxx1Pulses;
+typedef Pxx1Pulses> SerialPxx1Pulses;
#endif
diff --git a/radio/src/pulses/pxx2.cpp b/radio/src/pulses/pxx2.cpp
index d7d32b588..9876d58ab 100644
--- a/radio/src/pulses/pxx2.cpp
+++ b/radio/src/pulses/pxx2.cpp
@@ -21,55 +21,318 @@
#include "opentx.h"
#include "pulses/pxx2.h"
-void Pxx2Pulses::setupFrame(uint8_t port)
+uint8_t Pxx2Pulses::addFlag0(uint8_t module)
{
- initFrame();
- initCrc();
-
- static uint8_t pass[NUM_MODULES] = { MODULES_INIT(0) };
- uint8_t sendUpperChannels = 0;
- if (pass[port]++ & 0x01) {
- sendUpperChannels = g_model.moduleData[port].channelsCount;
+ uint8_t flag0 = g_model.header.modelId[module] & 0x3F;
+ if (g_model.moduleData[module].failsafeMode != FAILSAFE_NOT_SET && g_model.moduleData[module].failsafeMode != FAILSAFE_RECEIVER) {
+ if (moduleSettings[module].counter == 0) {
+ flag0 |= PXX2_CHANNELS_FLAG0_FAILSAFE;
+ }
}
+ if (moduleSettings[module].mode == MODULE_MODE_RANGECHECK) {
+ flag0 |= PXX2_CHANNELS_FLAG0_RANGECHECK;
+ }
+ Pxx2Transport::addByte(flag0);
+ return flag0;
+}
- // Model ID
- addByte(g_model.header.modelId[port]);
+void Pxx2Pulses::addFlag1()
+{
+ uint8_t flag1 = 0;
+ Pxx2Transport::addByte(flag1);
+}
+
+void Pxx2Pulses::addPulsesValues(uint16_t low, uint16_t high)
+{
+ Pxx2Transport::addByte(low); // Low byte of channel
+ Pxx2Transport::addByte(((low >> 8) & 0x0F) | (high << 4)); // 4 bits each from 2 channels
+ Pxx2Transport::addByte(high >> 4); // High byte of channel
+}
+
+void Pxx2Pulses::addChannels(uint8_t module)
+{
+ uint16_t pulseValue = 0;
+ uint16_t pulseValueLow = 0;
+
+ uint8_t channel = g_model.moduleData[module].channelsStart;
+ uint8_t count = sentModuleChannels(module);
+
+ for (int8_t i = 0; i < count; i++, channel++) {
+ int value = channelOutputs[channel] + 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+ pulseValue = limit(1, (value * 512 / 682) + 1024, 2046);
+ if (i & 1)
+ addPulsesValues(pulseValueLow, pulseValue);
+ else
+ pulseValueLow = pulseValue;
+ }
+}
+
+void Pxx2Pulses::addFailsafe(uint8_t module)
+{
+ uint16_t pulseValue = 0;
+ uint16_t pulseValueLow = 0;
+
+ uint8_t channel = g_model.moduleData[module].channelsStart;
+ uint8_t count = sentModuleChannels(module);
+
+ for (int8_t i = 0; i < count; i++, channel++) {
+ if (g_model.moduleData[module].failsafeMode == FAILSAFE_HOLD) {
+ pulseValue = 2047;
+ }
+ else if (g_model.moduleData[module].failsafeMode == FAILSAFE_NOPULSES) {
+ pulseValue = 0;
+ }
+ else {
+ int16_t failsafeValue = g_model.failsafeChannels[channel];
+ if (failsafeValue == FAILSAFE_CHANNEL_HOLD) {
+ pulseValue = 2047;
+ }
+ else if (failsafeValue == FAILSAFE_CHANNEL_NOPULSE) {
+ pulseValue = 0;
+ }
+ else {
+ failsafeValue += 2*PPM_CH_CENTER(channel) - 2*PPM_CENTER;
+ pulseValue = limit(1, (failsafeValue * 512 / 682) + 1024, 2046);
+ }
+ }
+ if (i & 1)
+ addPulsesValues(pulseValueLow, pulseValue);
+ else
+ pulseValueLow = pulseValue;
+ }
+}
+
+void Pxx2Pulses::setupChannelsFrame(uint8_t module)
+{
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_CHANNELS);
+
+ // Flag0
+ uint8_t flag0 = addFlag0(module);
// Flag1
- uint8_t flag1 = addFlag1(port);
+ addFlag1();
- // Flag2
- addByte(0);
+ // Failsafe / Channels
+ if (flag0 & PXX2_CHANNELS_FLAG0_FAILSAFE)
+ addFailsafe(module);
+ else
+ addChannels(module);
+}
- // Channels
- addChannels(port, flag1 & PXX_SEND_FAILSAFE, sendUpperChannels);
+void Pxx2Pulses::setupTelemetryFrame(uint8_t module)
+{
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_TELEMETRY);
+ for (uint8_t i = 0; i < outputTelemetryBuffer.size; i++) {
+ Pxx2Transport::addByte(outputTelemetryBuffer.data[i]);
+ }
+ outputTelemetryBuffer.reset();
+}
- // Extra flags
- addExtraFlags(port);
-
- // Flag3, reserved
- addByte(0);
-
-#if defined(LUA)
- if (outputTelemetryBufferTrigger != 0x00 && outputTelemetryBufferSize > 0) {
- // CMD/Resp
- addByte(1);
- // primID (1 byte) + dataID (2 bytes) + value (4 bytes)
- for (uint8_t i=0; i<7; i++) {
- addByte(outputTelemetryBuffer[i]);
+void Pxx2Pulses::setupHardwareInfoFrame(uint8_t module)
+{
+ if (reusableBuffer.hardwareAndSettings.modules[module].current <= reusableBuffer.hardwareAndSettings.modules[module].maximum) {
+ if (reusableBuffer.hardwareAndSettings.modules[module].timeout == 0) {
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_HW_INFO);
+ Pxx2Transport::addByte(reusableBuffer.hardwareAndSettings.modules[module].current);
+ reusableBuffer.hardwareAndSettings.modules[module].timeout = 20;
+ reusableBuffer.hardwareAndSettings.modules[module].current++;
+ }
+ else {
+ reusableBuffer.hardwareAndSettings.modules[module].timeout--;
+ setupChannelsFrame(module);
}
- outputTelemetryBufferTrigger = 0x00;
- outputTelemetryBufferSize = 0;
}
else {
- // CMD/Resp
- addByte(0);
+ moduleSettings[module].mode = MODULE_MODE_NORMAL;
+ setupChannelsFrame(module);
}
-#else
- // CMD/Resp
- addByte(0);
-#endif
-
- // CRC
- addByte(crc); // TODO need to check the CRC chosen algorithm
}
+
+void Pxx2Pulses::setupRegisterFrame(uint8_t module)
+{
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_REGISTER);
+
+ if (reusableBuffer.moduleSetup.pxx2.registerStep == REGISTER_RX_NAME_SELECTED) {
+ Pxx2Transport::addByte(0x01);
+ for (uint8_t i=0; i reusableBuffer.hardwareAndSettings.moduleSettings.timeout) {
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_TX_SETTINGS);
+ uint8_t flag0 = 0;
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.state == PXX2_SETTINGS_WRITE)
+ flag0 |= PXX2_TX_SETTINGS_FLAG0_WRITE;
+ Pxx2Transport::addByte(flag0);
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.state == PXX2_SETTINGS_WRITE) {
+ uint8_t flag1 = reusableBuffer.hardwareAndSettings.moduleSettings.rfProtocol << 4;
+ if (reusableBuffer.hardwareAndSettings.moduleSettings.externalAntenna)
+ flag1 |= PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA;
+ Pxx2Transport::addByte(flag1);
+ Pxx2Transport::addByte(reusableBuffer.hardwareAndSettings.moduleSettings.txPower);
+ }
+ reusableBuffer.hardwareAndSettings.moduleSettings.timeout = get_tmr10ms() + 200/*next try in 2s*/;
+ }
+ else {
+ setupChannelsFrame(module);
+ }
+}
+
+void Pxx2Pulses::setupReceiverSettingsFrame(uint8_t module)
+{
+ if (get_tmr10ms() > reusableBuffer.hardwareAndSettings.receiverSettings.timeout) {
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_RX_SETTINGS);
+ uint8_t flag0 = reusableBuffer.hardwareAndSettings.receiverSettings.receiverId;
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.state == PXX2_SETTINGS_WRITE)
+ flag0 |= PXX2_RX_SETTINGS_FLAG0_WRITE;
+ Pxx2Transport::addByte(flag0);
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.state == PXX2_SETTINGS_WRITE) {
+ uint8_t flag1 = 0;
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.telemetryDisabled)
+ flag1 |= PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED;
+ if (reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate)
+ flag1 |= PXX2_RX_SETTINGS_FLAG1_FASTPWM;
+ Pxx2Transport::addByte(flag1);
+ uint8_t outputsCount = min(24, reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount);
+ for (int i = 0; i < outputsCount; i++) {
+ Pxx2Transport::addByte(min(23, reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[i]));
+ }
+ }
+ reusableBuffer.hardwareAndSettings.receiverSettings.timeout = get_tmr10ms() + 200/*next try in 2s*/;
+ }
+ else {
+ setupChannelsFrame(module);
+ }
+}
+
+void Pxx2Pulses::setupBindFrame(uint8_t module)
+{
+ if (reusableBuffer.moduleSetup.pxx2.bindStep == BIND_WAIT) {
+ if (get_tmr10ms() > reusableBuffer.moduleSetup.pxx2.bindWaitTimeout) {
+ moduleSettings[module].mode = MODULE_MODE_NORMAL;
+ reusableBuffer.moduleSetup.pxx2.bindStep = BIND_OK;
+ POPUP_INFORMATION(STR_BIND_OK);
+ }
+ return;
+ }
+
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_BIND);
+
+ if (reusableBuffer.moduleSetup.pxx2.bindStep == BIND_RX_NAME_SELECTED) {
+ Pxx2Transport::addByte(0x01);
+ for (uint8_t i=0; i 1000) {
+ moduleSettings[module].counter = 1002;
+ return;
+ }
+
+ moduleSettings[module].counter = 1002;
+
+ addFrameType(PXX2_TYPE_C_POWER_METER, PXX2_TYPE_ID_SPECTRUM);
+ Pxx2Transport::addByte(0x00);
+
+ reusableBuffer.spectrumAnalyser.freq = 2440000000; // 2440MHz
+ Pxx2Transport::addWord(reusableBuffer.spectrumAnalyser.freq);
+
+ reusableBuffer.spectrumAnalyser.span = 40000000; // 40MHz
+ Pxx2Transport::addWord(reusableBuffer.spectrumAnalyser.span);
+
+ reusableBuffer.spectrumAnalyser.step = 100000; // 100KHz
+ Pxx2Transport::addWord(reusableBuffer.spectrumAnalyser.step);
+}
+
+
+void Pxx2Pulses::setupPowerMeter(uint8_t module)
+{
+ if (moduleSettings[module].counter > 1000) {
+ moduleSettings[module].counter = 1002;
+ return;
+ }
+
+ moduleSettings[module].counter = 1002;
+
+ addFrameType(PXX2_TYPE_C_POWER_METER, PXX2_TYPE_ID_POWER_METER);
+ Pxx2Transport::addByte(0x00);
+
+ Pxx2Transport::addWord(reusableBuffer.powerMeter.freq);
+}
+
+void Pxx2Pulses::setupShareMode(uint8_t module)
+{
+ addFrameType(PXX2_TYPE_C_MODULE, PXX2_TYPE_ID_SHARE);
+ Pxx2Transport::addByte(reusableBuffer.moduleSetup.pxx2.shareReceiverId);
+}
+
+void Pxx2Pulses::setupFrame(uint8_t module)
+{
+ initFrame();
+
+ switch (moduleSettings[module].mode) {
+ case MODULE_MODE_GET_HARDWARE_INFO:
+ setupHardwareInfoFrame(module);
+ break;
+ case MODULE_MODE_MODULE_SETTINGS:
+ setupModuleSettingsFrame(module);
+ break;
+ case MODULE_MODE_RECEIVER_SETTINGS:
+ setupReceiverSettingsFrame(module);
+ break;
+ case MODULE_MODE_REGISTER:
+ setupRegisterFrame(module);
+ break;
+ case MODULE_MODE_BIND:
+ setupBindFrame(module);
+ break;
+ case MODULE_MODE_SPECTRUM_ANALYSER:
+ setupSpectrumAnalyser(module);
+ break;
+ case MODULE_MODE_POWER_METER:
+ setupPowerMeter(module);
+ break;
+ case MODULE_MODE_SHARE:
+ setupShareMode(module);
+ break;
+ default:
+ if (outputTelemetryBuffer.size > 0 && outputTelemetryBuffer.destination == module) {
+ setupTelemetryFrame(module);
+ }
+ else {
+ setupChannelsFrame(module);
+ }
+ break;
+ }
+
+ if (moduleSettings[module].counter-- == 0) {
+ moduleSettings[module].counter = 1000;
+ }
+
+ endFrame();
+}
+
+template class PxxPulses;
diff --git a/radio/src/pulses/pxx2.h b/radio/src/pulses/pxx2.h
index 939d0204d..be47b43ab 100644
--- a/radio/src/pulses/pxx2.h
+++ b/radio/src/pulses/pxx2.h
@@ -21,52 +21,202 @@
#ifndef _PULSES_PXX2_H_
#define _PULSES_PXX2_H_
+#include "fifo.h"
+#include "io/frsky_pxx2.h"
#include "./pxx.h"
-class SportCrcMixin {
+#define PXX2_TYPE_C_MODULE 0x01
+ #define PXX2_TYPE_ID_REGISTER 0x01
+ #define PXX2_TYPE_ID_BIND 0x02
+ #define PXX2_TYPE_ID_CHANNELS 0x03
+ #define PXX2_TYPE_ID_TX_SETTINGS 0x04
+ #define PXX2_TYPE_ID_RX_SETTINGS 0x05
+ #define PXX2_TYPE_ID_HW_INFO 0x06
+ #define PXX2_TYPE_ID_SHARE 0x07
+ #define PXX2_TYPE_ID_TELEMETRY 0xFE
+
+#define PXX2_TYPE_C_POWER_METER 0x02
+ #define PXX2_TYPE_ID_POWER_METER 0x01
+ #define PXX2_TYPE_ID_SPECTRUM 0x02
+
+#define PXX2_TYPE_C_OTA 0xFE
+
+#define PXX2_CHANNELS_FLAG0_FAILSAFE (1 << 6)
+#define PXX2_CHANNELS_FLAG0_RANGECHECK (1 << 7)
+
+#define PXX2_RX_SETTINGS_FLAG0_WRITE (1 << 6)
+
+#define PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED (1 << 7)
+#define PXX2_RX_SETTINGS_FLAG1_READONLY (1 << 6)
+#define PXX2_RX_SETTINGS_FLAG1_FASTPWM (1 << 4)
+
+#define PXX2_TX_SETTINGS_FLAG0_WRITE (1 << 6)
+#define PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA (1 << 3)
+
+#define PXX2_HW_INFO_TX_ID 0xFF
+
+enum PXX2RegisterSteps {
+ REGISTER_START,
+ REGISTER_RX_NAME_RECEIVED,
+ REGISTER_RX_NAME_SELECTED,
+ REGISTER_OK
+};
+
+enum PXX2BindSteps {
+ BIND_START,
+ BIND_RX_NAME_SELECTED,
+ BIND_WAIT,
+ BIND_OK
+};
+
+enum PXX2ReceiverStatus {
+ PXX2_HARDWARE_INFO,
+ PXX2_SETTINGS_READ,
+ PXX2_SETTINGS_WRITE,
+ PXX2_SETTINGS_OK
+};
+
+extern ModuleFifo intmoduleFifo;
+extern ModuleFifo extmoduleFifo;
+
+class Pxx2CrcMixin {
protected:
void initCrc()
{
- crc = 0;
+ crc = 0xFFFF;
}
void addToCrc(uint8_t byte)
{
- crc += byte; // 0-1FF
- crc += crc >> 8; // 0-100
- crc &= 0x00ff;
+ crc -= byte;
}
uint16_t crc;
};
-
-class Pxx2Transport: public DataBuffer, public SportCrcMixin {
+class Pxx2Transport: public DataBuffer, public Pxx2CrcMixin {
protected:
- void addByte(uint8_t byte)
+ void addWord(uint32_t word)
{
- SportCrcMixin::addToCrc(byte);
- *ptr++ = byte;
+ addByte(word);
+ addByte(word >> 8);
+ addByte(word >> 16);
+ addByte(word >> 24);
}
- void addTail()
+ void addByte(uint8_t byte)
{
- // nothing
+ Pxx2CrcMixin::addToCrc(byte);
+ addByteWithoutCrc(byte);
+ };
+
+ void addByteWithoutCrc(uint8_t byte)
+ {
+ *ptr++ = byte;
}
};
class Pxx2Pulses: public PxxPulses {
public:
- void setupFrame(uint8_t port);
+ void setupFrame(uint8_t module);
protected:
- uint8_t data[64];
- uint8_t * ptr;
+ void setupHardwareInfoFrame(uint8_t module);
+
+ void setupRegisterFrame(uint8_t module);
+
+ void setupBindFrame(uint8_t module);
+
+ void setupShareMode(uint8_t module);
+
+ void setupModuleSettingsFrame(uint8_t module);
+
+ void setupReceiverSettingsFrame(uint8_t module);
+
+ void setupChannelsFrame(uint8_t module);
+
+ void setupTelemetryFrame(uint8_t module);
+
+ void setupSpectrumAnalyser(uint8_t module);
+
+ void setupPowerMeter(uint8_t module);
+
+ void addHead()
+ {
+ // send 7E, do not CRC
+ Pxx2Transport::addByteWithoutCrc(0x7E);
+
+ // reserve 1 byte for LEN
+ Pxx2Transport::addByteWithoutCrc(0x00);
+ }
+
+ void addFrameType(uint8_t type_c, uint8_t type_id)
+ {
+ // TYPE_C + TYPE_ID
+ // TODO optimization ? Pxx2Transport::addByte(0x26); // This one is CRC-ed on purpose
+
+ Pxx2Transport::addByte(type_c);
+ Pxx2Transport::addByte(type_id);
+ }
+
+ uint8_t addFlag0(uint8_t module);
+
+ void addFlag1();
+
+ void addPulsesValues(uint16_t low, uint16_t high);
+
+ void addChannels(uint8_t module);
+
+ void addFailsafe(uint8_t module);
+
+ void addCrc()
+ {
+ Pxx2Transport::addByteWithoutCrc(Pxx2CrcMixin::crc >> 8);
+ Pxx2Transport::addByteWithoutCrc(Pxx2CrcMixin::crc);
+ }
void initFrame()
{
+ // init the CRC counter
+ initCrc();
+
+ // reset the frame pointer
Pxx2Transport::initBuffer();
+
+ // add the frame head
+ addHead();
+ }
+
+ void endFrame()
+ {
+ uint8_t size = getSize() - 2;
+
+ if (size > 0) {
+ // update the frame LEN = frame length minus the 2 first bytes
+ data[1] = getSize() - 2;
+
+ // now add the CRC
+ addCrc();
+ }
+ else {
+ Pxx2Transport::initBuffer();
+ }
}
};
+union PXX2Version
+{
+ uint8_t major;
+ uint8_t minor:4;
+ uint8_t revision:4;
+};
+
+struct PXX2HardwareInformation
+{
+ uint8_t modelID;
+ PXX2Version hwVersion;
+ PXX2Version swVersion;
+ uint8_t variant;
+};
+
#endif
diff --git a/radio/src/pulses/sbus_arm.cpp b/radio/src/pulses/sbus.cpp
similarity index 81%
rename from radio/src/pulses/sbus_arm.cpp
rename to radio/src/pulses/sbus.cpp
index 5824f17fe..26d4367b1 100644
--- a/radio/src/pulses/sbus_arm.cpp
+++ b/radio/src/pulses/sbus.cpp
@@ -48,17 +48,17 @@ static void _send_level(uint8_t v)
{
/* Copied over from DSM, this looks doubious and in my logic analyzer
output the low->high is about 2 ns late */
- if (modulePulsesData[EXTERNAL_MODULE].dsm2.index & 1)
+ if (extmodulePulsesData.dsm2.index & 1)
v += 2;
else
v -= 2;
- *modulePulsesData[EXTERNAL_MODULE].dsm2.ptr++ = v - 1;
- modulePulsesData[EXTERNAL_MODULE].dsm2.index+=1;
- modulePulsesData[EXTERNAL_MODULE].dsm2.rest -=v;
+ *extmodulePulsesData.dsm2.ptr++ = v - 1;
+ extmodulePulsesData.dsm2.index+=1;
+ extmodulePulsesData.dsm2.rest -=v;
}
-void sendByteSbus(uint8_t b) //max 11 changes 0 10 10 10 10 P 1
+void sendByteSbus(uint8_t b) // max 11 changes 0 10 10 10 10 P 1
{
bool lev = 0;
uint8_t parity = 1;
@@ -107,17 +107,17 @@ inline int getChannelValue(uint8_t port, int channel)
return channelOutputs[ch] + 2 * PPM_CH_CENTER(ch) - 2*PPM_CENTER;
}
-void setupPulsesSbus(uint8_t port)
+void setupPulsesSbus()
{
#if defined(PPM_PIN_SERIAL)
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialByte = 0;
- modulePulsesData[EXTERNAL_MODULE].dsm2.serialBitCount = 0;
+ extmodulePulsesData.dsm2.serialByte = 0;
+ extmodulePulsesData.dsm2.serialBitCount = 0;
#else
- modulePulsesData[EXTERNAL_MODULE].dsm2.rest = SBUS_PERIOD_HALF_US;
- modulePulsesData[EXTERNAL_MODULE].dsm2.index = 0;
+ extmodulePulsesData.dsm2.rest = SBUS_PERIOD_HALF_US;
+ extmodulePulsesData.dsm2.index = 0;
#endif
- modulePulsesData[EXTERNAL_MODULE].dsm2.ptr = modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
+ extmodulePulsesData.dsm2.ptr = extmodulePulsesData.dsm2.pulses;
// Sync Byte
sendByteSbus(SBUS_FRAME_BEGIN_BYTE);
@@ -127,7 +127,7 @@ void setupPulsesSbus(uint8_t port)
// byte 1-22, channels 0..2047, limits not really clear (B
for (int i=0; i 0)
+ if (getChannelValue(EXTERNAL_MODULE, 16) > 0)
flags |=SBUS_FLAG_CHANNEL_17;
- if (getChannelValue(port, 17) > 0)
+ if (getChannelValue(EXTERNAL_MODULE, 17) > 0)
flags |=SBUS_FLAG_CHANNEL_18;
sendByteSbus(flags);
diff --git a/radio/src/rtos.h b/radio/src/rtos.h
index 1478b778a..28532298b 100644
--- a/radio/src/rtos.h
+++ b/radio/src/rtos.h
@@ -27,14 +27,13 @@
extern "C++" {
#endif
-#define doNothing() do { } while(0) // seems unused? don't ever use this with SIMU
-
#if defined(SIMU)
#include
#include
#define SIMU_SLEEP_OR_EXIT_MS(x) simuSleep(x)
+ #define RTOS_MS_PER_TICK 1
typedef pthread_t RTOS_TASK_HANDLE;
typedef pthread_mutex_t RTOS_MUTEX_HANDLE;
@@ -59,7 +58,7 @@ extern "C++" {
static inline void RTOS_WAIT_TICKS(uint32_t x)
{
- RTOS_WAIT_MS(x * 2);
+ RTOS_WAIT_MS(x * RTOS_MS_PER_TICK);
}
#ifdef __cplusplus
@@ -149,7 +148,7 @@ extern "C++" {
}
#endif
- #define RTOS_MS_PER_TICK (CFG_CPU_FREQ / CFG_SYSTICK_FREQ / (CFG_CPU_FREQ / 1000)) // RTOS timer tick length in ms (currently 2)
+ #define RTOS_MS_PER_TICK ((CFG_CPU_FREQ / CFG_SYSTICK_FREQ) / (CFG_CPU_FREQ / 1000)) // RTOS timer tick length in ms (currently 2)
typedef OS_TID RTOS_TASK_HANDLE;
typedef OS_MutexID RTOS_MUTEX_HANDLE;
diff --git a/radio/src/sbus.cpp b/radio/src/sbus.cpp
index 6817fa0f1..e9b975144 100644
--- a/radio/src/sbus.cpp
+++ b/radio/src/sbus.cpp
@@ -30,11 +30,10 @@
#define SBUS_FAILSAFE_BIT 3
#define SBUS_CH_BITS 11
-#define SBUS_CH_MASK ((1<= 0; i--) {
+ if (path[i] == '/') {
+ return &path[i + 1];
+ }
+ }
+ return path;
+}
+
const char * getFileExtension(const char * filename, uint8_t size, uint8_t extMaxLen, uint8_t *fnlen, uint8_t *extlen)
{
int len = size;
@@ -275,7 +285,7 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen
lastpopupMenuOffset = 0;
memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss));
}
- else if (popupMenuOffset == popupMenuNoItems - MENU_MAX_DISPLAY_LINES) {
+ else if (popupMenuOffset == popupMenuItemsCount - MENU_MAX_DISPLAY_LINES) {
lastpopupMenuOffset = 0xffff;
memset(reusableBuffer.modelsel.menu_bss, 0, sizeof(reusableBuffer.modelsel.menu_bss));
}
@@ -292,14 +302,14 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen
memset(reusableBuffer.modelsel.menu_bss[0], 0, MENU_LINE_LENGTH);
}
- popupMenuNoItems = 0;
+ popupMenuItemsCount = 0;
POPUP_MENU_SET_BSS_FLAG();
FRESULT res = f_opendir(&dir, path);
if (res == FR_OK) {
if (flags & LIST_NONE_SD_FILE) {
- popupMenuNoItems++;
+ popupMenuItemsCount++;
if (selection) {
lastpopupMenuOffset++;
}
@@ -338,7 +348,7 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen
continue;
}
- popupMenuNoItems++;
+ popupMenuItemsCount++;
if (!(flags & LIST_SD_FILE_EXT)) {
fno.fname[fnLen] = '\0'; // strip extension
@@ -359,10 +369,9 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen
}
}
}
- for (uint8_t i=0; i=0; i--) {
@@ -374,7 +383,7 @@ bool sdListFiles(const char * path, const char * extension, const uint8_t maxlen
break;
}
}
- for (uint8_t i=0; i= 212
+ lcdDrawRect(60, 6*FH+4, 132, 3);
+#else
+ lcdDrawRect(10, 6*FH+4, 102, 3);
+#endif
+
+ // Models conversion
+ for (uint8_t id=0; id= 212
+ lcdDrawSolidHorizontalLine(61, 6*FH+5, 10+id*2, FORCE);
+#else
+ lcdDrawSolidHorizontalLine(11, 6*FH+5, 10+(id*3)/2, FORCE);
+#endif
+ lcdRefresh();
+ if (eeModelExists(id)) {
+ convertModelData(id, conversionVersionStart);
+ }
+ }
+
+ return true;
+}
diff --git a/radio/src/storage/conversions/conversions.h b/radio/src/storage/conversions/conversions.h
new file mode 100644
index 000000000..4da4a9ba7
--- /dev/null
+++ b/radio/src/storage/conversions/conversions.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+bool eeConvert();
+void convertModelData(int id, int version);
+
+// Conversions 216 to 217
+void convertModelData_216_to_217(ModelData &model);
+void convertRadioData_216_to_217(RadioData &settings);
+
+// Conversions 217 to 218
+void convertModelData_217_to_218(ModelData &model);
+void convertRadioData_217_to_218(RadioData &settings);
+
+// Conversions 218 to 219
+void convertModelData_218_to_219(ModelData &model);
+void convertRadioData_218_to_219(RadioData &settings);
diff --git a/radio/src/storage/eeprom_conversions.cpp b/radio/src/storage/conversions/conversions_216_218.cpp
similarity index 92%
rename from radio/src/storage/eeprom_conversions.cpp
rename to radio/src/storage/conversions/conversions_216_218.cpp
index 0046fb2d1..ddce57aef 100644
--- a/radio/src/storage/eeprom_conversions.cpp
+++ b/radio/src/storage/conversions/conversions_216_218.cpp
@@ -19,6 +19,7 @@
*/
#include "opentx.h"
+#include "datastructs_218.h"
enum Mix216Sources {
MIXSRC216_NONE,
@@ -376,22 +377,22 @@ PACK(typedef struct {
int8_t swtch;
uint8_t func;
PACK(union {
- PACK(struct {
- char name[8];
- }) play;
+ PACK(struct {
+ char name[8];
+ }) play;
- PACK(struct {
- int16_t val;
- uint8_t mode;
- uint8_t param;
- int32_t spare2;
- }) all;
+ PACK(struct {
+ int16_t val;
+ uint8_t mode;
+ uint8_t param;
+ int32_t spare2;
+ }) all;
- PACK(struct {
- int32_t val1;
- int32_t val2;
- }) clear;
- });
+ PACK(struct {
+ int32_t val1;
+ int32_t val2;
+ }) clear;
+ });
uint8_t active;
}) CustomFunctionData_v216;
#else
@@ -436,8 +437,8 @@ typedef union {
PACK(struct FrSkyChannelData_v216 {
- uint8_t unused[7];
-});
+ uint8_t unused[7];
+ });
PACK(typedef struct {
@@ -486,6 +487,34 @@ PACK(typedef struct {
uint8_t ppmPulsePol;
}) ModuleData_v216;
+PACK(typedef struct {
+ uint8_t type:4;
+ int8_t rfProtocol:4;
+ uint8_t channelsStart;
+ int8_t channelsCount; // 0=8 channels
+ union {
+ struct {
+ uint8_t failsafeMode:4; // only 3 bits used
+ uint8_t subType:3;
+ uint8_t invertedSerial:1; // telemetry serial inverted from standard
+ };
+ struct {
+ uint8_t failsafeMode:4; // only 3 bits used
+ uint8_t freq:2;
+ uint8_t region:2;
+ } r9m;
+ };
+ int16_t failsafeChannels[MAX_OUTPUT_CHANNELS];
+ union {
+ struct {
+ int8_t delay:6;
+ uint8_t pulsePol:1;
+ uint8_t outputType:1; // false = open drain, true = push pull
+ int8_t frameLength;
+ } ppm;
+ };
+}) ModuleData_v217;
+
#if defined(PCBTARANIS)
#define MODELDATA_EXTRA_216 \
uint8_t externalModule; \
@@ -511,7 +540,7 @@ PACK(typedef struct {
uint8_t spare:3; \
uint8_t trainerMode:3; \
uint8_t potsWarnMode:2; \
- ModuleData moduleData[NUM_MODULES+1]; \
+ ModuleData_v217 moduleData[NUM_MODULES+1]; \
char curveNames[MAX_CURVES][6]; \
ScriptData scriptsData[MAX_SCRIPTS]; \
char inputNames[MAX_INPUTS][LEN_INPUT_NAME]; \
@@ -521,7 +550,7 @@ PACK(typedef struct {
#define MODELDATA_EXTRA_217 \
uint8_t spare:6; \
uint8_t potsWarnMode:2; \
- ModuleData moduleData[NUM_MODULES+1]; \
+ ModuleData_v217 moduleData[NUM_MODULES+1]; \
uint8_t potsWarnEnabled; \
int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]; \
uint8_t rxBattAlarms[2];
@@ -766,7 +795,7 @@ PACK(typedef struct {
int8_t varioRange;
int8_t varioRepeat;
int8_t backgroundVolume;
-
+
TARANIS_FIELD(uint8_t serial2Mode:6)
TARANIS_FIELD(uint8_t slidersConfig:2)
TARANIS_FIELD(uint8_t potsConfig)
@@ -782,7 +811,7 @@ PACK(typedef struct {
TARANIS_PCBX9E_FIELD(char bluetoothName[LEN_BLUETOOTH_NAME])
}) RadioData_v216;
-void ConvertRadioData_216_to_217(RadioData & settings)
+void convertRadioData_216_to_217(RadioData &settings)
{
RadioData_v216 * settings_v216 = (RadioData_v216 *)&settings;
settings_v216->version = 217;
@@ -792,11 +821,11 @@ void ConvertRadioData_216_to_217(RadioData & settings)
#endif
}
-void ConvertSpecialFunctions_217_to_218(CustomFunctionData * cf218, CustomFunctionData_v216 * cf216)
+void ConvertSpecialFunctions_217_to_218(CustomFunctionData_v218 * cf218, CustomFunctionData_v216 * cf216)
{
for (int i=0; i= 212
- lcdDrawRect(60, 6*FH+4, 132, 3);
-#else
- lcdDrawRect(10, 6*FH+4, 102, 3);
-#endif
-
- // Models conversion
- for (uint8_t id=0; id= 212
- lcdDrawSolidHorizontalLine(61, 6*FH+5, 10+id*2, FORCE);
-#else
- lcdDrawSolidHorizontalLine(11, 6*FH+5, 10+(id*3)/2, FORCE);
-#endif
- lcdRefresh();
- if (eeModelExists(id)) {
- ConvertModel(id, conversionVersionStart);
- }
-
- }
-
- return true;
-}
diff --git a/radio/src/storage/conversions/conversions_218_219.cpp b/radio/src/storage/conversions/conversions_218_219.cpp
new file mode 100644
index 000000000..8b2983afc
--- /dev/null
+++ b/radio/src/storage/conversions/conversions_218_219.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "opentx.h"
+#include "datastructs_218.h"
+
+/*
+ * PCBHORUS: 64 telemetry sensors instead of 32
+ * ALL: ReceiverData array added
+ * ALL: registrationId added
+ * ALL: failsafeChannels moved from ModuleData to ModelData
+ * ALL: ModuleData / TrainerModuleData modified
+ *
+ */
+
+typedef ModelData ModelData_v219;
+
+void convertModelData_218_to_219(ModelData &model)
+{
+ assert(sizeof(ModelData_v218) <= sizeof(ModelData));
+
+ ModelData_v218 oldModel;
+ memcpy(&oldModel, &model, sizeof(oldModel));
+ ModelData_v219 & newModel = (ModelData_v219 &) model;
+
+ memset(&newModel.rssiAlarms + sizeof(RssiAlarmData), 0, sizeof(ModelData_v219) - offsetof(ModelData_v219, rssiAlarms) - sizeof(RssiAlarmData));
+
+ char name[LEN_MODEL_NAME+1];
+ zchar2str(name, oldModel.header.name, LEN_MODEL_NAME);
+ TRACE("Model %s conversion from v218 to v219", name);
+
+ for (int i=0; i off, abs, stk, stk%, sw/!sw, !m_sw/!m_sw
+ uint32_t start:23;
+ int32_t value:24;
+ uint32_t countdownBeep:2;
+ uint32_t minuteBeep:1;
+ uint32_t persistent:2;
+ int32_t countdownStart:2;
+ uint32_t direction:1;
+ char name[LEN_TIMER_NAME_218];
+}) TimerData_v218;
+
+PACK(typedef struct {
+ trim_t trim[NUM_STICKS];
+ char name[LEN_FLIGHT_MODE_NAME_218];
+ int16_t swtch:9; // swtch of phase[0] is not used
+ int16_t spare:7;
+ uint8_t fadeIn;
+ uint8_t fadeOut;
+ int16_t rotaryEncoders[1];
+ gvar_t gvars[9];
+}) FlightModeData_v218;
+
+PACK(typedef struct {
+ int16_t weight:11; // GV1=-1024, -GV1=1023
+ uint16_t destCh:5;
+ uint16_t srcRaw:10; // srcRaw=0 means not used
+ uint16_t carryTrim:1;
+ uint16_t mixWarn:2; // mixer warning
+ uint16_t mltpx:2; // multiplex method: 0 means +=, 1 means *=, 2 means :=
+ uint16_t spare:1;
+ int32_t offset:14;
+ int32_t swtch:9;
+ uint32_t flightModes:9;
+ CurveRef curve;
+ uint8_t delayUp;
+ uint8_t delayDown;
+ uint8_t speedUp;
+ uint8_t speedDown;
+ char name[LEN_EXPOMIX_NAME_218];
+}) MixData_v218;
+
+PACK(typedef struct {
+ uint16_t mode:2;
+ uint16_t scale:14;
+ uint16_t srcRaw:10;
+ int16_t carryTrim:6;
+ uint32_t chn:5;
+ int32_t swtch:9;
+ uint32_t flightModes:9;
+ int32_t weight:8;
+ int32_t spare:1;
+ char name[LEN_EXPOMIX_NAME_218];
+ int8_t offset;
+ CurveRef curve;
+}) ExpoData_v218;
+
+PACK(typedef struct {
+ uint8_t type:1;
+ uint8_t smooth:1;
+ int8_t points:6; // describes number of points - 5
+ char name[LEN_CURVE_NAME_218];
+}) CurveData_v218;
+
+PACK(typedef struct {
+ int16_t calib[4];
+ TrainerMix mix[4];
+}) TrainerData_v218;
+
+PACK(typedef struct { // Logical Switches data
+ uint8_t func;
+ int32_t v1:10;
+ int32_t v3:10;
+ int32_t andsw:9;
+ uint32_t andswtype:1;
+ uint32_t spare:2;
+ int16_t v2;
+ uint8_t delay;
+ uint8_t duration;
+}) LogicalSwitchData_v218;
+
+PACK(typedef struct {
+ int16_t swtch:9;
+ uint16_t func:7;
+ PACK(union {
+ PACK(struct {
+ char name[8];
+ }) play;
+
+ PACK(struct {
+ int16_t val;
+ uint8_t mode;
+ uint8_t param;
+ int32_t spare2;
+ }) all;
+
+ PACK(struct {
+ int32_t val1;
+ int32_t val2;
+ }) clear;
+ });
+ uint8_t active;
+}) CustomFunctionData_v218;
+
+PACK(typedef struct {
+ char name[6];
+ uint32_t min:12;
+ uint32_t max:12;
+ uint32_t popup:1;
+ uint32_t prec:1;
+ uint32_t unit:2;
+ uint32_t spare:4;
+}) GVarData_v218;
+
+#if defined(PCBX12S)
+#define MODELDATA_EXTRA_218 uint8_t spare:3;uint8_t trainerMode:3;uint8_t potsWarnMode:2; ModuleData_v218 moduleData[NUM_MODULES+1];ScriptData scriptsData[MAX_SCRIPTS_218];char inputNames[MAX_INPUTS_218][LEN_INPUT_NAME_218];;uint8_t potsWarnEnabled;;int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS];;
+#elif defined(PCBX10)
+#define MODELDATA_EXTRA_218 uint8_t spare:3;;uint8_t trainerMode:3;;uint8_t potsWarnMode:2;; ModuleData_v218 moduleData[NUM_MODULES+1];ScriptData scriptsData[MAX_SCRIPTS_218];;char inputNames[MAX_INPUTS_218][LEN_INPUT_NAME_218];;uint8_t potsWarnEnabled;;int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS];;uint8_t potsWarnSpares[NUM_DUMMY_ANAS];;
+#elif defined(PCBTARANIS)
+#define MODELDATA_EXTRA_218 uint8_t spare:3; uint8_t trainerMode:3; uint8_t potsWarnMode:2; ModuleData_v218 moduleData[NUM_MODULES+1]; ScriptData scriptsData[MAX_SCRIPTS_218]; char inputNames[MAX_INPUTS_218][LEN_INPUT_NAME_218]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS];
+#elif defined(PCBSKY9X)
+#define MODELDATA_EXTRA_218 uint8_t spare:6; uint8_t potsWarnMode:2; ModuleData_v218 moduleData[NUM_MODULES+1]; char inputNames[MAX_INPUTS_218][LEN_INPUT_NAME_218]; uint8_t potsWarnEnabled; int8_t potsWarnPosition[NUM_POTS+NUM_SLIDERS]; uint8_t rxBattAlarms[2];
+#else
+ #define MODELDATA_EXTRA_218
+#endif
+
+PACK(typedef struct {
+ ModelHeader header;
+ TimerData_v218 timers[MAX_TIMERS_218];
+ uint8_t telemetryProtocol:3;
+ uint8_t thrTrim:1; // Enable Throttle Trim
+ uint8_t noGlobalFunctions:1;
+ uint8_t displayTrims:2;
+ uint8_t ignoreSensorIds:1;
+ int8_t trimInc:3; // Trim Increments
+ uint8_t disableThrottleWarning:1;
+ uint8_t displayChecklist:1;
+ uint8_t extendedLimits:1;
+ uint8_t extendedTrims:1;
+ uint8_t throttleReversed:1;
+ BeepANACenter beepANACenter;
+ MixData_v218 mixData[MAX_MIXERS_218];
+ LimitData limitData[MAX_OUTPUT_CHANNELS_218];
+ ExpoData_v218 expoData[MAX_EXPOS_218];
+
+ CurveData_v218 curves[MAX_CURVES_218];
+ int8_t points[MAX_CURVE_POINTS_218];
+
+ LogicalSwitchData_v218 logicalSw[32];
+ CustomFunctionData_v218 customFn[MAX_SPECIAL_FUNCTIONS_218];
+ SwashRingData swashR;
+ FlightModeData_v218 flightModeData[MAX_FLIGHT_MODES_218];
+
+ uint8_t thrTraceSrc;
+
+ swarnstate_t switchWarningState;
+ swarnenable_t switchWarningEnable;
+
+ GVarData_v218 gvars[MAX_GVARS_218];
+
+ FrSkyTelemetryData frsky;
+ RssiAlarmData rssiAlarms;
+
+ MODELDATA_EXTRA_218
+
+ TelemetrySensor telemetrySensors[MAX_TELEMETRY_SENSORS_218];
+
+ TARANIS_PCBX9E_FIELD(uint8_t toplcdTimer)
+}) ModelData_v218;
+
+#define EXTRA_GENERAL_FIELDS_GENERAL_218 \
+ uint8_t backlightBright; \
+ uint32_t globalTimer; \
+ uint8_t bluetoothBaudrate:4; \
+ uint8_t bluetoothMode:4; \
+ uint8_t countryCode; \
+ uint8_t imperial:1; \
+ uint8_t jitterFilter:1; /* 0 - active */\
+ uint8_t disableRssiPoweroffAlarm:1; \
+ uint8_t USBMode:2; \
+ uint8_t spareExtraArm:3; \
+ char ttsLanguage[2]; \
+ int8_t beepVolume:4; \
+ int8_t wavVolume:4; \
+ int8_t varioVolume:4; \
+ int8_t backgroundVolume:4; \
+ int8_t varioPitch; \
+ int8_t varioRange; \
+ int8_t varioRepeat; \
+ CustomFunctionData_v218 customFn[MAX_SPECIAL_FUNCTIONS_218];
+
+#if defined(PCBHORUS)
+#define EXTRA_GENERAL_FIELDS_218 \
+ EXTRA_GENERAL_FIELDS_GENERAL_218 \
+ uint8_t serial2Mode:4; \
+ uint8_t slidersConfig:4; \
+ uint32_t switchConfig; \
+ uint8_t potsConfig; /* two bits per pot */ \
+ char switchNames[NUM_SWITCHES_218][LEN_SWITCH_NAME_218]; \
+ char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_DUMMY_ANAS][LEN_ANA_NAME_218]; \
+ char currModelFilename[LEN_MODEL_FILENAME_218+1]; \
+ uint8_t spare:1; \
+ uint8_t blOffBright:7; \
+ char bluetoothName[LEN_BLUETOOTH_NAME_218];
+#elif defined(PCBTARANIS)
+#if defined(BLUETOOTH)
+#define BLUETOOTH_FIELDS_218 \
+ uint8_t spare; \
+ char bluetoothName[LEN_BLUETOOTH_NAME_218];
+#else
+#define BLUETOOTH_FIELDS
+#endif
+#define EXTRA_GENERAL_FIELDS_218 \
+ EXTRA_GENERAL_FIELDS_GENERAL_218 \
+ uint8_t serial2Mode:4; \
+ uint8_t slidersConfig:4; \
+ uint8_t potsConfig; /* two bits per pot */\
+ uint8_t backlightColor; \
+ swarnstate_t switchUnlockStates; \
+ swconfig_t switchConfig; \
+ char switchNames[NUM_SWITCHES_218][LEN_SWITCH_NAME_218]; \
+ char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME_218]; \
+ BLUETOOTH_FIELDS
+#elif defined(PCBSKY9X)
+#define EXTRA_GENERAL_FIELDS_218 \
+ EXTRA_GENERAL_FIELDS_GENERAL_218 \
+ int8_t txCurrentCalibration; \
+ int8_t temperatureWarn; \
+ uint8_t mAhWarn; \
+ uint16_t mAhUsed; \
+ int8_t temperatureCalib; \
+ uint8_t optrexDisplay; \
+ uint8_t sticksGain; \
+ uint8_t rotarySteps; \
+ char switchNames[NUM_SWITCHES_218][LEN_SWITCH_NAME_218]; \
+ char anaNames[NUM_STICKS+NUM_POTS+NUM_SLIDERS][LEN_ANA_NAME_218];
+#elif defined(CPUARM)
+ #define EXTRA_GENERAL_FIELDS_218 EXTRA_GENERAL_FIELDS_GENERAL_218
+#elif defined(PXX)
+ #define EXTRA_GENERAL_FIELDS_218 uint8_t countryCode;
+#else
+ #define EXTRA_GENERAL_FIELDS_218
+#endif
+
+#if defined(PCBHORUS)
+#define SPLASH_MODE_218 uint8_t splashSpares:3
+#elif defined(FSPLASH)
+#define SPLASH_MODE_218 uint8_t splashMode:3
+#else
+#define SPLASH_MODE_218 int8_t splashMode:3
+#endif
+
+PACK(typedef struct {
+ uint8_t version;
+ uint16_t variant;
+ CalibData calib[NUM_STICKS+NUM_POTS+NUM_SLIDERS+NUM_MOUSE_ANALOGS+NUM_DUMMY_ANAS];
+ uint16_t chkSum;
+ N_HORUS_FIELD(int8_t currModel);
+ N_HORUS_FIELD(uint8_t contrast);
+ uint8_t vBatWarn;
+ int8_t txVoltageCalibration;
+ int8_t backlightMode;
+ TrainerData_v218 trainer;
+ uint8_t view; // index of view in main screen
+ BUZZER_FIELD_218
+ uint8_t fai:1;
+ int8_t beepMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all
+ uint8_t alarmsFlash:1;
+ uint8_t disableMemoryWarning:1;
+ uint8_t disableAlarmWarning:1;
+ uint8_t stickMode:2;
+ int8_t timezone:5;
+ uint8_t adjustRTC:1;
+ uint8_t inactivityTimer;
+ SPLASH_MODE_218; /* 3bits */
+ int8_t hapticMode:2; // -2=quiet, -1=only alarms, 0=no keys, 1=all
+ uint8_t lightAutoOff;
+ uint8_t templateSetup; // RETA order for receiver channels
+ int8_t PPM_Multiplier;
+ int8_t hapticLength;
+ N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t reNavigation));
+ N_HORUS_FIELD(N_TARANIS_FIELD(uint8_t stickReverse));
+ int8_t beepLength:3;
+ int8_t hapticStrength:3;
+ uint8_t gpsFormat:1;
+ uint8_t unexpectedShutdown:1;
+ uint8_t speakerPitch;
+ int8_t speakerVolume;
+ int8_t vBatMin;
+ int8_t vBatMax;
+
+ EXTRA_GENERAL_FIELDS_218
+
+ THEME_DATA
+}) RadioData_v218;
+
+#endif //OPENTX_DATASTRUCTS_218_H
diff --git a/radio/src/storage/datacopy.cpp b/radio/src/storage/datacopy.cpp
index 8b4d95cdd..ebbca4595 100644
--- a/radio/src/storage/datacopy.cpp
+++ b/radio/src/storage/datacopy.cpp
@@ -1,4 +1,4 @@
-//This file was auto-generated by generate_datacopy.py script on Mon Jul 2 14:20:48 2018. Do not edit this file!
+//This file was auto-generated by generate_datacopy.py script on Tue Mar 19 19:58:50 2019. Do not edit this file!
@@ -193,6 +193,27 @@ void copyTelemetrySensor(A * dest, B * src)
dest->param = src->param;
}
+template
+void copyTrainerModuleData(A * dest, B * src)
+{
+ dest->mode = src->mode;
+ dest->spare = src->spare;
+ dest->channelsStart = src->channelsStart;
+ dest->channelsCount = src->channelsCount;
+ dest->frameLength = src->frameLength;
+ dest->delay = src->delay;
+ dest->pulsePol = src->pulsePol;
+}
+
+template
+void copyReceiverData(A * dest, B * src)
+{
+ dest->used = src->used;
+ dest->telemetry = src->telemetry;
+ dest->dirty = src->dirty;
+ memcpy(dest->name, src->name, sizeof(dest->name));
+}
+
template
void copyModuleData(A * dest, B * src)
{
@@ -200,10 +221,7 @@ void copyModuleData(A * dest, B * src)
dest->rfProtocol = src->rfProtocol;
dest->channelsStart = src->channelsStart;
dest->channelsCount = src->channelsCount;
- dest->failsafeMode = src->failsafeMode;
- dest->subType = src->subType;
- dest->invertedSerial = src->invertedSerial;
- memcpy(dest->failsafeChannels, src->failsafeChannels, sizeof(dest->failsafeChannels));
+ copyModuleData_r9m(&dest->r9m, &src->r9m);
copyModuleData_ppm(&dest->ppm, &src->ppm);
}
@@ -266,9 +284,15 @@ void copyModelData(A * dest, B * src)
for (int i=0; i<9; i++) {
copyGVarData(&dest->gvars[i], &src->gvars[i]);
}
- for (int i=0; i<3; i++) {
+ for (int i=0; i<2; i++) {
copyModuleData(&dest->moduleData[i], &src->moduleData[i]);
}
+ for (int i=0; i<10; i++) {
+ copyReceiverData(&dest->receiverData[i], &src->receiverData[i]);
+ }
+ memcpy(dest->failsafeChannels, src->failsafeChannels, sizeof(dest->failsafeChannels));
+ copyTrainerModuleData(&dest->trainerData, &src->trainerData);
+ memcpy(dest->modelRegistrationID, src->modelRegistrationID, sizeof(dest->modelRegistrationID));
}
template
@@ -306,6 +330,7 @@ void copyRadioData(A * dest, B * src)
for (int i=0; i<13; i++) {
copyCalibData(&dest->calib[i], &src->calib[i]);
}
+ dest->spareRadio = src->spareRadio;
dest->stickMode = src->stickMode;
dest->telemetryBaudrate = src->telemetryBaudrate;
dest->splashSpares = src->splashSpares;
@@ -316,6 +341,7 @@ void copyRadioData(A * dest, B * src)
dest->slidersConfig = src->slidersConfig;
dest->switchConfig = src->switchConfig;
dest->potsConfig = src->potsConfig;
+ memcpy(dest->ownerRegistrationID, src->ownerRegistrationID, sizeof(dest->ownerRegistrationID));
}
template
@@ -326,6 +352,14 @@ void copyCustomFunctionData_all(A * dest, B * src)
dest->param = src->param;
}
+template
+void copyModuleData_r9m(A * dest, B * src)
+{
+ dest->failsafeMode = src->failsafeMode;
+ dest->freq = src->freq;
+ dest->region = src->region;
+}
+
template
void copyModuleData_ppm(A * dest, B * src)
{
diff --git a/radio/src/storage/eeprom_common.h b/radio/src/storage/eeprom_common.h
index 0e994dc16..00c840c03 100644
--- a/radio/src/storage/eeprom_common.h
+++ b/radio/src/storage/eeprom_common.h
@@ -25,8 +25,6 @@ uint16_t eeLoadGeneralSettingsData();
bool eeModelExists(uint8_t id);
void eeLoadModel(uint8_t id);
-bool eeConvert();
-void ConvertModel(int id, int version);
uint8_t eeFindEmptyModel(uint8_t id, bool down);
void selectModel(uint8_t sub);
diff --git a/radio/src/storage/eeprom_raw.cpp b/radio/src/storage/eeprom_raw.cpp
index 78ec6f677..b7867d7d7 100644
--- a/radio/src/storage/eeprom_raw.cpp
+++ b/radio/src/storage/eeprom_raw.cpp
@@ -23,6 +23,7 @@
#include
#include "opentx.h"
#include "timers.h"
+#include "conversions/conversions.h"
#define EEPROM_MARK 0x84697771 /* thanks ;) */
#define EEPROM_ZONE_SIZE (8*1024)
@@ -584,7 +585,7 @@ const char * eeRestoreModel(uint8_t i_fileDst, char *model_name)
#if defined(EEPROM_CONVERSIONS)
if (version < EEPROM_VER) {
- ConvertModel(i_fileDst, version);
+ convertModelData(i_fileDst, version);
eeLoadModel(g_eeGeneral.currModel);
}
#endif
diff --git a/radio/src/storage/eeprom_raw.h b/radio/src/storage/eeprom_raw.h
index 64ac9f182..ca2b50f82 100644
--- a/radio/src/storage/eeprom_raw.h
+++ b/radio/src/storage/eeprom_raw.h
@@ -29,8 +29,6 @@ void eeDeleteModel( uint8_t id ) ;
bool eeCopyModel(uint8_t dst, uint8_t src);
void eeSwapModels(uint8_t id1, uint8_t id2);
-#define DISPLAY_PROGRESS_BAR(x)
-
#if defined(SDCARD)
const char * eeBackupModel(uint8_t i_fileSrc);
const char * eeRestoreModel(uint8_t i_fileDst, char *model_name);
diff --git a/radio/src/storage/eeprom_rlc.cpp b/radio/src/storage/eeprom_rlc.cpp
index 81a621790..4eda3f925 100644
--- a/radio/src/storage/eeprom_rlc.cpp
+++ b/radio/src/storage/eeprom_rlc.cpp
@@ -22,6 +22,7 @@
#include
#include "opentx.h"
#include "timers.h"
+#include "conversions/conversions.h"
uint8_t s_write_err = 0; // error reasons
RlcFile theFile; //used for any file operation
@@ -467,7 +468,7 @@ const char * eeBackupModel(uint8_t i_fileSrc)
len = i+1;
if (len) {
if (buf[i])
- buf[i] = idx2char(buf[i]);
+ buf[i] = zchar2char(buf[i]);
else
buf[i] = '_';
}
@@ -596,7 +597,7 @@ const char * eeRestoreModel(uint8_t i_fileDst, char *model_name)
#if defined(EEPROM_CONVERSIONS)
if (version < EEPROM_VER) {
storageCheck(true);
- ConvertModel(i_fileDst, version);
+ convertModelData(i_fileDst, version);
eeLoadModel(g_eeGeneral.currModel);
}
#endif
@@ -615,9 +616,6 @@ void RlcFile::writeRlc(uint8_t i_fileId, uint8_t typ, uint8_t *buf, uint16_t i_l
m_rlc_buf = buf;
m_rlc_len = i_len;
m_cur_rlc_len = 0;
-#if defined (EEPROM_PROGRESS_BAR)
- m_ratio = (typ == FILE_TYP_MODEL ? 100 : 10);
-#endif
do {
nextRlcWriteStep();
@@ -742,17 +740,6 @@ void RlcFile::flush()
ENABLE_SYNC_WRITE(false);
}
-#if defined (EEPROM_PROGRESS_BAR)
-void RlcFile::drawProgressBar(uint8_t x)
-{
- if (storageDirtyMsk || isWriting() || eeprom_buffer_size) {
- uint8_t len = storageDirtyMsk ? 1 : limit((uint8_t)1, (uint8_t)(7 - (m_rlc_len/m_ratio)), (uint8_t)7);
- lcdDrawFilledRect(x+1, 0, 5, FH, SOLID, ERASE);
- lcdDrawFilledRect(x+2, 7-len, 3, len);
- }
-}
-#endif
-
// For conversions ...
uint16_t eeLoadGeneralSettingsData()
{
@@ -880,7 +867,7 @@ void eeDeleteModel(uint8_t idx)
#if defined(SDCARD)
void eepromBackup()
{
- char filename[60];
+ char path[60];
uint8_t buffer[1024];
FIL file;
@@ -897,20 +884,20 @@ void eepromBackup()
}
// prepare the filename...
- char * tmp = strAppend(filename, EEPROMS_PATH "/eeprom");
+ char * tmp = strAppend(path, EEPROMS_PATH "/eeprom");
#if defined(RTCLOCK)
tmp = strAppendDate(tmp, true);
#endif
strAppend(tmp, EEPROM_EXT);
// open the file for writing...
- f_open(&file, filename, FA_WRITE | FA_CREATE_ALWAYS);
+ f_open(&file, path, FA_WRITE | FA_CREATE_ALWAYS);
for (int i=0; i= 10 ? hex-9 : 27+hex);
}
-char idx2char(int8_t idx)
+char zchar2char(int8_t idx)
{
if (idx == 0) return ' ';
if (idx < 0) {
@@ -44,7 +44,7 @@ char idx2char(int8_t idx)
return ' ';
}
-int8_t char2idx(char c)
+int8_t char2zchar(char c)
{
if (c == '_') return 37;
#if LEN_SPECIAL_CHARS > 0
@@ -63,14 +63,14 @@ void str2zchar(char * dest, const char * src, int size)
{
memset(dest, 0, size);
for (int c=0; c 0) {
@@ -122,7 +132,7 @@ char * strcat_zchar(char * dest, const char * name, uint8_t size, const char * d
len = i+1;
if (len) {
if (dest[i])
- dest[i] = idx2char(dest[i]);
+ dest[i] = zchar2char(dest[i]);
else
dest[i] = '_';
}
@@ -266,7 +276,7 @@ char * getSwitchString(char * dest, swsrc_t idx)
else
*s++ = 'A'+swinfo.quot;
#else
- *s++ = 'A'+swinfo.quot;
+ *s++ = 'A' + swinfo.quot;
#endif
}
*s++ = "\300-\301"[swinfo.rem];
diff --git a/radio/src/switches.cpp b/radio/src/switches.cpp
index 7eb1f12af..c180f67aa 100644
--- a/radio/src/switches.cpp
+++ b/radio/src/switches.cpp
@@ -132,17 +132,29 @@ void getSwitchesPosition(bool startup)
CHECK_3POS(0, SW_SA);
CHECK_3POS(1, SW_SB);
CHECK_3POS(2, SW_SC);
+#if !defined(PCBX3)
CHECK_3POS(3, SW_SD);
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#endif
+#if defined(PCBXLITES) || defined(PCBX3)
+ CHECK_2POS(SW_SE);
+#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX3)
+ // No SE
+#else
CHECK_3POS(4, SW_SE);
#endif
-#if !defined(PCBXLITE)
+#if defined(PCBXLITE) && !defined(PCBXLITES)
+ // No SF
+#else
CHECK_2POS(SW_SF);
#endif
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#if defined(PCBX7) || defined(PCBXLITE) || defined(PCBX3)
+ // No SG
+#else
CHECK_3POS(5, SW_SG);
#endif
-#if !defined(PCBXLITE)
+#if defined(PCBXLITE) || defined(PCBX3)
+ // No SH
+#else
CHECK_2POS(SW_SH);
#endif
#if defined(PCBX9E)
diff --git a/radio/src/targets/common/arm/CMakeLists.txt b/radio/src/targets/common/arm/CMakeLists.txt
index 51110e88b..d60248f3a 100644
--- a/radio/src/targets/common/arm/CMakeLists.txt
+++ b/radio/src/targets/common/arm/CMakeLists.txt
@@ -8,6 +8,7 @@ option(TRACE_FATFS "Traces FatFS enabled" OFF)
option(TRACE_AUDIO "Traces audio enabled" OFF)
option(DEBUG_TRACE_BUFFER "Debug Trace Screen" OFF)
option(MULTIMODULE "DIY Multiprotocol TX Module (https://github.com/pascallanger/DIY-Multiprotocol-TX-Module)" OFF)
+option(CROSSFIRE "Crossfire TX Module" OFF)
option(SUPPORT_D16_EU_ONLY "XJT module only supports D16-EU and LR12-EU" OFF) # TODO rename to XJT_EU_ONLY
option(DEBUG_INTERRUPTS "Count interrupts" OFF)
option(DEBUG_USB_INTERRUPTS "Count individual USB interrupts" OFF)
@@ -19,27 +20,33 @@ if(TIMERS EQUAL 3)
else()
add_definitions(-DTIMERS=2)
endif()
+
if(LOG_TELEMETRY)
add_definitions(-DLOG_TELEMETRY)
endif()
+
if(TRACE_SD_CARD)
add_definitions(-DTRACE_SD_CARD)
set(DEBUG ON)
set(DEBUG_TRACE_BUFFER ON)
endif()
+
if(TRACE_FATFS)
add_definitions(-DTRACE_FATFS)
set(DEBUG ON)
set(DEBUG_TRACE_BUFFER ON)
endif()
+
if(TRACE_AUDIO)
add_definitions(-DTRACE_AUDIO)
set(DEBUG ON)
set(DEBUG_TRACE_BUFFER ON)
endif()
+
if(DEBUG_TRACE_BUFFER)
add_definitions(-DDEBUG_TRACE_BUFFER)
endif()
+
if(DEBUG_INTERRUPTS)
add_definitions(-DDEBUG_INTERRUPTS)
set(DEBUG ON)
@@ -47,14 +54,17 @@ if(DEBUG_INTERRUPTS)
add_definitions(-DDEBUG_USB_INTERRUPTS)
endif()
endif()
+
if(DEBUG_TASKS)
add_definitions(-DDEBUG_TASKS)
set(DEBUG ON)
endif()
+
if(DEBUG_TIMERS)
add_definitions(-DDEBUG_TIMERS)
set(DEBUG ON)
endif()
+
if(CLI)
add_definitions(-DCLI)
set(FIRMWARE_SRC ${FIRMWARE_SRC} cli.cpp)
@@ -62,23 +72,61 @@ if(CLI)
elseif(DEBUG)
set(SRC ${SRC} dump.cpp)
endif()
+
if(DEBUG)
add_definitions(-DDEBUG)
endif()
+
if(SUPPORT_D16_EU_ONLY)
add_definitions(-DMODULE_D16_EU_ONLY_SUPPORT)
endif()
+
if(HAPTIC)
add_definitions(-DHAPTIC)
set(SRC ${SRC} haptic.cpp)
set(TARGET_SRC ${TARGET_SRC} haptic_driver.cpp)
endif()
+
+# Protocols supported
+
+add_definitions(-DDSM2 -DSBUS)
+
+if(PXX1)
+ add_definitions(-DPXX -DPXX1)
+ set(PULSES_SRC
+ ${PULSES_SRC}
+ pxx1.cpp
+ )
+endif()
+
+if(PXX2)
+ add_definitions(-DPXX -DPXX2)
+ set(PULSES_SRC
+ ${PULSES_SRC}
+ pxx2.cpp
+ )
+endif()
+
if(MULTIMODULE)
add_definitions(-DMULTIMODULE)
- set(SRC ${SRC} pulses/multi_arm.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/multi.cpp)
+ set(SRC ${SRC} pulses/multi.cpp telemetry/spektrum.cpp telemetry/flysky_ibus.cpp telemetry/multi.cpp)
endif()
+
+if(CROSSFIRE)
+ add_definitions(-DCROSSFIRE)
+ set(PULSES_SRC
+ ${PULSES_SRC}
+ crossfire.cpp
+ )
+ set(SRC
+ ${SRC}
+ telemetry/crossfire.cpp
+ )
+endif()
+
add_definitions(-DCPUARM)
-add_definitions(-DTELEMETRY_FRSKY -DTELEMETRY_FRSKY_SPORT -DGPS -DPXX -DDSM2)
+add_definitions(-DTELEMETRY_FRSKY -DTELEMETRY_FRSKY_SPORT -DGPS)
+
add_definitions(-DBOLD_FONT -DBATTGRAPH -DTHRTRACE)
add_definitions(-DREQUIRED_SDCARD_VERSION="${SDCARD_VERSION}")
include_directories(${COOS_DIR} ${COOS_DIR}/kernel ${COOS_DIR}/portable)
@@ -86,31 +134,36 @@ foreach(LANGUAGE ${TTS_LANGUAGES})
string(TOLOWER ${LANGUAGE} lang_lower)
set(SRC ${SRC} translations/tts_${lang_lower}.cpp)
endforeach()
+
set(SRC
${SRC}
- main_arm.cpp
- tasks_arm.cpp
- audio_arm.cpp
+ main.cpp
+ tasks.cpp
+ audio.cpp
io/frsky_sport.cpp
telemetry/telemetry.cpp
telemetry/telemetry_holders.cpp
telemetry/telemetry_sensors.cpp
telemetry/frsky.cpp
- telemetry/frsky_d_arm.cpp
+ telemetry/frsky_d.cpp
telemetry/frsky_sport.cpp
+ telemetry/frsky_pxx2.cpp
crc16.cpp
vario.cpp
)
+
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
diskio.cpp
)
+
set(TARGET_SRC
${TARGET_SRC}
pulses_driver.cpp
keys_driver.cpp
telemetry_driver.cpp
)
+
set(FIRMWARE_SRC
${FIRMWARE_SRC}
${COOS_DIR}/kernel/core.c
@@ -128,17 +181,8 @@ set(FIRMWARE_SRC
set(PULSES_SRC
${PULSES_SRC}
- pulses_arm.cpp
- ppm_arm.cpp
- pxx.cpp
- pxx1.cpp
- dsm2_arm.cpp
- sbus_arm.cpp
+ pulses.cpp
+ ppm.cpp
+ dsm2.cpp
+ sbus.cpp
)
-
-if(PXX2)
- set(PULSES_SRC
- ${PULSES_SRC}
- pxx2.cpp
- )
-endif()
diff --git a/radio/src/targets/common/arm/stm32/CMakeLists.txt b/radio/src/targets/common/arm/stm32/CMakeLists.txt
index 0398e2f74..e99cde823 100644
--- a/radio/src/targets/common/arm/stm32/CMakeLists.txt
+++ b/radio/src/targets/common/arm/stm32/CMakeLists.txt
@@ -8,7 +8,7 @@ option(USB_SERIAL "Enable USB serial (CDC)" OFF)
set(ARCH ARM)
set(STM32USB_DIR ${THIRDPARTY_DIR}/STM32_USB-Host-Device_Lib_V2.2.0/Libraries)
-add_definitions(-DSTM32 -DLUA_INPUTS -DVARIO -DCROSSFIRE)
+add_definitions(-DSTM32 -DLUA_INPUTS -DVARIO)
include_directories(${RADIO_SRC_DIRECTORY}/targets/common/arm/stm32)
include_directories(${STM32USB_DIR}/STM32_USB_OTG_Driver/inc)
@@ -53,6 +53,7 @@ if(DEBUG OR CLI OR USB_SERIAL)
)
add_definitions(-DUSB_SERIAL)
endif()
+
set(STM32USB_SRC
${STM32USB_SRC}
STM32_USB_Device_Library/Class/msc/src/usbd_msc_data.c
@@ -60,31 +61,37 @@ set(STM32USB_SRC
STM32_USB_Device_Library/Class/msc/src/usbd_msc_bot.c
STM32_USB_Device_Library/Class/msc/src/usbd_msc_core.c
)
+
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
../common/arm/stm32/usbd_storage_msd.cpp
)
+
set(FIRMWARE_TARGET_SRC
${FIRMWARE_TARGET_SRC}
../common/arm/stm32/usbd_hid_joystick.c
)
+
if(GVARS)
set(GUI_SRC
${GUI_SRC}
${GVAR_SCREEN}
)
endif()
+
set(FIRMWARE_SRC
${FIRMWARE_SRC}
serial.cpp
syscalls.c
)
+
foreach(FILE ${STM32LIB_SRC})
set(FIRMWARE_SRC
${FIRMWARE_SRC}
${STM32LIB_DIR}/${FILE}
)
endforeach()
+
foreach(FILE ${STM32USB_SRC})
set(FIRMWARE_SRC
${FIRMWARE_SRC}
@@ -94,11 +101,5 @@ endforeach()
set(SRC
${SRC}
- telemetry/crossfire.cpp
io/bootloader_flash.cpp
)
-
-set(PULSES_SRC
- ${PULSES_SRC}
- crossfire.cpp
- )
diff --git a/radio/src/targets/common/arm/stm32/adc_driver.cpp b/radio/src/targets/common/arm/stm32/adc_driver.cpp
index a96cfe8e3..eea2776fe 100644
--- a/radio/src/targets/common/arm/stm32/adc_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/adc_driver.cpp
@@ -38,6 +38,8 @@
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,1,-1, 1,1,-1, 1,1, 1};
#elif defined(PCBX7)
const int8_t ana_direction[NUM_ANALOGS] = {-1,1,-1,1, 1,1, 1};
+#elif defined(PCBX3)
+ const int8_t ana_direction[NUM_ANALOGS] = {-1,1,-1,1, 1,1};
#elif defined(PCBXLITE)
const int8_t ana_direction[NUM_ANALOGS] = {1,-1,-1,1, -1,1, 1};
#elif defined(REV4a)
@@ -58,7 +60,7 @@
#define NUM_ANALOGS_ADC NUM_ANALOGS
#endif
-uint16_t adcValues[NUM_ANALOGS] __DMA;
+uint16_t adcValues[NUM_ANALOGS + 1/*RTC*/] __DMA;
void adcInit()
{
@@ -90,7 +92,7 @@ void adcInit()
ADC_MAIN->CR1 = ADC_CR1_SCAN;
ADC_MAIN->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
- ADC_MAIN->SQR1 = (NUM_ANALOGS_ADC-1) << 20; // bits 23:20 = number of conversions
+ ADC_MAIN->SQR1 = (NUM_ANALOGS_ADC + 1/*RTC*/ - 1) << 20; // bits 23:20 = number of conversions
#if defined(PCBX10)
if (STICKS_PWM_ENABLED()) {
@@ -102,23 +104,26 @@ void adcInit()
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
}
#elif defined(PCBX9E)
- ADC_MAIN->SQR2 = (ADC_CHANNEL_POT4<<0) + (ADC_CHANNEL_SLIDER3<<5) + (ADC_CHANNEL_SLIDER4<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
+ ADC_MAIN->SQR2 = (ADC_CHANNEL_POT4<<0) + (ADC_CHANNEL_SLIDER3<<5) + (ADC_CHANNEL_SLIDER4<<10) + (ADC_CHANNEL_BATT<<15) + (ADC_CHANNEL_RTC<<20); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT2<<20) + (ADC_CHANNEL_POT3<<25); // conversions 1 to 6
#elif defined(PCBXLITE)
if (STICKS_PWM_ENABLED()) {
ADC_MAIN->SQR2 = 0;
- ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_BATT<<10);
+ ADC_MAIN->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_POT2<<5) + (ADC_CHANNEL_BATT<<10) + (ADC_CHANNEL_RTC<<15);
}
else {
- ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0);
+ ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0) + (ADC_CHANNEL_RTC<<5);
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
}
#elif defined(PCBX7)
// TODO why do we invert POT1 and POT2 here?
- ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0); // conversions 7 and more
+ ADC_MAIN->SQR2 = (ADC_CHANNEL_BATT<<0) + (ADC_CHANNEL_RTC<<5); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<25) + (ADC_CHANNEL_POT2<<20); // conversions 1 to 6
+#elif defined(PCBX3)
+ ADC_MAIN->SQR2 = (ADC_CHANNEL_RTC<<0); // conversions 7 and more
+ ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_BATT<<25); // conversions 1 to 6
#else
- ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15); // conversions 7 and more
+ ADC_MAIN->SQR2 = (ADC_CHANNEL_POT3<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10) + (ADC_CHANNEL_BATT<<15) + (ADC_CHANNEL_RTC<<20); // conversions 7 and more
ADC_MAIN->SQR3 = (ADC_CHANNEL_STICK_LH<<0) + (ADC_CHANNEL_STICK_LV<<5) + (ADC_CHANNEL_STICK_RV<<10) + (ADC_CHANNEL_STICK_RH<<15) + (ADC_CHANNEL_POT1<<20) + (ADC_CHANNEL_POT2<<25); // conversions 1 to 6
#endif
@@ -130,13 +135,13 @@ void adcInit()
ADC_DMA_Stream->CR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC;
ADC_DMA_Stream->PAR = CONVERT_PTR_UINT(&ADC_MAIN->DR);
ADC_DMA_Stream->M0AR = CONVERT_PTR_UINT(&adcValues[FIRST_ANALOG_ADC]);
- ADC_DMA_Stream->NDTR = NUM_ANALOGS_ADC;
+ ADC_DMA_Stream->NDTR = NUM_ANALOGS_ADC + 1/*RTC*/;
ADC_DMA_Stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0;
#if defined(PCBX9E)
ADC_EXT->CR1 = ADC_CR1_SCAN;
ADC_EXT->CR2 = ADC_CR2_ADON | ADC_CR2_DMA | ADC_CR2_DDS;
- ADC_EXT->SQR1 = (NUM_ANALOGS_ADC_EXT-1) << 20;
+ ADC_EXT->SQR1 = (NUM_ANALOGS_ADC_EXT - 1) << 20;
ADC_EXT->SQR2 = 0;
ADC_EXT->SQR3 = (ADC_CHANNEL_POT1<<0) + (ADC_CHANNEL_SLIDER1<<5) + (ADC_CHANNEL_SLIDER2<<10); // conversions 1 to 3
ADC_EXT->SMPR1 = 0;
@@ -223,6 +228,14 @@ void adcStop()
{
}
+uint16_t getRTCBattVoltage()
+{
+ ADC->CCR |= ADC_CCR_VBATE;
+ adcSingleRead();
+ ADC->CCR &= ADC_CCR_VBATE;
+ return adcValues[TX_RTC] * 330 / 2048;
+}
+
#if !defined(SIMU)
uint16_t getAnalogValue(uint8_t index)
{
diff --git a/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp b/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp
index 985b7b6f0..3f2bb898e 100644
--- a/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/bluetooth_driver.cpp
@@ -24,7 +24,7 @@ Fifo btTxFifo;
Fifo btRxFifo;
#if defined(PCBX7) || defined(PCBXLITE)
-uint8_t btChipPresent = 0;
+volatile uint8_t btChipPresent = 0;
#endif
enum BluetoothWriteState
@@ -40,15 +40,11 @@ volatile uint8_t bluetoothWriteState = BLUETOOTH_WRITE_IDLE;
void bluetoothInit(uint32_t baudrate)
{
GPIO_InitTypeDef GPIO_InitStructure;
- USART_InitTypeDef USART_InitStructure;
-
- USART_DeInit(BT_USART);
-
GPIO_InitStructure.GPIO_Pin = BT_EN_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(BT_EN_GPIO, &GPIO_InitStructure);
#if defined(BT_BRTS_GPIO_PIN)
@@ -63,32 +59,28 @@ void bluetoothInit(uint32_t baudrate)
GPIO_Init(BT_BCTS_GPIO, &GPIO_InitStructure);
#endif
- GPIO_InitStructure.GPIO_Pin = BT_TX_GPIO_PIN|BT_RX_GPIO_PIN;
+ GPIO_PinAFConfig(BT_USART_GPIO, BT_TX_GPIO_PinSource, BT_GPIO_AF);
+ GPIO_PinAFConfig(BT_USART_GPIO, BT_RX_GPIO_PinSource, BT_GPIO_AF);
+
+ GPIO_InitStructure.GPIO_Pin = BT_TX_GPIO_PIN | BT_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(BT_GPIO_TXRX, &GPIO_InitStructure);
-
- GPIO_PinAFConfig(BT_GPIO_TXRX, BT_TX_GPIO_PinSource, BT_GPIO_AF);
- GPIO_PinAFConfig(BT_GPIO_TXRX, BT_RX_GPIO_PinSource, BT_GPIO_AF);
+ GPIO_Init(BT_USART_GPIO, &GPIO_InitStructure);
USART_DeInit(BT_USART);
+ USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+ USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(BT_USART, &USART_InitStructure);
-
USART_Cmd(BT_USART, ENABLE);
- USART_ITConfig(BT_USART, USART_IT_RXNE, ENABLE);
- NVIC_InitTypeDef NVIC_InitStructure;
- NVIC_InitStructure.NVIC_IRQChannel = BT_USART_IRQn;
- NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 8;
- NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
- NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
- NVIC_Init(&NVIC_InitStructure);
+ USART_ITConfig(BT_USART, USART_IT_RXNE, ENABLE);
+ NVIC_SetPriority(BT_USART_IRQn, 6);
+ NVIC_EnableIRQ(BT_USART_IRQn);
btRxFifo.clear();
btTxFifo.clear();
diff --git a/radio/src/targets/common/arm/stm32/cpu_id.cpp b/radio/src/targets/common/arm/stm32/cpu_id.cpp
index ef8977d13..cd5a97a93 100644
--- a/radio/src/targets/common/arm/stm32/cpu_id.cpp
+++ b/radio/src/targets/common/arm/stm32/cpu_id.cpp
@@ -20,13 +20,14 @@
#include "opentx.h"
+#if defined(SIMU)
+const uint32_t cpu_uid[3] = { 0x12345678, 0x55AA55AA, 0x87654321};
+#else
+const uint32_t * cpu_uid = (uint32_t *)0x1FFF7A10;
+#endif
+
void getCPUUniqueID(char * s)
{
-#if defined(SIMU)
- uint32_t cpu_uid[3] = { 0x12345678, 0x55AA55AA, 0x87654321};
-#else
- uint32_t * cpu_uid = (uint32_t *)0x1FFF7A10;
-#endif
char * tmp = strAppendUnsigned(s, cpu_uid[0], 8, 16);
*tmp = ' ';
tmp = strAppendUnsigned(tmp+1, cpu_uid[1], 8, 16);
diff --git a/radio/src/targets/common/arm/stm32/cpu_id.h b/radio/src/targets/common/arm/stm32/cpu_id.h
new file mode 100644
index 000000000..eb95f8b3b
--- /dev/null
+++ b/radio/src/targets/common/arm/stm32/cpu_id.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+
+void getCPUUniqueID(char * s);
+
+#define LEN_CPU_UID (3*8+2)
+
+#if defined(SIMU)
+extern const uint32_t cpu_uid[3];
+#else
+extern const uint32_t * cpu_uid;
+#endif
\ No newline at end of file
diff --git a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp
index a930fd227..0f459d81d 100755
--- a/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/intmodule_serial_driver.cpp
@@ -20,43 +20,31 @@
#include "opentx.h"
+ModuleFifo intmoduleFifo;
+
void intmoduleStop()
{
- INTERNAL_MODULE_OFF();
-
- NVIC_DisableIRQ(INTMODULE_TIMER_IRQn);
+ GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
- INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE;
- INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
-}
-
-void intmoduleNoneStart()
-{
- INTERNAL_MODULE_OFF();
GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
- GPIO_SetBits(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PIN); // Set high
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_Init(INTMODULE_GPIO, &GPIO_InitStructure);
- INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
- INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
- INTMODULE_TIMER->ARR = 36000; // 18mS
- INTMODULE_TIMER->CCR2 = 32000; // Update time
- INTMODULE_TIMER->EGR = 1; // Restart
- INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
- INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
- INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
- NVIC_EnableIRQ(INTMODULE_TIMER_IRQn);
- NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7);
+ GPIO_ResetBits(INTMODULE_GPIO, INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN);
}
void intmodulePxxStart()
+{
+ intmoduleSerialStart(INTMODULE_PXX_BAUDRATE, false);
+}
+
+void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable)
{
INTERNAL_MODULE_ON();
@@ -67,97 +55,94 @@ void intmodulePxxStart()
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
- // TX Pin
- GPIO_PinAFConfig(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PinSource, INTMODULE_TX_GPIO_AF);
+ GPIO_PinAFConfig(INTMODULE_GPIO, INTMODULE_GPIO_PinSource_TX, INTMODULE_GPIO_AF);
+ GPIO_PinAFConfig(INTMODULE_GPIO, INTMODULE_GPIO_PinSource_RX, INTMODULE_GPIO_AF);
GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN | INTMODULE_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_Init(INTMODULE_GPIO, &GPIO_InitStructure);
- // RX Pin
- GPIO_PinAFConfig(INTMODULE_RX_GPIO, INTMODULE_RX_GPIO_PinSource, INTMODULE_TX_GPIO_AF);
- GPIO_InitStructure.GPIO_Pin = INTMODULE_RX_GPIO_PIN;
- GPIO_Init(INTMODULE_RX_GPIO, &GPIO_InitStructure);
-
- // UART config
USART_DeInit(INTMODULE_USART);
USART_InitTypeDef USART_InitStructure;
- USART_InitStructure.USART_BaudRate = INTMODULE_USART_PXX_BAUDRATE;
+ USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+ USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(INTMODULE_USART, &USART_InitStructure);
USART_Cmd(INTMODULE_USART, ENABLE);
- // Timer
- INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
- INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
- INTMODULE_TIMER->ARR = PXX_PERIOD_HALF_US;
- INTMODULE_TIMER->CCR2 = PXX_PERIOD_HALF_US - 2000; // Update time
- INTMODULE_TIMER->CCER = TIM_CCER_CC3E;
- INTMODULE_TIMER->CCMR2 = 0;
- INTMODULE_TIMER->EGR = 1; // Restart
-
- INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_0; // Toggle CC1 o/p
- INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
- INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
- INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
-
- NVIC_EnableIRQ(INTMODULE_TIMER_IRQn);
- NVIC_SetPriority(INTMODULE_TIMER_IRQn, 7);
+ if (rxEnable) {
+ intmoduleFifo.clear();
+ USART_ITConfig(INTMODULE_USART, USART_IT_RXNE, ENABLE);
+ NVIC_SetPriority(INTMODULE_USART_IRQn, 6);
+ NVIC_EnableIRQ(INTMODULE_USART_IRQn);
+ }
}
-extern "C" void INTMODULE_DMA_STREAM_IRQHandler(void)
+#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
+extern "C" void INTMODULE_USART_IRQHandler(void)
{
- DEBUG_INTERRUPT(INT_DMA2S7);
- if (DMA_GetITStatus(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC)) {
- // TODO we could send the 8 next channels here (when needed)
- DMA_ClearITPendingBit(INTMODULE_DMA_STREAM, INTMODULE_DMA_FLAG_TC);
+ uint32_t status = INTMODULE_USART->SR;
+
+ while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
+ uint8_t data = INTMODULE_USART->DR;
+ if (status & USART_FLAG_ERRORS) {
+ intmoduleFifo.errors++;
+ }
+ else {
+ hardwareOptions.pxx2Enabled = true;
+ intmoduleFifo.push(data);
+ }
+ status = INTMODULE_USART->SR;
}
}
+void intmoduleSendBuffer(const uint8_t * data, uint8_t size)
+{
+ if (size == 0)
+ return;
+
+ DMA_InitTypeDef DMA_InitStructure;
+ DMA_DeInit(INTMODULE_DMA_STREAM);
+ DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL;
+ DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR);
+ DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+ DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(data);
+ DMA_InitStructure.DMA_BufferSize = size;
+ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
+ DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
+ DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
+ DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
+ DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
+ DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+ DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+ DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure);
+ DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE);
+ USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
+}
+
void intmoduleSendNextFrame()
{
- if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) {
- DMA_InitTypeDef DMA_InitStructure;
- DMA_DeInit(INTMODULE_DMA_STREAM);
- DMA_InitStructure.DMA_Channel = INTMODULE_DMA_CHANNEL;
- DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&INTMODULE_USART->DR);
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
- DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx_uart.getData());
- DMA_InitStructure.DMA_BufferSize = modulePulsesData[INTERNAL_MODULE].pxx_uart.getSize();
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(INTMODULE_DMA_STREAM, &DMA_InitStructure);
+ switch(moduleSettings[INTERNAL_MODULE].protocol) {
+#if defined(PXX2)
+ case PROTOCOL_CHANNELS_PXX2:
+ intmoduleSendBuffer(intmodulePulsesData.pxx2.getData(), intmodulePulsesData.pxx2.getSize());
+ break;
+#endif
- DMA_Cmd(INTMODULE_DMA_STREAM, ENABLE);
- USART_DMACmd(INTMODULE_USART, USART_DMAReq_Tx, ENABLE);
+#if defined(PXX1)
+ case PROTOCOL_CHANNELS_PXX1_SERIAL:
+ intmoduleSendBuffer(intmodulePulsesData.pxx_uart.getData(), intmodulePulsesData.pxx_uart.getSize());
+ break;
+#endif
}
}
-
-extern "C" void INTMODULE_TIMER_IRQHandler()
-{
- DEBUG_INTERRUPT(INT_TIM1CC);
- DEBUG_TIMER_SAMPLE(debugTimerIntPulses);
- DEBUG_TIMER_START(debugTimerIntPulsesDuration);
-
- INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // clear flag
- setupPulses(INTERNAL_MODULE);
- intmoduleSendNextFrame();
-
- DEBUG_TIMER_STOP(debugTimerIntPulsesDuration);
-}
diff --git a/radio/src/targets/common/arm/stm32/lsm6ds3_driver.cpp b/radio/src/targets/common/arm/stm32/lsm6ds3_driver.cpp
new file mode 100644
index 000000000..8b8699b41
--- /dev/null
+++ b/radio/src/targets/common/arm/stm32/lsm6ds3_driver.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include "opentx.h"
+
+//#define ACC_LSB_VALUE 0.000488 // 0.488 mg/LSB
+//#define GYRO_LSB_VALUE 0.07 // 70mDPS in 2000 deg/second
+
+/* COMMON VALUES FOR ACCEL-GYRO SENSORS */
+#define LSM6DS3_WHO_AM_I 0x0f
+#define LSM6DS3_WHO_AM_I_DEF 0x69
+#define LSM6DS3_AXIS_EN_MASK 0x38
+#define LSM6DS3_INT1_CTRL_ADDR 0x0d
+#define LSM6DS3_INT2_CTRL_ADDR 0x0e
+#define LSM6DS3_INT1_FULL 0x20
+#define LSM6DS3_INT1_FTH 0x08
+#define LSM6DS3_MD1_ADDR 0x5e
+#define LSM6DS3_ODR_LIST_NUM 5
+#define LSM6DS3_ODR_POWER_OFF_VAL 0x00
+#define LSM6DS3_ODR_26HZ_VAL 0x02
+#define LSM6DS3_ODR_52HZ_VAL 0x03
+#define LSM6DS3_ODR_104HZ_VAL 0x04
+#define LSM6DS3_ODR_208HZ_VAL 0x05
+#define LSM6DS3_ODR_416HZ_VAL 0x06
+#define LSM6DS3_FS_LIST_NUM 4
+#define LSM6DS3_BDU_ADDR 0x12
+#define LSM6DS3_BDU_MASK 0x40
+#define LSM6DS3_EN_BIT 0x01
+#define LSM6DS3_DIS_BIT 0x00
+#define LSM6DS3_FUNC_EN_ADDR 0x19
+#define LSM6DS3_FUNC_EN_MASK 0x04
+#define LSM6DS3_FUNC_CFG_ACCESS_ADDR 0x01
+#define LSM6DS3_FUNC_CFG_ACCESS_MASK 0x01
+#define LSM6DS3_FUNC_CFG_ACCESS_MASK2 0x04
+#define LSM6DS3_FUNC_CFG_REG2_MASK 0x80
+#define LSM6DS3_FUNC_CFG_START1_ADDR 0x62
+#define LSM6DS3_FUNC_CFG_START2_ADDR 0x63
+#define LSM6DS3_SELFTEST_ADDR 0x14
+#define LSM6DS3_SELFTEST_ACCEL_MASK 0x03
+#define LSM6DS3_SELFTEST_GYRO_MASK 0x0c
+#define LSM6DS3_SELF_TEST_DISABLED_VAL 0x00
+#define LSM6DS3_SELF_TEST_POS_SIGN_VAL 0x01
+#define LSM6DS3_SELF_TEST_NEG_ACCEL_SIGN_VAL 0x02
+#define LSM6DS3_SELF_TEST_NEG_GYRO_SIGN_VAL 0x03
+#define LSM6DS3_LIR_ADDR 0x58
+#define LSM6DS3_LIR_MASK 0x01
+#define LSM6DS3_TIMER_EN_ADDR 0x58
+#define LSM6DS3_TIMER_EN_MASK 0x80
+#define LSM6DS3_PEDOMETER_EN_ADDR 0x58
+#define LSM6DS3_PEDOMETER_EN_MASK 0x40
+#define LSM6DS3_INT2_ON_INT1_ADDR 0x13
+#define LSM6DS3_INT2_ON_INT1_MASK 0x20
+#define LSM6DS3_MIN_DURATION_MS 1638
+#define LSM6DS3_ROUNDING_ADDR 0x16
+#define LSM6DS3_ROUNDING_MASK 0x04
+#define LSM6DS3_FIFO_MODE_ADDR 0x0a
+#define LSM6DS3_FIFO_MODE_MASK 0x07
+#define LSM6DS3_FIFO_MODE_BYPASS 0x00
+#define LSM6DS3_FIFO_MODE_CONTINUOS 0x06
+#define LSM6DS3_FIFO_THRESHOLD_IRQ_MASK 0x08
+#define LSM6DS3_FIFO_ODR_ADDR 0x0a
+#define LSM6DS3_FIFO_ODR_MASK 0x78
+#define LSM6DS3_FIFO_ODR_MAX 0x07
+#define LSM6DS3_FIFO_ODR_MAX_HZ 800
+#define LSM6DS3_FIFO_ODR_OFF 0x00
+#define LSM6DS3_FIFO_CTRL3_ADDR 0x08
+#define LSM6DS3_FIFO_ACCEL_DECIMATOR_MASK 0x07
+#define LSM6DS3_FIFO_GYRO_DECIMATOR_MASK 0x38
+#define LSM6DS3_FIFO_CTRL4_ADDR 0x09
+#define LSM6DS3_FIFO_STEP_C_DECIMATOR_MASK 0x38
+#define LSM6DS3_FIFO_THR_L_ADDR 0x06
+#define LSM6DS3_FIFO_THR_H_ADDR 0x07
+#define LSM6DS3_FIFO_THR_H_MASK 0x0f
+#define LSM6DS3_FIFO_THR_IRQ_MASK 0x08
+#define LSM6DS3_FIFO_PEDO_E_ADDR 0x07
+#define LSM6DS3_FIFO_PEDO_E_MASK 0x80
+#define LSM6DS3_FIFO_STEP_C_FREQ 25
+
+/* CUSTOM VALUES FOR ACCEL SENSOR */
+#define LSM6DS3_ACCEL_ODR_ADDR 0x10
+#define LSM6DS3_ACCEL_ODR_MASK 0xf0
+#define LSM6DS3_ACCEL_FS_ADDR 0x10
+#define LSM6DS3_ACCEL_FS_MASK 0x0c
+#define LSM6DS3_ACCEL_FS_2G_VAL 0x00
+#define LSM6DS3_ACCEL_FS_4G_VAL 0x02
+#define LSM6DS3_ACCEL_FS_8G_VAL 0x03
+#define LSM6DS3_ACCEL_FS_16G_VAL 0x01
+#define LSM6DS3_ACCEL_FS_2G_GAIN 61
+#define LSM6DS3_ACCEL_FS_4G_GAIN 122
+#define LSM6DS3_ACCEL_FS_8G_GAIN 244
+#define LSM6DS3_ACCEL_FS_16G_GAIN 488
+#define LSM6DS3_ACCEL_OUT_X_L_ADDR 0x28
+#define LSM6DS3_ACCEL_OUT_Y_L_ADDR 0x2a
+#define LSM6DS3_ACCEL_OUT_Z_L_ADDR 0x2c
+#define LSM6DS3_ACCEL_AXIS_EN_ADDR 0x18
+#define LSM6DS3_ACCEL_DRDY_IRQ_MASK 0x01
+#define LSM6DS3_ACCEL_STD 1
+#define LSM6DS3_ACCEL_STD_FROM_PD 2
+
+/* CUSTOM VALUES FOR GYRO SENSOR */
+#define LSM6DS3_GYRO_ODR_ADDR 0x11
+#define LSM6DS3_GYRO_ODR_MASK 0xf0
+#define LSM6DS3_GYRO_FS_ADDR 0x11
+#define LSM6DS3_GYRO_FS_MASK 0x0c
+#define LSM6DS3_GYRO_FS_245_VAL 0x00
+#define LSM6DS3_GYRO_FS_500_VAL 0x01
+#define LSM6DS3_GYRO_FS_1000_VAL 0x02
+#define LSM6DS3_GYRO_FS_2000_VAL 0x03
+#define LSM6DS3_GYRO_FS_245_GAIN 8750
+#define LSM6DS3_GYRO_FS_500_GAIN 17500
+#define LSM6DS3_GYRO_FS_1000_GAIN 35000
+#define LSM6DS3_GYRO_FS_2000_GAIN 70000
+#define LSM6DS3_GYRO_OUT_X_L_ADDR 0x22
+#define LSM6DS3_GYRO_OUT_Y_L_ADDR 0x24
+#define LSM6DS3_GYRO_OUT_Z_L_ADDR 0x26
+#define LSM6DS3_GYRO_AXIS_EN_ADDR 0x19
+#define LSM6DS3_GYRO_DRDY_IRQ_MASK 0x02
+#define LSM6DS3_GYRO_STD 6
+#define LSM6DS3_GYRO_STD_FROM_PD 2
+
+#define LSM6DS3_OUT_XYZ_SIZE 8
+
+/* CUSTOM VALUES FOR SIGNIFICANT MOTION SENSOR */
+#define LSM6DS3_SIGN_MOTION_EN_ADDR 0x19
+#define LSM6DS3_SIGN_MOTION_EN_MASK 0x01
+#define LSM6DS3_SIGN_MOTION_DRDY_IRQ_MASK 0x40
+
+/* CUSTOM VALUES FOR STEP DETECTOR SENSOR */
+#define LSM6DS3_STEP_DETECTOR_DRDY_IRQ_MASK 0x80
+
+/* CUSTOM VALUES FOR STEP COUNTER SENSOR */
+#define LSM6DS3_STEP_COUNTER_DRDY_IRQ_MASK 0x80
+#define LSM6DS3_STEP_COUNTER_OUT_L_ADDR 0x4b
+#define LSM6DS3_STEP_COUNTER_OUT_SIZE 2
+#define LSM6DS3_STEP_COUNTER_RES_ADDR 0x19
+#define LSM6DS3_STEP_COUNTER_RES_MASK 0x06
+#define LSM6DS3_STEP_COUNTER_RES_ALL_EN 0x03
+#define LSM6DS3_STEP_COUNTER_RES_FUNC_EN 0x02
+#define LSM6DS3_STEP_COUNTER_DURATION_ADDR 0x15
+
+/* CUSTOM VALUES FOR TILT SENSOR */
+#define LSM6DS3_TILT_EN_ADDR 0x58
+#define LSM6DS3_TILT_EN_MASK 0x20
+#define LSM6DS3_TILT_DRDY_IRQ_MASK 0x02
+
+#define LSM6DS3_ENABLE_AXIS 0x07
+#define LSM6DS3_FIFO_DIFF_L 0x3a
+#define LSM6DS3_FIFO_DIFF_MASK 0x0fff
+#define LSM6DS3_FIFO_DATA_OUT_L 0x3e
+#define LSM6DS3_FIFO_ELEMENT_LEN_BYTE 6
+#define LSM6DS3_FIFO_BYTE_FOR_CHANNEL 2
+#define LSM6DS3_FIFO_DATA_OVR_2REGS 0x4000
+#define LSM6DS3_FIFO_DATA_OVR 0x40
+
+#define LSM6DS3_SRC_FUNC_ADDR 0x53
+#define LSM6DS3_FIFO_DATA_AVL_ADDR 0x3b
+
+#define LSM6DS3_SRC_SIGN_MOTION_DATA_AVL 0x40
+#define LSM6DS3_SRC_STEP_DETECTOR_DATA_AVL 0x10
+#define LSM6DS3_SRC_TILT_DATA_AVL 0x20
+#define LSM6DS3_SRC_STEP_COUNTER_DATA_AVL 0x80
+#define LSM6DS3_FIFO_DATA_AVL 0x80
+#define LSM6DS3_RESET_ADDR 0x12
+#define LSM6DS3_RESET_MASK 0x01
+
+#define LSM6DS3_ADDRESS 0xD6
+#define LSM6DSLTR_ID 0x6A
+
+static const char configure[][2] =
+ {
+ {LSM6DS3_ACCEL_AXIS_EN_ADDR, 0x38}, ///< xyz
+ {LSM6DS3_ACCEL_ODR_ADDR, (0x3 << 4) | (0x1 << 2) | (0x3 << 0)}, //ODR_52Hz|16G|BW_50Hz
+ {LSM6DS3_GYRO_AXIS_EN_ADDR, 0x38}, ///< xyz
+ {LSM6DS3_GYRO_ODR_ADDR, (3 << 4) | (3 << 2) | (0 << 0)}, ///< ODR_52Hz|2000dps|
+ {LSM6DS3_INT1_CTRL_ADDR, 0x3}, ///< GYRO_READY | ACCL_READY
+ {LSM6DS3_INT2_CTRL_ADDR, 0x3}, ///< GYRO_READY | ACCL_READY
+ };
+
+volatile int lsm6ds3_state = 1;
+
+static void i2c2Init()
+{
+ I2C_DeInit(I2CX);
+
+ I2C_InitTypeDef I2C_InitStructure;
+ I2C_InitStructure.I2C_ClockSpeed = I2CX_SPEED;
+ I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
+ I2C_InitStructure.I2C_OwnAddress1 = 0x00;
+ I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
+ I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
+ I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
+ I2C_Init(I2CX, &I2C_InitStructure);
+ I2C_Cmd(I2CX, ENABLE);
+
+ GPIO_PinAFConfig(I2CX_SCL_GPIO, I2CX_SCL_GPIO_PinSource, I2CX_GPIO_AF);
+ GPIO_PinAFConfig(I2CX_SDA_GPIO, I2CX_SDA_GPIO_PinSource, I2CX_GPIO_AF);
+
+ GPIO_InitTypeDef GPIO_InitStructure;
+ GPIO_InitStructure.GPIO_Pin = I2CX_SCL_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(I2CX_SCL_GPIO, &GPIO_InitStructure);
+
+ GPIO_InitStructure.GPIO_Pin = I2CX_SDA_GPIO_PIN;
+ GPIO_Init(I2CX_SDA_GPIO, &GPIO_InitStructure);
+}
+
+#define I2C_TIMEOUT_MAX 10000
+bool I2C2_WaitEvent(uint32_t event)
+{
+ uint32_t timeout = I2C_TIMEOUT_MAX;
+ while (!I2C_CheckEvent(I2CX, event)) {
+ if ((timeout--) == 0) return false;
+ }
+ return true;
+}
+
+bool I2C2_WaitEventCleared(uint32_t event)
+{
+ uint32_t timeout = I2C_TIMEOUT_MAX;
+ while (I2C_CheckEvent(I2CX, event)) {
+ if ((timeout--) == 0) return false;
+ }
+ return true;
+}
+
+int setGyroRegister(uint8_t address, uint8_t value)
+{
+ if (!I2C2_WaitEventCleared(I2C_FLAG_BUSY))
+ return -1;
+
+ I2C_GenerateSTART(I2CX, ENABLE);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
+ return -1;
+
+ I2C_Send7bitAddress(I2CX, LSM6DS3_ADDRESS, I2C_Direction_Transmitter);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
+ return -1;
+
+ I2C_SendData(I2CX, address);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED)) // TODO TRANSMITTING
+ return -1;
+
+ I2C_SendData(I2CX, value);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))
+ return -1;
+
+ I2C_GenerateSTOP(I2CX, ENABLE);
+
+ return 0;
+}
+
+int readGyroRegister(uint8_t address)
+{
+ if (!I2C2_WaitEventCleared(I2C_FLAG_BUSY))
+ return -1;
+
+ I2C_GenerateSTART(I2CX, ENABLE);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
+ return -1;
+
+ I2C_Send7bitAddress(I2CX, LSM6DS3_ADDRESS, I2C_Direction_Transmitter);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
+ return -1;
+
+ I2C_SendData(I2CX, address);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED))
+ return -1;
+
+ I2C_GenerateSTART(I2CX, ENABLE);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_MODE_SELECT))
+ return -1;
+
+ I2C_Send7bitAddress(I2CX, LSM6DS3_ADDRESS, I2C_Direction_Receiver);
+
+ I2C_AcknowledgeConfig(I2CX, DISABLE);
+ if (!I2C2_WaitEvent(I2C_EVENT_MASTER_BYTE_RECEIVED))
+ return -1;
+
+ uint8_t value = I2C_ReceiveData(I2CX);
+
+ I2C_GenerateSTOP(I2CX, ENABLE);
+
+ return value;
+}
+
+int gyroInit()
+{
+ i2c2Init();
+
+ uint8_t id = readGyroRegister(LSM6DS3_WHO_AM_I);
+ if (id != LSM6DSLTR_ID) {
+ return -1;
+ }
+
+ TRACE("OK");
+
+ setGyroRegister(0x12, 0x05);
+ delay_ms(1);
+ setGyroRegister(0x12, 0x04);
+ delay_ms(1);
+
+ TRACE("OK2");
+
+ for (uint8_t i = 0; i < DIM(configure); i++) {
+ setGyroRegister(configure[i][0], configure[i][1]);
+ }
+
+ TRACE("OK4");
+
+ return 0;
+}
+
+#if 0
+int gyroRead(void *buffer, int len, OFFSET offset1)
+{
+ char t_char[10];
+ short t_short[7];
+
+ short *p_short;
+ I2C_transfer_block i2c_block[2];
+
+ xSemaphoreTake(lsm6ds3_sema, portMAX_DELAY);
+
+ t_char[0] = LSM6DS3_GYRO_OUT_X_L_ADDR;
+
+ i2c_block[0].addr = LSM6DS3_ADDRESS;
+ i2c_block[0].rw = I2C_WRITE;
+ i2c_block[0].stop_mode = I2C_WRITE_BYPASS_STOP;
+ i2c_block[0].len = 1;
+ i2c_block[0].buf = t_char;
+
+ i2c_block[1].addr = LSM6DS3_ADDRESS;
+ i2c_block[1].rw = I2C_READ;
+ i2c_block[1].stop_mode = I2C_WRITE_APPEND_STOP;
+
+ i2c_block[1].len = len;
+ i2c_block[1].buf = (char *) t_short;
+
+ i2c_dma_transfer(i2c_block, 2);
+
+ {
+ p_short = (short *) buffer;
+ *p_short++ = t_short[0];
+ *p_short++ = -t_short[1];
+ *p_short++ = t_short[2];
+
+ *p_short++ = -t_short[3];
+ *p_short++ = t_short[4];
+ *p_short++ = -t_short[5];
+ }
+
+ return len;
+}
+
+#endif
\ No newline at end of file
diff --git a/radio/src/targets/common/arm/stm32/serial2_driver.cpp b/radio/src/targets/common/arm/stm32/serial2_driver.cpp
index 049f09374..cb39d4173 100644
--- a/radio/src/targets/common/arm/stm32/serial2_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/serial2_driver.cpp
@@ -97,7 +97,7 @@ void serial2Init(unsigned int mode, unsigned int protocol)
break;
#endif
case UART_MODE_TELEMETRY:
- if (protocol == PROTOCOL_FRSKY_D_SECONDARY) {
+ if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
uart3Setup(FRSKY_D_BAUDRATE, true);
}
break;
diff --git a/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp b/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp
index a3c065963..e219f5521 100644
--- a/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/sticks_pwm_driver.cpp
@@ -20,7 +20,6 @@
#include "opentx.h"
-bool sticks_pwm_disabled = false;
volatile uint32_t pwm_interrupt_count;
volatile uint16_t timer_capture_values[NUM_PWMSTICKS];
diff --git a/radio/src/targets/common/arm/stm32/usb_driver.cpp b/radio/src/targets/common/arm/stm32/usb_driver.cpp
index 7b4aaf530..e47774623 100644
--- a/radio/src/targets/common/arm/stm32/usb_driver.cpp
+++ b/radio/src/targets/common/arm/stm32/usb_driver.cpp
@@ -44,7 +44,7 @@ int getSelectedUsbMode()
void setSelectedUsbMode(int mode)
{
- selectedUsbMode = usbMode (mode);
+ selectedUsbMode = usbMode(mode);
}
int usbPlugged()
diff --git a/radio/src/targets/horus/CMakeLists.txt b/radio/src/targets/horus/CMakeLists.txt
index 28c7abcde..ef12c59b4 100644
--- a/radio/src/targets/horus/CMakeLists.txt
+++ b/radio/src/targets/horus/CMakeLists.txt
@@ -146,6 +146,7 @@ add_definitions(-DBLUETOOTH)
set(SRC
${SRC}
bluetooth.cpp
+ io/frsky_device_firmware_update.cpp
)
set(STM32LIB_SRC
diff --git a/radio/src/targets/horus/adc_driver.cpp b/radio/src/targets/horus/adc_driver.cpp
index bfd6f63f4..248bd85ef 100644
--- a/radio/src/targets/horus/adc_driver.cpp
+++ b/radio/src/targets/horus/adc_driver.cpp
@@ -20,7 +20,7 @@
#include "opentx.h"
-uint16_t adcValues[NUM_ANALOGS] __DMA;
+uint16_t adcValues[NUM_ANALOGS + 1/*RTC*/] __DMA;
#define ADC_CS_HIGH() (ADC_SPI_GPIO->BSRRL = ADC_SPI_PIN_CS)
#define ADC_CS_LOW() (ADC_SPI_GPIO->BSRRH = ADC_SPI_PIN_CS)
diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp
index 02f54c5fc..0ac2357a5 100644
--- a/radio/src/targets/horus/board.cpp
+++ b/radio/src/targets/horus/board.cpp
@@ -29,6 +29,8 @@ extern "C" {
}
#endif
+HardwareOptions hardwareOptions;
+
void watchdogInit(unsigned int duration)
{
IWDG->KR = 0x5555; // Unlock registers
@@ -178,9 +180,6 @@ void boardInit()
pwrInit();
delaysInit();
- // FrSky removed the volume chip in latest board, that's why it doesn't answer!
- // i2cInit();
-
#if defined(DEBUG)
serial2Init(0, 0); // default serial mode (None if DEBUG not defined)
#endif
@@ -190,9 +189,14 @@ void boardInit()
TRACE("\nHorus board started :)");
TRACE("RCC->CSR = %08x", RCC->CSR);
+#if defined(PXX2)
+ #warning "PXX2 probe is not implemented"
+ hardwareOptions.pxx2Enabled = true;
+#endif
+
audioInit();
- // we need to initialize g_FATFS_Obj here, because it is in .ram section (because of DMA access)
+ // we need to initialize g_FATFS_Obj here, because it is in .ram section (because of DMA access)
// and this section is un-initialized
memset(&g_FATFS_Obj, 0, sizeof(g_FATFS_Obj));
@@ -202,7 +206,7 @@ void boardInit()
sticksPwmInit();
delay_ms(20);
if (pwm_interrupt_count < 32) {
- sticks_pwm_disabled = true;
+ hardwareOptions.sticksPwmDisabled = true;
}
#endif
@@ -252,7 +256,7 @@ uint8_t currentTrainerMode = 0xff;
void checkTrainerSettings()
{
- uint8_t requiredTrainerMode = g_model.trainerMode;
+ uint8_t requiredTrainerMode = g_model.trainerData.mode;
if (requiredTrainerMode != currentTrainerMode) {
switch (currentTrainerMode) {
case TRAINER_MODE_MASTER_TRAINER_JACK:
diff --git a/radio/src/targets/horus/board.h b/radio/src/targets/horus/board.h
index d14f2f706..03fd11070 100644
--- a/radio/src/targets/horus/board.h
+++ b/radio/src/targets/horus/board.h
@@ -21,8 +21,8 @@
#ifndef _BOARD_HORUS_H_
#define _BOARD_HORUS_H_
-#include "stddef.h"
-#include "stdbool.h"
+#include "../definitions.h"
+#include "cpu_id.h"
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
@@ -97,7 +97,7 @@ extern "C" {
extern uint16_t sessionTimer;
-#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE)
+#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#if defined(PCBX10)
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_SET)
@@ -105,6 +105,14 @@ extern uint16_t sessionTimer;
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_RESET)
#endif
+#if defined(PCBX10)
+ #define NUM_SLIDERS 2
+ #define NUM_PWMSTICKS 4
+#else
+ #define NUM_SLIDERS 4
+ #define NUM_PWMSTICKS 0
+#endif
+
// Board driver
void boardInit(void);
void boardOff(void);
@@ -131,9 +139,15 @@ void delay_ms(uint32_t ms);
#define IS_FIRMWARE_COMPATIBLE_WITH_BOARD() (!IS_HORUS_PROD())
#endif
-// CPU Unique ID
-#define LEN_CPU_UID (3*8+2)
-void getCPUUniqueID(char * s);
+// Hardware options
+PACK(typedef struct {
+#if NUM_PWMSTICKS > 0
+ uint8_t sticksPwmDisabled:1;
+#endif
+ uint8_t pxx2Enabled:1;
+}) HardwareOptions;
+
+extern HardwareOptions hardwareOptions;
// SD driver
#define BLOCK_SIZE 512 /* Block Size in Bytes */
@@ -180,23 +194,44 @@ void SDRAM_Init(void);
// Pulses driver
#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
-#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
+
+#if defined(INTMODULE_USART)
+ #define INTERNAL_MODULE_OFF() intmoduleStop()
+#else
+ #define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
+#endif
+
#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
#define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET)
#define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
-#define IS_UART_MODULE(port) (port == INTERNAL_MODULE)
-void init_no_pulses(uint32_t port);
-void disable_no_pulses(uint32_t port);
-void init_ppm(uint32_t module_index);
-void disable_ppm(uint32_t module_index);
-void init_pxx(uint32_t module_index);
-void disable_pxx(uint32_t module_index);
-void init_serial(uint32_t module_index, uint32_t baudrate, uint32_t period_half_us);
-void disable_serial(uint32_t module_index);
-void init_module_timer( uint32_t module_index, uint32_t period, uint8_t state);
-void disable_module_timer( uint32_t module_index);
+#if !defined(PXX2)
+ #define IS_PXX2_INTERNAL_ENABLED() (false)
+ #define IS_PXX1_INTERNAL_ENABLED() (true)
+#elif !defined(PXX1)
+ #define IS_PXX2_INTERNAL_ENABLED() (true)
+ #define IS_PXX1_INTERNAL_ENABLED() (false)
+#else
+ // TODO #define PXX2_PROBE
+ // TODO #define IS_PXX2_INTERNAL_ENABLED() (hardwareOptions.pxx2Enabled)
+ #define IS_PXX2_INTERNAL_ENABLED() (true)
+ #define IS_PXX1_INTERNAL_ENABLED() (true)
+#endif
+
+void init_ppm(uint8_t module);
+void disable_ppm(uint8_t module);
+void init_pxx1_pulses(uint8_t module);
+void disable_pxx1_pulses(uint8_t module);
+void init_pxx2(uint8_t module);
+void disable_pxx2(uint8_t module);
+void init_serial(uint8_t module, uint32_t baudrate, uint32_t period_half_us);
+void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable);
+void disable_serial(uint8_t module);
+void intmoduleStop();
+void intmoduleSendBuffer(const uint8_t * data, uint8_t size);
+void intmoduleSendNextFrame();
+void extmoduleSendNextFrame();
// Trainer driver
void init_trainer_ppm(void);
@@ -280,6 +315,7 @@ enum EnumSwitchesPositions
SW_SH0,
SW_SH1,
SW_SH2,
+ NUM_SWITCHES_POSITIONS
};
void keysInit(void);
uint8_t keyState(uint8_t index);
@@ -334,13 +370,6 @@ void watchdogInit(unsigned int duration);
// ADC driver
#define NUM_POTS 3
#define NUM_XPOTS NUM_POTS
-#if defined(PCBX10)
- #define NUM_SLIDERS 2
- #define NUM_PWMSTICKS 4
-#else
- #define NUM_SLIDERS 4
- #define NUM_PWMSTICKS 0
-#endif
enum Analogs {
STICK1,
STICK2,
@@ -365,9 +394,10 @@ enum Analogs {
#endif
SLIDER_LAST = SLIDER_FIRST + NUM_SLIDERS - 1,
TX_VOLTAGE,
- MOUSE1,
+ MOUSE1, // TODO why after voltage?
MOUSE2,
- NUM_ANALOGS
+ NUM_ANALOGS,
+ TX_RTC = NUM_ANALOGS
};
enum CalibratedAnalogs {
@@ -394,9 +424,10 @@ enum CalibratedAnalogs {
#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST)
#define IS_SLIDER(x) ((x)>=SLIDER_FIRST && (x)<=SLIDER_LAST)
-extern uint16_t adcValues[NUM_ANALOGS];
+extern uint16_t adcValues[NUM_ANALOGS + 1/*RTC*/];
void adcInit(void);
void adcRead(void);
+uint16_t getRTCBattVoltage();
uint16_t getAnalogValue(uint8_t index);
#define NUM_MOUSE_ANALOGS 2
#if defined(PCBX10)
@@ -406,8 +437,7 @@ uint16_t getAnalogValue(uint8_t index);
#endif
#if NUM_PWMSTICKS > 0
-extern bool sticks_pwm_disabled;
-#define STICKS_PWM_ENABLED() (sticks_pwm_disabled == false)
+#define STICKS_PWM_ENABLED() (!hardwareOptions.sticksPwmDisabled)
void sticksPwmInit(void);
void sticksPwmRead(uint16_t * values);
extern volatile uint32_t pwm_interrupt_count;
diff --git a/radio/src/targets/horus/extmodule_driver.cpp b/radio/src/targets/horus/extmodule_driver.cpp
index 724c16837..4fb25ab08 100644
--- a/radio/src/targets/horus/extmodule_driver.cpp
+++ b/radio/src/targets/horus/extmodule_driver.cpp
@@ -20,8 +20,6 @@
#include "opentx.h"
-void extmoduleSendNextFrame();
-
void extmoduleStop()
{
EXTERNAL_MODULE_OFF();
@@ -34,38 +32,6 @@ void extmoduleStop()
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
}
-void extmoduleTimerStart(uint32_t period, uint8_t state)
-{
- if (state)
- EXTERNAL_MODULE_ON();
- else
- EXTERNAL_MODULE_OFF();
-
- GPIO_PinAFConfig(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PinSource, 0);
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(EXTMODULE_TX_GPIO, &GPIO_InitStructure);
- GPIO_SetBits(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PIN); // Set high
-
- EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
- EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
- EXTMODULE_TIMER->ARR = (2000 * period);
- EXTMODULE_TIMER->CCR2 = (2000 * period) - 1000;
- EXTMODULE_TIMER->EGR = 1; // Restart
- EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
- EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
- EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
-
- NVIC_EnableIRQ(EXTMODULE_TIMER_IRQn);
- NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
-}
-
-
void extmodulePpmStart()
{
EXTERNAL_MODULE_ON();
@@ -102,8 +68,8 @@ void extmodulePpmStart()
EXTMODULE_TIMER->DIER = TIM_DIER_UDE; // Update DMA request
EXTMODULE_TIMER->CR1 = TIM_CR1_CEN; // Start timer
#else
- EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
- EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
+ EXTMODULE_TIMER->CCR1 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE)*2;
+ EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
EXTMODULE_TIMER->EGR = 1; // Reloads register values now
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Update DMA request
@@ -165,6 +131,11 @@ void extmodulePxxStart()
NVIC_SetPriority(EXTMODULE_TIMER_IRQn, 7);
}
+void extmodulePxx2Start()
+{
+ // TODO just enable the S.PORT line (or let telemetry init do it)
+}
+
#if defined(DSM2)
void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us)
{
@@ -213,29 +184,56 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us)
}
#endif
+#if defined(EXTMODULE_USART)
+void extmoduleSendBuffer(const uint8_t * data, uint8_t size)
+{
+ DMA_InitTypeDef DMA_InitStructure;
+ DMA_DeInit(EXTMODULE_DMA_STREAM);
+ DMA_InitStructure.DMA_Channel = EXTMODULE_DMA_CHANNEL;
+ DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&EXTMODULE_USART->DR);
+ DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+ DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(data);
+ DMA_InitStructure.DMA_BufferSize = size;
+ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
+ DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
+ DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
+ DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
+ DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
+ DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+ DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+ DMA_Init(EXTMODULE_DMA_STREAM, &DMA_InitStructure);
+ DMA_Cmd(EXTMODULE_DMA_STREAM, ENABLE);
+ USART_DMACmd(EXTMODULE_USART, USART_DMAReq_Tx, ENABLE);
+}
+#endif
+
void extmoduleSendNextFrame()
{
- if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) {
+ if (moduleSettings[EXTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_PPM) {
#if defined(PCBX10) || PCBREV >= 13
- EXTMODULE_TIMER->CCR3 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
- EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0);
- EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
+ EXTMODULE_TIMER->CCR3 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE)*2;
+ EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0);
+ EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
#else
- EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
- EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
- EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
+ EXTMODULE_TIMER->CCR1 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE)*2;
+ EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0);
+ EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
#endif
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
- EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].ppm.pulses);
- EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].ppm.ptr - modulePulsesData[EXTERNAL_MODULE].ppm.pulses;
+ EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.ppm.pulses);
+ EXTMODULE_DMA_STREAM->NDTR = extmodulePulsesData.ppm.ptr - extmodulePulsesData.ppm.pulses;
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
}
- else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) {
- EXTMODULE_TIMER->CCR2 = modulePulsesData[EXTERNAL_MODULE].pxx.getLast() - 4000; // 2mS in advance
+#if defined(PXX1)
+ else if (moduleSettings[EXTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_PXX1_PULSES) {
+ EXTMODULE_TIMER->CCR2 = extmodulePulsesData.pxx.getLast() - 4000; // 2mS in advance
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
#if defined(PCBX10) || PCBREV >= 13
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
@@ -243,25 +241,34 @@ void extmoduleSendNextFrame()
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
#endif
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
- EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.getData());
- EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.getSize();
+ EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData());
+ EXTMODULE_DMA_STREAM->NDTR = extmodulePulsesData.pxx.getSize();
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
}
- else if (IS_DSM2_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_MULTIMODULE_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_SBUS_PROTOCOL(s_current_protocol[EXTERNAL_MODULE])) {
- EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - 1) - 4000; // 2mS in advance
+ else if (moduleSettings[EXTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_PXX1_SERIAL) {
+ #warning "Take it from 2.2"
+ }
+#endif
+#if defined(PXX2)
+ else if (moduleSettings[EXTERNAL_MODULE].protocol == PROTOCOL_CHANNELS_PXX2) {
+ // TODO
+ }
+#endif
+ else if (IS_DSM2_PROTOCOL(moduleSettings[EXTERNAL_MODULE].protocol) || IS_MULTIMODULE_PROTOCOL(moduleSettings[EXTERNAL_MODULE].protocol) || IS_SBUS_PROTOCOL(moduleSettings[EXTERNAL_MODULE].protocol)) {
+ EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.dsm2.ptr - 1) - 4000; // 2mS in advance
EXTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
#if defined(PCBX10) || PCBREV >= 13
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- if (IS_SBUS_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]))
+ if (IS_SBUS_PROTOCOL(moduleSettings[EXTERNAL_MODULE].protocol))
EXTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC3P : 0); // reverse polarity for Sbus if needed
#else
EXTMODULE_DMA_STREAM->CR |= EXTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- if (IS_SBUS_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]))
+ if (IS_SBUS_PROTOCOL(moduleSettings[EXTERNAL_MODULE].protocol))
EXTMODULE_TIMER->CCER = TIM_CCER_CC1E | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? TIM_CCER_CC1P : 0); // reverse polarity for Sbus if needed
#endif
EXTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
- EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
- EXTMODULE_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
+ EXTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses);
+ EXTMODULE_DMA_STREAM->NDTR = extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses;
EXTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
}
else {
@@ -284,6 +291,6 @@ extern "C" void EXTMODULE_TIMER_IRQHandler()
{
EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
- setupPulses(EXTERNAL_MODULE);
- extmoduleSendNextFrame();
+ if (setupPulses(EXTERNAL_MODULE))
+ extmoduleSendNextFrame();
}
diff --git a/radio/src/targets/horus/hal.h b/radio/src/targets/horus/hal.h
index c5f9ff11e..64eca001d 100644
--- a/radio/src/targets/horus/hal.h
+++ b/radio/src/targets/horus/hal.h
@@ -197,6 +197,7 @@
#define ADC_DMA DMA2
#define ADC_DMA_Stream DMA2_Stream0
#define ADC_SAMPTIME 3
+ #define ADC_CHANNEL_RTC 0 // TODO later ... ADC1_IN18
#elif defined(PCBX10)
#define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_DMA2)
#define ADC_RCC_APB1Periph (RCC_APB1Periph_TIM5)
@@ -234,6 +235,7 @@
#define ADC_CHANNEL_BATT ADC_Channel_5 // ADC3_IN5
#define ADC_CHANNEL_EXT1 ADC_Channel_6 // ADC3_IN6
#define ADC_CHANNEL_EXT2 ADC_Channel_7 // ADC3_IN7
+ #define ADC_CHANNEL_RTC 0 // TODO later ... ADC1_IN18
#define ADC_MAIN ADC3
#define ADC_SAMPTIME 3
#define ADC_DMA DMA2
@@ -249,8 +251,6 @@
#define PWR_SWITCH_GPIO_REG PWR_GPIO->IDR
#define PWR_SWITCH_GPIO_PIN GPIO_Pin_0 // PJ.00
#define PWR_ON_GPIO_PIN GPIO_Pin_1 // PJ.01
-#define PWR_ON_GPIO_MODER GPIO_MODER_MODER1
-#define PWR_ON_GPIO_MODER_OUT GPIO_MODER_MODER1_0
// S.Port update connector
#define SPORT_MAX_BAUDRATE 250000 // < 400000
@@ -512,17 +512,17 @@
#endif
// Internal Module
+#define HARDWARE_INTERNAL_MODULE
#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
#define INTMODULE_PWR_GPIO GPIOA
#define INTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PA.08
-#define INTMODULE_TX_GPIO GPIOB
+#define INTMODULE_GPIO GPIOB
#define INTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PB.06
-#define INTMODULE_RX_GPIO GPIOB
#define INTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PB.07
-#define INTMODULE_TX_GPIO_PinSource GPIO_PinSource6
-#define INTMODULE_RX_GPIO_PinSource GPIO_PinSource7
+#define INTMODULE_GPIO_PinSource_TX GPIO_PinSource6
+#define INTMODULE_GPIO_PinSource_RX GPIO_PinSource7
#define INTMODULE_USART USART1
-#define INTMODULE_TX_GPIO_AF GPIO_AF_USART1
+#define INTMODULE_GPIO_AF GPIO_AF_USART1
#define INTMODULE_USART_IRQn USART1_IRQn
#define INTMODULE_DMA_STREAM DMA2_Stream7
#define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn
@@ -634,7 +634,7 @@
#define BT_USART USART6
#define BT_GPIO_AF GPIO_AF_USART6
#define BT_USART_IRQn USART6_IRQn
-#define BT_GPIO_TXRX GPIOG
+#define BT_USART_GPIO GPIOG
#define BT_TX_GPIO_PIN GPIO_Pin_14 // PG.14
#define BT_RX_GPIO_PIN GPIO_Pin_9 // PG.09
#define BT_TX_GPIO_PinSource GPIO_PinSource14
diff --git a/radio/src/targets/horus/pulses_driver.cpp b/radio/src/targets/horus/pulses_driver.cpp
index 97305df0b..57fca8889 100644
--- a/radio/src/targets/horus/pulses_driver.cpp
+++ b/radio/src/targets/horus/pulses_driver.cpp
@@ -20,90 +20,76 @@
#include "opentx.h"
-void intmoduleStop(void);
-void extmoduleStop(void);
+void intmoduleStop();
+void intmodulePxxStart();
+void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable);
-void intmoduleNoneStart(void);
-void intmodulePxxStart(void);
-
-void extmoduleTimerStart(uint32_t period, uint8_t state);
-void extmodulePpmStart(void);
-void extmodulePxxStart(void);
+void extmoduleStop();
+void extmodulePpmStart();
+void extmodulePxxStart();
+void extmodulePxx2Start();
void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us);
-void init_no_pulses(uint32_t port)
+
+void init_ppm(uint8_t module)
{
- if (port == INTERNAL_MODULE)
- intmoduleNoneStart();
- else
- extmoduleTimerStart(18, false);
+ if (module == EXTERNAL_MODULE) {
+ extmodulePpmStart();
+ }
}
-void disable_no_pulses(uint32_t port)
+void disable_ppm(uint8_t module)
{
- if (port == INTERNAL_MODULE)
+ if (module == EXTERNAL_MODULE) {
+ extmoduleStop();
+ }
+}
+
+void init_pxx2(uint8_t module)
+{
+ if (module == INTERNAL_MODULE)
+ intmoduleSerialStart(INTMODULE_PXX_BAUDRATE, true);
+ else
+ extmodulePxx2Start();
+}
+
+void disable_pxx2(uint8_t module)
+{
+ if (module == INTERNAL_MODULE)
intmoduleStop();
else
extmoduleStop();
}
-void init_ppm(uint32_t port)
+void init_pxx1_pulses(uint8_t module)
{
- if (port == EXTERNAL_MODULE) {
- extmodulePpmStart();
- }
-}
-
-void disable_ppm(uint32_t port)
-{
- if (port == EXTERNAL_MODULE) {
- extmoduleStop();
- }
-}
-
-void init_pxx(uint32_t port)
-{
- if (port == INTERNAL_MODULE)
+ if (module == INTERNAL_MODULE)
intmodulePxxStart();
else
extmodulePxxStart();
}
-void disable_pxx(uint32_t port)
+void disable_pxx1_pulses(uint8_t module)
{
- if (port == INTERNAL_MODULE)
+ if (module == INTERNAL_MODULE)
intmoduleStop();
else
extmoduleStop();
}
#if defined(DSM2)
-void init_serial(uint32_t port, uint32_t baudrate, uint32_t period_half_us)
+void init_serial(uint8_t module, uint32_t baudrate, uint32_t period_half_us)
{
- if (port == EXTERNAL_MODULE) {
+ if (module == EXTERNAL_MODULE) {
extmoduleSerialStart(baudrate, period_half_us);
}
}
-void disable_serial(uint32_t port)
+void disable_serial(uint8_t module)
{
- if (port == EXTERNAL_MODULE) {
+ if (module == EXTERNAL_MODULE) {
extmoduleStop();
}
}
#endif
-void init_module_timer(uint32_t port, uint32_t period, uint8_t state)
-{
- if (port == EXTERNAL_MODULE) {
- extmoduleTimerStart(period, state);
- }
-}
-
-void disable_module_timer(uint32_t port)
-{
- if (port == EXTERNAL_MODULE) {
- extmoduleStop();
- }
-}
-
diff --git a/radio/src/targets/horus/telemetry_driver.cpp b/radio/src/targets/horus/telemetry_driver.cpp
index 8541c0742..21e9f6c5a 100644
--- a/radio/src/targets/horus/telemetry_driver.cpp
+++ b/radio/src/targets/horus/telemetry_driver.cpp
@@ -175,9 +175,8 @@ extern "C" void TELEMETRY_DMA_TX_IRQHandler(void)
if (DMA_GetITStatus(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC)) {
DMA_ClearITPendingBit(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC);
TELEMETRY_USART->CR1 |= USART_CR1_TCIE;
- if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
- outputTelemetryBufferSize = 0;
- outputTelemetryBufferTrigger = 0x7E;
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) {
+ outputTelemetryBuffer.reset();
}
}
}
@@ -205,10 +204,10 @@ extern "C" void TELEMETRY_USART_IRQHandler(void)
else {
telemetryNoDMAFifo.push(data);
#if defined(LUA)
- if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) {
static uint8_t prevdata;
- if (prevdata == 0x7E && outputTelemetryBufferSize > 0 && data == outputTelemetryBufferTrigger) {
- sportSendBuffer(outputTelemetryBuffer, outputTelemetryBufferSize);
+ if (prevdata == 0x7E && outputTelemetryBuffer.size > 0 && data == outputTelemetryBuffer.trigger && outputTelemetryBuffer.destination == SPORT_MODULE) {
+ sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size);
}
prevdata = data;
}
diff --git a/radio/src/targets/horus/trainer_driver.cpp b/radio/src/targets/horus/trainer_driver.cpp
index d05648b47..d5b34cc1e 100644
--- a/radio/src/targets/horus/trainer_driver.cpp
+++ b/radio/src/targets/horus/trainer_driver.cpp
@@ -37,8 +37,8 @@ void init_trainer_ppm()
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
TRAINER_TIMER->ARR = 45000;
- TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
- TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
+ TRAINER_TIMER->CCR2 = GET_TRAINER_PPM_DELAY() * 2;
+ TRAINER_TIMER->CCER = TIM_CCER_CC2E | (GET_TRAINER_PPM_POLARITY() ? 0 : TIM_CCER_CC2P);
TRAINER_TIMER->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_0; // Force O/P high
TRAINER_TIMER->BDTR = TIM_BDTR_MOE;
TRAINER_TIMER->EGR = 1;
@@ -100,8 +100,8 @@ void stop_trainer_capture()
void trainerSendNextFrame()
{
- TRAINER_TIMER->CCR2 = GET_PPM_DELAY(TRAINER_MODULE)*2;
- TRAINER_TIMER->CCER = TIM_CCER_CC2E | (g_model.moduleData[TRAINER_MODULE].ppm.pulsePol ? 0 : TIM_CCER_CC2P);
+ TRAINER_TIMER->CCR2 = GET_TRAINER_PPM_DELAY() * 2;
+ TRAINER_TIMER->CCER = TIM_CCER_CC2E | (GET_TRAINER_PPM_POLARITY() ? 0 : TIM_CCER_CC2P);
TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp
index dedbaec25..cf35464b1 100644
--- a/radio/src/targets/simu/simpgmspace.cpp
+++ b/radio/src/targets/simu/simpgmspace.cpp
@@ -267,12 +267,19 @@ void simuSetSwitch(uint8_t swtch, int8_t state)
#endif
#if defined(SWITCHES_GPIO_REG_C_L)
SWITCH_3_CASE(2, SWITCHES_GPIO_REG_C_L, SWITCHES_GPIO_REG_C_H, SWITCHES_GPIO_PIN_C_L, SWITCHES_GPIO_PIN_C_H)
+ #endif
+ #if defined(SWITCHES_GPIO_REG_D_L)
SWITCH_3_CASE(3, SWITCHES_GPIO_REG_D_L, SWITCHES_GPIO_REG_D_H, SWITCHES_GPIO_PIN_D_L, SWITCHES_GPIO_PIN_D_H)
+ #elif defined(SWITCHES_GPIO_REG_D)
+ SWITCH_CASE (3, SWITCHES_GPIO_REG_D, SWITCHES_GPIO_PIN_D)
#endif
#if defined(PCBX7)
SWITCH_CASE (4, SWITCHES_GPIO_REG_F, SWITCHES_GPIO_PIN_F)
SWITCH_CASE (5, SWITCHES_GPIO_REG_H, SWITCHES_GPIO_PIN_H)
- #elif !defined(PCBXLITE)
+ #elif defined(PCBXLITES)
+ SWITCH_CASE (4, SWITCHES_GPIO_REG_E, SWITCHES_GPIO_PIN_E)
+ SWITCH_CASE (5, SWITCHES_GPIO_REG_F, SWITCHES_GPIO_PIN_F)
+ #elif !defined(PCBXLITE) && !defined(PCBX3)
SWITCH_3_CASE(4, SWITCHES_GPIO_REG_E_L, SWITCHES_GPIO_REG_E_H, SWITCHES_GPIO_PIN_E_L, SWITCHES_GPIO_PIN_E_H)
SWITCH_CASE (5, SWITCHES_GPIO_REG_F, SWITCHES_GPIO_PIN_F)
SWITCH_3_CASE(6, SWITCHES_GPIO_REG_G_L, SWITCHES_GPIO_REG_G_H, SWITCHES_GPIO_PIN_G_L, SWITCHES_GPIO_PIN_G_H)
@@ -327,7 +334,7 @@ void StartSimu(bool tests, const char * sdPath, const char * settingsPath)
if (simu_running)
return;
- s_current_protocol[0] = 255;
+ moduleSettings[0].protocol = PROTOCOL_CHANNELS_UNINITIALIZED;
menuLevel = 0;
simu_start_mode = (tests ? 0 : 0x02 /* OPENTX_START_NO_CHECKS */);
@@ -693,6 +700,10 @@ uint32_t isBootloaderStart(const uint8_t * block) { return 1; }
void LCD_ControlLight(uint16_t dutyCycle) { }
#endif
+#if defined(PCBXLITES)
+bool isJackPlugged() { return false; }
+#endif
+
void serialPrintf(const char * format, ...) { }
void serialCrlf() { }
void serialPutc(char c) { }
diff --git a/radio/src/targets/sky9x/CMakeLists.txt b/radio/src/targets/sky9x/CMakeLists.txt
index 2da8e1305..176293564 100644
--- a/radio/src/targets/sky9x/CMakeLists.txt
+++ b/radio/src/targets/sky9x/CMakeLists.txt
@@ -9,6 +9,7 @@ set(NAVIGATION_TYPE 9x)
set(TARGET_DIR sky9x)
set(FIRMWARE_DEPENDENCIES ${FIRMWARE_DEPENDENCIES} 9x_bitmaps)
set(PPM_LIMITS_SYMETRICAL YES)
+set(PXX1 YES)
if(PCB STREQUAL 9XRPRO)
add_definitions(-Dat91sam3s8 -DREVX)
diff --git a/radio/src/targets/sky9x/board.h b/radio/src/targets/sky9x/board.h
index c49fd1119..a37321b1a 100644
--- a/radio/src/targets/sky9x/board.h
+++ b/radio/src/targets/sky9x/board.h
@@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
- * th9x - http://code.google.com/p/th9x
+ * th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@@ -60,7 +60,7 @@ enum EnumKeys
KEY_PLUS = KEY_UP,
KEY_RIGHT,
KEY_LEFT,
-
+
TRM_BASE,
TRM_LH_DWN = TRM_BASE,
TRM_LH_UP,
@@ -257,10 +257,13 @@ void init_no_pulses(uint32_t port);
void disable_no_pulses(uint32_t port);
void init_ppm(uint32_t port);
void disable_ppm(uint32_t port);
-void init_pxx(uint32_t port);
-void disable_pxx(uint32_t port);
+void init_pxx1_pulses(uint32_t port);
+void disable_pxx1_pulses(uint32_t port);
void init_serial(uint32_t port, uint32_t baudrate, uint32_t period_half_us);
void disable_serial(uint32_t port);
+void init_module_timer( uint32_t module_index, uint32_t period, uint8_t state);
+void disable_module_timer( uint32_t module_index);
+void extmoduleSendNextFrame();
// SD driver
#if defined(SIMU)
@@ -405,8 +408,9 @@ void debugPutc(const char c);
// Telemetry driver
void telemetryPortInit(uint32_t baudrate, uint8_t mode);
uint32_t telemetryTransmitPending();
-void telemetryTransmitBuffer(uint8_t * buffer, uint32_t size);
+void telemetryTransmitBuffer(const uint8_t * buffer, uint32_t size);
void rxPdcUsart( void (*pChProcess)(uint8_t x) );
+void sportSendBuffer(const uint8_t * buffer, uint32_t size);
// Second UART driver
void serial2TelemetryInit(unsigned int protocol);
diff --git a/radio/src/targets/sky9x/pulses_driver.cpp b/radio/src/targets/sky9x/pulses_driver.cpp
index 02f8d5cf5..4058bedd4 100644
--- a/radio/src/targets/sky9x/pulses_driver.cpp
+++ b/radio/src/targets/sky9x/pulses_driver.cpp
@@ -23,8 +23,8 @@
void setExternalModulePolarity()
{
Pwm * pwmptr = PWM;
- pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
- if (GET_PPM_POLARITY(EXTERNAL_MODULE))
+ pwmptr->PWM_CH_NUM[3].PWM_CDTYUPD = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
+ if (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE))
pwmptr->PWM_CH_NUM[3].PWM_CMR &= ~0x00000200; // CPOL
else
pwmptr->PWM_CH_NUM[3].PWM_CMR |= 0x00000200; // CPOL
@@ -33,8 +33,8 @@ void setExternalModulePolarity()
void setExtraModulePolarity()
{
Pwm * pwmptr = PWM;
- pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE) * 2; // Duty in half uS
- if (GET_PPM_POLARITY(EXTRA_MODULE))
+ pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_MODULE_PPM_DELAY(EXTRA_MODULE) * 2; // Duty in half uS
+ if (GET_MODULE_PPM_POLARITY(EXTRA_MODULE))
pwmptr->PWM_CH_NUM[1].PWM_CMR &= ~0x00000200; // CPOL
else
pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200; // CPOL
@@ -63,8 +63,6 @@ void init_main_ppm(uint32_t period, uint32_t out_enable)
{
Pwm * pwmptr;
- setupPulsesPPMModule(EXTERNAL_MODULE);
-
if (out_enable) {
module_output_active();
}
@@ -74,7 +72,7 @@ void init_main_ppm(uint32_t period, uint32_t out_enable)
pwmptr->PWM_CH_NUM[3].PWM_CMR = 0x0004000B; // CLKA
pwmptr->PWM_CH_NUM[3].PWM_CPDR = period; // Period in half uS
pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = period; // Period in half uS
- pwmptr->PWM_CH_NUM[3].PWM_CDTY = GET_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
+ pwmptr->PWM_CH_NUM[3].PWM_CDTY = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE) * 2; // Duty in half uS
pwmptr->PWM_ENA = PWM_ENA_CHID3; // Enable channel 3
pwmptr->PWM_IER1 = PWM_IER1_CHID3;
@@ -98,13 +96,13 @@ void init_second_ppm(uint32_t period)
Pwm * pwmptr = PWM;
configure_pins(PIO_PC15, PIN_PERIPHERAL | PIN_INPUT | PIN_PER_B | PIN_PORTC | PIN_NO_PULLUP);
pwmptr->PWM_CH_NUM[1].PWM_CMR = 0x0000000B; // CLKB
- if (!GET_PPM_POLARITY(EXTRA_MODULE)) {
+ if (!GET_MODULE_PPM_POLARITY(EXTRA_MODULE)) {
pwmptr->PWM_CH_NUM[1].PWM_CMR |= 0x00000200; // CPOL
}
pwmptr->PWM_CH_NUM[1].PWM_CPDR = period; // Period
pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = period; // Period
- pwmptr->PWM_CH_NUM[1].PWM_CDTY = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
- pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_PPM_DELAY(EXTRA_MODULE)*2; // Duty
+ pwmptr->PWM_CH_NUM[1].PWM_CDTY = GET_MODULE_PPM_DELAY(EXTRA_MODULE)*2; // Duty
+ pwmptr->PWM_CH_NUM[1].PWM_CDTYUPD = GET_MODULE_PPM_DELAY(EXTRA_MODULE)*2; // Duty
pwmptr->PWM_ENA = PWM_ENA_CHID1; // Enable channel 1
pwmptr->PWM_IER1 = PWM_IER1_CHID1;
#endif
@@ -129,6 +127,22 @@ void init_no_pulses(uint32_t port)
}
}
+void init_module_timer(uint32_t port, uint32_t period, uint8_t state)
+{
+ if (port == EXTERNAL_MODULE) {
+ // TODO use period here
+ init_main_ppm(3000, 0);
+ }
+}
+
+void disable_module_timer(uint32_t port)
+{
+ if (port == EXTERNAL_MODULE) {
+ disable_ppm(EXTERNAL_MODULE);
+ }
+}
+
+
void disable_no_pulses(uint32_t port)
{
if (port == EXTERNAL_MODULE) {
@@ -200,7 +214,7 @@ void disable_ssc()
sscptr->SSC_CR = SSC_CR_TXDIS;
}
-void init_pxx(uint32_t port)
+void init_pxx1_pulses(uint32_t port)
{
if (port == EXTERNAL_MODULE) {
init_main_ppm(2500 * 2, 0);
@@ -211,7 +225,7 @@ void init_pxx(uint32_t port)
}
}
-void disable_pxx(uint32_t port)
+void disable_pxx1_pulses(uint32_t port)
{
if (port == EXTERNAL_MODULE) {
disable_ssc();
@@ -251,6 +265,10 @@ void disable_serial(uint32_t port)
}
}
+void extmoduleSendNextFrame()
+{
+
+}
#if !defined(SIMU)
extern "C" void PWM_IRQHandler(void)
{
@@ -260,8 +278,8 @@ extern "C" void PWM_IRQHandler(void)
if (reason & PWM_ISR1_CHID3) {
// Use the current protocol, don't switch until set_up_pulses
- switch (s_current_protocol[EXTERNAL_MODULE]) {
- case PROTO_PXX:
+ switch (moduleSettings[EXTERNAL_MODULE].protocol) {
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
// Alternate periods of 6.5mS and 2.5 mS
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
if (period == 2500 * 2) {
@@ -278,15 +296,15 @@ extern "C" void PWM_IRQHandler(void)
else {
// Kick off serial output here
Ssc * sscptr = SSC;
- sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.getData());
- sscptr->SSC_TCR = modulePulsesData[EXTERNAL_MODULE].pxx.getSize();
+ sscptr->SSC_TPR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData());
+ sscptr->SSC_TCR = extmodulePulsesData.pxx.getSize();
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
}
break;
- case PROTO_DSM2_LP45:
- case PROTO_DSM2_DSM2:
- case PROTO_DSM2_DSMX:
+ case PROTOCOL_CHANNELS_DSM2_LP45:
+ case PROTOCOL_CHANNELS_DSM2_DSM2:
+ case PROTOCOL_CHANNELS_DSM2_DSMX:
// Alternate periods of 19.5mS and 2.5 mS
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
if (period == 2500 * 2) {
@@ -302,16 +320,16 @@ extern "C" void PWM_IRQHandler(void)
else {
// Kick off serial output here
Ssc * sscptr = SSC;
- sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
- sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
+ sscptr->SSC_TPR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses);
+ sscptr->SSC_TCR = (uint8_t *)extmodulePulsesData.dsm2.ptr - (uint8_t *)extmodulePulsesData.dsm2.pulses;
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
}
break;
#if defined(MULTIMODULE)
- case PROTO_MULTIMODULE:
+ case PROTOCOL_CHANNELS_MULTIMODULE:
#endif
- case PROTO_SBUS:
+ case PROTOCOL_CHANNELS_SBUS:
// Todo: how to do inverted polarity on this platform?
// Alternate periods of 5.5mS and 3.5 mS
period = pwmptr->PWM_CH_NUM[3].PWM_CPDR;
@@ -328,15 +346,15 @@ extern "C" void PWM_IRQHandler(void)
else {
// Kick off serial output here
Ssc * sscptr = SSC;
- sscptr->SSC_TPR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
- sscptr->SSC_TCR = (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - (uint8_t *)modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
+ sscptr->SSC_TPR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses);
+ sscptr->SSC_TCR = (uint8_t *)extmodulePulsesData.dsm2.ptr - (uint8_t *)extmodulePulsesData.dsm2.pulses;
sscptr->SSC_PTCR = SSC_PTCR_TXTEN; // Start transfers
}
break;
default:
- pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *modulePulsesData[EXTERNAL_MODULE].ppm.ptr++;
- if (*modulePulsesData[EXTERNAL_MODULE].ppm.ptr == 0) {
+ pwmptr->PWM_CH_NUM[3].PWM_CPDRUPD = *extmodulePulsesData.ppm.ptr++;
+ if (*extmodulePulsesData.ppm.ptr == 0) {
setExternalModulePolarity();
setupPulses(EXTERNAL_MODULE);
}
@@ -347,11 +365,12 @@ extern "C" void PWM_IRQHandler(void)
#if !defined(REVA)
if (reason & PWM_ISR1_CHID1) {
- pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++;
+ // TODO EXTRA_MODULE will be broken
+ /*pwmptr->PWM_CH_NUM[1].PWM_CPDRUPD = *modulePulsesData[EXTRA_MODULE].ppm.ptr++;
if (*modulePulsesData[EXTRA_MODULE].ppm.ptr == 0) {
- setupPulsesPPMModule(EXTRA_MODULE);
+ setupPulses(EXTRA_MODULE);
setExtraModulePolarity();
- }
+ }*/
}
#endif
}
diff --git a/radio/src/targets/sky9x/telemetry_driver.cpp b/radio/src/targets/sky9x/telemetry_driver.cpp
index e9dc3edaa..4875c5d35 100644
--- a/radio/src/targets/sky9x/telemetry_driver.cpp
+++ b/radio/src/targets/sky9x/telemetry_driver.cpp
@@ -2,7 +2,7 @@
* Copyright (C) OpenTX
*
* Based on code named
- * th9x - http://code.google.com/p/th9x
+ * th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
@@ -135,12 +135,11 @@ void rxPdcUsart( void (*pChProcess)(uint8_t x) )
#endif
}
-uint32_t txPdcUsart(uint8_t *buffer, uint32_t size)
+uint32_t txPdcUsart(const uint8_t * buffer, uint32_t size)
{
- Usart *pUsart = SECOND_USART;
+ Usart * pUsart = SECOND_USART;
- if ( pUsart->US_TNCR == 0 )
- {
+ if (pUsart->US_TNCR == 0) {
#ifndef SIMU
pUsart->US_TNPR = (uint32_t)buffer ;
#endif
@@ -174,7 +173,12 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
#endif
}
-void telemetryTransmitBuffer(uint8_t * buffer, uint32_t size)
+void sportSendBuffer(const uint8_t * buffer, uint32_t size)
+{
+ telemetryTransmitBuffer(buffer, size);
+}
+
+void telemetryTransmitBuffer(const uint8_t * buffer, uint32_t size)
{
txPdcUsart(buffer, size);
}
diff --git a/radio/src/targets/taranis/CMakeLists.txt b/radio/src/targets/taranis/CMakeLists.txt
index 78b09bfb5..0a6a952eb 100644
--- a/radio/src/targets/taranis/CMakeLists.txt
+++ b/radio/src/targets/taranis/CMakeLists.txt
@@ -31,6 +31,7 @@ if(PCB STREQUAL X9E)
set(FONTS_TARGET taranis_fonts)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS NO)
elseif(PCB STREQUAL X9D+)
set(CPU_TYPE STM32F2)
set(CPU_TYPE_FULL STM32F205xE) # for size report
@@ -47,6 +48,7 @@ elseif(PCB STREQUAL X9D+)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(SERIAL2_DRIVER ../common/arm/stm32/serial2_driver.cpp)
set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS NO)
elseif(PCB STREQUAL X9D)
set(CPU_TYPE STM32F2)
set(CPU_TYPE_FULL STM32F205xE) # for size report
@@ -63,6 +65,7 @@ elseif(PCB STREQUAL X9D)
set(LCD_DRIVER lcd_driver_aspi.cpp)
set(SERIAL2_DRIVER ../common/arm/stm32/serial2_driver.cpp)
set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS NO)
elseif(PCB STREQUAL X7)
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32F2)
@@ -80,8 +83,28 @@ elseif(PCB STREQUAL X7)
set(FONTS_TARGET 9x_fonts_1bit)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS YES)
+elseif(PCB STREQUAL X3)
+ set(PXX_FREQUENCY "HIGH")
+ set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
+ set(CPU_TYPE STM32F2)
+ set(CPU_TYPE_FULL STM32F205xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
+ set(HAPTIC YES)
+ set(LUA_EXPORT lua_export_x3)
+ set(FLAVOUR x3)
+ add_definitions(-DPCBX3 -DSOFTWARE_VOLUME)
+ add_definitions(-DEEPROM_VARIANT=0x4000)
+ add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
+ set(GUI_DIR 128x64)
+ set(NAVIGATION_TYPE x7)
+ set(BITMAPS_TARGET 9x_bitmaps)
+ set(FONTS_TARGET 9x_fonts_1bit)
+ set(LCD_DRIVER lcd_driver_spi.cpp)
+ set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS YES)
elseif(PCB STREQUAL XLITE)
- set(PXX_FREQUENCY "HIGH" CACHE STRING "PXX frequency (LOW / HIGH)")
+ set(PXX_FREQUENCY "HIGH" CACHE STRING "PXX frequency (LOW / HIGH)") # always use HIGH except on some prototype boards
set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
set(CPU_TYPE STM32F2)
set(CPU_TYPE_FULL STM32F205xE) # for size report
@@ -89,7 +112,7 @@ elseif(PCB STREQUAL XLITE)
set(HAPTIC YES)
set(LUA_EXPORT lua_export_xlite)
set(FLAVOUR xlite)
- add_definitions(-DPCBXLITE -DSOFTWARE_VOLUME)
+ add_definitions(-DPCBXLITE -DSOFTWARE_VOLUME -DEXTERNAL_ANTENNA -DSTICKS_PWM)
add_definitions(-DEEPROM_VARIANT=0x2000)
add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
set(GUI_DIR 128x64)
@@ -98,9 +121,40 @@ elseif(PCB STREQUAL XLITE)
set(FONTS_TARGET 9x_fonts_1bit)
set(LCD_DRIVER lcd_driver_spi.cpp)
set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS YES)
+elseif(PCB STREQUAL XLITES)
+ set(PXX_FREQUENCY "HIGH")
+ set(PWR_BUTTON "PRESS" CACHE STRING "Pwr button type (PRESS/SWITCH)")
+ set(CPU_TYPE STM32F2)
+ set(CPU_TYPE_FULL STM32F205xE) # for size report
+ set(LINKER_SCRIPT targets/taranis/stm32f2_flash.ld)
+ set(HAPTIC YES)
+ set(LUA_EXPORT lua_export_xlite)
+ set(FLAVOUR xlites)
+ add_definitions(-DPCBXLITES -DPCBXLITE -DSOFTWARE_VOLUME -DEXTERNAL_ANTENNA -DSTICKS_PWM)
+ add_definitions(-DEEPROM_VARIANT=0x1000)
+ add_definitions(-DPWR_BUTTON_${PWR_BUTTON})
+ set(GUI_DIR 128x64)
+ set(NAVIGATION_TYPE xlite)
+ set(BITMAPS_TARGET 9x_bitmaps)
+ set(FONTS_TARGET 9x_fonts_1bit)
+ set(LCD_DRIVER lcd_driver_spi.cpp)
+ set(GVAR_SCREEN model_gvars.cpp)
+ set(STATUS_LEDS YES)
endif()
-if(PCB STREQUAL XLITE)
+#if(PCB STREQUAL XLITES)
+# add_definitions(-DGYRO)
+# set(TARGET_SRC
+# ${TARGET_SRC}
+# ../common/arm/stm32/lsm6ds3_driver.cpp
+# )
+#endif()
+
+if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES OR PCB STREQUAL X3)
+ option(PXX1 "PXX1 protocol support" OFF)
+ option(PXX2 "PXX2 protocol support" ON)
+ add_definitions(-DINTERNAL_MODULE_SERIAL)
if(PXX_FREQUENCY STREQUAL HIGH)
add_definitions(-DPXX_FREQUENCY_HIGH)
endif()
@@ -112,19 +166,26 @@ if(PCB STREQUAL XLITE)
../common/arm/stm32/intmodule_serial_driver.cpp
)
else()
+ set(PXX1 YES)
+ option(PXX2 "PXX2 protocol support" ON)
set(TARGET_SRC
${TARGET_SRC}
intmodule_pulses_driver.cpp
- trainer_driver.cpp
)
- add_definitions(-DSBUS)
set(PULSES_SRC
${PULSES_SRC}
../sbus.cpp
)
endif()
-if(PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL XLITE)
+if(NOT PCB STREQUAL XLITE)
+ set(TARGET_SRC
+ ${TARGET_SRC}
+ trainer_driver.cpp
+ )
+endif()
+
+if(PCB STREQUAL X9E OR PCB STREQUAL X7 OR PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
add_definitions(-DBLUETOOTH)
set(TARGET_SRC
${TARGET_SRC}
@@ -149,7 +210,13 @@ endif()
add_definitions(-DPCBTARANIS)
add_definitions(-DAUDIO -DVOICE -DRTCLOCK)
-set(GUI_SRC ${GUI_SRC}
+set(SRC
+ ${SRC}
+ io/frsky_device_firmware_update.cpp
+ )
+
+set(GUI_SRC
+ ${GUI_SRC}
model_input_edit.cpp
model_mix_edit.cpp
model_display.cpp
@@ -163,7 +230,7 @@ set(GUI_SRC ${GUI_SRC}
../screenshot.cpp
)
-if(PCB STREQUAL X7 OR PCB STREQUAL XLITE)
+if(STATUS_LEDS)
set(LED_DRIVER led_driver.cpp)
endif()
@@ -177,7 +244,7 @@ set(TARGET_SRC
../common/arm/stm32/adc_driver.cpp
)
-if(PCB STREQUAL XLITE)
+if(PCB STREQUAL XLITE OR PCB STREQUAL XLITES)
set(TARGET_SRC
${TARGET_SRC}
../common/arm/stm32/sticks_pwm_driver.cpp
diff --git a/radio/src/targets/taranis/backlight_driver.cpp b/radio/src/targets/taranis/backlight_driver.cpp
index 97b225ac9..83e774ea2 100644
--- a/radio/src/targets/taranis/backlight_driver.cpp
+++ b/radio/src/targets/taranis/backlight_driver.cpp
@@ -97,7 +97,7 @@ uint8_t isBacklightEnabled()
{
return (BACKLIGHT_TIMER->CCR4 != 0 || BACKLIGHT_TIMER->CCR2 != 0);
}
-#elif defined(PCBX7) || defined(PCBXLITE)
+#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX3)
void backlightInit()
{
GPIO_InitTypeDef GPIO_InitStructure;
diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp
index 5c092ee03..6a8bfcf5f 100644
--- a/radio/src/targets/taranis/board.cpp
+++ b/radio/src/targets/taranis/board.cpp
@@ -29,6 +29,8 @@ extern "C" {
}
#endif
+HardwareOptions hardwareOptions;
+
void watchdogInit(unsigned int duration)
{
IWDG->KR = 0x5555; // Unlock registers
@@ -149,20 +151,25 @@ void boardInit()
INTMODULE_RCC_AHB1Periph | EXTMODULE_RCC_AHB1Periph |
TELEMETRY_RCC_AHB1Periph | SPORT_UPDATE_RCC_AHB1Periph |
SERIAL_RCC_AHB1Periph | TRAINER_RCC_AHB1Periph |
- HEARTBEAT_RCC_AHB1Periph | BT_RCC_AHB1Periph, ENABLE);
+ HEARTBEAT_RCC_AHB1Periph | BT_RCC_AHB1Periph | GYRO_RCC_AHB1Periph,
+ ENABLE);
RCC_APB1PeriphClockCmd(LCD_RCC_APB1Periph | AUDIO_RCC_APB1Periph | ADC_RCC_APB1Periph |
BACKLIGHT_RCC_APB1Periph | HAPTIC_RCC_APB1Periph | INTERRUPT_xMS_RCC_APB1Periph |
TIMER_2MHz_RCC_APB1Periph | I2C_RCC_APB1Periph |
SD_RCC_APB1Periph | TRAINER_RCC_APB1Periph |
TELEMETRY_RCC_APB1Periph | SERIAL_RCC_APB1Periph |
- INTMODULE_RCC_APB1Periph | BT_RCC_APB1Periph, ENABLE);
+ INTMODULE_RCC_APB1Periph | BT_RCC_APB1Periph | GYRO_RCC_APB1Periph, ENABLE);
RCC_APB2PeriphClockCmd(BACKLIGHT_RCC_APB2Periph | ADC_RCC_APB2Periph |
HAPTIC_RCC_APB2Periph | INTMODULE_RCC_APB2Periph |
EXTMODULE_RCC_APB2Periph | HEARTBEAT_RCC_APB2Periph |
BT_RCC_APB2Periph, ENABLE);
+#if defined(BLUETOOTH)
+ bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE);
+#endif
+
#if !defined(PCBX9E)
// some X9E boards need that the pwrInit() is moved a little bit later
pwrInit();
@@ -180,7 +187,7 @@ void boardInit()
sticksPwmInit();
delay_ms(20);
if (pwm_interrupt_count < 32) {
- sticks_pwm_disabled = true;
+ hardwareOptions.sticksPwmDisabled = true;
}
#endif
@@ -202,8 +209,8 @@ void boardInit()
hapticInit();
#endif
-#if defined(BLUETOOTH)
- bluetoothInit(BLUETOOTH_DEFAULT_BAUDRATE);
+#if defined(PXX2_PROBE)
+ intmodulePxx2Probe();
#endif
#if defined(DEBUG)
@@ -272,6 +279,17 @@ void boardInit()
if (HAS_SPORT_UPDATE_CONNECTOR()) {
sportUpdateInit();
}
+
+#if defined(JACK_DETECT_GPIO)
+ initJackDetect();
+#endif
+
+ initSpeakerEnable();
+ enableSpeaker();
+
+ initHeadphoneTrainerSwitch();
+
+ vbattRTC = getRTCBattVoltage();
#endif // !defined(SIMU)
}
@@ -302,7 +320,7 @@ uint8_t currentTrainerMode = 0xff;
void checkTrainerSettings()
{
- uint8_t requiredTrainerMode = g_model.trainerMode;
+ uint8_t requiredTrainerMode = g_model.trainerData.mode;
if (requiredTrainerMode != currentTrainerMode) {
switch (currentTrainerMode) {
case TRAINER_MODE_MASTER_TRAINER_JACK:
@@ -357,3 +375,65 @@ uint16_t getBatteryVoltage()
instant_vbat += 20; // add 0.2V because of the diode TODO check if this is needed, but removal will beak existing calibrations!!!
return (uint16_t)instant_vbat;
}
+
+#if defined(AUDIO_SPEAKER_ENABLE_GPIO)
+void initSpeakerEnable()
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_InitStructure.GPIO_Pin = AUDIO_SPEAKER_ENABLE_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(AUDIO_SPEAKER_ENABLE_GPIO, &GPIO_InitStructure);
+}
+
+void enableSpeaker()
+{
+ GPIO_SetBits(AUDIO_SPEAKER_ENABLE_GPIO, AUDIO_SPEAKER_ENABLE_GPIO_PIN);
+}
+
+void disableSpeaker()
+{
+ GPIO_ResetBits(AUDIO_SPEAKER_ENABLE_GPIO, AUDIO_SPEAKER_ENABLE_GPIO_PIN);
+}
+#endif
+
+#if defined(HEADPHONE_TRAINER_SWITCH_GPIO)
+void initHeadphoneTrainerSwitch()
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_InitStructure.GPIO_Pin = HEADPHONE_TRAINER_SWITCH_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(HEADPHONE_TRAINER_SWITCH_GPIO, &GPIO_InitStructure);
+}
+
+void enableHeadphone()
+{
+ GPIO_ResetBits(HEADPHONE_TRAINER_SWITCH_GPIO, HEADPHONE_TRAINER_SWITCH_GPIO_PIN);
+}
+
+void enableTrainer()
+{
+ GPIO_SetBits(HEADPHONE_TRAINER_SWITCH_GPIO, HEADPHONE_TRAINER_SWITCH_GPIO_PIN);
+}
+#endif
+
+#if defined(JACK_DETECT_GPIO)
+void initJackDetect(void)
+{
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_InitStructure.GPIO_Pin = JACK_DETECT_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(JACK_DETECT_GPIO, &GPIO_InitStructure);
+}
+#endif
\ No newline at end of file
diff --git a/radio/src/targets/taranis/board.h b/radio/src/targets/taranis/board.h
index be890a8ad..650e6625e 100644
--- a/radio/src/targets/taranis/board.h
+++ b/radio/src/targets/taranis/board.h
@@ -21,8 +21,9 @@
#ifndef _BOARD_H_
#define _BOARD_H_
-#include "stddef.h"
-#include "stdbool.h"
+#include
+#include "../definitions.h"
+#include "cpu_id.h"
#if defined(__cplusplus) && !defined(SIMU)
extern "C" {
@@ -124,10 +125,6 @@ void delay_ms(uint32_t ms);
}
#endif
-// CPU Unique ID
-#define LEN_CPU_UID (3*8+2)
-void getCPUUniqueID(char * s);
-
// SD driver
#define BLOCK_SIZE 512 /* Block Size in Bytes */
#if !defined(SIMU) || defined(SIMU_DISKIO)
@@ -168,35 +165,58 @@ uint32_t isBootloaderStart(const uint8_t * buffer);
// Pulses driver
#define INTERNAL_MODULE_ON() GPIO_SetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
-#define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
-#define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
-#define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
-#define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET)
-#define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
-#if defined(INTMODULE_USART) && defined(EXTMODULE_USART)
- #define IS_UART_MODULE(port) (true)
-#elif defined(INTMODULE_USART)
- #define IS_UART_MODULE(port) (port == INTERNAL_MODULE)
+#if defined(INTMODULE_USART)
+ #define INTERNAL_MODULE_OFF() intmoduleStop()
#else
- #define IS_UART_MODULE(port) (false)
+ #define INTERNAL_MODULE_OFF() GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN)
#endif
-void init_no_pulses(uint32_t port);
-void disable_no_pulses(uint32_t port);
-void init_ppm( uint32_t module_index);
-void disable_ppm( uint32_t module_index);
-void init_pxx( uint32_t module_index);
-void disable_pxx( uint32_t module_index);
-void init_serial( uint32_t module_index, uint32_t baudrate, uint32_t period);
-void disable_serial( uint32_t module_index);
-void init_module_timer( uint32_t module_index, uint32_t period, uint8_t state);
-void disable_module_timer( uint32_t module_index);
+
+#define IS_INTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN) == Bit_SET)
+
+void init_ppm(uint8_t module);
+void disable_ppm(uint8_t module);
+void init_pxx2(uint8_t module);
+void disable_pxx2(uint8_t module);
+void init_pxx1_pulses(uint8_t module);
+void init_pxx1_serial(uint8_t module);
+void disable_pxx1_pulses(uint8_t module);
+void disable_pxx1_serial(uint8_t module);
+void init_serial(uint8_t module, uint32_t baudrate, uint32_t period);
+void disable_serial(uint8_t module);
+void intmoduleStop();
+void intmodulePxxStart();
+void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable);
+#if defined(TARANIS_INTERNAL_PPM)
+void intmodulePpmStart(void);
+#endif
+void intmoduleSendBuffer(const uint8_t * data, uint8_t size);
+void intmoduleSendNextFrame();
+
+void extmoduleStop();
+void extmodulePpmStart();
+void extmodulePxxPulsesStart();
+void extmodulePxxSerialStart();
+void extmodulePxx2Start();
+void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us);
+void extmoduleInvertedSerialStart(uint32_t baudrate);
+void extmoduleSendBuffer(const uint8_t * data, uint8_t size);
+void extmoduleSendNextFrame();
// Trainer driver
-#define SLAVE_MODE() (g_model.trainerMode == TRAINER_MODE_SLAVE)
+#define SLAVE_MODE() (g_model.trainerData.mode == TRAINER_MODE_SLAVE)
#if defined(PCBX9E)
#define TRAINER_CONNECTED() (true)
-#elif defined(PCBX7)
+#elif defined(PCBX7) || defined(PCBX3)
#define TRAINER_CONNECTED() (GPIO_ReadInputDataBit(TRAINER_DETECT_GPIO, TRAINER_DETECT_GPIO_PIN) == Bit_SET)
+#elif defined(PCBXLITES)
+ enum JackState
+ {
+ SPEAKER_ACTIVE,
+ HEADPHONE_ACTIVE,
+ TRAINER_ACTIVE,
+ };
+ extern uint8_t jackState;
+ #define TRAINER_CONNECTED() (jackState == TRAINER_ACTIVE)
#elif defined(PCBXLITE)
#define TRAINER_CONNECTED() false // there is no Trainer jack on Taranis X-Lite
#else
@@ -310,25 +330,27 @@ enum EnumSwitchesPositions
SW_SC0,
SW_SC1,
SW_SC2,
+#if !defined(PCBX3)
SW_SD0,
SW_SD1,
SW_SD2,
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#endif
+#if defined(PCBX9) || defined(PCBXLITES) || defined(PCBX3)
SW_SE0,
SW_SE1,
SW_SE2,
#endif
-#if !defined(PCBXLITE)
+#if defined(PCBX9) || defined(PCBX7) || defined(PCBXLITES) || defined(PCBX3)
SW_SF0,
SW_SF1,
SW_SF2,
#endif
-#if !defined(PCBX7) && !defined(PCBXLITE)
+#if defined(PCBX9)
SW_SG0,
SW_SG1,
SW_SG2,
#endif
-#if !defined(PCBXLITE)
+#if defined(PCBX9) || defined(PCBX7)
SW_SH0,
SW_SH1,
SW_SH2,
@@ -365,11 +387,16 @@ enum EnumSwitchesPositions
SW_SR1,
SW_SR2,
#endif
+ NUM_SWITCHES_POSITIONS
};
-#if defined(PCBXLITE)
+#if defined(PCBXLITES)
+ #define NUM_SWITCHES 6
+#elif defined(PCBXLITE)
#define NUM_SWITCHES 4
#elif defined(PCBX7)
#define NUM_SWITCHES 6
+#elif defined(PCBX3)
+ #define NUM_SWITCHES 5
#elif defined(PCBX9E)
#define NUM_SWITCHES 18 // yes, it's a lot!
#else
@@ -383,7 +410,7 @@ uint32_t readTrims(void);
#define TRIMS_PRESSED() (readTrims())
#define KEYS_PRESSED() (readKeys())
-#if defined(PCBX9E) || defined(PCBX7)
+#if defined(PCBX9E) || defined(PCBX7) || defined(PCBX3)
// Rotary Encoder driver
#define ROTARY_ENCODER_NAVIGATION
void checkRotaryEncoder(void);
@@ -412,10 +439,13 @@ enum Analogs {
STICK4,
POT_FIRST,
POT1 = POT_FIRST,
+#if defined(PCBX3)
+ POT_LAST = POT1,
+#elif defined(PCBXLITE) || defined(PCBX7)
POT2,
-#if defined(PCBX7) || defined(PCBXLITE)
POT_LAST = POT2,
#elif defined(PCBX9E)
+ POT2,
POT3,
POT4,
POT_LAST = POT4,
@@ -424,13 +454,15 @@ enum Analogs {
SLIDER3,
SLIDER4,
#else
+ POT2,
POT3,
POT_LAST = POT3,
SLIDER1,
SLIDER2,
#endif
TX_VOLTAGE,
- NUM_ANALOGS
+ NUM_ANALOGS,
+ TX_RTC = NUM_ANALOGS
};
#define NUM_POTS (POT_LAST-POT_FIRST+1)
@@ -440,18 +472,39 @@ enum Analogs {
#define NUM_MOUSE_ANALOGS 0
#define NUM_DUMMY_ANAS 0
-#if defined(PCBXLITE)
+#if defined(STICKS_PWM)
#define NUM_PWMSTICKS 4
- extern bool sticks_pwm_disabled;
- #define STICKS_PWM_ENABLED() (sticks_pwm_disabled == false)
+ #define STICKS_PWM_ENABLED() (!hardwareOptions.sticksPwmDisabled)
void sticksPwmInit(void);
void sticksPwmRead(uint16_t * values);
- extern volatile uint32_t pwm_interrupt_count;
+ extern volatile uint32_t pwm_interrupt_count; // TODO => reusable buffer (boot section)
#define NUM_TRIMS_KEYS 4
#else
#define NUM_TRIMS_KEYS 8
#endif
+PACK(typedef struct {
+#if NUM_PWMSTICKS > 0
+ uint8_t sticksPwmDisabled:1;
+#endif
+ uint8_t pxx2Enabled:1;
+}) HardwareOptions;
+
+extern HardwareOptions hardwareOptions;
+
+#if !defined(PXX2)
+ #define IS_PXX2_INTERNAL_ENABLED() (false)
+ #define IS_PXX1_INTERNAL_ENABLED() (true)
+#elif !defined(PXX1) || defined(PCBXLITES) || defined(PCBX3)
+ #define IS_PXX2_INTERNAL_ENABLED() (true)
+ #define IS_PXX1_INTERNAL_ENABLED() (false)
+#else
+ // TODO #define PXX2_PROBE
+ // TODO #define IS_PXX2_INTERNAL_ENABLED() (hardwareOptions.pxx2Enabled)
+ #define IS_PXX2_INTERNAL_ENABLED() (true)
+ #define IS_PXX1_INTERNAL_ENABLED() (true)
+#endif
+
enum CalibratedAnalogs {
CALIBRATED_STICK1,
CALIBRATED_STICK2,
@@ -469,11 +522,14 @@ enum CalibratedAnalogs {
#else
#define IS_POT(x) ((x)>=POT_FIRST && (x)<=POT_LAST)
#endif
+
#define IS_SLIDER(x) ((x)>POT_LAST && (x)CR1 &= ~TIM_CR1_CEN;
- EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz
- EXTMODULE_TIMER->ARR = (2000 * period);
- EXTMODULE_TIMER->CCR2 = (2000 * period) - 1000;
- EXTMODULE_TIMER->EGR = 1; // Restart
- EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
- EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
- EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
-
- NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn);
- NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7);
-}
-
void extmodulePpmStart()
{
EXTERNAL_MODULE_ON();
@@ -89,17 +56,18 @@ void extmodulePpmStart()
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz
EXTMODULE_TIMER->ARR = 45000;
- EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
- EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // // we are using complementary output so logic has to be reversed here
+ EXTMODULE_TIMER->CCR1 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE)*2;
+ EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // // we are using complementary output so logic has to be reversed here
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_0; // Force O/P high
EXTMODULE_TIMER->EGR = 1;
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE;
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC2PE; // PWM mode 1
+ EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
+ EXTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms
+ EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
- extmoduleSendNextFrame();
-
NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn);
NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn, 7);
NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn);
@@ -130,10 +98,11 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us)
EXTMODULE_TIMER->EGR = 1; // Restart
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_0;
+ EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
+ EXTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms
+ EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
- extmoduleSendNextFrame();
-
NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn);
NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn, 7);
NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn);
@@ -141,7 +110,9 @@ void extmoduleSerialStart(uint32_t /*baudrate*/, uint32_t period_half_us)
}
#if defined(EXTMODULE_USART)
-void extmoduleInvertedSerialStart(uint32_t baudrate, uint32_t period_half_us)
+ModuleFifo extmoduleFifo;
+
+void extmoduleInvertedSerialStart(uint32_t baudrate)
{
EXTERNAL_MODULE_ON();
@@ -152,23 +123,17 @@ void extmoduleInvertedSerialStart(uint32_t baudrate, uint32_t period_half_us)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
- // TX Pin
- GPIO_PinAFConfig(EXTMODULE_TX_GPIO, EXTMODULE_TX_GPIO_PinSource, EXTMODULE_USART_TX_GPIO_AF);
+ // TX + RX Pins
+ GPIO_PinAFConfig(EXTMODULE_USART_GPIO, EXTMODULE_TX_GPIO_PinSource, EXTMODULE_USART_GPIO_AF);
+ GPIO_PinAFConfig(EXTMODULE_USART_GPIO, EXTMODULE_RX_GPIO_PinSource, EXTMODULE_USART_GPIO_AF);
GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN;
+ GPIO_InitStructure.GPIO_Pin = EXTMODULE_TX_GPIO_PIN | EXTMODULE_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(EXTMODULE_TX_GPIO, &GPIO_InitStructure);
-
-#if 0
- // RX Pin
- GPIO_PinAFConfig(EXTMODULE_RX_GPIO, EXTMODULE_RX_GPIO_PinSource, EXTMODULE_TX_GPIO_USART_AF);
- GPIO_InitStructure.GPIO_Pin = EXTMODULE_RX_GPIO_PIN;
- GPIO_Init(EXTMODULE_RX_GPIO, &GPIO_InitStructure);
-#endif
+ GPIO_Init(EXTMODULE_USART_GPIO, &GPIO_InitStructure);
// UART config
USART_DeInit(EXTMODULE_USART);
@@ -178,30 +143,78 @@ void extmoduleInvertedSerialStart(uint32_t baudrate, uint32_t period_half_us)
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
- USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
+ USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(EXTMODULE_USART, &USART_InitStructure);
USART_Cmd(EXTMODULE_USART, ENABLE);
- // Timer
- EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
- EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz
- EXTMODULE_TIMER->ARR = period_half_us;
- EXTMODULE_TIMER->CCR2 = period_half_us - 2000; // Update time
- EXTMODULE_TIMER->EGR = 1; // Restart
- EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
- EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
- EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
+ extmoduleFifo.clear();
- NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn);
- NVIC_SetPriority(EXTMODULE_TIMER_CC_IRQn, 7);
+ USART_ITConfig(EXTMODULE_USART, USART_IT_RXNE, ENABLE);
+ NVIC_SetPriority(EXTMODULE_USART_IRQn, 6);
+ NVIC_EnableIRQ(EXTMODULE_USART_IRQn);
}
-void extmodulePxxStart()
+void extmoduleSendBuffer(const uint8_t * data, uint8_t size)
{
- extmoduleInvertedSerialStart(EXTMODULE_USART_PXX_BAUDRATE, PXX_PERIOD_HALF_US);
+ DMA_InitTypeDef DMA_InitStructure;
+ DMA_DeInit(EXTMODULE_USART_DMA_STREAM);
+ DMA_InitStructure.DMA_Channel = EXTMODULE_USART_DMA_CHANNEL;
+ DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&EXTMODULE_USART->DR);
+ DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+ DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(data);
+ DMA_InitStructure.DMA_BufferSize = size;
+ DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+ DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+ DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
+ DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
+ DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
+ DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
+ DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
+ DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
+ DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+ DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
+ DMA_Init(EXTMODULE_USART_DMA_STREAM, &DMA_InitStructure);
+ DMA_Cmd(EXTMODULE_USART_DMA_STREAM, ENABLE);
+ USART_DMACmd(EXTMODULE_USART, USART_DMAReq_Tx, ENABLE);
+}
+
+// TODO remove this when we have adaptative speed
+//uint8_t counter = 0;
+//#include
+
+#define USART_FLAG_ERRORS (USART_FLAG_ORE | USART_FLAG_NE | USART_FLAG_FE | USART_FLAG_PE)
+extern "C" void EXTMODULE_USART_IRQHandler(void)
+{
+ uint32_t status = EXTMODULE_USART->SR;
+
+ while (status & (USART_FLAG_RXNE | USART_FLAG_ERRORS)) {
+ uint8_t data = EXTMODULE_USART->DR;
+ if (status & USART_FLAG_ERRORS) {
+ extmoduleFifo.errors++;
+// if (!counter++) {
+// TRACE_NOCRLF("%02X ", (uint8_t)status);
+// }
+ }
+ else {
+ extmoduleFifo.push(data);
+ }
+ status = EXTMODULE_USART->SR;
+ }
+}
+
+void extmodulePxx2Start()
+{
+ extmoduleInvertedSerialStart(EXTMODULE_USART_PXX2_BAUDRATE);
}
#else
-void extmodulePxxStart()
+void extmodulePxx2Start()
+{
+ // TODO just enable the S.PORT line (or let telemetry init do it)
+}
+#endif
+
+#if defined(PXX1)
+void extmodulePxxPulsesStart()
{
EXTERNAL_MODULE_ON();
@@ -217,7 +230,7 @@ void extmodulePxxStart()
EXTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
EXTMODULE_TIMER->PSC = EXTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS (2Mhz)
- EXTMODULE_TIMER->ARR = PXX_PERIOD_HALF_US;
+ EXTMODULE_TIMER->ARR = PXX_PULSES_PERIOD * 2000; // 0.5uS (2Mhz)
EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | EXTMODULE_TIMER_OUTPUT_POLARITY; // polarity, default low
EXTMODULE_TIMER->BDTR = TIM_BDTR_MOE; // Enable outputs
EXTMODULE_TIMER->CCR1 = 18;
@@ -225,10 +238,11 @@ void extmodulePxxStart()
EXTMODULE_TIMER->EGR = 1; // Restart
EXTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
EXTMODULE_TIMER->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2;
+ EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
+ EXTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms
+ EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
EXTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
- extmoduleSendNextFrame();
-
NVIC_EnableIRQ(EXTMODULE_TIMER_DMA_STREAM_IRQn);
NVIC_SetPriority(EXTMODULE_TIMER_DMA_STREAM_IRQn, 7);
NVIC_EnableIRQ(EXTMODULE_TIMER_CC_IRQn);
@@ -236,65 +250,83 @@ void extmodulePxxStart()
}
#endif
+#if defined(PXX1) && defined(EXTMODULE_USART)
+void extmodulePxxSerialStart()
+{
+ extmoduleInvertedSerialStart(EXTMODULE_PXX_SERIAL_BAUDRATE);
+}
+#endif
+
void extmoduleSendNextFrame()
{
- if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PPM) {
- EXTMODULE_TIMER->CCR1 = GET_PPM_DELAY(EXTERNAL_MODULE)*2;
- EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_PPM_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // // we are using complementary output so logic has to be reversed here
- EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
- EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
- EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
- EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].ppm.pulses);
- EXTMODULE_TIMER_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].ppm.ptr - modulePulsesData[EXTERNAL_MODULE].ppm.pulses;
- EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
- }
- else if (s_current_protocol[EXTERNAL_MODULE] == PROTO_PXX) {
-#if defined(EXTMODULE_USART)
- DMA_InitTypeDef DMA_InitStructure;
- DMA_DeInit(EXTMODULE_USART_DMA_STREAM);
- DMA_InitStructure.DMA_Channel = EXTMODULE_USART_DMA_CHANNEL;
- DMA_InitStructure.DMA_PeripheralBaseAddr = CONVERT_PTR_UINT(&EXTMODULE_USART->DR);
- DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
- DMA_InitStructure.DMA_Memory0BaseAddr = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx_uart.getData());
- DMA_InitStructure.DMA_BufferSize = modulePulsesData[EXTERNAL_MODULE].pxx_uart.getSize();
- DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
- DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
- DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
- DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
- DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
- DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
- DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
- DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
- DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
- DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
- DMA_Init(EXTMODULE_USART_DMA_STREAM, &DMA_InitStructure);
- DMA_Cmd(EXTMODULE_USART_DMA_STREAM, ENABLE);
- USART_DMACmd(EXTMODULE_USART, USART_DMAReq_Tx, ENABLE);
- EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
-#else
- EXTMODULE_TIMER->CCR2 = modulePulsesData[EXTERNAL_MODULE].pxx.getLast() - 4000; // 2mS in advance
- EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
- EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
- EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].pxx.getData());
- EXTMODULE_TIMER_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].pxx.getSize();
- EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+ switch(moduleSettings[EXTERNAL_MODULE].protocol) {
+ case PROTOCOL_CHANNELS_PPM:
+ EXTMODULE_TIMER->CCR1 = GET_MODULE_PPM_DELAY(EXTERNAL_MODULE) * 2;
+ EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_MODULE_PPM_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // // we are using complementary output so logic has to be reversed here
+ EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
+ EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
+ EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.ppm.pulses);
+ EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.ppm.ptr - extmodulePulsesData.ppm.pulses;
+ EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+ break;
+
+#if defined(PXX1)
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
+ EXTMODULE_TIMER->CCR2 = extmodulePulsesData.pxx.getLast() - 4000; // 2mS in advance
+ EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
+ EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.pxx.getData());
+ EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.pxx.getSize();
+ EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+ break;
#endif
- }
- else if (IS_DSM2_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_MULTIMODULE_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]) || IS_SBUS_PROTOCOL(s_current_protocol[EXTERNAL_MODULE])) {
- if (IS_SBUS_PROTOCOL(s_current_protocol[EXTERNAL_MODULE]))
+
+#if defined(PXX1) && defined(EXTMODULE_USART)
+ case PROTOCOL_CHANNELS_PXX1_SERIAL:
+ extmoduleSendBuffer(extmodulePulsesData.pxx_uart.getData(), extmodulePulsesData.pxx_uart.getSize());
+ break;
+#endif
+
+#if defined(PXX2)
+ case PROTOCOL_CHANNELS_PXX2:
+ #if defined(EXTMODULE_USART)
+ extmoduleSendBuffer(extmodulePulsesData.pxx2.getData(), extmodulePulsesData.pxx2.getSize());
+ #else
+ sportSendBuffer(extmodulePulsesData.pxx2.getData(), extmodulePulsesData.pxx2.getSize());
+ #endif
+ break;
+#endif
+
+#if defined(DSM2)
+ case PROTOCOL_CHANNELS_SBUS:
EXTMODULE_TIMER->CCER = EXTMODULE_TIMER_OUTPUT_ENABLE | (GET_SBUS_POLARITY(EXTERNAL_MODULE) ? EXTMODULE_TIMER_OUTPUT_POLARITY : 0); // reverse polarity for Sbus if needed
- EXTMODULE_TIMER->CCR2 = *(modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - 1) - 4000; // 2mS in advance
- EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
- EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
- EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[EXTERNAL_MODULE].dsm2.pulses);
- EXTMODULE_TIMER_DMA_STREAM->NDTR = modulePulsesData[EXTERNAL_MODULE].dsm2.ptr - modulePulsesData[EXTERNAL_MODULE].dsm2.pulses;
- EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
- }
- else {
- EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
+ // no break
+ case PROTOCOL_CHANNELS_DSM2_LP45:
+ case PROTOCOL_CHANNELS_DSM2_DSM2:
+ case PROTOCOL_CHANNELS_DSM2_DSMX:
+ case PROTOCOL_CHANNELS_MULTIMODULE:
+ EXTMODULE_TIMER->CCR2 = *(extmodulePulsesData.dsm2.ptr - 1) - 4000; // 2mS in advance
+ EXTMODULE_TIMER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ EXTMODULE_TIMER_DMA_STREAM->CR |= EXTMODULE_TIMER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ EXTMODULE_TIMER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&EXTMODULE_TIMER->ARR);
+ EXTMODULE_TIMER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(extmodulePulsesData.dsm2.pulses);
+ EXTMODULE_TIMER_DMA_STREAM->NDTR = extmodulePulsesData.dsm2.ptr - extmodulePulsesData.dsm2.pulses;
+ EXTMODULE_TIMER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+ break;
+#endif
+
+#if defined(CROSSFIRE)
+ case PROTOCOL_CHANNELS_CROSSFIRE:
+ sportSendBuffer(extmodulePulsesData.crossfire.pulses, extmodulePulsesData.crossfire.length);
+ break;
+#endif
+
+ default:
+ EXTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
+ break;
}
}
@@ -313,6 +345,7 @@ extern "C" void EXTMODULE_TIMER_CC_IRQHandler()
{
EXTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
EXTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
- setupPulses(EXTERNAL_MODULE);
- extmoduleSendNextFrame();
+ if (setupPulses(EXTERNAL_MODULE)) {
+ extmoduleSendNextFrame();
+ }
}
diff --git a/radio/src/targets/taranis/hal.h b/radio/src/targets/taranis/hal.h
index 716bae368..6f12e32d7 100644
--- a/radio/src/targets/taranis/hal.h
+++ b/radio/src/targets/taranis/hal.h
@@ -55,6 +55,15 @@
#define KEYS_GPIO_PIN_EXIT GPIO_Pin_2 // PD.02
#define KEYS_GPIO_REG_ENTER GPIOE->IDR
#define KEYS_GPIO_PIN_ENTER GPIO_Pin_10 // PE.10
+#elif defined(PCBX3)
+ #define KEYS_GPIO_REG_PAGE GPIOE->IDR
+ #define KEYS_GPIO_PIN_PAGE GPIO_Pin_8 // PE.08
+ #define KEYS_GPIO_REG_MENU GPIOE->IDR
+ #define KEYS_GPIO_PIN_MENU GPIO_Pin_7 // PE.07
+ #define KEYS_GPIO_REG_EXIT GPIOE->IDR
+ #define KEYS_GPIO_PIN_EXIT GPIO_Pin_9 // PE.09
+ #define KEYS_GPIO_REG_ENTER GPIOE->IDR
+ #define KEYS_GPIO_PIN_ENTER GPIO_Pin_11 // PE.11
#else
#define KEYS_GPIO_REG_MENU GPIOD->IDR
#define KEYS_GPIO_PIN_MENU GPIO_Pin_7 // PD.07
@@ -81,10 +90,15 @@
#define ENC_GPIO_PIN_A GPIO_Pin_9 // PE.09
#define ENC_GPIO_PIN_B GPIO_Pin_11 // PE.11
#define ROTARY_ENCODER_POSITION() (((ENC_GPIO->IDR >> 10) & 0x02) + ((ENC_GPIO->IDR >> 9) & 0x01))
+#elif defined(PCBX3)
+ #define ENC_GPIO GPIOE
+ #define ENC_GPIO_PIN_A GPIO_Pin_10 // PE.10
+ #define ENC_GPIO_PIN_B GPIO_Pin_12 // PE.12
+ #define ROTARY_ENCODER_POSITION() (((ENC_GPIO->IDR >> 12) & 0x01) + ((ENC_GPIO->IDR >> 9) & 0x02))
#endif
// This is for SIMU: reuse rotary encoder pins to map UP and DOWN keyboard keys
-#if defined(SIMU) && (defined(PCBX9E) || defined(PCBX7))
+#if defined(SIMU) && (defined(PCBX9E) || defined(PCBX7) || defined(PCBX3))
#define KEYS_GPIO_REG_PLUS ENC_GPIO->IDR
#define KEYS_GPIO_PIN_PLUS ENC_GPIO_PIN_A
#define KEYS_GPIO_REG_MINUS ENC_GPIO->IDR
@@ -135,6 +149,23 @@
#define TRIMS_GPIO_PIN_RVU GPIO_Pin_2 // PC.02
#define TRIMS_GPIO_REG_RHR GPIOE->IDR
#define TRIMS_GPIO_PIN_RHR GPIO_Pin_4 // PE.04
+#elif defined(PCBX3)
+ #define TRIMS_GPIO_REG_LHR GPIOC->IDR
+ #define TRIMS_GPIO_PIN_LHR GPIO_Pin_4 // PC.04
+ #define TRIMS_GPIO_REG_LHL GPIOC->IDR
+ #define TRIMS_GPIO_PIN_LHL GPIO_Pin_5 // PC.05
+ #define TRIMS_GPIO_REG_LVU GPIOB->IDR
+ #define TRIMS_GPIO_PIN_LVU GPIO_Pin_0 // PB.00
+ #define TRIMS_GPIO_REG_LVD GPIOB->IDR
+ #define TRIMS_GPIO_PIN_LVD GPIO_Pin_1 // PB.01
+ #define TRIMS_GPIO_REG_RVU GPIOE->IDR
+ #define TRIMS_GPIO_PIN_RVU GPIO_Pin_13 // PE.13
+ #define TRIMS_GPIO_REG_RHR GPIOD->IDR
+ #define TRIMS_GPIO_PIN_RHR GPIO_Pin_8 // PD.08
+ #define TRIMS_GPIO_REG_RVD GPIOE->IDR
+ #define TRIMS_GPIO_PIN_RVD GPIO_Pin_14 // PE.14
+ #define TRIMS_GPIO_REG_RHL GPIOD->IDR
+ #define TRIMS_GPIO_PIN_RHL GPIO_Pin_9 // PD.09
#else
#define TRIMS_GPIO_REG_LHL GPIOE->IDR
#define TRIMS_GPIO_PIN_LHL GPIO_Pin_4 // PE.04
@@ -160,7 +191,7 @@
#define SWITCHES_GPIO_PIN_A_H GPIO_Pin_10 // PD.10
#define SWITCHES_GPIO_REG_A_L GPIOD->IDR
#define SWITCHES_GPIO_PIN_A_L GPIO_Pin_14 // PD.14
-#elif defined(PCBXLITE)
+#elif defined(PCBXLITE) || defined(PCBX3)
#define SWITCHES_GPIO_REG_A_H GPIOE->IDR
#define SWITCHES_GPIO_PIN_A_H GPIO_Pin_1 // PE.01
#define SWITCHES_GPIO_REG_A_L GPIOE->IDR
@@ -192,6 +223,11 @@
#define SWITCHES_GPIO_PIN_B_L GPIO_Pin_15 // PE.15
#define SWITCHES_GPIO_REG_B_H GPIOA->IDR
#define SWITCHES_GPIO_PIN_B_H GPIO_Pin_5 // PA.05
+#elif defined(PCBX3)
+ #define SWITCHES_GPIO_REG_B_L GPIOB->IDR
+ #define SWITCHES_GPIO_PIN_B_L GPIO_Pin_4 // PB.04
+ #define SWITCHES_GPIO_REG_B_H GPIOB->IDR
+ #define SWITCHES_GPIO_PIN_B_H GPIO_Pin_5 // PB.05
#else
#define SWITCHES_GPIO_REG_B_H GPIOE->IDR
#define SWITCHES_GPIO_PIN_B_H GPIO_Pin_1 // PE.01
@@ -204,7 +240,7 @@
#define SWITCHES_GPIO_PIN_C_H GPIO_Pin_13 // PF.13
#define SWITCHES_GPIO_REG_C_L GPIOF->IDR
#define SWITCHES_GPIO_PIN_C_L GPIO_Pin_14 // PF.14
-#elif defined(PCBXLITE)
+#elif defined(PCBXLITE) || defined(PCBX3)
#define SWITCHES_GPIO_REG_C_L GPIOE->IDR
#define SWITCHES_GPIO_PIN_C_L GPIO_Pin_2 // PE.02
#define SWITCHES_GPIO_REG_C_H GPIOE->IDR
@@ -241,6 +277,8 @@
#define SWITCHES_GPIO_PIN_D_L GPIO_Pin_1 // PE.01
#define SWITCHES_GPIO_REG_D_H GPIOE->IDR
#define SWITCHES_GPIO_PIN_D_H GPIO_Pin_2 // PE.02
+#elif defined(PCBX3)
+ // no SWD
#else
#define SWITCHES_GPIO_REG_D_H GPIOE->IDR
#define SWITCHES_GPIO_PIN_D_H GPIO_Pin_7 // PE.07
@@ -253,6 +291,12 @@
#define SWITCHES_GPIO_PIN_E_H GPIO_Pin_7 // PE.07
#define SWITCHES_GPIO_REG_E_L GPIOE->IDR
#define SWITCHES_GPIO_PIN_E_L GPIO_Pin_13 // PE.13
+#elif defined(PCBXLITES)
+ #define SWITCHES_GPIO_REG_E GPIOE->IDR
+ #define SWITCHES_GPIO_PIN_E GPIO_Pin_5 // PE.05
+#elif defined(PCBX3)
+ #define SWITCHES_GPIO_REG_E GPIOC->IDR
+ #define SWITCHES_GPIO_PIN_E GPIO_Pin_13 // PC.13
#elif defined(PCBX7) || defined(PCBXLITE)
// no SWE
#else
@@ -265,11 +309,17 @@
#if defined(PCBX9E)
#define SWITCHES_GPIO_REG_F GPIOE->IDR
#define SWITCHES_GPIO_PIN_F GPIO_Pin_11 // PE.11
+#elif defined(PCBXLITES)
+ #define SWITCHES_GPIO_REG_F GPIOC->IDR
+ #define SWITCHES_GPIO_PIN_F GPIO_Pin_3 // PC.03
#elif defined(PCBXLITE)
// no SWF
#elif defined(PCBX7)
#define SWITCHES_GPIO_REG_F GPIOE->IDR
#define SWITCHES_GPIO_PIN_F GPIO_Pin_14 // PE.14
+#elif defined(PCBX3)
+ #define SWITCHES_GPIO_REG_F GPIOA->IDR
+ #define SWITCHES_GPIO_PIN_F GPIO_Pin_5 // PA.05
#else
#define SWITCHES_GPIO_REG_F GPIOE->IDR
#define SWITCHES_GPIO_PIN_F GPIO_Pin_14 // PE.14
@@ -280,7 +330,7 @@
#define SWITCHES_GPIO_PIN_G_H GPIO_Pin_3 // PF.03
#define SWITCHES_GPIO_REG_G_L GPIOF->IDR
#define SWITCHES_GPIO_PIN_G_L GPIO_Pin_4 // PF.04
-#elif defined(PCBX7) || defined(PCBXLITE)
+#elif defined(PCBX7) || defined(PCBXLITE) || defined(PCBX3)
// no SWG
#else
#define SWITCHES_GPIO_REG_G_H GPIOE->IDR
@@ -295,7 +345,7 @@
#elif defined(PCBX9DP)
#define SWITCHES_GPIO_REG_H GPIOD->IDR
#define SWITCHES_GPIO_PIN_H GPIO_Pin_14 // PD.14
-#elif defined(PCBXLITE)
+#elif defined(PCBXLITE) || defined(PCBX3)
// no SWH
#elif defined(PCBX7)
#define SWITCHES_GPIO_REG_H GPIOD->IDR
@@ -364,6 +414,12 @@
#define KEYS_GPIOC_PINS (TRIMS_GPIO_PIN_RVD | TRIMS_GPIO_PIN_RVU | TRIMS_GPIO_PIN_RHL | TRIMS_GPIO_PIN_RHR)
#define KEYS_GPIOD_PINS (KEYS_GPIO_PIN_MENU | KEYS_GPIO_PIN_EXIT | KEYS_GPIO_PIN_PAGE | SWITCHES_GPIO_PIN_H)
#define KEYS_GPIOE_PINS (KEYS_GPIO_PIN_PLUS | KEYS_GPIO_PIN_ENTER | KEYS_GPIO_PIN_MINUS | TRIMS_GPIO_PIN_LHR | TRIMS_GPIO_PIN_LHL | TRIMS_GPIO_PIN_LVD | TRIMS_GPIO_PIN_LVU | SWITCHES_GPIO_PIN_F | SWITCHES_GPIO_PIN_A_L | SWITCHES_GPIO_PIN_B_H | SWITCHES_GPIO_PIN_B_L | SWITCHES_GPIO_PIN_C_H | SWITCHES_GPIO_PIN_D_H | SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_G_H | SWITCHES_GPIO_PIN_G_L)
+#elif defined(PCBXLITES)
+ #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE)
+ #define KEYS_GPIOA_PINS (GPIO_Pin_5 | GPIO_Pin_6)
+ #define KEYS_GPIOB_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5)
+ #define KEYS_GPIOC_PINS (GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5)
+ #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14)
#elif defined(PCBXLITE)
#define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE)
#define KEYS_GPIOA_PINS (GPIO_Pin_5 | GPIO_Pin_6)
@@ -371,11 +427,18 @@
#define KEYS_GPIOC_PINS (GPIO_Pin_4 | GPIO_Pin_5)
#define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14)
#elif defined(PCBX7)
- #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE)
+ #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
#define KEYS_GPIOA_PINS SWITCHES_GPIO_PIN_B_H
#define KEYS_GPIOC_PINS (TRIMS_GPIO_PIN_LHR | TRIMS_GPIO_PIN_RVD | TRIMS_GPIO_PIN_RVU)
#define KEYS_GPIOD_PINS (TRIMS_GPIO_PIN_LHL | KEYS_GPIO_PIN_MENU | KEYS_GPIO_PIN_EXIT | KEYS_GPIO_PIN_PAGE | SWITCHES_GPIO_PIN_C_L | SWITCHES_GPIO_PIN_H)
#define KEYS_GPIOE_PINS (ENC_GPIO_PIN_A | ENC_GPIO_PIN_B | KEYS_GPIO_PIN_ENTER | TRIMS_GPIO_PIN_RHR | TRIMS_GPIO_PIN_RHL | TRIMS_GPIO_PIN_LVD | TRIMS_GPIO_PIN_LVU | SWITCHES_GPIO_PIN_C_H | SWITCHES_GPIO_PIN_D_L | SWITCHES_GPIO_PIN_D_H | SWITCHES_GPIO_PIN_B_L | SWITCHES_GPIO_PIN_A_L | SWITCHES_GPIO_PIN_A_H | SWITCHES_GPIO_PIN_F)
+#elif defined(PCBX3)
+ #define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
+ #define KEYS_GPIOA_PINS (GPIO_Pin_5)
+ #define KEYS_GPIOB_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5)
+ #define KEYS_GPIOC_PINS (GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_13)
+ #define KEYS_GPIOD_PINS (GPIO_Pin_8 | GPIO_Pin_9)
+ #define KEYS_GPIOE_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_13 | GPIO_Pin_14)
#else
#define KEYS_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE)
#define KEYS_GPIOA_PINS (SWITCHES_GPIO_PIN_C_L)
@@ -393,6 +456,7 @@
#define ADC_SET_DMA_FLAGS() ADC_DMA->HIFCR = (DMA_HIFCR_CTCIF4 | DMA_HIFCR_CHTIF4 | DMA_HIFCR_CTEIF4 | DMA_HIFCR_CDMEIF4 | DMA_HIFCR_CFEIF4)
#define ADC_TRANSFER_COMPLETE() (ADC_DMA->HISR & DMA_HISR_TCIF4)
#define ADC_SAMPTIME 2 // sample time = 28 cycles
+#define ADC_CHANNEL_RTC ADC_Channel_18 // ADC1_IN18
#if defined(PCBX9E)
#define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_DMA2)
#define ADC_RCC_APB1Periph 0
@@ -507,6 +571,24 @@
#define ADC_CHANNEL_POT1 ADC_Channel_6
#define ADC_CHANNEL_POT2 ADC_Channel_8
#define ADC_CHANNEL_BATT ADC_Channel_10
+#elif defined(PCBX3)
+ #define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2)
+ #define ADC_RCC_APB1Periph 0
+ #define ADC_RCC_APB2Periph RCC_APB2Periph_ADC1
+ #define ADC_GPIO_PIN_STICK_LH GPIO_Pin_0 // PA.00
+ #define ADC_GPIO_PIN_STICK_LV GPIO_Pin_1 // PA.01
+ #define ADC_GPIO_PIN_STICK_RV GPIO_Pin_2 // PA.02
+ #define ADC_GPIO_PIN_STICK_RH GPIO_Pin_3 // PA.03
+ #define ADC_CHANNEL_STICK_LH ADC_Channel_0 // ADC1_IN0
+ #define ADC_CHANNEL_STICK_LV ADC_Channel_1 // ADC1_IN1
+ #define ADC_CHANNEL_STICK_RV ADC_Channel_2 // ADC1_IN2
+ #define ADC_CHANNEL_STICK_RH ADC_Channel_3 // ADC1_IN3
+ #define ADC_GPIO_PIN_POT1 GPIO_Pin_1 // PC.01
+ #define ADC_GPIO_PIN_BATT GPIO_Pin_0 // PC.00
+ #define ADC_GPIOA_PINS (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3)
+ #define ADC_GPIOC_PINS (GPIO_Pin_0 | GPIO_Pin_1)
+ #define ADC_CHANNEL_POT1 ADC_Channel_11 // ADC1_IN11
+ #define ADC_CHANNEL_BATT ADC_Channel_10 // ADC1_IN10
#else
#define ADC_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2)
#define ADC_RCC_APB1Periph 0
@@ -536,9 +618,14 @@
#endif
// PWR and LED driver
-#define PWR_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
+#define PWR_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE)
-#if defined(PCBXLITE)
+#if defined(PCBX3)
+ #define PWR_SWITCH_GPIO GPIOA
+ #define PWR_SWITCH_GPIO_PIN GPIO_Pin_7 // PA.07
+ #define PWR_ON_GPIO GPIOA
+ #define PWR_ON_GPIO_PIN GPIO_Pin_6 // PA.06
+#elif defined(PCBXLITE)
#define PWR_SWITCH_GPIO GPIOA
#define PWR_SWITCH_GPIO_PIN GPIO_Pin_7 // PA.07
#define PWR_ON_GPIO GPIOE
@@ -549,8 +636,6 @@
#define PWR_ON_GPIO GPIOD
#define PWR_ON_GPIO_PIN GPIO_Pin_0 // PD.00
#endif
-#define PWR_ON_GPIO_MODER GPIO_MODER_MODER0
-#define PWR_ON_GPIO_MODER_OUT GPIO_MODER_MODER0_0
#if defined(PCBXLITE)
#define STATUS_LEDS
@@ -572,33 +657,50 @@
#define LED_RED_GPIO_PIN GPIO_Pin_5 // PC.05
#define LED_BLUE_GPIO GPIOB
#define LED_BLUE_GPIO_PIN GPIO_Pin_1 // PB.01
+#elif defined(PCBX3)
+ #define STATUS_LEDS
+ #define GPIO_LED_GPIO_ON GPIO_SetBits
+ #define GPIO_LED_GPIO_OFF GPIO_ResetBits
+ #define LED_RED_GPIO GPIOE
+ #define LED_RED_GPIO_PIN GPIO_Pin_5 // PE.05
+ #define LED_GREEN_GPIO GPIOE
+ #define LED_GREEN_GPIO_PIN GPIO_Pin_4 // PE.04
+ #define LED_BLUE_GPIO GPIOE
+ #define LED_BLUE_GPIO_PIN GPIO_Pin_6 // PE.06
#endif
// Internal Module
-#if defined(PCBXLITE)
- #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
+#define HARDWARE_INTERNAL_MODULE
+#if defined(PCBXLITE) || defined(PCBX3)
#define INTMODULE_RCC_APB1Periph RCC_APB1Periph_TIM3
#define INTMODULE_RCC_APB2Periph RCC_APB2Periph_USART1
- #define INTMODULE_PWR_GPIO GPIOD
- #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_9 // PD.09
- #define INTMODULE_TX_GPIO GPIOB
+ #if defined(PCBXLITES) || defined(PCBX3)
+ #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA2)
+ #define INTMODULE_PWR_GPIO GPIOA
+ #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_15 // PA.15
+ #else
+ #define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
+ #define INTMODULE_PWR_GPIO GPIOD
+ #define INTMODULE_PWR_GPIO_PIN GPIO_Pin_9 // PD.09
+ #endif
+ #define INTMODULE_GPIO GPIOB
#define INTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PB.06
- #define INTMODULE_RX_GPIO GPIOB
#define INTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PB.07
- #define INTMODULE_TX_GPIO_PinSource GPIO_PinSource6
- #define INTMODULE_RX_GPIO_PinSource GPIO_PinSource7
+ #define INTMODULE_GPIO_PinSource_TX GPIO_PinSource6
+ #define INTMODULE_GPIO_PinSource_RX GPIO_PinSource7
#define INTMODULE_USART USART1
- #define INTMODULE_TX_GPIO_AF GPIO_AF_USART1
+ #define INTMODULE_GPIO_AF GPIO_AF_USART1
+ #define INTMODULE_USART_IRQHandler USART1_IRQHandler
#define INTMODULE_USART_IRQn USART1_IRQn
#define INTMODULE_DMA_STREAM DMA2_Stream7
- #define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn
- #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler
+ #define INTMODULE_DMA_STREAM_IRQ DMA2_Stream7_IRQn
+ #define INTMODULE_DMA_STREAM_IRQHandler DMA2_Stream7_IRQHandler
#define INTMODULE_DMA_FLAG_TC DMA_IT_TCIF7
#define INTMODULE_DMA_CHANNEL DMA_Channel_4
- #define INTMODULE_TIMER TIM3
- #define INTMODULE_TIMER_IRQn TIM3_IRQn
- #define INTMODULE_TIMER_IRQHandler TIM3_IRQHandler
- #define INTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
+ // #define INTMODULE_TIMER TIM3
+ // #define INTMODULE_TIMER_IRQn TIM3_IRQn
+ // #define INTMODULE_TIMER_IRQHandler TIM3_IRQHandler
+ // #define INTMODULE_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
#elif defined(PCBX9E) || defined(PCBX9DP) || defined(PCBX7)
#define INTMODULE_PULSES
#define INTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2)
@@ -643,14 +745,30 @@
// External Module
#define EXTMODULE_PULSES
-#if defined(PCBXLITE)
- #define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
+
+#if defined(PCBXLITE) || defined(PCBX3)
#define EXTMODULE_RCC_APB2Periph (RCC_APB2Periph_TIM8 | RCC_APB2Periph_USART6)
- #define EXTMODULE_PWR_GPIO GPIOD
- #define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_11 // PD.11
+ #if defined(PCBX3)
+ #define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA2)
+ #define EXTMODULE_PWR_GPIO GPIOA
+ #define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PA.08
+ #define EXTERNAL_MODULE_ON() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
+ #define EXTERNAL_MODULE_OFF() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
+ #define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_RESET)
+ #else
+ #define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
+ #define EXTMODULE_PWR_GPIO GPIOD
+ #define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_11 // PD.11
+ #define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
+ #define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
+ #define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
+ #endif
#define EXTMODULE_TX_GPIO GPIOC
+ #define EXTMODULE_USART_GPIO GPIOC
#define EXTMODULE_TX_GPIO_PIN GPIO_Pin_6 // PC.06
#define EXTMODULE_TX_GPIO_PinSource GPIO_PinSource6
+ #define EXTMODULE_RX_GPIO_PIN GPIO_Pin_7 // PC.07
+ #define EXTMODULE_RX_GPIO_PinSource GPIO_PinSource7
#define EXTMODULE_TIMER TIM8
#define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#define EXTMODULE_TIMER_CC_IRQn TIM8_CC_IRQn
@@ -663,19 +781,22 @@
#define EXTMODULE_TIMER_DMA_FLAG_TC DMA_IT_TCIF1
#define EXTMODULE_TIMER_OUTPUT_ENABLE TIM_CCER_CC1E
#define EXTMODULE_TIMER_OUTPUT_POLARITY TIM_CCER_CC1P
- #define EXTMODULE_USART_TX_GPIO_AF GPIO_AF_USART6
+ #define EXTMODULE_USART_GPIO_AF GPIO_AF_USART6
#define EXTMODULE_USART USART6
#define EXTMODULE_USART_IRQn USART6_IRQn
+ #define EXTMODULE_USART_IRQHandler USART6_IRQHandler
#define EXTMODULE_USART_DMA_CHANNEL DMA_Channel_5
#define EXTMODULE_USART_DMA_STREAM DMA2_Stream6
#define EXTMODULE_USART_DMA_STREAM_IRQn DMA2_Stream6_IRQn
- #define EXTMODULE_USART_DMA_STREAM_IRQHandler DMA2_Stream6_IRQHandler
- #define EXTMODULE_USART_DMA_FLAG_TC DMA_IT_TCIF6
#else
+ #define EXTMODULE_PULSES
#define EXTMODULE_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA2)
#define EXTMODULE_RCC_APB2Periph RCC_APB2Periph_TIM8
#define EXTMODULE_PWR_GPIO GPIOD
#define EXTMODULE_PWR_GPIO_PIN GPIO_Pin_8 // PD.08
+ #define EXTERNAL_MODULE_ON() GPIO_SetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
+ #define EXTERNAL_MODULE_OFF() GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN)
+ #define IS_EXTERNAL_MODULE_ON() (GPIO_ReadInputDataBit(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN) == Bit_SET)
#define EXTMODULE_TX_GPIO GPIOA
#define EXTMODULE_TX_GPIO_PIN GPIO_Pin_7 // PA.07
#define EXTMODULE_TX_GPIO_PinSource GPIO_PinSource7
@@ -687,18 +808,49 @@
#define EXTMODULE_TIMER_DMA_STREAM DMA2_Stream1
#define EXTMODULE_TIMER_DMA_STREAM_IRQn DMA2_Stream1_IRQn
#define EXTMODULE_TIMER_DMA_STREAM_IRQHandler DMA2_Stream1_IRQHandler
- #define EXTMODULE_TIMER_DMA_FLAG_TC DMA_IT_TCIF1
+ #define EXTMODULE_TIMER_DMA_FLAG_TC DMA_IT_TCIF1
#define EXTMODULE_TIMER_OUTPUT_ENABLE TIM_CCER_CC1NE
#define EXTMODULE_TIMER_OUTPUT_POLARITY TIM_CCER_CC1NP
- #define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
+ #define EXTMODULE_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
#endif
// Trainer Port
-#if defined(PCBXLITE)
+#if defined(PCBXLITES) || defined(PCBX3)
+ // on these 2 radios the trainer port already uses DMA1_Stream6, we won't use the DMA
+ #define TRAINER_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
+ #define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM4
+ #define TRAINER_GPIO GPIOD
+ #define TRAINER_IN_GPIO_PIN GPIO_Pin_13 // PD.13
+ #define TRAINER_IN_GPIO_PinSource GPIO_PinSource13
+ #define TRAINER_OUT_GPIO_PIN GPIO_Pin_12 // PD.12
+ #define TRAINER_OUT_GPIO_PinSource GPIO_PinSource12
+#if defined(PCBX3)
+ #define TRAINER_DETECT_GPIO GPIOD
+ #define TRAINER_DETECT_GPIO_PIN GPIO_Pin_11 // PD.11
+#endif
+ #define TRAINER_TIMER TIM4
+ #define TRAINER_TIMER_IRQn TIM4_IRQn
+ #define TRAINER_GPIO_AF GPIO_AF_TIM4 // TIM4_CH1 (Out) + TIM4_CH2 (In)
+ #define TRAINER_TIMER_IRQn TIM4_IRQn
+ #define TRAINER_TIMER_IRQHandler TIM4_IRQHandler
+ #define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
+ #define TRAINER_OUT_CCMR1 TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE;
+ #define TRAINER_IN_CCMR1 TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_CC2S_0;
+ #define TRAINER_OUT_COUNTER_REGISTER TRAINER_TIMER->CCR1
+ #define TRAINER_IN_COUNTER_REGISTER TRAINER_TIMER->CCR2
+ #define TRAINER_SETUP_REGISTER TRAINER_TIMER->CCR3
+ #define TRAINER_OUT_INTERRUPT_FLAG TIM_SR_CC3IF
+ #define TRAINER_OUT_INTERRUPT_ENABLE TIM_DIER_CC3IE
+ #define TRAINER_IN_INTERRUPT_ENABLE TIM_DIER_CC2IE
+ #define TRAINER_IN_INTERRUPT_FLAG TIM_SR_CC2IF
+ #define TRAINER_OUT_CCER TIM_CCER_CC1E
+ #define TRAINER_CCER_POLARYTY TIM_CCER_CC1P
+ #define TRAINER_IN_CCER TIM_CCER_CC2E
+#elif defined(PCBXLITE)
#define TRAINER_RCC_AHB1Periph 0
#define TRAINER_RCC_APB1Periph 0
#else
- #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC)
+ #define TRAINER_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_DMA1)
#define TRAINER_RCC_APB1Periph RCC_APB1Periph_TIM3
#define TRAINER_GPIO GPIOC
#define TRAINER_IN_GPIO_PIN GPIO_Pin_8 // PC.08
@@ -719,10 +871,22 @@
#define TRAINER_TIMER_IRQn TIM3_IRQn
#define TRAINER_TIMER_IRQHandler TIM3_IRQHandler
#define TRAINER_TIMER_FREQ (PERI1_FREQUENCY * TIMER_MULT_APB1)
+ #define TRAINER_OUT_CCMR2 TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE;
+ #define TRAINER_IN_CCMR2 TIM_CCMR2_IC3F_0 | TIM_CCMR2_IC3F_1 | TIM_CCMR2_CC3S_0;
+ #define TRAINER_OUT_COUNTER_REGISTER TRAINER_TIMER->CCR4
+ #define TRAINER_IN_COUNTER_REGISTER TRAINER_TIMER->CCR3
+ #define TRAINER_SETUP_REGISTER TRAINER_TIMER->CCR1
+ #define TRAINER_OUT_INTERRUPT_FLAG TIM_SR_CC1IF
+ #define TRAINER_OUT_INTERRUPT_ENABLE TIM_DIER_CC1IE
+ #define TRAINER_IN_INTERRUPT_ENABLE TIM_DIER_CC3IE
+ #define TRAINER_IN_INTERRUPT_FLAG TIM_SR_CC3IF
+ #define TRAINER_OUT_CCER TIM_CCER_CC4E
+ #define TRAINER_IN_CCER TIM_CCER_CC3E
+ #define TRAINER_CCER_POLARYTY TIM_CCER_CC4P
#endif
// Serial Port
-#if defined(PCBX7) || defined(PCBXLITE)
+#if defined(PCBX7) || defined(PCBXLITE) || defined(PCBX3)
#define SERIAL_RCC_AHB1Periph 0
#define SERIAL_RCC_APB1Periph 0
#else
@@ -784,14 +948,21 @@
#define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define SPORT_UPDATE_PWR_GPIO GPIOD
#define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_8 // PD.08
- #define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
+ #define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
#define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
#elif defined(PCBX7)
#define SPORT_MAX_BAUDRATE 250000 // < 400000
#define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
#define SPORT_UPDATE_PWR_GPIO GPIOB
#define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_2 // PB.02
- #define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
+ #define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
+ #define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
+#elif defined(PCBX3)
+ #define SPORT_MAX_BAUDRATE 250000 // not tested
+ #define SPORT_UPDATE_RCC_AHB1Periph RCC_AHB1Periph_GPIOE
+ #define SPORT_UPDATE_PWR_GPIO GPIOE
+ #define SPORT_UPDATE_PWR_GPIO_PIN GPIO_Pin_15 // PE.15
+ #define GPIO_SPORT_UPDATE_PWR_GPIO_ON GPIO_SetBits
#define GPIO_SPORT_UPDATE_PWR_GPIO_OFF GPIO_ResetBits
#else
#define SPORT_MAX_BAUDRATE 400000
@@ -799,7 +970,7 @@
#endif
// Heartbeat
-#if defined(PCBXLITE)
+#if defined(PCBXLITE) || defined(PCBX3)
#define HEARTBEAT_RCC_AHB1Periph RCC_AHB1Periph_GPIOD
#define HEARTBEAT_RCC_APB2Periph 0
#define HEARTBEAT_GPIO GPIOD
@@ -857,6 +1028,19 @@
#define BACKLIGHT_GPIO_PinSource_2 GPIO_PinSource13
#define BACKLIGHT_GPIO_AF_1 GPIO_AF_TIM4
#define BACKLIGHT_GPIO_AF_2 GPIO_AF_TIM4
+#elif defined(PCBXLITES) || defined(PCBX3)
+ #define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
+ #define BACKLIGHT_RCC_APB1Periph 0
+ #define BACKLIGHT_RCC_APB2Periph RCC_APB2Periph_TIM1
+ #define BACKLIGHT_TIMER_FREQ (PERI2_FREQUENCY * TIMER_MULT_APB2)
+ #define BACKLIGHT_TIMER TIM1
+ #define BACKLIGHT_GPIO GPIOA
+ #define BACKLIGHT_GPIO_PIN GPIO_Pin_10 // PA.10
+ #define BACKLIGHT_GPIO_PinSource GPIO_PinSource10
+ #define BACKLIGHT_GPIO_AF GPIO_AF_TIM1
+ #define BACKLIGHT_CCMR2 TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2 // Channel 3, PWM
+ #define BACKLIGHT_CCER TIM_CCER_CC3E
+ #define BACKLIGHT_COUNTER_REGISTER BACKLIGHT_TIMER->CCR3
#elif defined(PCBXLITE)
#define BACKLIGHT_RCC_AHB1Periph RCC_AHB1Periph_GPIOA
#define BACKLIGHT_RCC_APB1Periph 0
@@ -917,7 +1101,7 @@
#define LCD_DMA_FLAG_INT DMA_HIFCR_CTCIF7
#define LCD_SPI SPI3
#define LCD_GPIO_AF GPIO_AF_SPI3
-#elif defined(PCBXLITE)
+#elif defined(PCBXLITE) || defined(PCBX3)
#define LCD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1)
#define LCD_RCC_APB1Periph RCC_APB1Periph_SPI3
#define LCD_SPI_GPIO GPIOC
@@ -977,7 +1161,7 @@
#define I2C_RCC_APB1Periph RCC_APB1Periph_I2C1
#define I2C I2C1
#define I2C_GPIO_AF GPIO_AF_I2C1
-#if defined(PCBXLITE)
+#if defined(PCBXLITE) || defined(PCBX3)
#define I2C_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOD)
#define I2C_SPI_GPIO GPIOB
#define I2C_SDA_GPIO_PIN GPIO_Pin_9 // PB.09
@@ -1005,11 +1189,29 @@
#define I2C_ADDRESS_VOLUME 0x5C
#define I2C_FLASH_PAGESIZE 64
+// Second I2C Bus: IMU
+#if defined(PCBXLITES)
+ #define GYRO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC)
+ #define GYRO_RCC_APB1Periph RCC_APB1Periph_I2C3
+ #define I2CX I2C3
+ #define I2CX_SCL_GPIO GPIOA
+ #define I2CX_SCL_GPIO_PIN GPIO_Pin_8 // PA.08
+ #define I2CX_SDA_GPIO GPIOC
+ #define I2CX_SDA_GPIO_PIN GPIO_Pin_9 // PC.09
+ #define I2CX_GPIO_AF GPIO_AF_I2C3
+ #define I2CX_SCL_GPIO_PinSource GPIO_PinSource8
+ #define I2CX_SDA_GPIO_PinSource GPIO_PinSource9
+ #define I2CX_SPEED 400000
+#else
+ #define GYRO_RCC_AHB1Periph 0
+ #define GYRO_RCC_APB1Periph 0
+#endif
+
// SD - SPI2
#define SD_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_DMA1)
#define SD_RCC_APB1Periph RCC_APB1Periph_SPI2
#define SD_GPIO_PRESENT_GPIO GPIOD
-#if defined(PCBXLITE)
+#if defined(PCBXLITE) || defined(PCBX3)
#define SD_GPIO_PRESENT_GPIO_PIN GPIO_Pin_10 // PD.10
#else
#define SD_GPIO_PRESENT_GPIO_PIN GPIO_Pin_9 // PD.09
@@ -1037,7 +1239,6 @@
#endif
// Audio
-#define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1)
#define AUDIO_RCC_APB1Periph (RCC_APB1Periph_TIM6 | RCC_APB1Periph_DAC)
#define AUDIO_OUTPUT_GPIO GPIOA
#define AUDIO_OUTPUT_GPIO_PIN GPIO_Pin_4 // PA.04
@@ -1049,8 +1250,20 @@
#define AUDIO_TIMER TIM6
#define AUDIO_DMA DMA1
+#if defined(PCBXLITES)
+ #define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_DMA1)
+ #define JACK_DETECT_GPIO GPIOC
+ #define JACK_DETECT_GPIO_PIN GPIO_Pin_13 // PC.13
+ #define AUDIO_SPEAKER_ENABLE_GPIO GPIOD
+ #define AUDIO_SPEAKER_ENABLE_GPIO_PIN GPIO_Pin_14 // PD.14
+ #define HEADPHONE_TRAINER_SWITCH_GPIO GPIOD
+ #define HEADPHONE_TRAINER_SWITCH_GPIO_PIN GPIO_Pin_9 // PD.09
+#else
+ #define AUDIO_RCC_AHB1Periph (RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1)
+#endif
+
// Haptic
-#if defined(PCBXLITE)
+#if defined(PCBXLITE) || defined(PCBX3)
#define HAPTIC_PWM
#define HAPTIC_RCC_AHB1Periph RCC_AHB1Periph_GPIOB
#define HAPTIC_RCC_APB1Periph RCC_APB1Periph_TIM2
@@ -1106,7 +1319,7 @@
#define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOG)
#define BT_RCC_APB1Periph 0
#define BT_RCC_APB2Periph RCC_APB2Periph_USART6
- #define BT_GPIO_TXRX GPIOG
+ #define BT_USART_GPIO GPIOG
#define BT_TX_GPIO_PIN GPIO_Pin_14 // PG.14
#define BT_RX_GPIO_PIN GPIO_Pin_9 // PG.09
#define BT_EN_GPIO GPIOD
@@ -1119,7 +1332,7 @@
#define BT_RX_GPIO_PinSource GPIO_PinSource9
#define BT_USART_IRQHandler USART6_IRQHandler
#elif defined(PCBX7) || defined(PCBXLITE)
- #define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_DMA1)
+ #define BT_RCC_AHB1Periph (RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOE) // RCC_AHB1Periph_DMA1
#define BT_RCC_APB1Periph RCC_APB1Periph_USART3
#define BT_RCC_APB2Periph 0
#define BT_EN_GPIO GPIOE
@@ -1128,7 +1341,7 @@
#else
#define BT_EN_GPIO_PIN GPIO_Pin_12 // PE.12
#endif
- #define BT_GPIO_TXRX GPIOB
+ #define BT_USART_GPIO GPIOB
#define BT_TX_GPIO_PIN GPIO_Pin_10 // PB.10
#define BT_RX_GPIO_PIN GPIO_Pin_11 // PB.11
#define BT_TX_GPIO_PinSource GPIO_PinSource10
@@ -1137,8 +1350,8 @@
#define BT_USART USART3
#define BT_USART_IRQHandler USART3_IRQHandler
#define BT_USART_IRQn USART3_IRQn
- #define BT_DMA_Stream_RX DMA1_Stream1
- #define BT_DMA_Channel_RX DMA_Channel_4
+ // #define BT_DMA_Stream_RX DMA1_Stream1
+ // #define BT_DMA_Channel_RX DMA_Channel_4
#else
#define BT_RCC_AHB1Periph 0
#define BT_RCC_APB1Periph 0
diff --git a/radio/src/targets/taranis/i2c_driver.cpp b/radio/src/targets/taranis/i2c_driver.cpp
index 65138b7eb..2620312ba 100644
--- a/radio/src/targets/taranis/i2c_driver.cpp
+++ b/radio/src/targets/taranis/i2c_driver.cpp
@@ -179,7 +179,7 @@ uint8_t eepromIsTransferComplete()
* @param NumByteToWrite : number of bytes to write to the EEPROM.
* @retval None
*/
-bool I2C_EE_PageWrite(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t NumByteToWrite)
+bool I2C_EE_PageWrite(uint8_t * pBuffer, uint16_t WriteAddr, uint8_t NumByteToWrite)
{
if (!I2C_WaitEventCleared(I2C_FLAG_BUSY))
return false;
diff --git a/radio/src/targets/taranis/intmodule_pulses_driver.cpp b/radio/src/targets/taranis/intmodule_pulses_driver.cpp
index 1999dc796..719c0ff21 100644
--- a/radio/src/targets/taranis/intmodule_pulses_driver.cpp
+++ b/radio/src/targets/taranis/intmodule_pulses_driver.cpp
@@ -32,61 +32,46 @@ void intmoduleStop()
INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
}
-void intmoduleNoneStart()
-{
- INTERNAL_MODULE_OFF();
-
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Pin = INTMODULE_TX_GPIO_PIN;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_Init(INTMODULE_TX_GPIO, &GPIO_InitStructure);
- GPIO_SetBits(INTMODULE_TX_GPIO, INTMODULE_TX_GPIO_PIN); // Set high
-
- INTMODULE_TIMER->CR1 &= ~TIM_CR1_CEN;
- INTMODULE_TIMER->PSC = INTMODULE_TIMER_FREQ / 2000000 - 1; // 0.5uS from 30MHz
- INTMODULE_TIMER->ARR = 36000; // 18mS
- INTMODULE_TIMER->CCR2 = 32000; // Update time
- INTMODULE_TIMER->EGR = 1; // Restart
- INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
- INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
- INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
-
- NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn);
- NVIC_SetPriority(INTMODULE_TIMER_CC_IRQn, 7);
-}
-
void intmoduleSendNextFrame()
{
- if (s_current_protocol[INTERNAL_MODULE] == PROTO_PXX) {
- INTMODULE_TIMER->CCR2 = modulePulsesData[INTERNAL_MODULE].pxx.getLast() - 4000; // 2mS in advance
- INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
- INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);
- INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].pxx.getData());
- INTMODULE_DMA_STREAM->NDTR = modulePulsesData[INTERNAL_MODULE].pxx.getSize();
- INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
- }
-#if defined(TARANIS_INTERNAL_PPM)
- else if (s_current_protocol[INTERNAL_MODULE] == PROTO_PPM) {
- INTMODULE_TIMER->CCR3 = GET_PPM_DELAY(INTERNAL_MODULE)*2;
- INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_PPM_POLARITY(INTERNAL_MODULE) ? 0 : TIM_CCER_CC3P);
- INTMODULE_TIMER->CCR2 = *(modulePulsesData[INTERNAL_MODULE].ppm.ptr - 1) - 4000; // 2mS in advance
- INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
- INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
- INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);
- INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(modulePulsesData[INTERNAL_MODULE].ppm.pulses);
- INTMODULE_DMA_STREAM->NDTR = modulePulsesData[INTERNAL_MODULE].ppm.ptr - modulePulsesData[INTERNAL_MODULE].ppm.pulses;
- INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
- }
+ switch (moduleSettings[INTERNAL_MODULE].protocol) {
+#if defined(PXX1)
+ case PROTOCOL_CHANNELS_PXX1_PULSES:
+ INTMODULE_TIMER->CCR2 = intmodulePulsesData.pxx.getLast() - 4000; // 2mS in advance
+ INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);
+ INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(intmodulePulsesData.pxx.getData());
+ INTMODULE_DMA_STREAM->NDTR = intmodulePulsesData.pxx.getSize();
+ INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+ break;
#endif
- else {
- INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
+
+#if defined(TARANIS_INTERNAL_PPM)
+ case PROTOCOL_CHANNELS_PPM:
+ INTMODULE_TIMER->CCR3 = GET_MODULE_PPM_DELAY(INTERNAL_MODULE) * 2;
+ INTMODULE_TIMER->CCER = TIM_CCER_CC3E | (GET_MODULE_PPM_POLARITY(INTERNAL_MODULE) ? 0 : TIM_CCER_CC3P);
+ INTMODULE_TIMER->CCR2 = *(intmodulePulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
+ INTMODULE_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+ INTMODULE_DMA_STREAM->CR |= INTMODULE_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
+ INTMODULE_DMA_STREAM->PAR = CONVERT_PTR_UINT(&INTMODULE_TIMER->ARR);
+ INTMODULE_DMA_STREAM->M0AR = CONVERT_PTR_UINT(intmodulePulsesData.ppm.pulses);
+ INTMODULE_DMA_STREAM->NDTR = intmodulePulsesData.ppm.ptr - intmodulePulsesData.ppm.pulses;
+ INTMODULE_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+ break;
+#endif
+
+ default:
+ INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE;
+ break;
}
}
+void intmoduleSerialStart(uint32_t baudrate, uint8_t rxEnable)
+{
+ // nothing, the pulses will be sent through telemetry port
+}
+
void intmodulePxxStart()
{
INTERNAL_MODULE_ON();
@@ -111,10 +96,11 @@ void intmodulePxxStart()
INTMODULE_TIMER->EGR = 1; // Restart
INTMODULE_TIMER->DIER |= TIM_DIER_UDE; // Enable DMA on update
INTMODULE_TIMER->CCMR2 = TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2;
+ INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
+ INTMODULE_TIMER->CCR2 = 16000; // The first frame will be sent in 20ms
+ INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
INTMODULE_TIMER->CR1 |= TIM_CR1_CEN;
- intmoduleSendNextFrame();
-
NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn);
NVIC_SetPriority(INTMODULE_DMA_STREAM_IRQn, 7);
NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn);
@@ -143,10 +129,11 @@ void intmodulePpmStart()
INTMODULE_TIMER->BDTR = TIM_BDTR_MOE;
INTMODULE_TIMER->EGR = 1;
INTMODULE_TIMER->DIER = TIM_DIER_UDE;
+ INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF; // Clear flag
+ INTMODULE_TIMER->CCR2 = 40000; // The first frame will be sent in 20ms
+ INTMODULE_TIMER->DIER |= TIM_DIER_CC2IE; // Enable this interrupt
INTMODULE_TIMER->CR1 = TIM_CR1_CEN;
- intmoduleSendNextFrame();
-
NVIC_EnableIRQ(INTMODULE_DMA_STREAM_IRQn);
NVIC_SetPriority(INTMODULE_DMA_STREAM_IRQn, 7);
NVIC_EnableIRQ(INTMODULE_TIMER_CC_IRQn);
@@ -169,6 +156,7 @@ extern "C" void INTMODULE_TIMER_CC_IRQHandler()
{
INTMODULE_TIMER->DIER &= ~TIM_DIER_CC2IE; // Stop this interrupt
INTMODULE_TIMER->SR &= ~TIM_SR_CC2IF;
- setupPulses(INTERNAL_MODULE);
- intmoduleSendNextFrame();
+ if (setupPulses(INTERNAL_MODULE)) {
+ intmoduleSendNextFrame();
+ }
}
diff --git a/radio/src/targets/taranis/keys_driver.cpp b/radio/src/targets/taranis/keys_driver.cpp
index 1f44b824f..b4a061d6f 100644
--- a/radio/src/targets/taranis/keys_driver.cpp
+++ b/radio/src/targets/taranis/keys_driver.cpp
@@ -207,9 +207,15 @@ uint32_t switchState(uint8_t index)
ADD_3POS_CASE(A, 0);
ADD_3POS_CASE(B, 1);
ADD_3POS_CASE(C, 2);
+#if !defined(PCBX3)
ADD_3POS_CASE(D, 3);
-#if defined(PCBXLITE)
- // no SWF, SWG and SWH on XLITE
+#endif
+#if defined(PCBXLITES) || defined(PCBX3)
+ ADD_2POS_CASE(E);
+ ADD_2POS_CASE(F);
+ // no SWG and SWH on XLITES and X3
+#elif defined(PCBXLITE) || defined(PCBX3)
+ // no SWE, SWF, SWG and SWH on X3 and XLITE
#elif defined(PCBX7)
ADD_2POS_CASE(F);
ADD_2POS_CASE(H);
diff --git a/radio/src/targets/taranis/pulses_driver.cpp b/radio/src/targets/taranis/pulses_driver.cpp
index 9b7cfea4d..fd5853856 100644
--- a/radio/src/targets/taranis/pulses_driver.cpp
+++ b/radio/src/targets/taranis/pulses_driver.cpp
@@ -20,103 +20,94 @@
#include "opentx.h"
-void intmoduleStop(void);
-void extmoduleStop(void);
-
-void intmoduleNoneStart(void);
-void intmodulePxxStart(void);
-#if defined(TARANIS_INTERNAL_PPM)
-void intmodulePpmStart(void);
-#endif
-
-void extmoduleTimerStart(uint32_t period, uint8_t state);
-void extmodulePpmStart(void);
-void extmodulePxxStart(void);
-void extmoduleSerialStart(uint32_t baudrate, uint32_t period_half_us);
-
-
-void init_pxx(uint32_t port)
+#if defined(PXX1)
+void init_pxx1_pulses(uint8_t module)
{
- if (port == INTERNAL_MODULE)
+ if (module == INTERNAL_MODULE)
intmodulePxxStart();
else
- extmodulePxxStart();
+ extmodulePxxPulsesStart();
}
-void disable_pxx(uint32_t port)
+void init_pxx1_serial(uint8_t module)
{
- if (port == INTERNAL_MODULE)
+ if (module == INTERNAL_MODULE)
+ intmodulePxxStart();
+#if defined(EXTMODULE_USART)
+ else
+ extmodulePxxSerialStart();
+#endif
+}
+
+void disable_pxx1_pulses(uint8_t module)
+{
+ if (module == INTERNAL_MODULE)
+ intmoduleStop();
+ else
+ extmoduleStop();
+}
+
+void disable_pxx1_serial(uint8_t module)
+{
+ if (module == INTERNAL_MODULE)
+ intmoduleStop();
+ else
+ extmoduleStop();
+}
+#endif
+
+void init_pxx2(uint8_t module)
+{
+ if (module == INTERNAL_MODULE)
+ intmoduleSerialStart(INTMODULE_PXX_BAUDRATE, true);
+ else
+ extmodulePxx2Start();
+}
+
+void disable_pxx2(uint8_t module)
+{
+ if (module == INTERNAL_MODULE)
intmoduleStop();
else
extmoduleStop();
}
#if defined(DSM2)
-void init_serial(uint32_t port, uint32_t baudrate, uint32_t period_half_us)
+void init_serial(uint8_t module, uint32_t baudrate, uint32_t period_half_us)
{
- if (port == EXTERNAL_MODULE) {
+ if (module == EXTERNAL_MODULE) {
extmoduleSerialStart(baudrate, period_half_us);
}
}
-void disable_serial(uint32_t port)
+void disable_serial(uint8_t module)
{
- if (port == EXTERNAL_MODULE) {
+ if (module == EXTERNAL_MODULE) {
extmoduleStop();
}
}
#endif
-void init_ppm(uint32_t port)
+void init_ppm(uint8_t module)
{
- if (port == EXTERNAL_MODULE) {
+ if (module == EXTERNAL_MODULE) {
extmodulePpmStart();
}
#if defined(TARANIS_INTERNAL_PPM)
- else if (port == INTERNAL_MODULE) {
+ else {
intmodulePpmStart();
}
#endif
}
-void disable_ppm(uint32_t port)
+void disable_ppm(uint8_t module)
{
- if (port == EXTERNAL_MODULE) {
+ if (module == EXTERNAL_MODULE) {
extmoduleStop();
}
#if defined(TARANIS_INTERNAL_PPM)
- else if (port == INTERNAL_MODULE) {
+ else {
intmoduleStop();
}
#endif
}
-
-void init_no_pulses(uint32_t port)
-{
- if (port == INTERNAL_MODULE)
- intmoduleNoneStart();
- else
- extmoduleTimerStart(18, false);
-}
-
-void disable_no_pulses(uint32_t port)
-{
- if (port == INTERNAL_MODULE)
- intmoduleStop();
- else
- extmoduleStop();
-}
-
-void init_module_timer(uint32_t port, uint32_t period, uint8_t state)
-{
- if (port == EXTERNAL_MODULE) {
- extmoduleTimerStart(period, state);
- }
-}
-
-void disable_module_timer(uint32_t port)
-{
- if (port == EXTERNAL_MODULE) {
- extmoduleStop();
- }
-}
diff --git a/radio/src/targets/taranis/pwr_driver.cpp b/radio/src/targets/taranis/pwr_driver.cpp
index d754d3473..f233eaaac 100644
--- a/radio/src/targets/taranis/pwr_driver.cpp
+++ b/radio/src/targets/taranis/pwr_driver.cpp
@@ -32,8 +32,8 @@ void pwrInit()
GPIO_ResetBits(INTMODULE_PWR_GPIO, INTMODULE_PWR_GPIO_PIN);
GPIO_InitStructure.GPIO_Pin = INTMODULE_PWR_GPIO_PIN;
GPIO_Init(INTMODULE_PWR_GPIO, &GPIO_InitStructure);
-
- GPIO_ResetBits(EXTMODULE_PWR_GPIO, EXTMODULE_PWR_GPIO_PIN);
+
+ EXTERNAL_MODULE_OFF();
GPIO_InitStructure.GPIO_Pin = EXTMODULE_PWR_GPIO_PIN;
GPIO_Init(EXTMODULE_PWR_GPIO, &GPIO_InitStructure);
diff --git a/radio/src/targets/taranis/telemetry_driver.cpp b/radio/src/targets/taranis/telemetry_driver.cpp
index f3b58159e..31c632c05 100644
--- a/radio/src/targets/taranis/telemetry_driver.cpp
+++ b/radio/src/targets/taranis/telemetry_driver.cpp
@@ -37,12 +37,10 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
- USART_InitTypeDef USART_InitStructure;
- GPIO_InitTypeDef GPIO_InitStructure;
-
- GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_RX, TELEMETRY_GPIO_AF);
GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_TX, TELEMETRY_GPIO_AF);
+ GPIO_PinAFConfig(TELEMETRY_GPIO, TELEMETRY_GPIO_PinSource_RX, TELEMETRY_GPIO_AF);
+ GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = TELEMETRY_TX_GPIO_PIN | TELEMETRY_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
@@ -56,6 +54,8 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
GPIO_Init(TELEMETRY_DIR_GPIO, &GPIO_InitStructure);
TELEMETRY_DIR_INPUT();
+ USART_DeInit(TELEMETRY_USART);
+ USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = baudrate;
if (mode & TELEMETRY_SERIAL_8E2) {
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
@@ -70,8 +70,8 @@ void telemetryPortInit(uint32_t baudrate, uint8_t mode)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
USART_Init(TELEMETRY_USART, &USART_InitStructure);
-
USART_Cmd(TELEMETRY_USART, ENABLE);
+
USART_ITConfig(TELEMETRY_USART, USART_IT_RXNE, ENABLE);
NVIC_SetPriority(TELEMETRY_USART_IRQn, 6);
NVIC_EnableIRQ(TELEMETRY_USART_IRQn);
@@ -127,9 +127,8 @@ extern "C" void TELEMETRY_DMA_TX_IRQHandler(void)
if (DMA_GetITStatus(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC)) {
DMA_ClearITPendingBit(TELEMETRY_DMA_Stream_TX, TELEMETRY_DMA_TX_FLAG_TC);
TELEMETRY_USART->CR1 |= USART_CR1_TCIE;
- if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
- outputTelemetryBufferSize = 0;
- outputTelemetryBufferTrigger = 0x7E;
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || telemetryProtocol == PROTOCOL_TELEMETRY_PXX2) {
+ outputTelemetryBuffer.reset();
}
}
}
@@ -157,10 +156,10 @@ extern "C" void TELEMETRY_USART_IRQHandler(void)
else {
telemetryFifo.push(data);
#if defined(LUA)
- if (telemetryProtocol == PROTOCOL_FRSKY_SPORT) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT) {
static uint8_t prevdata;
- if (prevdata == 0x7E && outputTelemetryBufferSize > 0 && data == outputTelemetryBufferTrigger) {
- sportSendBuffer(outputTelemetryBuffer, outputTelemetryBufferSize);
+ if (prevdata == 0x7E && outputTelemetryBuffer.size > 0 && data == outputTelemetryBuffer.trigger && outputTelemetryBuffer.destination == SPORT_MODULE) {
+ sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size);
}
prevdata = data;
}
@@ -174,7 +173,7 @@ extern "C" void TELEMETRY_USART_IRQHandler(void)
uint8_t telemetryGetByte(uint8_t * byte)
{
#if defined(SERIAL2)
- if (telemetryProtocol == PROTOCOL_FRSKY_D_SECONDARY) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
if (serial2Mode == UART_MODE_TELEMETRY)
return serial2RxFifo.pop(*byte);
else
diff --git a/radio/src/targets/taranis/top_lcd_driver.cpp b/radio/src/targets/taranis/top_lcd_driver.cpp
index e0bf2f467..743d0784d 100644
--- a/radio/src/targets/taranis/top_lcd_driver.cpp
+++ b/radio/src/targets/taranis/top_lcd_driver.cpp
@@ -374,7 +374,7 @@ void setTopSecondTimer(uint32_t value)
uint32_t secs = qr.rem;
qr = div(qr.quot, 60);
uint32_t mins = qr.rem;
- uint32_t hours = qr.quot;
+ uint32_t hours = min(qr.quot, 99);
qr = div(secs, 10);
segs = OpTimeLCDsegs[qr.rem];
diff --git a/radio/src/targets/taranis/trainer_driver.cpp b/radio/src/targets/taranis/trainer_driver.cpp
index 1992d635e..000c0721b 100644
--- a/radio/src/targets/taranis/trainer_driver.cpp
+++ b/radio/src/targets/taranis/trainer_driver.cpp
@@ -20,7 +20,9 @@
#include "opentx.h"
+#if defined(HEARTBEAT_USART)
DMAFifo<32> heartbeatFifo __DMA (HEARTBEAT_DMA_Stream);
+#endif
void trainerSendNextFrame();
@@ -39,7 +41,11 @@ void init_trainer_ppm()
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN;
TRAINER_TIMER->PSC = TRAINER_TIMER_FREQ / 2000000 - 1; // 0.5uS
TRAINER_TIMER->ARR = 45000;
- TRAINER_TIMER->CCMR2 = TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2 | TIM_CCMR2_OC4PE; // PWM mode 1
+#if defined(TRAINER_OUT_CCMR1)
+ TRAINER_TIMER->CCMR1 = TRAINER_OUT_CCMR1;
+#elif defined(TRAINER_OUT_CCMR2)
+ TRAINER_TIMER->CCMR2 = TRAINER_OUT_CCMR2;
+#endif
TRAINER_TIMER->BDTR = TIM_BDTR_MOE;
TRAINER_TIMER->EGR = 1;
TRAINER_TIMER->DIER |= TIM_DIER_UDE;
@@ -48,18 +54,23 @@ void init_trainer_ppm()
setupPulsesPPMTrainer();
trainerSendNextFrame();
+#if defined(TRAINER_DMA_STREAM)
NVIC_EnableIRQ(TRAINER_DMA_IRQn);
NVIC_SetPriority(TRAINER_DMA_IRQn, 7);
+#endif
+
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
NVIC_SetPriority(TRAINER_TIMER_IRQn, 7);
}
void stop_trainer_ppm()
{
+#if defined(TRAINER_DMA_STREAM)
NVIC_DisableIRQ(TRAINER_DMA_IRQn);
- NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
-
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
+#endif
+
+ NVIC_DisableIRQ(TRAINER_TIMER_IRQn);
TRAINER_TIMER->DIER = 0;
TRAINER_TIMER->CR1 &= ~TIM_CR1_CEN; // Stop counter
}
@@ -79,10 +90,14 @@ void init_trainer_capture()
TRAINER_TIMER->ARR = 0xFFFF;
TRAINER_TIMER->PSC = (PERI1_FREQUENCY * TIMER_MULT_APB1) / 2000000 - 1; // 0.5uS
TRAINER_TIMER->CR2 = 0;
- TRAINER_TIMER->CCMR2 = TIM_CCMR2_IC3F_0 | TIM_CCMR2_IC3F_1 | TIM_CCMR2_CC3S_0;
- TRAINER_TIMER->CCER = TIM_CCER_CC3E;
+#if defined(TRAINER_IN_CCMR1)
+ TRAINER_TIMER->CCMR1 = TRAINER_IN_CCMR1;
+#elif defined(TRAINER_IN_CCMR2)
+ TRAINER_TIMER->CCMR2 = TRAINER_IN_CCMR2;
+#endif
+ TRAINER_TIMER->CCER = TRAINER_IN_CCER;
TRAINER_TIMER->SR &= ~TIM_SR_CC3IF & ~TIM_SR_CC2IF & ~TIM_SR_UIF; // Clear flags
- TRAINER_TIMER->DIER |= TIM_DIER_CC3IE;
+ TRAINER_TIMER->DIER |= TRAINER_IN_INTERRUPT_ENABLE;
TRAINER_TIMER->CR1 = TIM_CR1_CEN;
NVIC_EnableIRQ(TRAINER_TIMER_IRQn);
@@ -98,18 +113,26 @@ void stop_trainer_capture()
void trainerSendNextFrame()
{
- TRAINER_TIMER->CCR4 = GET_PPM_DELAY(TRAINER_MODULE)*2;
- TRAINER_TIMER->CCER = TIM_CCER_CC4E | (GET_PPM_POLARITY(TRAINER_MODULE) ? 0 : TIM_CCER_CC4P);
- TRAINER_TIMER->CCR1 = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
+ TRAINER_OUT_COUNTER_REGISTER = GET_TRAINER_PPM_DELAY() * 2;
+ TRAINER_TIMER->CCER = TRAINER_OUT_CCER | (GET_TRAINER_PPM_POLARITY() ? 0 : TRAINER_CCER_POLARYTY);
+ TRAINER_SETUP_REGISTER = *(trainerPulsesData.ppm.ptr - 1) - 4000; // 2mS in advance
+#if defined(TRAINER_DMA_STREAM)
TRAINER_DMA_STREAM->CR &= ~DMA_SxCR_EN; // Disable DMA
TRAINER_DMA_STREAM->CR |= TRAINER_DMA_CHANNEL | DMA_SxCR_DIR_0 | DMA_SxCR_MINC | DMA_SxCR_PSIZE_0 | DMA_SxCR_MSIZE_0 | DMA_SxCR_PL_0 | DMA_SxCR_PL_1;
TRAINER_DMA_STREAM->PAR = CONVERT_PTR_UINT(&TRAINER_TIMER->ARR);
TRAINER_DMA_STREAM->M0AR = CONVERT_PTR_UINT(trainerPulsesData.ppm.pulses);
TRAINER_DMA_STREAM->NDTR = trainerPulsesData.ppm.ptr - trainerPulsesData.ppm.pulses;
TRAINER_DMA_STREAM->CR |= DMA_SxCR_EN | DMA_SxCR_TCIE; // Enable DMA
+#else
+ trainerPulsesData.ppm.ptr = trainerPulsesData.ppm.pulses;
+ TRAINER_TIMER->DIER |= TIM_DIER_UDE;
+ TRAINER_TIMER->SR &= ~TIM_SR_UIF; // Clear this flag
+ TRAINER_TIMER->DIER |= TIM_DIER_UIE; // Enable this interrupt
+#endif
}
+#if defined(TRAINER_DMA_STREAM)
extern "C" void TRAINER_DMA_IRQHandler()
{
if (!DMA_GetITStatus(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC))
@@ -117,9 +140,10 @@ extern "C" void TRAINER_DMA_IRQHandler()
DMA_ClearITPendingBit(TRAINER_DMA_STREAM, TRAINER_DMA_FLAG_TC);
- TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
- TRAINER_TIMER->DIER |= TIM_DIER_CC1IE; // Enable this interrupt
+ TRAINER_TIMER->SR &= ~TRAINER_OUT_INTERRUPT_FLAG; // Clear flag
+ TRAINER_TIMER->DIER |= TRAINER_OUT_INTERRUPT_ENABLE; // Enable this interrupt
}
+#endif
extern "C" void TRAINER_TIMER_IRQHandler()
{
@@ -129,14 +153,15 @@ extern "C" void TRAINER_TIMER_IRQHandler()
bool doCapture = false;
// What mode? in or out?
- if ((TRAINER_TIMER->DIER & TIM_DIER_CC3IE) && (TRAINER_TIMER->SR & TIM_SR_CC3IF)) {
+ if ((TRAINER_TIMER->DIER & TRAINER_IN_INTERRUPT_ENABLE) && (TRAINER_TIMER->SR & TRAINER_IN_INTERRUPT_FLAG)) {
// capture mode on trainer jack
- capture = TRAINER_TIMER->CCR3;
+ capture = TRAINER_IN_COUNTER_REGISTER;
if (TRAINER_CONNECTED() && currentTrainerMode == TRAINER_MODE_MASTER_TRAINER_JACK) {
doCapture = true;
}
}
+#if defined(TRAINER_MODULE_HEARTBEAT)
if ((TRAINER_TIMER->DIER & TIM_DIER_CC2IE) && (TRAINER_TIMER->SR & TIM_SR_CC2IF)) {
// capture mode on heartbeat pin (external module)
capture = TRAINER_TIMER->CCR2;
@@ -144,22 +169,36 @@ extern "C" void TRAINER_TIMER_IRQHandler()
doCapture = true;
}
}
+#endif
if (doCapture) {
captureTrainerPulses(capture);
}
// PPM out compare interrupt
- if ((TRAINER_TIMER->DIER & TIM_DIER_CC1IE) && (TRAINER_TIMER->SR & TIM_SR_CC1IF)) {
+ if ((TRAINER_TIMER->DIER & TRAINER_OUT_INTERRUPT_ENABLE) && (TRAINER_TIMER->SR & TRAINER_OUT_INTERRUPT_FLAG)) {
// compare interrupt
- TRAINER_TIMER->DIER &= ~TIM_DIER_CC1IE; // stop this interrupt
- TRAINER_TIMER->SR &= ~TIM_SR_CC1IF; // Clear flag
+ TRAINER_TIMER->DIER &= ~TRAINER_OUT_INTERRUPT_ENABLE; // stop this interrupt
+ TRAINER_TIMER->SR &= ~TRAINER_OUT_INTERRUPT_FLAG; // Clear flag
setupPulsesPPMTrainer();
trainerSendNextFrame();
}
+
+#if !defined(TRAINER_DMA_STREAM)
+ // PPM out update interrupt
+ if ((TRAINER_TIMER->DIER & TIM_DIER_UIE) && (TRAINER_TIMER->SR & TIM_SR_UIF)) {
+ TRAINER_TIMER->SR &= ~TIM_SR_UIF; // Clear flag
+ TRAINER_TIMER->ARR = *trainerPulsesData.ppm.ptr++;
+ if (*trainerPulsesData.ppm.ptr == 0) {
+ TRAINER_TIMER->SR &= ~TRAINER_OUT_INTERRUPT_FLAG; // Clear this flag
+ TRAINER_TIMER->DIER |= TRAINER_OUT_INTERRUPT_ENABLE; // Enable this interrupt
+ }
+ }
+#endif
}
-void init_cppm_on_heartbeat_capture(void)
+#if defined(TRAINER_MODULE_HEARTBEAT)
+void init_cppm_on_heartbeat_capture()
{
EXTERNAL_MODULE_ON();
@@ -196,7 +235,9 @@ void stop_cppm_on_heartbeat_capture()
EXTERNAL_MODULE_OFF();
}
}
+#endif
+#if defined(HEARTBEAT_USART)
void init_sbus_on_heartbeat_capture()
{
EXTERNAL_MODULE_ON();
@@ -258,13 +299,16 @@ void stop_sbus_on_heartbeat_capture()
EXTERNAL_MODULE_OFF();
}
}
+#endif
int sbusGetByte(uint8_t * byte)
{
switch (currentTrainerMode) {
+#if defined(HEARTBEAT_USART)
case TRAINER_MODE_MASTER_SBUS_EXTERNAL_MODULE:
return heartbeatFifo.pop(*byte);
-#if !defined(PCBX7) && !defined(PCBX9E)
+#endif
+#if !defined(PCBX7) && !defined(PCBX9E) && !defined(PCBX3) && !defined(PCBXLITE)
case TRAINER_MODE_MASTER_BATTERY_COMPARTMENT:
return serial2RxFifo.pop(*byte);
#endif
diff --git a/radio/src/tasks_arm.cpp b/radio/src/tasks.cpp
similarity index 77%
rename from radio/src/tasks_arm.cpp
rename to radio/src/tasks.cpp
index fecc02333..2c787860b 100644
--- a/radio/src/tasks_arm.cpp
+++ b/radio/src/tasks.cpp
@@ -73,6 +73,32 @@ bool isForcePowerOffRequested()
return false;
}
+bool isModuleSynchronous(uint8_t module)
+{
+ uint8_t protocol = moduleSettings[module].protocol;
+ if (protocol == PROTOCOL_CHANNELS_PXX2 || protocol == PROTOCOL_CHANNELS_CROSSFIRE || protocol == PROTOCOL_CHANNELS_NONE)
+ return true;
+#if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
+ if (protocol == PROTOCOL_CHANNELS_PXX1_SERIAL)
+ return true;
+#endif
+ return false;
+}
+
+void sendSynchronousPulses()
+{
+ for (uint8_t module = 0; module < NUM_MODULES; module++) {
+ if (isModuleSynchronous(module) && setupPulses(module)) {
+#if defined(HARDWARE_INTERNAL_MODULE)
+ if (module == INTERNAL_MODULE)
+ intmoduleSendNextFrame();
+#endif
+ if (module == EXTERNAL_MODULE)
+ extmoduleSendNextFrame();
+ }
+ }
+}
+
uint32_t nextMixerTime[NUM_MODULES];
TASK_FUNCTION(mixerTask)
@@ -82,15 +108,17 @@ TASK_FUNCTION(mixerTask)
while(1) {
-#if defined(SBUS)
+#if defined(PCBX9D) || defined(PCBX7)
+ // SBUS on Hearbeat PIN (which is a serial RX)
processSbusInput();
#endif
RTOS_WAIT_TICKS(1);
#if defined(SIMU)
- if (pwrCheck() == e_power_off)
+ if (pwrCheck() == e_power_off) {
TASK_RETURN();
+ }
#else
if (isForcePowerOffRequested()) {
pwrOff();
@@ -153,7 +181,9 @@ TASK_FUNCTION(mixerTask)
}
t0 = getTmr2MHz() - t0;
- if (t0 > maxMixerDuration) maxMixerDuration = t0 ;
+ if (t0 > maxMixerDuration) maxMixerDuration = t0;
+
+ sendSynchronousPulses();
}
}
}
@@ -161,12 +191,23 @@ TASK_FUNCTION(mixerTask)
void scheduleNextMixerCalculation(uint8_t module, uint16_t period_ms)
{
// Schedule next mixer calculation time,
- // for now assume mixer calculation takes 2 ms.
- nextMixerTime[module] = (uint32_t)RTOS_GET_TIME() + period_ms / 2 - 1/*2ms*/;
+
+ if (isModuleSynchronous(module)) {
+ nextMixerTime[module] += period_ms / RTOS_MS_PER_TICK;
+ if (nextMixerTime[module] < RTOS_GET_TIME()) {
+ // we are late ... let's add some small delay
+ nextMixerTime[module] = (uint32_t) RTOS_GET_TIME() + (period_ms / RTOS_MS_PER_TICK);
+ }
+ }
+ else {
+ // for now assume mixer calculation takes 2 ms.
+ nextMixerTime[module] = (uint32_t) RTOS_GET_TIME() + (period_ms / RTOS_MS_PER_TICK) - 1 /* 1 tick in advance*/;
+ }
+
DEBUG_TIMER_STOP(debugTimerMixerCalcToUsage);
}
-#define MENU_TASK_PERIOD_TICKS 25 // 50ms
+#define MENU_TASK_PERIOD_TICKS (50 / RTOS_MS_PER_TICK) // 50ms
#if defined(COLORLCD) && defined(CLI)
bool perMainEnabled = true;
diff --git a/radio/src/tasks_arm.h b/radio/src/tasks.h
similarity index 100%
rename from radio/src/tasks_arm.h
rename to radio/src/tasks.h
diff --git a/radio/src/telemetry/crossfire.h b/radio/src/telemetry/crossfire.h
index b80ebdf36..d0f2652ad 100644
--- a/radio/src/telemetry/crossfire.h
+++ b/radio/src/telemetry/crossfire.h
@@ -21,6 +21,9 @@
#ifndef _CROSSFIRE_H_
#define _CROSSFIRE_H_
+#include
+#include "dataconstants.h"
+
// Device address
#define BROADCAST_ADDRESS 0x00
#define RADIO_ADDRESS 0xEA
@@ -86,10 +89,10 @@ const uint8_t CROSSFIRE_PERIODS[] = {
4,
16,
};
-#define CROSSFIRE_BAUDRATE CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate]
+#define CROSSFIRE_BAUDRATE CROSSFIRE_BAUDRATES[g_eeGeneral.telemetryBaudrate]
#define CROSSFIRE_PERIOD CROSSFIRE_PERIODS[g_eeGeneral.telemetryBaudrate]
#else
-#define CROSSFIRE_BAUDRATE 400000
+#define CROSSFIRE_BAUDRATE 400000
#define CROSSFIRE_PERIOD 4 // 4ms
#endif
diff --git a/radio/src/telemetry/frsky.cpp b/radio/src/telemetry/frsky.cpp
index 02622bfeb..8098a8a74 100644
--- a/radio/src/telemetry/frsky.cpp
+++ b/radio/src/telemetry/frsky.cpp
@@ -20,10 +20,78 @@
#include "opentx.h"
-void processFrskyTelemetryData(uint8_t data)
+bool checkPXX2PacketCRC(const uint8_t * packet)
+{
+ // TODO ...
+
+ return true;
+ // TRACE("checkPXX2PacketCRC(): checksum error ");
+ // DUMP(packet, FRSKY_SPORT_PACKET_SIZE);
+}
+
+void createFrSkyPXX2Sensor(uint16_t type, uint8_t value){
+ uint8_t buffer[5] = {0x18, 0x10, 0, 0, 0};
+ buffer[2] = type & 0xF;
+ buffer[3] = type >> 8;
+ buffer[4] = value;
+ sportProcessTelemetryPacketWithoutCrc(buffer);
+}
+
+void processFrskyPXX2Data(uint8_t data)
{
static uint8_t dataState = STATE_DATA_IDLE;
+ switch (dataState) {
+ case STATE_DATA_IDLE:
+ if (data == START_STOP) {
+ telemetryRxBufferCount = 0;
+ dataState = STATE_DATA_START;
+ }
+ break;
+
+ case STATE_DATA_START:
+ if (telemetryRxBufferCount == 0 && data > 0x0C) {
+ // wrong length
+ telemetryRxBufferCount = 0;
+ dataState = STATE_DATA_IDLE;
+ }
+ else if (telemetryRxBufferCount < TELEMETRY_RX_PACKET_SIZE) {
+ telemetryRxBuffer[telemetryRxBufferCount++] = data;
+ if (telemetryRxBuffer[0] + 3 /* 1 byte for length, 2 bytes for CRC */ == telemetryRxBufferCount) {
+ if (checkPXX2PacketCRC(telemetryRxBuffer)) {
+ R9ModuleStreaming = TELEMETRY_TIMEOUT10ms; // reset counter only if valid packets are being detected
+ uint8_t R9Region = (telemetryRxBuffer[3] & 0x30) >> 4;
+ if (R9Region != 0x04) {
+ g_model.moduleData[EXTERNAL_MODULE].r9m.region = R9Region;
+ }
+ if (telemetryRxBuffer[2] & 0x80) {
+ createFrSkyPXX2Sensor(RSSI_ID, telemetryRxBuffer[2] & 0x7f);
+ }
+ else {
+ createFrSkyPXX2Sensor(BATT_ID, telemetryRxBuffer[2] & 0x7f);
+ }
+ if((telemetryRxBuffer[3] & 0x04) == 0) {
+ createFrSkyPXX2Sensor(R9_PWR_ID, (telemetryRxBuffer[3] & 0x03));
+ }
+ if (telemetryRxBuffer[0] == 0x0C) {
+ sportProcessTelemetryPacketWithoutCrc(telemetryRxBuffer + 5 /* LEN, TYPE, RSSI/BAT, TP/SS/FW_T, FW_VER, Data ID */);
+ }
+ }
+ telemetryRxBufferCount = 0;
+ dataState = STATE_DATA_IDLE;
+ }
+ }
+ else {
+ // overflow guard
+ telemetryRxBufferCount = 0;
+ dataState = STATE_DATA_IDLE;
+ }
+ break;
+ }
+}
+
+void processFrskyTelemetryData(uint8_t data)
+{
#if defined(PCBSKY9X) && defined(BLUETOOTH)
// TODO if (g_model.bt_telemetry)
btPushByte(data);
@@ -41,6 +109,19 @@ void processFrskyTelemetryData(uint8_t data)
}
#endif
+ if (pushFrskyTelemetryData(data)) {
+ if (IS_FRSKY_SPORT_PROTOCOL()) {
+ sportProcessTelemetryPacket(telemetryRxBuffer);
+ } else {
+ frskyDProcessPacket(telemetryRxBuffer);
+ }
+ }
+}
+
+bool pushFrskyTelemetryData(uint8_t data)
+{
+ static uint8_t dataState = STATE_DATA_IDLE;
+
switch (dataState) {
case STATE_DATA_START:
if (data == START_STOP) {
@@ -68,8 +149,8 @@ void processFrskyTelemetryData(uint8_t data)
}
else {
// end of frame detected
- frskyDProcessPacket(telemetryRxBuffer);
dataState = STATE_DATA_IDLE;
+ return true;
}
break;
}
@@ -96,9 +177,13 @@ void processFrskyTelemetryData(uint8_t data)
#if defined(TELEMETRY_FRSKY_SPORT)
if (IS_FRSKY_SPORT_PROTOCOL() && telemetryRxBufferCount >= FRSKY_SPORT_PACKET_SIZE) {
- sportProcessPacket(telemetryRxBuffer);
+ // end of frame detected
dataState = STATE_DATA_IDLE;
+ return true;
}
#endif
+
+ return false;
}
+
diff --git a/radio/src/telemetry/frsky.h b/radio/src/telemetry/frsky.h
index 96145e3e7..b665f4fdf 100644
--- a/radio/src/telemetry/frsky.h
+++ b/radio/src/telemetry/frsky.h
@@ -23,6 +23,7 @@
#include "../definitions.h"
#include "telemetry_holders.h"
+#include "../io/frsky_pxx2.h"
// Receive buffer state machine state enum
enum FrSkyDataState {
@@ -32,12 +33,7 @@ enum FrSkyDataState {
STATE_DATA_XOR,
};
-#if defined(PXX2)
-#include "io/pxx2.h"
-#define FRSKY_SPORT_BAUDRATE PXX2_BAUDRATE
-#else
#define FRSKY_SPORT_BAUDRATE 57600
-#endif
#define FRSKY_D_BAUDRATE 9600
@@ -196,9 +192,12 @@ enum FrSkyDataState {
#define BATT_ID 0xf104
#define RAS_ID 0xf105
#define XJT_VERSION_ID 0xf106
+#define R9_PWR_ID 0xf107
#define FUEL_QTY_FIRST_ID 0x0a10
#define FUEL_QTY_LAST_ID 0x0a1f
+
+
// Default sensor data IDs (Physical IDs + CRC)
#define DATA_ID_VARIO 0x00 // 0
#define DATA_ID_FLVSS 0xA1 // 1
@@ -208,7 +207,6 @@ enum FrSkyDataState {
#define DATA_ID_SP2UH 0x45 // 5
#define DATA_ID_SP2UR 0xC6 // 6
-
#if defined(NO_RAS)
#define IS_RAS_VALUE_VALID() (false)
#elif defined(PCBX10)
@@ -221,13 +219,6 @@ enum FrSkyDataState {
#define IS_HIDDEN_TELEMETRY_VALUE(id) ((id == SP2UART_A_ID) || (id == SP2UART_B_ID) || (id == XJT_VERSION_ID) || (id == RAS_ID) || (id == FACT_TEST_ID))
-enum AlarmLevel {
- alarm_off = 0,
- alarm_yellow = 1,
- alarm_orange = 2,
- alarm_red = 3
-};
-
#define ALARM_GREATER(channel, alarm) ((g_model.frsky.channels[channel].alarms_greater >> alarm) & 1)
#define ALARM_LEVEL(channel, alarm) ((g_model.frsky.channels[channel].alarms_level >> (2*alarm)) & 3)
@@ -289,11 +280,11 @@ typedef enum {
// FrSky D Telemetry Protocol
void processHubPacket(uint8_t id, int16_t value);
-void frskyDSendNextAlarm();
void frskyDProcessPacket(const uint8_t *packet);
// FrSky S.PORT Telemetry Protocol
void sportProcessTelemetryPacket(const uint8_t * packet);
+void sportProcessTelemetryPacketWithoutCrc(const uint8_t * packet);
void telemetryWakeup();
void telemetryReset();
@@ -313,14 +304,6 @@ enum TelemetryProtocol
TELEM_PROTO_FLYSKY_IBUS,
};
-enum TelemAnas {
- TELEM_ANA_A1,
- TELEM_ANA_A2,
- TELEM_ANA_A3,
- TELEM_ANA_A4,
- TELEM_ANA_COUNT
-};
-
struct TelemetryData {
TelemetryValueWithMin swr; // TODO Min not needed
TelemetryValueWithMin rssi; // TODO Min not needed
@@ -330,12 +313,8 @@ struct TelemetryData {
extern TelemetryData telemetryData;
- typedef uint16_t frskyCellVoltage_t;
-
-void frskySetCellsCount(uint8_t cellscount);
-void frskySetCellVoltage(uint8_t battnumber, frskyCellVoltage_t cellVolts);
-void frskyUpdateCells();
-
+bool pushFrskyTelemetryData(uint8_t data); // returns true when end of frame detected
void processFrskyTelemetryData(uint8_t data);
+void processFrskyPXX2Data(uint8_t data);
#endif // _FRSKY_H_
diff --git a/radio/src/telemetry/frsky_d_arm.cpp b/radio/src/telemetry/frsky_d.cpp
similarity index 100%
rename from radio/src/telemetry/frsky_d_arm.cpp
rename to radio/src/telemetry/frsky_d.cpp
diff --git a/radio/src/telemetry/frsky_pxx2.cpp b/radio/src/telemetry/frsky_pxx2.cpp
new file mode 100644
index 000000000..b7e54d887
--- /dev/null
+++ b/radio/src/telemetry/frsky_pxx2.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) OpenTX
+ *
+ * Based on code named
+ * th9x - http://code.google.com/p/th9x
+ * er9x - http://code.google.com/p/er9x
+ * gruvin9x - http://code.google.com/p/gruvin9x
+ *
+ * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include
+#include "opentx.h"
+
+class Pxx2Telemetry
+{
+ protected:
+ static void processGetHardwareInfoFrame(uint8_t module, uint8_t *frame);
+
+ static void processReceiverSettingsFrame(uint8_t module, uint8_t *frame);
+
+ static void processRegisterFrame(uint8_t module, uint8_t * frame);
+
+ static void processBindFrame(uint8_t module, uint8_t * frame);
+
+ static void processTelemetryFrame(uint8_t module, uint8_t * frame);
+
+ static void processSpectrumFrame(uint8_t module, uint8_t * frame);
+
+ static void processRadioFrame(uint8_t module, uint8_t * frame);
+
+ static void processPowerMeterFrame(uint8_t module, uint8_t * frame);
+
+ public:
+};
+
+void processGetHardwareInfoFrame(uint8_t module, uint8_t * frame)
+{
+ if (moduleSettings[module].mode != MODULE_MODE_GET_HARDWARE_INFO) {
+ return;
+ }
+
+ uint8_t index = frame[3];
+ if (index == 0xFF)
+ memcpy(&reusableBuffer.hardwareAndSettings.modules[module].information, &frame[4], sizeof(PXX2HardwareInformation));
+ else if (index < PXX2_MAX_RECEIVERS_PER_MODULE)
+ memcpy(&reusableBuffer.hardwareAndSettings.modules[module].receivers[index].information, &frame[4], sizeof(PXX2HardwareInformation));
+}
+
+void processModuleSettingsFrame(uint8_t module, uint8_t * frame)
+{
+ if (moduleSettings[module].mode != MODULE_MODE_MODULE_SETTINGS) {
+ return;
+ }
+
+ // Flag1
+ reusableBuffer.hardwareAndSettings.moduleSettings.txPower = frame[4] >> 4;
+ if (frame[4] & PXX2_TX_SETTINGS_FLAG1_EXTERNAL_ANTENNA)
+ reusableBuffer.hardwareAndSettings.moduleSettings.externalAntenna = 1;
+
+ // Power
+ reusableBuffer.hardwareAndSettings.moduleSettings.txPower = frame[5];
+
+ reusableBuffer.hardwareAndSettings.moduleSettings.state = PXX2_SETTINGS_OK;
+ reusableBuffer.hardwareAndSettings.moduleSettings.timeout = 0;
+ moduleSettings[module].mode = MODULE_MODE_NORMAL;
+}
+
+void processReceiverSettingsFrame(uint8_t module, uint8_t * frame)
+{
+ if (moduleSettings[module].mode != MODULE_MODE_RECEIVER_SETTINGS) {
+ return;
+ }
+
+ if (frame[4] & PXX2_RX_SETTINGS_FLAG1_FASTPWM)
+ reusableBuffer.hardwareAndSettings.receiverSettings.pwmRate = 1;
+
+ if (frame[4] & PXX2_RX_SETTINGS_FLAG1_TELEMETRY_DISABLED)
+ reusableBuffer.hardwareAndSettings.receiverSettings.telemetryDisabled = 1;
+
+ uint8_t outputsCount = min(16, frame[0] - 4);
+ reusableBuffer.hardwareAndSettings.receiverSettings.outputsCount = outputsCount;
+ for (uint8_t pin = 0; pin < outputsCount; pin++) {
+ reusableBuffer.hardwareAndSettings.receiverSettings.outputsMapping[pin] = frame[5 + pin];
+ }
+
+ reusableBuffer.hardwareAndSettings.receiverSettings.state = PXX2_SETTINGS_OK;
+ reusableBuffer.hardwareAndSettings.receiverSettings.timeout = 0;
+ moduleSettings[module].mode = MODULE_MODE_NORMAL;
+}
+
+void processRegisterFrame(uint8_t module, uint8_t * frame)
+{
+ if (moduleSettings[module].mode != MODULE_MODE_REGISTER) {
+ return;
+ }
+
+ switch(frame[3]) {
+ case 0x00:
+ if (reusableBuffer.moduleSetup.pxx2.registerStep == REGISTER_START) {
+ // RX_NAME follows, we store it for the next step
+ str2zchar(reusableBuffer.moduleSetup.pxx2.registerRxName, (const char *)&frame[4], PXX2_LEN_RX_NAME);
+ reusableBuffer.moduleSetup.pxx2.registerStep = REGISTER_RX_NAME_RECEIVED;
+ }
+ break;
+
+ case 0x01:
+ if (reusableBuffer.moduleSetup.pxx2.registerStep == REGISTER_RX_NAME_SELECTED) {
+ // RX_NAME + PASSWORD follow, we check they are good
+ if (cmpStrWithZchar((char *)&frame[4], reusableBuffer.moduleSetup.pxx2.registerRxName, PXX2_LEN_RX_NAME) &&
+ cmpStrWithZchar((char *)&frame[12], g_model.modelRegistrationID, PXX2_LEN_REGISTRATION_ID)) {
+ reusableBuffer.moduleSetup.pxx2.registerStep = REGISTER_OK;
+ moduleSettings[module].mode = MODULE_MODE_NORMAL;
+ POPUP_INFORMATION(STR_REG_OK);
+ } else {
+ TRACE("KO %s %s", &frame[4], reusableBuffer.moduleSetup.pxx2.registerRxName);
+ }
+ }
+ break;
+ }
+}
+
+void processBindFrame(uint8_t module, uint8_t * frame)
+{
+ if (moduleSettings[module].mode != MODULE_MODE_BIND) {
+ return;
+ }
+
+ switch(frame[3]) {
+ case 0x00:
+ if (reusableBuffer.moduleSetup.pxx2.bindStep == BIND_START) {
+ bool found = false;
+ for (uint8_t i=0; i reusableBuffer.powerMeter.peak) {
+ reusableBuffer.powerMeter.peak = reusableBuffer.powerMeter.power;
+ }
+}
+
+void processModuleFrame(uint8_t module, uint8_t *frame)
+{
+ switch (frame[2]) {
+ case PXX2_TYPE_ID_HW_INFO:
+ processGetHardwareInfoFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_ID_TX_SETTINGS:
+ processModuleSettingsFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_ID_RX_SETTINGS:
+ processReceiverSettingsFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_ID_REGISTER:
+ processRegisterFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_ID_BIND:
+ processBindFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_ID_TELEMETRY:
+ processTelemetryFrame(module, frame);
+ break;
+ }
+}
+
+void processToolsFrame(uint8_t module, uint8_t * frame)
+{
+ switch (frame[2]) {
+ case PXX2_TYPE_ID_POWER_METER:
+ processPowerMeterFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_ID_SPECTRUM:
+ processSpectrumAnalyserFrame(module, frame);
+ break;
+ }
+}
+
+void processPXX2Frame(uint8_t module, uint8_t *frame)
+{
+ switch (frame[1]) {
+ case PXX2_TYPE_C_MODULE:
+ processModuleFrame(module, frame);
+ break;
+
+ case PXX2_TYPE_C_POWER_METER:
+ processToolsFrame(module, frame);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void pushPXX2TelemetryPacket(uint8_t module, uint8_t rx_uid, SportTelemetryPacket * packet)
+{
+ // Flag0
+ outputTelemetryBuffer.push(rx_uid);
+
+ for (uint8_t i=1; iraw[i];
+ outputTelemetryBuffer.push(byte);
+ }
+
+ outputTelemetryBuffer.setDestination(module);
+}
diff --git a/radio/src/telemetry/frsky_sport.cpp b/radio/src/telemetry/frsky_sport.cpp
index 0309ecb2f..3bc4edde9 100644
--- a/radio/src/telemetry/frsky_sport.cpp
+++ b/radio/src/telemetry/frsky_sport.cpp
@@ -36,6 +36,7 @@ const FrSkySportSensor sportSensors[] = {
{ A3_FIRST_ID, A3_LAST_ID, 0, ZSTR_A3, UNIT_VOLTS, 2 },
{ A4_FIRST_ID, A4_LAST_ID, 0, ZSTR_A4, UNIT_VOLTS, 2 },
{ BATT_ID, BATT_ID, 0, ZSTR_BATT, UNIT_VOLTS, 1 },
+ { R9_PWR_ID, R9_PWR_ID, 0, ZSTR_R9PW, UNIT_MILLIWATTS, 0 },
{ T1_FIRST_ID, T1_LAST_ID, 0, ZSTR_TEMP1, UNIT_CELSIUS, 0 },
{ T2_FIRST_ID, T2_LAST_ID, 0, ZSTR_TEMP2, UNIT_CELSIUS, 0 },
{ RPM_FIRST_ID, RPM_LAST_ID, 0, ZSTR_RPM, UNIT_RPMS, 0 },
@@ -94,7 +95,7 @@ const FrSkySportSensor * getFrSkySportSensor(uint16_t id, uint8_t subId=0)
return result;
}
-bool checkSportPacket(const uint8_t *packet)
+bool checkSportPacket(const uint8_t * packet)
{
short crc = 0;
for (int i=1; i= 5)
processMultiStatusPacket(data);
break;
+
case DSMBindPacket:
if (len >= 10)
processDSMBindPacket(data);
break;
+
case SpektrumTelemetry:
// processSpektrumPacket expects data[0] to be the telemetry indicator 0xAA but does not check it,
// just send one byte of our header instead
@@ -121,41 +123,50 @@ static void processMultiTelemetryPaket(const uint8_t *packet)
else
TRACE("[MP] Received spektrum telemetry len %d < 17", len);
break;
+
case FlyskyIBusTelemetry:
if (len >= 28)
processFlySkyPacket(data);
else
TRACE("[MP] Received IBUS telemetry len %d < 28", len);
break;
+
case FrSkyHubTelemetry:
if (len >= 4)
frskyDProcessPacket(data);
else
TRACE("[MP] Received Frsky HUB telemetry len %d < 4", len);
break;
+
+#if defined(MULTI_SPORT)
case FrSkySportTelemtry:
if (len >= 4)
sportProcessTelemetryPacket(data);
else
TRACE("[MP] Received sport telemetry len %d < 4", len);
break;
+#endif
+
case InputSync:
if (len >= 6)
processMultiSyncPacket(data);
else
TRACE("[MP] Received input sync len %d < 6", len);
break;
+
case ConfigCommand:
// Just an ack to our command, ignore for now
break;
+
case FrskySportPolling:
#if defined(LUA)
- if (len >= 1 && outputTelemetryBufferSize > 0 && data[0] == outputTelemetryBufferTrigger) {
+ if (len >= 1 && outputTelemetryBuffer.size > 0 && data[0] == outputTelemetryBuffer.trigger) {
TRACE("MP Sending sport data out.");
- sportSendBuffer(outputTelemetryBuffer, outputTelemetryBufferSize);
+ sportSendBuffer(outputTelemetryBuffer.data, outputTelemetryBuffer.size);
}
#endif
break;
+
default:
TRACE("[MP] Unkown multi packet type 0x%02X, len %d", type, len);
break;
diff --git a/radio/src/telemetry/spektrum.cpp b/radio/src/telemetry/spektrum.cpp
index dd3d9246f..96c7102d0 100644
--- a/radio/src/telemetry/spektrum.cpp
+++ b/radio/src/telemetry/spektrum.cpp
@@ -173,14 +173,14 @@ const SpektrumSensor spektrumSensors[] = {
{I2C_CELLS, 8, uint16, ZSTR_CELLS, UNIT_VOLTS, 2},
{I2C_CELLS, 10, uint16, ZSTR_CELLS, UNIT_VOLTS, 2},
{I2C_CELLS, 12, uint16, ZSTR_TEMP2, UNIT_CELSIUS, 2},
-
+
// Vario-S
{0x40, 0, int16, ZSTR_ALT, UNIT_METERS, 1},
{0x40, 2, int16, ZSTR_VSPD, UNIT_METERS_PER_SECOND, 1},
// 0x50-0x56 custom 3rd party sensors
//{0x50, 0, int16, ZSTR_}
-
+
// 0x7d are transmitter channels frame data [7], probably only available on the Spektrum
// telemetry bus on the model itself
@@ -333,7 +333,7 @@ void processSpektrumPacket(const uint8_t *packet)
}
telemetryStreaming = TELEMETRY_TIMEOUT10ms;
}
-
+
uint16_t pseudoId = (sensor->i2caddress << 8 | sensor->startByte);
setTelemetryValue(TELEM_PROTO_SPEKTRUM, pseudoId, 0, instance, value, sensor->unit, sensor->precision);
}
@@ -400,8 +400,7 @@ void processDSMBindPacket(const uint8_t *packet)
setTelemetryValue(TELEM_PROTO_SPEKTRUM, (I2C_PSEUDO_TX << 8) + 4, 0, 0, debugval, UNIT_RAW, 0);
/* Finally stop binding as the rx just told us that it is bound */
- if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MM_RF_PROTO_DSM2
- && moduleFlag[EXTERNAL_MODULE] == MODULE_BIND) {
+ if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE && g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(true) == MM_RF_PROTO_DSM2 && moduleSettings[EXTERNAL_MODULE].mode == MODULE_MODE_BIND) {
multiBindStatus=MULTI_BIND_FINISHED;
}
}
diff --git a/radio/src/telemetry/telemetry.cpp b/radio/src/telemetry/telemetry.cpp
index 95af31711..04b37cf0b 100644
--- a/radio/src/telemetry/telemetry.cpp
+++ b/radio/src/telemetry/telemetry.cpp
@@ -18,9 +18,10 @@
* GNU General Public License for more details.
*/
-#include "opentx.h"
+#include
uint8_t telemetryStreaming = 0;
+uint8_t R9ModuleStreaming = 0;
uint8_t telemetryRxBuffer[TELEMETRY_RX_PACKET_SIZE]; // Receive buffer. 9 bytes (full packet), worst case 18 bytes with byte-stuffing (+1)
uint8_t telemetryRxBufferCount = 0;
@@ -38,44 +39,69 @@ uint8_t telemetryProtocol = 255;
uint8_t serialInversion = 0;
#endif
-
void processTelemetryData(uint8_t data)
{
#if defined(CROSSFIRE)
- if (telemetryProtocol == PROTOCOL_PULSES_CROSSFIRE) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
processCrossfireTelemetryData(data);
return;
}
#endif
+
#if defined(MULTIMODULE)
- if (telemetryProtocol == PROTOCOL_SPEKTRUM) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM) {
processSpektrumTelemetryData(data);
return;
}
- if (telemetryProtocol == PROTOCOL_FLYSKY_IBUS) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FLYSKY_IBUS) {
processFlySkyTelemetryData(data);
return;
}
- if (telemetryProtocol == PROTOCOL_MULTIMODULE) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE) {
processMultiTelemetryData(data);
return;
}
#endif
+
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_PXX2) {
+ processFrskyPXX2Data(data);
+ return;
+ }
+
processFrskyTelemetryData(data);
}
void telemetryWakeup()
{
uint8_t requiredTelemetryProtocol = modelTelemetryProtocol();
+
#if defined(REVX)
uint8_t requiredSerialInversion = g_model.moduleData[EXTERNAL_MODULE].invertedSerial;
if (telemetryProtocol != requiredTelemetryProtocol || serialInversion != requiredSerialInversion) {
serialInversion = requiredSerialInversion;
-#else
- if (telemetryProtocol != requiredTelemetryProtocol) {
-#endif
telemetryInit(requiredTelemetryProtocol);
}
+#else
+ if (telemetryProtocol != requiredTelemetryProtocol) {
+ telemetryInit(requiredTelemetryProtocol);
+ }
+#endif
+
+#if defined(INTMODULE_USART) || defined(EXTMODULE_USART)
+ uint8_t frame[PXX2_FRAME_MAXLENGTH];
+
+ #if defined(INTMODULE_USART)
+ while (intmoduleFifo.getFrame(frame)) {
+ processPXX2Frame(INTERNAL_MODULE, frame);
+ }
+ #endif
+
+ #if defined(EXTMODULE_USART)
+ while (extmoduleFifo.getFrame(frame)) {
+ processPXX2Frame(EXTERNAL_MODULE, frame);
+ }
+ #endif
+#endif
#if defined(STM32)
uint8_t data;
@@ -87,7 +113,7 @@ void telemetryWakeup()
} while (telemetryGetByte(&data));
}
#elif defined(PCBSKY9X)
- if (telemetryProtocol == PROTOCOL_FRSKY_D_SECONDARY) {
+ if (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
uint8_t data;
while (telemetrySecondPortReceive(data)) {
processTelemetryData(data);
@@ -99,7 +125,6 @@ void telemetryWakeup()
}
#endif
-
for (int i=0; i 0x33)
static tmr10ms_t alarmsCheckTime = 0;
@@ -194,7 +219,9 @@ void telemetryInterrupt10ms()
wshhStreaming--;
}
#endif
-
+ if (R9ModuleStreaming > 0) {
+ R9ModuleStreaming--;
+ }
if (telemetryStreaming > 0) {
telemetryStreaming--;
}
@@ -223,27 +250,27 @@ void telemetryInit(uint8_t protocol)
{
telemetryProtocol = protocol;
- if (protocol == PROTOCOL_FRSKY_D) {
+ if (protocol == PROTOCOL_TELEMETRY_FRSKY_D) {
telemetryPortInit(FRSKY_D_BAUDRATE, TELEMETRY_SERIAL_DEFAULT);
}
#if defined(MULTIMODULE)
- else if (protocol == PROTOCOL_MULTIMODULE || protocol == PROTOCOL_FLYSKY_IBUS) {
+ else if (protocol == PROTOCOL_TELEMETRY_MULTIMODULE || protocol == PROTOCOL_TELEMETRY_FLYSKY_IBUS) {
// The DIY Multi module always speaks 100000 baud regardless of the telemetry protocol in use
telemetryPortInit(MULTIMODULE_BAUDRATE, TELEMETRY_SERIAL_8E2);
#if defined(LUA)
- outputTelemetryBufferSize = 0;
- outputTelemetryBufferTrigger = 0x7E;
+ outputTelemetryBuffer.size = 0;
+ outputTelemetryBuffer.trigger = 0x7E;
#endif
}
- else if (protocol == PROTOCOL_SPEKTRUM) {
+ else if (protocol == PROTOCOL_TELEMETRY_SPEKTRUM) {
// Spektrum's own small race RX (SPM4648) uses 125000 8N1, use the same since there is no real standard
telemetryPortInit(125000, TELEMETRY_SERIAL_DEFAULT);
}
#endif
#if defined(CROSSFIRE)
- else if (protocol == PROTOCOL_PULSES_CROSSFIRE) {
+ else if (protocol == PROTOCOL_TELEMETRY_CROSSFIRE) {
telemetryPortInit(CROSSFIRE_BAUDRATE, TELEMETRY_SERIAL_DEFAULT);
#if defined(LUA)
outputTelemetryBufferSize = 0;
@@ -254,17 +281,22 @@ void telemetryInit(uint8_t protocol)
#endif
#if defined(SERIAL2) || defined(PCBSKY9X)
- else if (protocol == PROTOCOL_FRSKY_D_SECONDARY) {
+ else if (protocol == PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY) {
telemetryPortInit(0, TELEMETRY_SERIAL_DEFAULT);
- serial2TelemetryInit(PROTOCOL_FRSKY_D_SECONDARY);
+ serial2TelemetryInit(PROTOCOL_TELEMETRY_FRSKY_D_SECONDARY);
}
#endif
+ else if (protocol == PROTOCOL_TELEMETRY_PXX2) {
+ telemetryPortInit(PXX2_ON_SPORT_BAUDRATE, TELEMETRY_SERIAL_WITHOUT_DMA);
+#if defined(LUA)
+ outputTelemetryBuffer.reset();
+#endif
+ }
else {
telemetryPortInit(FRSKY_SPORT_BAUDRATE, TELEMETRY_SERIAL_WITHOUT_DMA);
#if defined(LUA)
- outputTelemetryBufferSize = 0;
- outputTelemetryBufferTrigger = 0x7E;
+ outputTelemetryBuffer.reset();
#endif
}
@@ -299,9 +331,7 @@ void logTelemetryWriteByte(uint8_t data)
}
#endif
-uint8_t outputTelemetryBuffer[TELEMETRY_OUTPUT_FIFO_SIZE] __DMA;
-uint8_t outputTelemetryBufferSize = 0;
-uint8_t outputTelemetryBufferTrigger = 0;
+OutputTelemetryBuffer outputTelemetryBuffer __DMA;
#if defined(LUA)
Fifo * luaInputTelemetryFifo = NULL;
diff --git a/radio/src/telemetry/telemetry.h b/radio/src/telemetry/telemetry.h
index a35d6b3b0..bdab8d178 100644
--- a/radio/src/telemetry/telemetry.h
+++ b/radio/src/telemetry/telemetry.h
@@ -26,9 +26,7 @@
#include "frsky.h"
#endif
-#if defined(CROSSFIRE)
- #include "crossfire.h"
-#endif
+#include "crossfire.h"
#if defined(MULTIMODULE)
#include "spektrum.h"
#include "flysky_ibus.h"
@@ -36,6 +34,7 @@
#endif
extern uint8_t telemetryStreaming; // >0 (true) == data is streaming in. 0 = no data detected for some time
+extern uint8_t R9ModuleStreaming; // >0 (true) == R9 module is connected and sending data 0 = no data detected for some time
#if defined(WS_HOW_HIGH)
extern uint8_t wshhStreaming;
@@ -97,7 +96,6 @@ void delTelemetryIndex(uint8_t index);
int availableTelemetryIndex();
int lastUsedTelemetryIndex();
-int32_t getTelemetryValue(uint8_t index, uint8_t & prec);
int32_t convertTelemetryValue(int32_t value, uint8_t unit, uint8_t prec, uint8_t destUnit, uint8_t destPrec);
void frskySportSetDefault(int index, uint16_t id, uint8_t subId, uint8_t instance);
@@ -107,38 +105,45 @@ void frskyDSetDefault(int index, uint16_t id);
#define IS_SPEED_UNIT(unit) ((unit) >= UNIT_KTS && (unit) <= UNIT_MPH)
extern uint8_t telemetryProtocol;
-#define IS_FRSKY_D_PROTOCOL() (telemetryProtocol == PROTOCOL_FRSKY_D)
+
#if defined (MULTIMODULE)
#define IS_D16_MULTI() ((g_model.moduleData[EXTERNAL_MODULE].getMultiProtocol(false) == MM_RF_PROTO_FRSKY) && (g_model.moduleData[EXTERNAL_MODULE].subType == MM_RF_FRSKY_SUBTYPE_D16 || g_model.moduleData[EXTERNAL_MODULE].subType == MM_RF_FRSKY_SUBTYPE_D16_8CH))
-#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_MULTIMODULE && IS_D16_MULTI()))
+#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT || (telemetryProtocol == PROTOCOL_TELEMETRY_MULTIMODULE && IS_D16_MULTI()))
#else
-#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_FRSKY_SPORT)
+#define IS_FRSKY_SPORT_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_FRSKY_SPORT)
#endif
-#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_SPEKTRUM)
+#define IS_SPEKTRUM_PROTOCOL() (telemetryProtocol == PROTOCOL_TELEMETRY_SPEKTRUM)
inline uint8_t modelTelemetryProtocol()
{
#if defined(CROSSFIRE)
if (g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_CROSSFIRE) {
- return PROTOCOL_PULSES_CROSSFIRE;
+ return PROTOCOL_TELEMETRY_CROSSFIRE;
}
#endif
-
+
if (!IS_INTERNAL_MODULE_ENABLED() && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_PPM) {
return g_model.telemetryProtocol;
}
-
+
+ if (!IS_INTERNAL_MODULE_ENABLED() && isModulePXX2(EXTERNAL_MODULE)) {
+ return PROTOCOL_TELEMETRY_PXX2;
+ }
+
+ if (!IS_INTERNAL_MODULE_ENABLED() && isModulePXX(EXTERNAL_MODULE)) {
+ return PROTOCOL_TELEMETRY_FRSKY_SPORT;
+ }
#if defined(MULTIMODULE)
if (!IS_INTERNAL_MODULE_ENABLED() && g_model.moduleData[EXTERNAL_MODULE].type == MODULE_TYPE_MULTIMODULE) {
- return PROTOCOL_MULTIMODULE;
+ return PROTOCOL_TELEMETRY_MULTIMODULE;
}
#endif
// default choice
- return PROTOCOL_FRSKY_SPORT;
+ return PROTOCOL_TELEMETRY_FRSKY_SPORT;
}
- #include "telemetry_sensors.h"
+#include "telemetry_sensors.h"
#if defined(LOG_TELEMETRY) && !defined(SIMU)
void logTelemetryWriteStart();
@@ -150,20 +155,40 @@ void logTelemetryWriteByte(uint8_t data);
#define LOG_TELEMETRY_WRITE_BYTE(data)
#endif
-#define TELEMETRY_OUTPUT_FIFO_SIZE 16
-extern uint8_t outputTelemetryBuffer[TELEMETRY_OUTPUT_FIFO_SIZE] __DMA;
-extern uint8_t outputTelemetryBufferSize;
-extern uint8_t outputTelemetryBufferTrigger;
+#define TELEMETRY_OUTPUT_FIFO_SIZE 20
-inline void telemetryOutputPushByte(uint8_t byte)
-{
- outputTelemetryBuffer[outputTelemetryBufferSize++] = byte;
-}
+class OutputTelemetryBuffer {
+ public:
+ OutputTelemetryBuffer() {
+ reset();
+ }
-inline void telemetryOutputSetTrigger(uint8_t byte)
-{
- outputTelemetryBufferTrigger = byte;
-}
+ void push(uint8_t byte) {
+ data[size++] = byte;
+ }
+
+ void setTrigger(uint8_t byte) {
+ trigger = byte;
+ }
+
+ void setDestination(uint8_t module) {
+ destination = module;
+ }
+
+ void reset() {
+ size = 0;
+ trigger = 0x7E;
+ destination = 0xFF;
+ }
+
+ public:
+ uint8_t data[TELEMETRY_OUTPUT_FIFO_SIZE];
+ uint8_t size;
+ uint8_t trigger;
+ uint8_t destination;
+};
+
+extern OutputTelemetryBuffer outputTelemetryBuffer __DMA;
#if defined(LUA)
#define LUA_TELEMETRY_INPUT_FIFO_SIZE 256
@@ -176,5 +201,7 @@ extern Fifo * luaInputTelemetryFifo;
#define IS_TELEMETRY_INTERNAL_MODULE() (false)
#endif
-#endif // _TELEMETRY_H_
+void processPXX2Frame(uint8_t module, uint8_t *frame);
+void pushPXX2TelemetryPacket(uint8_t module, uint8_t rx_uid, SportTelemetryPacket * packet);
+#endif // _TELEMETRY_H_
diff --git a/radio/src/telemetry/telemetry_sensors.cpp b/radio/src/telemetry/telemetry_sensors.cpp
index 049f3742a..d7ff7e15e 100644
--- a/radio/src/telemetry/telemetry_sensors.cpp
+++ b/radio/src/telemetry/telemetry_sensors.cpp
@@ -33,7 +33,7 @@ bool isFaiForbidden(source_t idx)
switch (telemetryProtocol) {
- case PROTOCOL_FRSKY_SPORT:
+ case PROTOCOL_TELEMETRY_FRSKY_SPORT:
if (sensor->id == RSSI_ID) {
return false;
}
@@ -42,7 +42,7 @@ bool isFaiForbidden(source_t idx)
}
break;
- case PROTOCOL_FRSKY_D:
+ case PROTOCOL_TELEMETRY_FRSKY_D:
if (sensor->id == D_RSSI_ID) {
return false;
}
@@ -52,7 +52,7 @@ bool isFaiForbidden(source_t idx)
break;
#if defined(CROSSFIRE)
- case PROTOCOL_PULSES_CROSSFIRE:
+ case PROTOCOL_TELEMETRY_CROSSFIRE:
if (sensor->id == RX_RSSI1_INDEX) {
return false;
}
diff --git a/radio/src/thirdparty/CoOS/OsConfig.h b/radio/src/thirdparty/CoOS/OsConfig.h
index c56e47529..341f262d0 100644
--- a/radio/src/thirdparty/CoOS/OsConfig.h
+++ b/radio/src/thirdparty/CoOS/OsConfig.h
@@ -85,7 +85,11 @@ System frequency (Hz).
/*!<
systick frequency (Hz).
*/
+#if defined(STM32)
+#define CFG_SYSTICK_FREQ (1000)
+#else
#define CFG_SYSTICK_FREQ (500)
+#endif
/*!<
max systerm api call num in ISR.
diff --git a/radio/src/trainer_input.cpp b/radio/src/trainer_input.cpp
index 838c78297..a84ed0d6e 100644
--- a/radio/src/trainer_input.cpp
+++ b/radio/src/trainer_input.cpp
@@ -24,7 +24,7 @@ int16_t ppmInput[MAX_TRAINER_CHANNELS];
uint8_t ppmInputValidityTimer;
-#include "audio_arm.h"
+#include "audio.h"
void checkTrainerSignalWarning()
{
diff --git a/radio/src/translations.cpp b/radio/src/translations.cpp
index c804a3fb3..7dc5add48 100644
--- a/radio/src/translations.cpp
+++ b/radio/src/translations.cpp
@@ -88,10 +88,12 @@ const char STR_OPEN9X[] =
ISTR(VVARIOCENTER)
ISTR(COUNTRYCODES)
ISTR(USBMODES)
+ ISTR(JACKMODES)
ISTR(VFAILSAFE)
ISTR(VTRAINERMODES)
ISTR(TARANIS_PROTOCOLS)
ISTR(R9M_REGION)
+ ISTR(R9MFLEX_FREQ)
ISTR(R9M_FCC_POWER_VALUES)
ISTR(R9M_LBT_POWER_VALUES)
ISTR(TELEMETRY_PROTOCOLS)
@@ -113,7 +115,8 @@ const char STR_OPEN9X[] =
;
// The 0-terminated-strings
-const char STR_POPUPS[] = TR_POPUPS;
+const char STR_POPUPS_ENTER_EXIT[] = TR_POPUPS_ENTER_EXIT;
+const char STR_OK[] = TR_OK;
#if !defined(OFS_EXIT)
const char STR_EXIT[] = TR_EXIT;
#endif
@@ -144,6 +147,7 @@ const char STR_PPMFRAME[] = TR_PPMFRAME;
const char STR_REFRESHRATE[] = TR_REFRESHRATE;
const char SSTR_WARN_BATTVOLTAGE[] = STR_WARN_BATTVOLTAGE;
const char STR_MS[] = TR_MS;
+const char STR_FREQUENCY[] = TR_FREQUENCY;
const char STR_SWITCH[] = TR_SWITCH;
const char STR_TRIMS[] = TR_TRIMS;
const char STR_FADEIN[] = TR_FADEIN;
@@ -350,6 +354,8 @@ const char STR_MENUGLOBALVARS[] = TR_MENUGLOBALVARS;
const char STR_RECEIVER_NUM[] = TR_RECEIVER_NUM;
const char STR_RECEIVER[] = TR_RECEIVER;
const char STR_REBIND[] = TR_REBIND;
+const char STR_REG_OK[] = TR_REG_OK;
+const char STR_BIND_OK[] = TR_BIND_OK;
#endif
const char STR_SYNCMENU[] = TR_SYNCMENU;
@@ -359,8 +365,12 @@ const char STR_MODULE_TELEMETRY[] = TR_MODULE_TELEMETRY;
const char STR_MODULE_TELEM_ON[] = TR_MODULE_TELEM_ON;
const char STR_COUNTRYCODE[] = TR_COUNTRYCODE;
const char STR_USBMODE[] = TR_USBMODE;
+const char STR_JACKMODE[] = TR_JACKMODE;
const char STR_FAILSAFE[] = TR_FAILSAFE;
const char STR_FAILSAFESET[] = TR_FAILSAFESET;
+const char STR_REG_ID[] = TR_REG_ID;
+const char STR_OWNER_ID[] = TR_OWNER_ID;
+const char STR_PINMAPSET[] = TR_PINMAPSET;
const char STR_HOLD[] = TR_HOLD;
const char STR_NONE[] = TR_NONE;
const char STR_MENUSENSOR[] = TR_MENUSENSOR;
@@ -397,7 +407,6 @@ const char STR_WAV_VOLUME[] = INDENT TR_WAV_VOLUME;
const char STR_BG_VOLUME[] = INDENT TR_BG_VOLUME;
const char STR_PERSISTENT_MAH[] = TR_PERSISTENT_MAH;
-#if defined(NAVIGATION_MENUS)
const char STR_SELECT_MODEL[] = TR_SELECT_MODEL;
const char STR_CREATE_CATEGORY[] = TR_CREATE_CATEGORY;
const char STR_RENAME_CATEGORY[] = TR_RENAME_CATEGORY;
@@ -427,7 +436,6 @@ const char STR_USB_MASS_STORAGE[] = TR_USB_MASS_STORAGE;
const char STR_USB_SERIAL[] = TR_USB_SERIAL;
const char STR_SETUP_SCREENS[] = TR_SETUP_SCREENS;
const char STR_MONITOR_SCREENS[] = TR_MONITOR_SCREENS;
-#endif
#if defined(MULTIMODULE)
const char STR_MULTI_CUSTOM[] = TR_MULTI_CUSTOM;
@@ -454,7 +462,7 @@ const char STR_SUBTYPE[] = TR_SUBTYPE;
const char STR_RESET_BTN[] = TR_RESET_BTN;
const char STR_DEBUG[] = TR_DEBUG;
-const char STR_SWITCHES_BTN[] = TR_SWITCHES_BTN;
+const char STR_KEYS_BTN[] = TR_KEYS_BTN;
const char STR_ANALOGS_BTN[] = TR_ANALOGS_BTN;
const char STR_CALIB_BTN[] = TR_CALIB_BTN;
@@ -485,7 +493,6 @@ const char STR_NIGHTLY_NOTSAFE[] = TR_NIGHTLY_NOTSAFE;
const char STR_WRONG_SDCARDVERSION[] = TR_WRONG_SDCARDVERSION;
const char STR_WRONG_PCBREV[] = TR_WRONG_PCBREV;
const char STR_EMERGENCY_MODE[] = TR_EMERGENCY_MODE;
-const char STR_PCBREV_ERROR[] = TR_PCBREV_ERROR;
const char STR_NO_FAILSAFE[] = TR_NO_FAILSAFE;
const char STR_KEYSTUCK[] = TR_KEYSTUCK;
@@ -553,11 +560,9 @@ const char STR_FLASH_BOOTLOADER[] = TR_FLASH_BOOTLOADER;
const char STR_FLASH_INTERNAL_MODULE[] = TR_FLASH_INTERNAL_MODULE;
const char STR_FLASH_EXTERNAL_MODULE[] = TR_FLASH_EXTERNAL_MODULE;
const char STR_FIRMWARE_UPDATE_ERROR[] = TR_FIRMWARE_UPDATE_ERROR;
+const char STR_FIRMWARE_UPDATE_SUCCESS[] = TR_FIRMWARE_UPDATE_SUCCESS;
const char STR_FLASH_EXTERNAL_DEVICE[] = TR_FLASH_EXTERNAL_DEVICE;
-const char STR_WRITING[] = TR_WRITING;
const char STR_CONFIRM_FORMAT[] = TR_CONFIRM_FORMAT;
-const char STR_EEBACKUP[] = TR_EEBACKUP;
-const char STR_FACTORYRESET[] = TR_FACTORYRESET;
const char STR_CONFIRMRESET[] = TR_CONFIRMRESET;
const char STR_TOO_MANY_LUA_SCRIPTS[] = TR_TO_MANY_LUA_SCRIPTS;
const char STR_BLCOLOR[] = TR_BLCOLOR;
@@ -578,6 +583,9 @@ const char STR_BLCOLOR[] = TR_BLCOLOR;
const char STR_TRAINER[] = TR_TRAINER;
const char STR_MODULE_BIND[] = TR_MODULE_BIND;
+const char STR_TRANSFER_BUTTON[] = TR_TRANSFER_BUTTON;
+const char STR_REGISTER_BUTTON[] = TR_REGISTER_BUTTON;
+const char STR_RXADD_BUTTON[] = TR_RXADD_BUTTON;
const char STR_BINDING_1_8_TELEM_ON[] = TR_BINDING_CH1_8_TELEM_ON;
const char STR_BINDING_1_8_TELEM_OFF[] = TR_BINDING_CH1_8_TELEM_OFF;
const char STR_BINDING_9_16_TELEM_ON[] = TR_BINDING_CH9_16_TELEM_ON;
@@ -636,7 +644,6 @@ const char STR_BLCOLOR[] = TR_BLCOLOR;
const char STR_USER_INTERFACE[] = TR_USER_INTERFACE;
const char STR_THEME[] = TR_THEME;
const char STR_SETUP[] = TR_SETUP;
- const char STR_MAINVIEWX[] = TR_MAINVIEWX;
const char STR_LAYOUT[] = TR_LAYOUT;
const char STR_ADDMAINVIEW[] = TR_ADDMAINVIEW;
const char STR_BACKGROUND_COLOR[] = TR_BACKGROUND_COLOR;
@@ -647,6 +654,7 @@ const char STR_BLCOLOR[] = TR_BLCOLOR;
const char STR_BYTES[] = TR_BYTES;
const char STR_ANTENNAPROBLEM[] = TR_ANTENNAPROBLEM;
const char STR_MODULE[] = TR_MODULE;
+const char STR_RX_NAME[] = TR_RX_NAME;
const char STR_ENABLE_POPUP[] = TR_ENABLE_POPUP;
const char STR_DISABLE_POPUP[] = TR_DISABLE_POPUP;
const char STR_POPUP[] = TR_POPUP;
@@ -693,6 +701,7 @@ const char STR_BLCOLOR[] = TR_BLCOLOR;
const char STR_MENU_OTHER[] = TR_MENU_OTHER;
const char STR_MENU_INVERT[] = TR_MENU_INVERT;
const char STR_JITTER_FILTER[] = TR_JITTER_FILTER;
+ const char STR_BUTTON_SHARE[] = TR_BUTTON_SHARE;
#if MENUS_LOCK == 1
const char STR_UNLOCKED[] = TR_UNLOCKED;
@@ -701,6 +710,8 @@ const char STR_BLCOLOR[] = TR_BLCOLOR;
#if defined(PCBTARANIS) || defined(DSM2)
const char STR_MODULE_RANGE[] = TR_MODULE_RANGE;
+ const char STR_RECEIVER_OPTIONS[] = TR_RECEIVER_OPTIONS;
+ const char STR_DEL_BUTTON[] = TR_DEL_BUTTON;
#endif
#if defined(BLUETOOTH)
diff --git a/radio/src/translations.h b/radio/src/translations.h
index 3cfadc987..e214f5300 100644
--- a/radio/src/translations.h
+++ b/radio/src/translations.h
@@ -185,11 +185,13 @@ extern const char STR_OPEN9X[];
#define OFS_VVARIOCENTER (OFS_VBEEPCOUNTDOWN + sizeof(TR_VBEEPCOUNTDOWN))
#define OFS_COUNTRYCODES (OFS_VVARIOCENTER + sizeof(TR_VVARIOCENTER))
#define OFS_USBMODES (OFS_COUNTRYCODES + sizeof(TR_COUNTRYCODES))
- #define OFS_VFAILSAFE (OFS_USBMODES + sizeof(TR_USBMODES))
+ #define OFS_JACKMODES (OFS_USBMODES + sizeof(TR_USBMODES))
+ #define OFS_VFAILSAFE (OFS_JACKMODES + sizeof(TR_JACKMODES))
#define OFS_VTRAINERMODES (OFS_VFAILSAFE + sizeof(TR_VFAILSAFE))
#define OFS_TARANIS_PROTOCOLS (OFS_VTRAINERMODES + sizeof(TR_VTRAINERMODES))
- #define OFS_R9M_REGION (OFS_TARANIS_PROTOCOLS + sizeof(TR_TARANIS_PROTOCOLS))
- #define OFS_R9M_FCC_POWER_VALUES (OFS_R9M_REGION + sizeof(TR_R9M_REGION))
+ #define OFS_R9M_REGION (OFS_TARANIS_PROTOCOLS + sizeof(TR_TARANIS_PROTOCOLS))
+ #define OFS_R9MFLEX_FREQ (OFS_R9M_REGION + sizeof(TR_R9M_REGION))
+ #define OFS_R9M_FCC_POWER_VALUES (OFS_R9MFLEX_FREQ + sizeof(TR_R9MFLEX_FREQ))
#define OFS_R9M_LBT_POWER_VALUES (OFS_R9M_FCC_POWER_VALUES + sizeof(TR_R9M_FCC_POWER_VALUES))
#define OFS_TELEMETRY_PROTOCOLS (OFS_R9M_LBT_POWER_VALUES + sizeof(TR_R9M_LBT_POWER_VALUES))
#define OFS_XJT_PROTOCOLS (OFS_TELEMETRY_PROTOCOLS + sizeof(TR_TELEMETRY_PROTOCOLS))
@@ -290,11 +292,13 @@ extern const char STR_OPEN9X[];
#define STR_COUNTRYCODES (STR_OPEN9X + OFS_COUNTRYCODES)
#define STR_USBMODES (STR_OPEN9X + OFS_USBMODES)
+ #define STR_JACKMODES (STR_OPEN9X + OFS_JACKMODES)
#define STR_VFAILSAFE (STR_OPEN9X + OFS_VFAILSAFE)
#define STR_VTRAINERMODES (STR_OPEN9X + OFS_VTRAINERMODES)
#define STR_TARANIS_PROTOCOLS (STR_OPEN9X + OFS_TARANIS_PROTOCOLS)
- #define STR_R9M_REGION (STR_OPEN9X + OFS_R9M_REGION)
+ #define STR_R9M_REGION (STR_OPEN9X + OFS_R9M_REGION)
+ #define STR_R9MFLEX_FREQ (STR_OPEN9X + OFS_R9MFLEX_FREQ)
#define STR_R9M_FCC_POWER_VALUES (STR_OPEN9X + OFS_R9M_FCC_POWER_VALUES)
#define STR_R9M_LBT_POWER_VALUES (STR_OPEN9X + OFS_R9M_LBT_POWER_VALUES)
#define STR_TELEMETRY_PROTOCOLS (STR_OPEN9X + OFS_TELEMETRY_PROTOCOLS)
@@ -324,10 +328,11 @@ extern const char STR_BLUETOOTH_LOCAL_ADDR[];
// The 0-terminated-strings
#define NO_INDENT(x) (x)+LEN_INDENT
-extern const char STR_POPUPS[];
+extern const char STR_POPUPS_ENTER_EXIT[];
+extern const char STR_OK[];
#if defined(OFS_EXIT)
- #define STR_EXIT (STR_POPUPS + OFS_EXIT)
+ #define STR_EXIT (STR_POPUPS_ENTER_EXIT + OFS_EXIT)
#else
extern const char STR_EXIT[];
#endif
@@ -361,6 +366,7 @@ extern const char STR_PPMFRAME[];
extern const char STR_REFRESHRATE[];
extern const char SSTR_WARN_BATTVOLTAGE[];
extern const char STR_MS[];
+extern const char STR_FREQUENCY[];
extern const char STR_SWITCH[];
extern const char STR_TRIMS[];
extern const char STR_FADEIN[];
@@ -564,6 +570,8 @@ extern const char STR_SUBTYPE[];
extern const char STR_RECEIVER_NUM[];
extern const char STR_RECEIVER[];
extern const char STR_REBIND[];
+extern const char STR_REG_OK[];
+extern const char STR_BIND_OK[];
#endif
extern const char STR_SYNCMENU[];
@@ -573,12 +581,17 @@ extern const char STR_MODULE_TELEMETRY[];
extern const char STR_MODULE_TELEM_ON[];
extern const char STR_FAILSAFE[];
extern const char STR_FAILSAFESET[];
+extern const char STR_RECEIVER[];
+extern const char STR_REG_ID[];
+extern const char STR_OWNER_ID[];
+extern const char STR_PINMAPSET[];
extern const char STR_HOLD[];
extern const char STR_NONE[];
extern const char STR_MENUSENSOR[];
extern const char STR_SENSOR[];
extern const char STR_COUNTRYCODE[];
extern const char STR_USBMODE[];
+extern const char STR_JACKMODE[];
extern const char STR_DISABLE_INTERNAL[];
#if defined(TELEMETRY_FRSKY)
@@ -616,7 +629,6 @@ extern const char STR_PERSISTENT_MAH[];
#define LEN_CALIB_FIELDS PSIZE(TR_BATT_CALIB)
#endif
-#if defined(NAVIGATION_MENUS)
extern const char STR_SELECT_MODEL[];
extern const char STR_CREATE_CATEGORY[];
extern const char STR_RENAME_CATEGORY[];
@@ -646,11 +658,10 @@ extern const char STR_PERSISTENT_MAH[];
extern const char STR_USB_SERIAL[];
extern const char STR_SETUP_SCREENS[];
extern const char STR_MONITOR_SCREENS[];
-#endif
extern const char STR_RESET_BTN[];
extern const char STR_DEBUG[];
-extern const char STR_SWITCHES_BTN[];
+extern const char STR_KEYS_BTN[];
extern const char STR_ANALOGS_BTN[];
extern const char STR_CALIB_BTN[];
@@ -682,7 +693,6 @@ extern const char STR_NIGHTLY_NOTSAFE[];
extern const char STR_WRONG_SDCARDVERSION[];
extern const char STR_WRONG_PCBREV[];
extern const char STR_EMERGENCY_MODE[];
-extern const char STR_PCBREV_ERROR[];
extern const char STR_NO_FAILSAFE[];
extern const char STR_KEYSTUCK[];
@@ -751,71 +761,72 @@ extern const char STR_FLASH_EXTERNAL_DEVICE[];
extern const char STR_FLASH_INTERNAL_MODULE[];
extern const char STR_FLASH_EXTERNAL_MODULE[];
extern const char STR_FIRMWARE_UPDATE_ERROR[];
-extern const char STR_WRITING[];
+extern const char STR_FIRMWARE_UPDATE_SUCCESS[];
extern const char STR_CONFIRM_FORMAT[];
-extern const char STR_EEBACKUP[];
-extern const char STR_FACTORYRESET[];
extern const char STR_CONFIRMRESET[];
extern const char STR_TOO_MANY_LUA_SCRIPTS[];
extern const char STR_BLCOLOR[];
- struct LanguagePack {
- const char * id;
- const char * name;
- void (*playNumber)(getvalue_t number, uint8_t unit, uint8_t flags, uint8_t id);
- void (*playDuration)(int seconds, uint8_t flags, uint8_t id);
- };
+struct LanguagePack {
+ const char * id;
+ const char * name;
+ void (*playNumber)(getvalue_t number, uint8_t unit, uint8_t flags, uint8_t id);
+ void (*playDuration)(int seconds, uint8_t flags, uint8_t id);
+};
- extern const LanguagePack * currentLanguagePack;
- extern uint8_t currentLanguagePackIdx;
+extern const LanguagePack * currentLanguagePack;
+extern uint8_t currentLanguagePackIdx;
+
+extern const LanguagePack czLanguagePack;
+extern const LanguagePack deLanguagePack;
+extern const LanguagePack enLanguagePack;
+extern const LanguagePack esLanguagePack;
+extern const LanguagePack frLanguagePack;
+extern const LanguagePack huLanguagePack;
+extern const LanguagePack itLanguagePack;
+extern const LanguagePack nlLanguagePack;
+extern const LanguagePack plLanguagePack;
+extern const LanguagePack ptLanguagePack;
+extern const LanguagePack ruLanguagePack;
+extern const LanguagePack seLanguagePack;
+extern const LanguagePack skLanguagePack;
+extern const LanguagePack * const languagePacks[];
+
+#if defined(LANGUAGE_PACKS_DEFINITION)
+const LanguagePack * const languagePacks[] = {
+ // alphabetical order
+ &czLanguagePack,
+ &deLanguagePack,
+ &enLanguagePack,
+ &esLanguagePack,
+ &frLanguagePack,
+ &huLanguagePack,
+ &itLanguagePack,
+ &nlLanguagePack,
+ &plLanguagePack,
+ &ptLanguagePack,
+ &ruLanguagePack,
+ &seLanguagePack,
+ &skLanguagePack,
+ NULL
+};
+#endif
- extern const LanguagePack czLanguagePack;
- extern const LanguagePack deLanguagePack;
- extern const LanguagePack enLanguagePack;
- extern const LanguagePack esLanguagePack;
- extern const LanguagePack frLanguagePack;
- extern const LanguagePack huLanguagePack;
- extern const LanguagePack itLanguagePack;
- extern const LanguagePack nlLanguagePack;
- extern const LanguagePack plLanguagePack;
- extern const LanguagePack ptLanguagePack;
- extern const LanguagePack ruLanguagePack;
- extern const LanguagePack seLanguagePack;
- extern const LanguagePack skLanguagePack;
- extern const LanguagePack * const languagePacks[];
- #if defined(LANGUAGE_PACKS_DEFINITION)
- const LanguagePack * const languagePacks[] = {
- // alphabetical order
- &czLanguagePack,
- &deLanguagePack,
- &enLanguagePack,
- &esLanguagePack,
- &frLanguagePack,
- &huLanguagePack,
- &itLanguagePack,
- &nlLanguagePack,
- &plLanguagePack,
- &ptLanguagePack,
- &ruLanguagePack,
- &seLanguagePack,
- &skLanguagePack,
- NULL
- };
- #endif
#if defined(SIMU)
#define LANGUAGE_PACK_DECLARE(lng, name) const LanguagePack lng ## LanguagePack = { #lng, name, lng ## _ ## playNumber, lng ## _ ## playDuration }
#else
#define LANGUAGE_PACK_DECLARE(lng, name) extern const LanguagePack lng ## LanguagePack = { #lng, name, lng ## _ ## playNumber, lng ## _ ## playDuration }
#endif
- #define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) LANGUAGE_PACK_DECLARE(lng, name); const LanguagePack * currentLanguagePack = & lng ## LanguagePack; uint8_t currentLanguagePackIdx
- inline PLAY_FUNCTION(playNumber, getvalue_t number, uint8_t unit, uint8_t flags) { currentLanguagePack->playNumber(number, unit, flags, id); }
- inline PLAY_FUNCTION(playDuration, int seconds, uint8_t flags) { currentLanguagePack->playDuration(seconds, flags, id); }
- extern const char STR_MODELNAME[];
- extern const char STR_PHASENAME[];
- extern const char STR_MIXNAME[];
- extern const char STR_INPUTNAME[];
- extern const char STR_EXPONAME[];
+#define LANGUAGE_PACK_DECLARE_DEFAULT(lng, name) LANGUAGE_PACK_DECLARE(lng, name); const LanguagePack * currentLanguagePack = & lng ## LanguagePack; uint8_t currentLanguagePackIdx
+inline PLAY_FUNCTION(playNumber, getvalue_t number, uint8_t unit, uint8_t flags) { currentLanguagePack->playNumber(number, unit, flags, id); }
+inline PLAY_FUNCTION(playDuration, int seconds, uint8_t flags) { currentLanguagePack->playDuration(seconds, flags, id); }
+
+extern const char STR_MODELNAME[];
+extern const char STR_PHASENAME[];
+extern const char STR_MIXNAME[];
+extern const char STR_INPUTNAME[];
+extern const char STR_EXPONAME[];
#if defined(COLORLCD)
#define TR_PHASES_HEADERS { TR_PHASES_HEADERS_NAME, TR_PHASES_HEADERS_SW, TR_PHASES_HEADERS_RUD_TRIM, TR_PHASES_HEADERS_ELE_TRIM, TR_PHASES_HEADERS_THT_TRIM, TR_PHASES_HEADERS_AIL_TRIM, TR_PHASES_HEADERS_CH5_TRIM, TR_PHASES_HEADERS_CH6_TRIM, TR_PHASES_HEADERS_FAD_IN, TR_PHASES_HEADERS_FAD_OUT }
@@ -836,123 +847,127 @@ extern const char STR_BLCOLOR[];
#endif
extern const char STR_TRAINER[];
- extern const char STR_MODULE_BIND[];
- extern const char STR_BINDING_1_8_TELEM_ON[];
- extern const char STR_BINDING_1_8_TELEM_OFF[];
- extern const char STR_BINDING_9_16_TELEM_ON[];
- extern const char STR_BINDING_9_16_TELEM_OFF[];
- extern const char STR_CHANNELRANGE[];
- extern const char STR_ANTENNASELECTION[];
- extern const char STR_ANTENNACONFIRM1[];
- extern const char STR_ANTENNACONFIRM2[];
- extern const char STR_R9MFLEXWARN1[];
- extern const char STR_R9MFLEXWARN2[];
- extern const char STR_SET[];
- extern const char STR_PREFLIGHT[];
- extern const char STR_CHECKLIST[];
- extern const char STR_VIEW_NOTES[];
- extern const char STR_MODEL_SELECT[];
- extern const char STR_RESET_SUBMENU[];
- extern const char STR_LOWALARM[];
- extern const char STR_CRITICALALARM[];
- extern const char STR_RSSIALARM_WARN[];
- extern const char STR_NO_RSSIALARM[];
- extern const char STR_DISABLE_ALARM[];
- extern const char STR_TELEMETRY_TYPE[];
- extern const char STR_TELEMETRY_SENSORS[];
- extern const char STR_VALUE[];
- extern const char STR_TOPLCDTIMER[];
- extern const char STR_UNIT[] ;
- extern const char STR_TELEMETRY_NEWSENSOR[];
- extern const char STR_ID[];
- extern const char STR_PRECISION[];
- extern const char STR_RATIO[];
- extern const char STR_FORMULA[];
- extern const char STR_CELLINDEX[];
- extern const char STR_LOGS[];
- extern const char STR_OPTIONS[];
- extern const char STR_ALTSENSOR[];
- extern const char STR_CELLSENSOR[];
- extern const char STR_GPSSENSOR[];
- extern const char STR_CURRENTSENSOR[];
- extern const char STR_AUTOOFFSET[];
- extern const char STR_ONLYPOSITIVE[];
- extern const char STR_FILTER[];
- extern const char STR_TELEMETRYFULL[];
- extern const char STR_SERVOS_OK[];
- extern const char STR_SERVOS_KO[];
- extern const char STR_INVERTED_SERIAL[];
- extern const char STR_IGNORE_INSTANCE[];
- extern const char STR_DISCOVER_SENSORS[];
- extern const char STR_STOP_DISCOVER_SENSORS[];
- extern const char STR_DELETE_ALL_SENSORS[];
- extern const char STR_CONFIRMDELETE[];
- extern const char STR_SELECT_WIDGET[];
- extern const char STR_REMOVE_WIDGET[];
- extern const char STR_WIDGET_SETTINGS[];
- extern const char STR_REMOVE_SCREEN[];
- extern const char STR_SETUP_WIDGETS[];
- extern const char STR_USER_INTERFACE[];
- extern const char STR_THEME[];
- extern const char STR_SETUP[];
- extern const char STR_MAINVIEWX[];
- extern const char STR_LAYOUT[];
- extern const char STR_ADDMAINVIEW[];
- extern const char STR_BACKGROUND_COLOR[];
- extern const char STR_MAIN_COLOR[];
- extern const char STR_TEXT_VIEWER[];
- extern const char STR_MULTI_RFPOWER[];
+extern const char STR_MODULE_BIND[];
+extern const char STR_TRANSFER_BUTTON[];
+extern const char STR_REGISTER_BUTTON[];
+extern const char STR_RXADD_BUTTON[];
+extern const char STR_BINDING_1_8_TELEM_ON[];
+extern const char STR_BINDING_1_8_TELEM_OFF[];
+extern const char STR_BINDING_9_16_TELEM_ON[];
+extern const char STR_BINDING_9_16_TELEM_OFF[];
+extern const char STR_CHANNELRANGE[];
+extern const char STR_ANTENNASELECTION[];
+extern const char STR_ANTENNACONFIRM1[];
+extern const char STR_ANTENNACONFIRM2[];
+extern const char STR_R9MFLEXWARN1[];
+extern const char STR_R9MFLEXWARN2[];
+extern const char STR_SET[];
+extern const char STR_PREFLIGHT[];
+extern const char STR_CHECKLIST[];
+extern const char STR_VIEW_NOTES[];
+extern const char STR_MODEL_SELECT[];
+extern const char STR_RESET_SUBMENU[];
+extern const char STR_LOWALARM[];
+extern const char STR_CRITICALALARM[];
+extern const char STR_RSSIALARM_WARN[];
+extern const char STR_NO_RSSIALARM[];
+extern const char STR_DISABLE_ALARM[];
+extern const char STR_TELEMETRY_TYPE[];
+extern const char STR_TELEMETRY_SENSORS[];
+extern const char STR_VALUE[];
+extern const char STR_TOPLCDTIMER[];
+extern const char STR_UNIT[] ;
+extern const char STR_TELEMETRY_NEWSENSOR[];
+extern const char STR_ID[];
+extern const char STR_PRECISION[];
+extern const char STR_RATIO[];
+extern const char STR_FORMULA[];
+extern const char STR_CELLINDEX[];
+extern const char STR_LOGS[];
+extern const char STR_OPTIONS[];
+extern const char STR_ALTSENSOR[];
+extern const char STR_CELLSENSOR[];
+extern const char STR_GPSSENSOR[];
+extern const char STR_CURRENTSENSOR[];
+extern const char STR_AUTOOFFSET[];
+extern const char STR_ONLYPOSITIVE[];
+extern const char STR_FILTER[];
+extern const char STR_TELEMETRYFULL[];
+extern const char STR_SERVOS_OK[];
+extern const char STR_SERVOS_KO[];
+extern const char STR_INVERTED_SERIAL[];
+extern const char STR_IGNORE_INSTANCE[];
+extern const char STR_DISCOVER_SENSORS[];
+extern const char STR_STOP_DISCOVER_SENSORS[];
+extern const char STR_DELETE_ALL_SENSORS[];
+extern const char STR_CONFIRMDELETE[];
+extern const char STR_SELECT_WIDGET[];
+extern const char STR_REMOVE_WIDGET[];
+extern const char STR_WIDGET_SETTINGS[];
+extern const char STR_REMOVE_SCREEN[];
+extern const char STR_SETUP_WIDGETS[];
+extern const char STR_USER_INTERFACE[];
+extern const char STR_THEME[];
+extern const char STR_SETUP[];
+extern const char STR_LAYOUT[];
+extern const char STR_ADDMAINVIEW[];
+extern const char STR_BACKGROUND_COLOR[];
+extern const char STR_MAIN_COLOR[];
+extern const char STR_TEXT_VIEWER[];
+extern const char STR_MULTI_RFPOWER[];
- extern const char STR_BYTES[];
- extern const char STR_ANTENNAPROBLEM[];
- extern const char STR_MODULE[];
- extern const char STR_ENABLE_POPUP[];
- extern const char STR_DISABLE_POPUP[];
- extern const char STR_POPUP[];
- extern const char STR_MIN[];
- extern const char STR_MAX[];
- extern const char STR_CURVE_PRESET[];
- extern const char STR_PRESET[];
- extern const char STR_MIRROR[];
- extern const char STR_CLEAR[];
- extern const char STR_RESET[];
- extern const char STR_COUNT[];
- extern const char STR_PT[];
- extern const char STR_PTS[];
- extern const char STR_SMOOTH[];
- extern const char STR_COPY_STICKS_TO_OFS[];
- extern const char STR_COPY_TRIMS_TO_OFS[];
- extern const char STR_INCDEC[];
- extern const char STR_GLOBALVAR[];
- extern const char STR_MIXSOURCE[];
- extern const char STR_CONSTANT[];
- extern const char STR_TOP_BAR[];
- extern const char STR_ALTITUDE[];
- extern const char STR_SCALE[];
- extern const char STR_VIEW_CHANNELS[];
- extern const char STR_POTWARNING[];
- extern const char STR_UART3MODE[];
- extern const char STR_THROTTLE_LABEL[];
- extern const char STR_SCRIPT[];
- extern const char STR_INPUTS[];
- extern const char STR_OUTPUTS[];
- extern const char STR_MENU_INPUTS[];
- extern const char STR_MENU_LUA[];
- extern const char STR_MENU_STICKS[];
- extern const char STR_MENU_POTS[];
- extern const char STR_MENU_MAX[];
- extern const char STR_MENU_HELI[];
- extern const char STR_MENU_TRIMS[];
- extern const char STR_MENU_SWITCHES[];
- extern const char STR_MENU_LOGICAL_SWITCHES[];
- extern const char STR_MENU_TRAINER[];
- extern const char STR_MENU_CHANNELS[];
- extern const char STR_MENU_GVARS[];
- extern const char STR_MENU_TELEMETRY[];
- extern const char STR_MENU_DISPLAY[];
- extern const char STR_MENU_OTHER[];
- extern const char STR_MENU_INVERT[];
- extern const char STR_JITTER_FILTER[];
+extern const char STR_BYTES[];
+extern const char STR_ANTENNAPROBLEM[];
+extern const char STR_MODULE[];
+extern const char STR_RX_NAME[];
+extern const char STR_ENABLE_POPUP[];
+extern const char STR_DISABLE_POPUP[];
+extern const char STR_POPUP[];
+extern const char STR_MIN[];
+extern const char STR_MAX[];
+extern const char STR_CURVE_PRESET[];
+extern const char STR_PRESET[];
+extern const char STR_MIRROR[];
+extern const char STR_CLEAR[];
+extern const char STR_RESET[];
+extern const char STR_COUNT[];
+extern const char STR_PT[];
+extern const char STR_PTS[];
+extern const char STR_SMOOTH[];
+extern const char STR_COPY_STICKS_TO_OFS[];
+extern const char STR_COPY_TRIMS_TO_OFS[];
+extern const char STR_INCDEC[];
+extern const char STR_GLOBALVAR[];
+extern const char STR_MIXSOURCE[];
+extern const char STR_CONSTANT[];
+extern const char STR_TOP_BAR[];
+extern const char STR_ALTITUDE[];
+extern const char STR_SCALE[];
+extern const char STR_VIEW_CHANNELS[];
+extern const char STR_POTWARNING[];
+extern const char STR_UART3MODE[];
+extern const char STR_THROTTLE_LABEL[];
+extern const char STR_SCRIPT[];
+extern const char STR_INPUTS[];
+extern const char STR_OUTPUTS[];
+extern const char STR_MENU_INPUTS[];
+extern const char STR_MENU_LUA[];
+extern const char STR_MENU_STICKS[];
+extern const char STR_MENU_POTS[];
+extern const char STR_MENU_MAX[];
+extern const char STR_MENU_HELI[];
+extern const char STR_MENU_TRIMS[];
+extern const char STR_MENU_SWITCHES[];
+extern const char STR_MENU_LOGICAL_SWITCHES[];
+extern const char STR_MENU_TRAINER[];
+extern const char STR_MENU_CHANNELS[];
+extern const char STR_MENU_GVARS[];
+extern const char STR_MENU_TELEMETRY[];
+extern const char STR_MENU_DISPLAY[];
+extern const char STR_MENU_OTHER[];
+extern const char STR_MENU_INVERT[];
+extern const char STR_JITTER_FILTER[];
+extern const char STR_BUTTON_SHARE[];
#if MENUS_LOCK == 1
extern const char STR_UNLOCKED[];
@@ -960,57 +975,55 @@ extern const char STR_BLCOLOR[];
#endif
#if defined(PCBTARANIS) || defined(DSM2)
- extern const char STR_MODULE_RANGE[];
+extern const char STR_MODULE_RANGE[];
+extern const char STR_RECEIVER_OPTIONS[];
+extern const char STR_DEL_BUTTON[];
#endif
+extern const char STR_ABOUTUS[];
+extern const char STR_ABOUT_OPENTX_1[];
+extern const char STR_ABOUT_OPENTX_2[];
+extern const char STR_ABOUT_OPENTX_3[];
+extern const char STR_ABOUT_OPENTX_4[];
+extern const char STR_ABOUT_OPENTX_5[];
- extern const char STR_ABOUTUS[];
- extern const char STR_ABOUT_OPENTX_1[];
- extern const char STR_ABOUT_OPENTX_2[];
- extern const char STR_ABOUT_OPENTX_3[];
- extern const char STR_ABOUT_OPENTX_4[];
- extern const char STR_ABOUT_OPENTX_5[];
+extern const char STR_ABOUT_BERTRAND_1[];
+extern const char STR_ABOUT_BERTRAND_2[];
+extern const char STR_ABOUT_BERTRAND_3[];
- extern const char STR_ABOUT_BERTRAND_1[];
- extern const char STR_ABOUT_BERTRAND_2[];
- extern const char STR_ABOUT_BERTRAND_3[];
+extern const char STR_ABOUT_MIKE_1[];
+extern const char STR_ABOUT_MIKE_2[];
+extern const char STR_ABOUT_MIKE_3[];
+extern const char STR_ABOUT_MIKE_4[];
- extern const char STR_ABOUT_MIKE_1[];
- extern const char STR_ABOUT_MIKE_2[];
- extern const char STR_ABOUT_MIKE_3[];
- extern const char STR_ABOUT_MIKE_4[];
+extern const char STR_ABOUT_ROMOLO_1[];
+extern const char STR_ABOUT_ROMOLO_2[];
+extern const char STR_ABOUT_ROMOLO_3[];
- extern const char STR_ABOUT_ROMOLO_1[];
- extern const char STR_ABOUT_ROMOLO_2[];
- extern const char STR_ABOUT_ROMOLO_3[];
+extern const char STR_ABOUT_ANDRE_1[];
+extern const char STR_ABOUT_ANDRE_2[];
+extern const char STR_ABOUT_ANDRE_3[];
- extern const char STR_ABOUT_ANDRE_1[];
- extern const char STR_ABOUT_ANDRE_2[];
- extern const char STR_ABOUT_ANDRE_3[];
+extern const char STR_ABOUT_ROB_1[];
+extern const char STR_ABOUT_ROB_2[];
- extern const char STR_ABOUT_ROB_1[];
- extern const char STR_ABOUT_ROB_2[];
+extern const char STR_ABOUT_MARTIN_1[];
+extern const char STR_ABOUT_MARTIN_2[];
- extern const char STR_ABOUT_MARTIN_1[];
- extern const char STR_ABOUT_MARTIN_2[];
+extern const char STR_ABOUT_KJELL_1[];
+extern const char STR_ABOUT_KJELL_2[];
+extern const char STR_ABOUT_KJELL_3[];
+extern const char STR_ABOUT_KJELL_4[];
- extern const char STR_ABOUT_KJELL_1[];
- extern const char STR_ABOUT_KJELL_2[];
- extern const char STR_ABOUT_KJELL_3[];
- extern const char STR_ABOUT_KJELL_4[];
+extern const char STR_ABOUT_HARDWARE_1[];
+extern const char STR_ABOUT_HARDWARE_2[];
+extern const char STR_ABOUT_HARDWARE_3[];
- extern const char STR_ABOUT_HARDWARE_1[];
- extern const char STR_ABOUT_HARDWARE_2[];
- extern const char STR_ABOUT_HARDWARE_3[];
+extern const char STR_ABOUT_PARENTS_1[];
+extern const char STR_ABOUT_PARENTS_2[];
+extern const char STR_ABOUT_PARENTS_3[];
+extern const char STR_ABOUT_PARENTS_4[];
- extern const char STR_ABOUT_PARENTS_1[];
- extern const char STR_ABOUT_PARENTS_2[];
- extern const char STR_ABOUT_PARENTS_3[];
- extern const char STR_ABOUT_PARENTS_4[];
-
-#define CHR_SHORT TR_CHR_SHORT
-#define CHR_LONG TR_CHR_LONG
-#define CHR_TOGGLE TR_CHR_TOGGLE
#define CHR_HOUR TR_CHR_HOUR
#define CHR_INPUT TR_CHR_INPUT
diff --git a/radio/src/translations/cz.h.txt b/radio/src/translations/cz.h.txt
index e98794833..e6b95aada 100644
--- a/radio/src/translations/cz.h.txt
+++ b/radio/src/translations/cz.h.txt
@@ -99,8 +99,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "Vyp\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Popup\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "Vyp\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 FrSky D\0 FrSky D (kabel)Spektrum\0 "
@@ -149,7 +152,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -157,21 +160,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POZ""NEG"
@@ -415,12 +408,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -537,9 +536,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
+ #define TR_POPUPS_ENTER_EXIT TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -573,6 +573,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Spínač"
#define TR_TRIMS "Trimy"
#define TR_FADEIN "Přechod Zap"
@@ -778,6 +779,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING TR("Bind...","Binding")
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -915,18 +918,23 @@
#define TR_FLASH_INTERNAL_MODULE TR("Flash vnitř. modulu", "Flash vnitřního modulu")
#define TR_FLASH_EXTERNAL_MODULE TR("Flash ext. modulu", "Flash externího zařízení")
#define TR_FIRMWARE_UPDATE_ERROR TR("Chyba zápisu FW", "Chyba zápisu firmware")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
#define TR_WRITING TR3("\14Zapisuji..", "\032Zapisuji..", "Zapisuji..")
#define TR_CONFIRM_FORMAT "Provést Formát?"
#define TR_INTERNALRF "Vnitřní RF modul"
#define TR_EXTERNALRF "Externí RF modul"
#define TR_FAILSAFE TR("Failsafe", "Mód Failsafe")
#define TR_FAILSAFESET "NASTAVENÍ FAILSAFE"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENZOR"
#define TR_SENSOR "SENZOR"
#define TR_COUNTRYCODE "Kód regionu"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Jazyk hlasu"
#define TR_UNITSSYSTEM "Jednotky"
#define TR_EDIT "Upravit"
@@ -956,10 +964,16 @@
#define TR_BUZZER INDENT"Pípák"
#define TR_BYTES "[B]"
#define TR_MODULE_BIND BUTTON(TR("Bnd", "Bind"))
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE BUTTON(TR("Rng", "Range"))
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN BUTTON("Reset")
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET BUTTON("Volby")
@@ -967,6 +981,7 @@
#define TR_ANTENNAPROBLEM CENTER "Problém s TX anténou!"
#define TR_MODELIDUSED TR("ID již použito","ID modelu je již použito")
#define TR_MODULE INDENT "Modul"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Typ", "Typ telemetrie")
#define TR_TELEMETRY_SENSORS "Senzory"
#define TR_VALUE "Hodnota"
@@ -1014,16 +1029,14 @@
#define TR_INPUTS "Vstupy"
#define TR_OUTPUTS "Výstupy"
#if defined(COLORLCD)
-#define TR_EEBACKUP "Záloha EEPROM"
-#define TR_FACTORYRESET "Factory reset"
+#define STR_EEBACKUP "Záloha EEPROM"
+#define STR_FACTORYRESET "Factory reset"
#else
-#define TR_EEBACKUP TR("[dlouze ENTER]: Záloha", "\010[dlouze ENTER] zálohuje EEPROM")
-#define TR_FACTORYRESET TR("[dlouze MENU]: Fact.reset", "\012[dlouze MENU]: Factory reset")
+#define STR_EEBACKUP TR("Záloha", "Zálohuje EEPROM")
+#define STR_FACTORYRESET TR("Fact.reset", "Factory reset")
#endif
-#define TR_CONFIRMRESET "Smazat modely a nastavení?"
-#define TR_TO_MANY_LUA_SCRIPTS "Příliš mnoho skriptů!"
-
-
+#define STR_CONFIRMRESET "Smazat modely a nastavení?"
+#define STR_TO_MANY_LUA_SCRIPTS "Příliš mnoho skriptů!"
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Název"
@@ -1196,6 +1209,7 @@
#define TR_JITTER_FILTER "ADC Filtr"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/de.h.txt b/radio/src/translations/de.h.txt
index 52dce402d..f0b7ba845 100644
--- a/radio/src/translations/de.h.txt
+++ b/radio/src/translations/de.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Fragen""Joyst\0""SDCard""Serial", "Fragen\0 ""Joystick""Speicher""Seriell\0")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "AUS\0""PPM\0""XJT\0""DSM?""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Popup\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "AUS\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (Kabel)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -152,7 +155,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -160,21 +163,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -430,12 +423,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -543,9 +542,10 @@
#define TR_EXIT "[EXIT]"
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -578,6 +578,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH TR("Schalt.", "Schalter")
#define TR_TRIMS "Trims"
#define TR_FADEIN "Langs. Ein"
@@ -783,6 +784,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -920,18 +923,23 @@
#define TR_FLASH_INTERNAL_MODULE TR("Flash int. XJT","Flash internes XJT-Modul")
#define TR_FLASH_EXTERNAL_MODULE TR("Flash ext. mod","Flash extern module")
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
-#define TR_WRITING "\032Writing..." //
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
+#define STR_WRITING "Writing..."
#define TR_CONFIRM_FORMAT "Formatieren bestätigen?"
#define TR_INTERNALRF "Internes HF-Modul"
#define TR_EXTERNALRF "Externes HF-Modul"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe Mode")
#define TR_FAILSAFESET "Failsafe setzen"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Landescode"
#define TR_USBMODE "USB Modus"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Sprach-Ansagen"
#define TR_UNITSSYSTEM "Einheiten"
#define TR_EDIT "Zeile Editieren"
@@ -961,10 +969,16 @@
#define TR_BUZZER INDENT "Summer"
#define TR_BYTES "Bytes"
#define TR_MODULE_BIND BUTTON(TR("Bnd","Bind")) //9XR-Pro
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE BUTTON(TR("Rng", "Range")) //9XR-Pro
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN BUTTON("Reset")
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET BUTTON("Set")
@@ -972,6 +986,7 @@
#define TR_ANTENNAPROBLEM CENTER "TX-Antennenproblem!"
#define TR_MODELIDUSED TR("ID schon benutzt", "Modell-ID schon benutzt")
#define TR_MODULE INDENT "Modul-Typ"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Typ", "Telemetrietyp")
#define TR_TELEMETRY_SENSORS "Sensoren"
#define TR_VALUE "Wert"
@@ -1018,8 +1033,8 @@
#define TR_SCRIPT "Lua-Skript"
#define TR_INPUTS "Eingaben"
#define TR_OUTPUTS "Ausgaben"
-#define TR_EEBACKUP TR("[ENTER Long] EEPROM->SD"," [ENTER Long] Backup EEPROM->SD-Karte")
-#define TR_FACTORYRESET TR("[MENU Long] Werksreset"," [MENU Long] Auf Werkseinstellungen")
+#define STR_EEBACKUP TR("EEPROM->SD", "Backup EEPROM->SD-Karte")
+#define STR_FACTORYRESET TR("Werksreset", "Auf Werkseinstellungen")
#define TR_CONFIRMRESET TR("Alles löschen? ","ALLE Modelle+Einst. löschen?")
#define TR_TO_MANY_LUA_SCRIPTS "Zu viele Lua-Skripte!"
@@ -1194,6 +1209,7 @@
#define TR_JITTER_FILTER "ADC Filter"
// ----------------------------------------------------------------
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/en.h.txt b/radio/src/translations/en.h.txt
index f04ada9cd..a5847f726 100644
--- a/radio/src/translations/en.h.txt
+++ b/radio/src/translations/en.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -151,7 +154,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -159,22 +162,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
-
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -420,12 +412,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -537,14 +535,17 @@
#if defined(PCBHORUS)
#define TR_EXIT "[RTN]"
+ #define TR_OK TR_ENTER
#else
#define TR_EXIT "[EXIT]"
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
+ #define TR_POPUPS_ENTER_EXIT TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
+
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -577,6 +578,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Switch"
#define TR_TRIMS "Trims"
#define TR_FADEIN "Fade in"
@@ -782,6 +784,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING TR("Bind...","Binding")
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -803,7 +807,7 @@
#define TR_POWEROFF "\027Power OFF..."
#define TR_SHUTDOWN "SHUTTING DOWN"
#define TR_SAVEMODEL "Saving model settings"
-#define TR_BATT_CALIB TR("Battery calib", "Battery calibration")
+#define TR_BATT_CALIB TR("Batt. calib", "Battery calibration")
#define TR_CURRENT_CALIB "Current calib"
#define TR_VOLTAGE TR(INDENT "Voltage", INDENT "Voltage source")
#define TR_CURRENT TR(INDENT "Current", INDENT "Current source")
@@ -919,18 +923,23 @@
#define TR_FLASH_INTERNAL_MODULE TR("Flash int. module", "Flash internal module")
#define TR_FLASH_EXTERNAL_MODULE TR("Flash ext. module", "Flash external module")
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update error", "Firmware update error")
-#define TR_WRITING TR3("\14Writing...", "\032Writing...", "Writing...")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
+#define STR_WRITING "Writing..."
#define TR_CONFIRM_FORMAT "Confirm Format?"
#define TR_INTERNALRF "Internal RF"
#define TR_EXTERNALRF "External RF"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe mode")
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Country code"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Voice language"
#define TR_UNITSSYSTEM "Units"
#define TR_EDIT "Edit"
@@ -960,11 +969,17 @@
#define TR_BUZZER INDENT "Buzzer"
#define TR_BYTES "bytes"
#define TR_MODULE_BIND BUTTON(TR("Bnd", "Bind"))
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON BUTTON("Add")
#define TR_MODULE_RANGE BUTTON(TR("Rng", "Range"))
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN BUTTON("Reset")
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
-#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_KEYS_BTN BUTTON(TR("Keys", "Switches"))
+#define TR_ANALOGS_BTN BUTTON(TR("Anas", "Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET BUTTON("Set")
#define TR_TRAINER "Trainer"
@@ -975,6 +990,7 @@
#define TR_MODELIDUSED TR("ID used in:","Receiver ID used in:")
#endif
#define TR_MODULE INDENT "Module"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_VALUE "Value"
@@ -1021,20 +1037,11 @@
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
-#if defined(COLORLCD)
-#define TR_EEBACKUP "EEPROM backup"
-#define TR_FACTORYRESET "Factory reset"
-#elif defined(PCBXLITE)
-#define TR_EEBACKUP "\001[ENT. Long]: Backup"
-#define TR_FACTORYRESET "\001[\300ENT. Long]: Fact. reset"
-#else
-#define TR_EEBACKUP TR("\001[ENTER Long]: Backup", "\012[ENTER Long]: EEPROM backup")
-#define TR_FACTORYRESET TR("\001[MENU Long]: Fact. reset", "\012[MENU Long]: Factory reset")
-#endif
+#define STR_EEBACKUP "EEPROM backup"
+#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET TR("Erase ALL", "Erase ALL models and settings?")
#define TR_TO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
-
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Name"
#define TR_PHASES_HEADERS_SW "Switch"
@@ -1205,6 +1212,7 @@
#define TR_JITTER_FILTER "ADC filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/es.h.txt b/radio/src/translations/es.h.txt
index a00d60d29..231d43006 100644
--- a/radio/src/translations/es.h.txt
+++ b/radio/src/translations/es.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -151,7 +154,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -159,21 +162,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -419,12 +412,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -541,9 +540,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -581,6 +581,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Interr"
#define TR_TRIMS "Trims"
#define TR_FADEIN "Inicio"
@@ -789,6 +790,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -926,18 +929,23 @@
#define TR_FLASH_INTERNAL_MODULE "Flash Internal Module"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
-#define TR_WRITING "\032Writing..."
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
+#define STR_WRITING "Writing..."
#define TR_CONFIRM_FORMAT "Confirm Format?"
#define TR_INTERNALRF "Interna RF"
#define TR_EXTERNALRF "Externa RF"
#define TR_FAILSAFE INDENT"Modo sgdad."
#define TR_FAILSAFESET "AJUSTES SGDAD."
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Codigo Pais"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Idioma voces"
#define TR_UNITSSYSTEM "Unidades"
#define TR_EDIT "Editar"
@@ -967,10 +975,16 @@
#define TR_BUZZER INDENT"Zumbador"
#define TR_BYTES "bytes"
#define TR_MODULE_BIND "[Enlace]"
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE "[Limites]"
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Ajuste]"
@@ -978,6 +992,7 @@
#define TR_ANTENNAPROBLEM CENTER "¡Problema antena TX!"
#define TR_MODELIDUSED TR("ID en uso", "ID modelo en uso")
#define TR_MODULE INDENT "Modulo"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_VALUE "Value"
@@ -1024,8 +1039,8 @@
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
-#define TR_EEBACKUP "\004[ENTER Long] to backup the EEPROM"
-#define TR_FACTORYRESET "\012[MENU Long]: Factory reset"
+#define STR_EEBACKUP "Backup the EEPROM"
+#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
@@ -1200,6 +1215,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/fi.h.txt b/radio/src/translations/fi.h.txt
index 818aaa110..b3226e134 100644
--- a/radio/src/translations/fi.h.txt
+++ b/radio/src/translations/fi.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -151,7 +154,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -159,21 +162,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -419,12 +412,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -533,9 +532,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -573,6 +573,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Switch"
#define TR_TRIMS "Trims"
#define TR_FADEIN "Fade In"
@@ -781,6 +782,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -918,18 +921,23 @@
#define TR_FLASH_INTERNAL_MODULE "Flash Internal Module"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
-#define TR_WRITING "\032Writing..."
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
+#define TR_WRITING "Writing..."
#define TR_CONFIRM_FORMAT "Confirm Format?"
#define TR_INTERNALRF "Internal RF"
#define TR_EXTERNALRF "External RF"
#define TR_FAILSAFE INDENT "Failsafe mode"
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Country Code"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Voice Language"
#define TR_UNITSSYSTEM "Units"
#define TR_EDIT "Edit"
@@ -959,10 +967,16 @@
#define TR_BUZZER INDENT"Buzzer"
#define TR_BYTES "bytes"
#define TR_MODULE_BIND "[Bind]"
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE "[Range]"
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Set]"
@@ -970,6 +984,7 @@
#define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!"
#define TR_MODELIDUSED TR("ID used in:", "Receiver ID used in:")
#define TR_MODULE INDENT "Module"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_VALUE "Value"
@@ -1016,8 +1031,8 @@
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
-#define TR_EEBACKUP "\004[ENTER Long] to backup the EEPROM"
-#define TR_FACTORYRESET "\012[MENU Long]: Factory reset"
+#define STR_EEBACKUP "Backup the EEPROM"
+#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
@@ -1186,6 +1201,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/fr.h.txt b/radio/src/translations/fr.h.txt
index cf2b657fe..9045b18fd 100644
--- a/radio/src/translations/fr.h.txt
+++ b/radio/src/translations/fr.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Popup\0""Joyst\0""SDCard""Série\0", "Demander""Joystick""Stockage""Série\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -151,7 +154,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -159,21 +162,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SLV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -432,12 +425,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -554,9 +553,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
+ #define TR_POPUPS_ENTER_EXIT TR(TR_EXIT "\010" TR_ENTER, TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER)
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -590,6 +590,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH TR("Inter", "Interrupteur")
#define TR_TRIMS "Trims"
#define TR_FADEIN "Fondu ON"
@@ -794,6 +795,8 @@
#define TR_MODULE_WAITFORBIND "Binder d'abord"
#define TR_MODULE_BINDING "Bind..."
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Télem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Télem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Télem ON"
@@ -930,18 +933,23 @@
#define TR_FLASH_INTERNAL_MODULE TR("Flasher module int.", "Flasher module interne")
#define TR_FLASH_EXTERNAL_MODULE TR("Flasher module ext.", "Flasher module externe")
#define TR_FIRMWARE_UPDATE_ERROR TR("Erreur màj FW","Erreur de mise à jour")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
#define TR_WRITING TR("\14Ecriture...", "\032Ecriture...")
#define TR_CONFIRM_FORMAT "Confirmer Formatage?"
#define TR_INTERNALRF "HF interne"
#define TR_EXTERNALRF "HF externe"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Type failsafe")
#define TR_FAILSAFESET "REGLAGES FAILSAFE"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "CAPTEUR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE TR("Zone géo.", "Zone géographique")
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG TR("Langue voix", "Langue annonces vocales")
#define TR_UNITSSYSTEM "Unités"
#define TR_EDIT "Editer"
@@ -971,17 +979,24 @@
#define TR_BUZZER INDENT "Bipeur"
#define TR_BYTES "bytes"
#define TR_MODULE_BIND BUTTON(TR("Bnd", "Bind"))
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE BUTTON(TR("Prt", "Port."))
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN BUTTON("RAZ")
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
-#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
+#define TR_KEYS_BTN BUTTON(TR("Swtchs", "Switches"))
+#define TR_ANALOGS_BTN BUTTON(TR("Anas", "Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET BUTTON("Déf")
#define TR_TRAINER "Ecolage"
#define TR_ANTENNAPROBLEM CENTER "Antenne radio défectueuse!"
#define TR_MODELIDUSED TR("ID affecté à :", "No de récepteur utilisé par :")
#define TR_MODULE INDENT "Type de module"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Type tél.", "Type télémétrie")
#define TR_TELEMETRY_SENSORS "Capteurs"
#define TR_VALUE "Valeur"
@@ -1029,19 +1044,18 @@
#define TR_INPUTS "Entrées"
#define TR_OUTPUTS "Sorties"
#if defined(COLORLCD)
-#define TR_EEBACKUP "Sauvegarder l'EEPROM"
-#define TR_FACTORYRESET "RAZ d'usine"
+#define STR_EEBACKUP "Sauvegarder l'EEPROM"
+#define STR_FACTORYRESET "RAZ d'usine"
#elif defined(PCBXLITE)
-#define TR_EEBACKUP "[ENTER Long]:Sauvegarde"
-#define TR_FACTORYRESET "[\300ENTER Long]: RAZ usine"
+#define STR_EEBACKUP "Sauvegarde"
+#define STR_FACTORYRESET "RAZ usine"
#else
-#define TR_EEBACKUP TR("[ENTER Long]:Sauvegarde", "\004[ENTER Long]: Sauvegarder l'EEPROM")
-#define TR_FACTORYRESET TR("\001[MENU Long]: RAZ d'usine", "\016[MENU Long]: RAZ d'usine")
+#define STR_EEBACKUP TR("Sauvegarde", "Sauvegarder l'EEPROM")
+#define STR_FACTORYRESET "RAZ d'usine"
#endif
#define TR_CONFIRMRESET TR("Effacer TOUT?","Effacer TOUS modèles/réglages?")
#define TR_TO_MANY_LUA_SCRIPTS "Trop de scripts lua!"
-
// Horus and Taranis column headers
#define TR_PHASES_HEADERS_NAME "Nom"
#define TR_PHASES_HEADERS_SW "Inter"
@@ -1212,6 +1226,7 @@
#define TR_JITTER_FILTER "Filtre ADC"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/it.h.txt b/radio/src/translations/it.h.txt
index 83d79217b..5b2730408 100644
--- a/radio/src/translations/it.h.txt
+++ b/radio/src/translations/it.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -151,7 +154,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -159,21 +162,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -421,12 +414,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -543,9 +542,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -579,6 +579,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Inter."
#define TR_TRIMS "Trims"
#define TR_FADEIN "Diss.In"
@@ -783,6 +784,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -920,18 +923,23 @@
#define TR_FLASH_INTERNAL_MODULE "Progr. Modulo Interno"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
#define TR_WRITING "\032Scrivendo..."
#define TR_CONFIRM_FORMAT "Confermi Format?"
#define TR_INTERNALRF "Modulo Interno"
#define TR_EXTERNALRF "Modulo esterno"
#define TR_FAILSAFE "Modo failsafe"
#define TR_FAILSAFESET TR("FAILSAFE","IMPOSTAZIONI FAILSAFE")
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE TR("Codice Paese","Standard 2.4Ghz")
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Lingua Voce"
#define TR_UNITSSYSTEM "Unità"
#define TR_EDIT "Modifica"
@@ -961,10 +969,16 @@
#define TR_BUZZER INDENT"Buzzer"
#define TR_BYTES "Bytes"
#define TR_MODULE_BIND "[Bind]"
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE "[Range]"
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Set]"
@@ -972,6 +986,7 @@
#define TR_ANTENNAPROBLEM CENTER "Problemi antenna TX!"
#define TR_MODELIDUSED TR("ID già usato","ID Modello già usato")
#define TR_MODULE INDENT "Modulo"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE "Tipo Telemetria"
#define TR_TELEMETRY_SENSORS "Sensori"
#define TR_VALUE "Valore"
@@ -1018,8 +1033,8 @@
#define TR_SCRIPT "Script"
#define TR_INPUTS "Ingresso"
#define TR_OUTPUTS "Uscita"
-#define TR_EEBACKUP "\004[ENTER Lungo] per copiare la EEPROM"
-#define TR_FACTORYRESET "\012[MENU Lungo]: Inizializza dati"
+#define STR_EEBACKUP "Copiare la EEPROM"
+#define STR_FACTORYRESET "Inizializza dati"
#define TR_CONFIRMRESET "Resettare TUTTI i dati?"
#define TR_TO_MANY_LUA_SCRIPTS "Troppi Scripts Lua!"
@@ -1195,6 +1210,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/nl.h.txt b/radio/src/translations/nl.h.txt
index c5774188e..2671ca6fb 100644
--- a/radio/src/translations/nl.h.txt
+++ b/radio/src/translations/nl.h.txt
@@ -103,8 +103,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "UIT\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Popup\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "UIT\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -153,7 +156,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -161,21 +164,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -414,12 +407,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -538,9 +537,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -573,6 +573,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH TR("Schak.", "Schakelaar")
#define TR_TRIMS "Trims"
#define TR_FADEIN "Fade in"
@@ -784,6 +785,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -921,18 +924,23 @@
#define TR_FLASH_INTERNAL_MODULE "Flash interne XJT-Module"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
#define TR_WRITING "\032Schrijven..."
#define TR_CONFIRM_FORMAT "Formatteren bevestigen?"
#define TR_INTERNALRF "Interne RF"
#define TR_EXTERNALRF "Externe RF"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafe Modus")
#define TR_FAILSAFESET "Failsafe instellen"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Landcode"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Taal"
#define TR_UNITSSYSTEM "Eenheden"
#define TR_EDIT "Wijzigen"
@@ -962,10 +970,16 @@
#define TR_BUZZER INDENT "Zoemer"
#define TR_BYTES "bytes"
#define TR_MODULE_BIND TR("[Bnd]", "[Bind]")
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE TR("[Rng]", "[Range]")
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Set]"
@@ -973,6 +987,7 @@
#define TR_ANTENNAPROBLEM CENTER "TX-Antenneprobleem!"
#define TR_MODELIDUSED TR("ID al gebruikt", "Model-ID al gebruikt")
#define TR_MODULE INDENT "Module-Type"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetrietype")
#define TR_TELEMETRY_SENSORS "Sensoren"
#define TR_VALUE "Waarde"
@@ -1020,11 +1035,11 @@
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
#if defined(COLORLCD)
-#define TR_EEBACKUP "EEPROM backup"
-#define TR_FACTORYRESET "Factory reset"
+#define STR_EEBACKUP "EEPROM backup"
+#define STR_FACTORYRESET "Factory reset"
#else
-#define TR_EEBACKUP TR("\001[ENTER Lang]: Backup", "\012[ENTER Lang]: EEPROM backup => SD")
-#define TR_FACTORYRESET TR("\001[MENU Lang]: Fact. reset", "\012[MENU Lang]: Factory reset")
+#define STR_EEBACKUP TR("Backup", "EEPROM backup => SD")
+#define STR_FACTORYRESET TR("Fact. reset", "Factory reset")
#endif
#define TR_CONFIRMRESET TR("Wis Alles?", "Wis ALLE modellen en instellingen?")
@@ -1202,6 +1217,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/pl.h.txt b/radio/src/translations/pl.h.txt
index ed2a754c9..b31b60316 100644
--- a/radio/src/translations/pl.h.txt
+++ b/radio/src/translations/pl.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -152,7 +155,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -160,21 +163,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POZ""NEG"
@@ -422,12 +415,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -544,9 +543,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -580,6 +580,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Przełą"
#define TR_TRIMS "Trymy"
#define TR_FADEIN "Pojawia"
@@ -784,6 +785,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -921,18 +924,23 @@
#define TR_FLASH_INTERNAL_MODULE "Sflashuj Moduł Wewnętrzny"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
#define TR_WRITING "\032Zapis... "
#define TR_CONFIRM_FORMAT "Zatwierdź Format?"
#define TR_INTERNALRF "Wewn.Moduł RF"
#define TR_EXTERNALRF "Zewn.Moduł RF"
#define TR_FAILSAFE TR(INDENT"Failsafe",INDENT"Tryb Failsafe")
#define TR_FAILSAFESET "USTAWIENIE FAILSAFE"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "CZUJNIK"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Kod regionu"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Język głosu"
#define TR_UNITSSYSTEM "Jednostki"
#define TR_EDIT "Edytuj"
@@ -962,10 +970,16 @@
#define TR_BUZZER INDENT"Brzęczyk"
#define TR_BYTES "bajty"
#define TR_MODULE_BIND TR("[BND]","[Bind]")
+#define TR_TRANSFER_BUTTON BUTTON("Transfert)
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE TR("[Zas]","Zasięg")
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Set]"
@@ -973,6 +987,7 @@
#define TR_ANTENNAPROBLEM CENTER "Problem z anteną TX"
#define TR_MODELIDUSED TR("ID zajęte","ID modelu zajęte")
#define TR_MODULE INDENT "Moduł "
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Typ ", "Typ Telemetrii")
#define TR_TELEMETRY_SENSORS "Czujniki"
#define TR_VALUE "Wartość"
@@ -1019,8 +1034,8 @@
#define TR_SCRIPT "Skrypt"
#define TR_INPUTS "Wejścia"
#define TR_OUTPUTS "Wyjścia"
-#define TR_EEBACKUP "\012[ENTER Długo] Backup EEPROMu"
-#define TR_FACTORYRESET "\012[MENU Long]: Ustaw.Fabrycz"
+#define STR_EEBACKUP "Backup EEPROMu"
+#define STR_FACTORYRESET "Ustaw.Fabrycz"
#define TR_CONFIRMRESET "WYkasować wszytkie modele? "
#define TR_TO_MANY_LUA_SCRIPTS "Za dużo skryptów Lua!"
@@ -1196,6 +1211,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/pt.h.txt b/radio/src/translations/pt.h.txt
index fe87fcff8..6c5b90e30 100644
--- a/radio/src/translations/pt.h.txt
+++ b/radio/src/translations/pt.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "OFF\0""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Popup\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "OFF\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -150,7 +153,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -158,21 +161,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
- #define TR_XPPM
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "POS""NEG"
@@ -418,12 +411,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -540,9 +539,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -580,6 +580,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Chave"
#define TR_TRIMS "Trims"
#define TR_FADEIN "Aparecer"
@@ -789,6 +790,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -925,18 +928,23 @@
#define TR_FLASH_INTERNAL_MODULE "Flash Internal Module"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
-#define TR_WRITING "\032Writing..."
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
+#define STR_WRITING "Writing..."
#define TR_CONFIRM_FORMAT "Confirm Format?"
#define TR_INTERNALRF "Internal RF"
#define TR_EXTERNALRF "External RF"
#define TR_FAILSAFE "Failsafe mode"
#define TR_FAILSAFESET "FAILSAFE SETTINGS"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Country Code"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Voice Language"
#define TR_UNITSSYSTEM "Units"
#define TR_EDIT "Edit"
@@ -966,10 +974,16 @@
#define TR_BUZZER INDENT"Buzzer"
#define TR_BYTES "bytes"
#define TR_MODULE_BIND "[Bind]"
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE "[Range]"
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Reset]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Set]"
@@ -977,6 +991,7 @@
#define TR_ANTENNAPROBLEM CENTER "TX Antenna problem!"
#define TR_MODELIDUSED TR("ID used in:", "Receiver ID used in:")
#define TR_MODULE INDENT "Module"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE TR("Type", "Telemetry Type")
#define TR_TELEMETRY_SENSORS "Sensors"
#define TR_VALUE "Value"
@@ -1023,8 +1038,8 @@
#define TR_SCRIPT "Script"
#define TR_INPUTS "Inputs"
#define TR_OUTPUTS "Outputs"
-#define TR_EEBACKUP "\004[ENTER Long] to backup the EEPROM"
-#define TR_FACTORYRESET "\012[MENU Long]: Factory reset"
+#define STR_EEBACKUP "Backup the EEPROM"
+#define STR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TO_MANY_LUA_SCRIPTS "Too many Lua scripts!"
@@ -1199,6 +1214,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/src/translations/se.h.txt b/radio/src/translations/se.h.txt
index 9e3e6f898..8eee8f3f6 100644
--- a/radio/src/translations/se.h.txt
+++ b/radio/src/translations/se.h.txt
@@ -101,8 +101,11 @@
#define LEN_USBMODES TR("\006", "\010")
#define TR_USBMODES TR("Ask\0 ""Joyst\0""SDCard""Serial", "Ask\0 ""Joystick""Storage\0""Serial\0 ")
-#define LEN_TARANIS_PROTOCOLS "\004"
-#define TR_TARANIS_PROTOCOLS "Av\0 ""PPM\0""XJT\0""DSM2""CRSF""MULT""R9M\0""SBUS"
+#define LEN_JACKMODES "\007"
+#define TR_JACKMODES "Ask\0 ""Audio\0 ""Trainer"
+
+#define LEN_TARANIS_PROTOCOLS "\005"
+#define TR_TARANIS_PROTOCOLS "Av\0 ""PPM\0 ""XJT\0 ""XJT2\0""DSM2\0""CRSF\0""MULT\0""R9M\0 ""R9M2\0""R9LT\0""R9LT2""R9LP2""SBUS\0"
#define LEN_TELEMETRY_PROTOCOLS "\017"
#define TR_TELEMETRY_PROTOCOLS "FrSky S.PORT\0 ""FrSky D\0 ""FrSky D (cable)""TBS Crossfire\0 ""Spektrum\0 ""AFHDS2A IBUS\0 ""Multi Telemetry"
@@ -149,7 +152,7 @@
#if defined(PXX)
#define TR_PXX "PXX\0 "
-#elif defined(DSM2) || defined(IRPROTOS)
+#elif defined(DSM2)
#define TR_PXX "[PXX]\0"
#else
#define TR_PXX
@@ -157,19 +160,11 @@
#if defined(DSM2)
#define TR_DSM2 "LP45\0 ""DSM2\0 ""DSMX\0 "
-#elif defined(IRPROTOS)
- #define TR_DSM2 "[LP45]""[DSM2]""[DSMX]"
#else
#define TR_DSM2
#endif
-#if defined(IRPROTOS)
- #define TR_IRPROTOS "SILV TRAC09PICZ SWIFT\0"
-#else
- #define TR_IRPROTOS
-#endif
-
-#define TR_VPROTOS "PPM\0 " TR_XPPM TR_PXX TR_DSM2 TR_IRPROTOS
+#define TR_VPROTOS "PPM\0 " TR_PXX TR_DSM2
#define LEN_POSNEG "\003"
#define TR_POSNEG "Pos""Neg"
@@ -426,12 +421,18 @@
#elif defined(PCBX9E)
#define TR_POTS_VSRCRAW "\310F1\0""\310F2\0""\310F3\0""\310F4\0""\311S1\0""\311S2\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0""\312SI\0""\312SJ\0""\312SK\0""\312SL\0""\312SM\0""\312SN\0""\312SO\0""\312SP\0""\312SQ\0""\312SR\0"
+#elif defined(PCBXLITES)
+ #define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0"
#elif defined(PCBXLITE)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0"
#elif defined(PCBX7)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SF\0""\312SH\0"
+#elif defined(PCBX3)
+ #define TR_POTS_VSRCRAW "\310S1\0"
+ #define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0"
#elif defined(PCBTARANIS)
#define TR_POTS_VSRCRAW "\310S1\0""\310S2\0""\310S3\0""\311LS\0""\311RS\0"
#define TR_SW_VSRCRAW "\312SA\0""\312SB\0""\312SC\0""\312SD\0""\312SE\0""\312SF\0""\312SG\0""\312SH\0"
@@ -550,9 +551,10 @@
#endif
#if defined(PCBTARANIS)
- #define TR_POPUPS TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_POPUPS_ENTER_EXIT TR_EXIT "\010" "\010" "\010" "\010" TR_ENTER
+ #define TR_OK TR("\010" "\010" "\010" "[OK]", "\010" "\010" "\010" "\010" "\010" "[OK]")
#else
- #define TR_POPUPS TR_ENTER "\010" TR_EXIT
+ #define TR_POPUPS_ENTER_EXIT TR_ENTER "\010" TR_EXIT
#define OFS_EXIT sizeof(TR_ENTER)
#endif
@@ -590,6 +592,7 @@
#define TR_REFRESHRATE TR(INDENT "Refresh", INDENT "Refresh rate")
#define STR_WARN_BATTVOLTAGE TR(INDENT "Output is VBAT: ", INDENT "Warning: output level is VBAT: ")
#define TR_MS "ms"
+#define TR_FREQUENCY INDENT "Frequency"
#define TR_SWITCH "Brytare"
#define TR_TRIMS "Trimmar"
#define TR_FADEIN "Tona In"
@@ -795,6 +798,8 @@
#define TR_MODULE_WAITFORBIND "Bind to load protocol"
#define TR_MODULE_BINDING "Binding"
#define TR_REBIND "Rebinding required"
+#define TR_REG_OK "Registration ok"
+#define TR_BIND_OK "Bind successful"
#define TR_BINDING_CH1_8_TELEM_ON "Ch1-8 Telem ON"
#define TR_BINDING_CH1_8_TELEM_OFF "Ch1-8 Telem OFF"
#define TR_BINDING_CH9_16_TELEM_ON "Ch9-16 Telem ON"
@@ -932,18 +937,23 @@
#define TR_FLASH_INTERNAL_MODULE "Flash Internal Module"
#define TR_FLASH_EXTERNAL_MODULE "Flash external module"
#define TR_FIRMWARE_UPDATE_ERROR TR("FW update Error","Firmware update error")
+#define TR_FIRMWARE_UPDATE_SUCCESS "Flash successful"
#define TR_WRITING "\032Skriver..."
#define TR_CONFIRM_FORMAT "Formatera Minnet?"
#define TR_INTERNALRF "Intern Radio"
#define TR_EXTERNALRF "Extern Radiomodul"
#define TR_FAILSAFE TR(INDENT "Failsafe", INDENT "Failsafeläge")
#define TR_FAILSAFESET "FailsafeInställning"
+#define TR_REG_ID TR("Reg. ID", "Registration ID")
+#define TR_OWNER_ID "Owner ID"
+#define TR_PINMAPSET "PINMAP"
#define TR_HOLD "HOLD"
#define TR_NONE "NONE"
#define TR_MENUSENSOR "SENSOR"
#define TR_SENSOR "SENSOR"
#define TR_COUNTRYCODE "Landskod"
#define TR_USBMODE "USB Mode"
+#define TR_JACKMODE "Jack Mode"
#define TR_VOICELANG "Röstspråk"
#define TR_UNITSSYSTEM "Enheter"
#define TR_EDIT "Redigera"
@@ -973,10 +983,16 @@
#define TR_BUZZER INDENT"Summer"
#define TR_BYTES "byte"
#define TR_MODULE_BIND TR("[Bnd]", "[Bind]")
+#define TR_TRANSFER_BUTTON BUTTON("Transfer")
+#define TR_REGISTER_BUTTON BUTTON(TR("Reg", "Register"))
+#define TR_RXADD_BUTTON "BUTTON(Add)"
#define TR_MODULE_RANGE TR("[Tst]", "[Testa]")
+#define TR_BUTTON_SHARE BUTTON("Share")
+#define TR_RECEIVER_OPTIONS TR("REC. OPTIONS", "RECEIVER OPTIONS")
+#define TR_DEL_BUTTON BUTTON(TR("Del", "Delete"))
#define TR_RESET_BTN "[Nollställ]"
#define TR_DEBUG "Debug"
-#define TR_SWITCHES_BTN BUTTON(TR("SW","Switches"))
+#define TR_KEYS_BTN BUTTON(TR("SW","Switches"))
#define TR_ANALOGS_BTN BUTTON(TR("Analog","Analogs"))
#define TR_CALIB_BTN BUTTON("Calibration")
#define TR_SET "[Spara]"
@@ -984,6 +1000,7 @@
#define TR_ANTENNAPROBLEM CENTER "Fel på TX-antennen"
#define TR_MODELIDUSED TR("ID finns redan","ModellID används redan")
#define TR_MODULE INDENT "Modul"
+#define TR_RX_NAME "Rx Name"
#define TR_TELEMETRY_TYPE "Telemetrityp"
#define TR_TELEMETRY_SENSORS "Sensorer"
#define TR_VALUE "Värde"
@@ -1030,8 +1047,8 @@
#define TR_SCRIPT "Programkod"
#define TR_INPUTS "Input"
#define TR_OUTPUTS "Outputs"
-#define TR_EEBACKUP "\004[ENTER Lång] säkerhetskopiera EEPROM"
-#define TR_FACTORYRESET "\012[MENU Long]: Factory reset"
+#define TR_EEBACKUP "Säkerhetskopiera EEPROM"
+#define TR_FACTORYRESET "Factory reset"
#define TR_CONFIRMRESET "Erase ALL models and settings?"
#define TR_TO_MANY_LUA_SCRIPTS "För många Lua-scripts!"
@@ -1207,6 +1224,7 @@
#define TR_JITTER_FILTER "ADC Filter"
#define ZSTR_RSSI "RSSI"
+#define ZSTR_R9PW "R9PW"
#define ZSTR_RAS "SWR"
#define ZSTR_A1 "A1"
#define ZSTR_A2 "A2"
diff --git a/radio/util/fwoptions.py b/radio/util/fwoptions.py
index b990212e1..a48fb7c22 100755
--- a/radio/util/fwoptions.py
+++ b/radio/util/fwoptions.py
@@ -81,7 +81,6 @@ options_taranis = {
"shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
"multimodule": ("MULTIMODULE", "YES", "NO"),
- "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None)
}
options_taranisplus = {
@@ -99,7 +98,6 @@ options_taranisplus = {
"shutdownconfirm": ("SHUTDOWN_CONFIRMATION", "YES", "NO"),
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
"multimodule": ("MULTIMODULE", "YES", "NO"),
- "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None)
}
options_xlite = {
@@ -116,7 +114,6 @@ options_xlite = {
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
"multimodule": ("MULTIMODULE", "YES", "NO"),
"stdr9m": ("MODULE_R9M_FULLSIZE", "YES", None),
- "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None)
}
options_taranisx9e = {
@@ -134,7 +131,6 @@ options_taranisx9e = {
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
"horussticks": ("STICKS", "HORUS", "STANDARD"),
"multimodule": ("MULTIMODULE", "YES", "NO"),
- "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None)
}
options_x12s = {
@@ -149,7 +145,6 @@ options_x12s = {
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
"multimodule": ("MULTIMODULE", "YES", "NO"),
"pcbdev": ("PCBREV", "10", None),
- "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None)
}
options_x10 = {
@@ -163,5 +158,4 @@ options_x10 = {
"nooverridech": ("OVERRIDE_CHANNEL_FUNCTION", "NO", "YES"),
"eu": ("SUPPORT_D16_EU_ONLY", "YES", "NO"),
"multimodule": ("MULTIMODULE", "YES", "NO"),
- "flexr9m": ("MODULE_R9M_FLEX_FW", "YES", None)
}
diff --git a/tools/commit-tests.sh b/tools/commit-tests.sh
index 70d54f240..51d4d235b 100755
--- a/tools/commit-tests.sh
+++ b/tools/commit-tests.sh
@@ -87,6 +87,15 @@ if [[ " 9XRPRO ARM9X ALL " =~ " ${FLAVOR} " ]] ; then
make -j${CORES} gtests ; ./gtests ${TEST_OPTIONS}
fi
+if [[ " X3 ALL " =~ " ${FLAVOR} " ]] ; then
+ # OpenTX on X3
+ rm -rf *
+ cmake ${COMMON_OPTIONS} -DPCB=X3 -DHELI=YES -DGVARS=YES ${SRCDIR}
+ make -j${CORES} ${FIRMARE_TARGET}
+ make -j${CORES} libsimulator
+ make -j${CORES} gtests ; ./gtests ${TEST_OPTIONS}
+fi
+
if [[ " X7 ALL " =~ " ${FLAVOR} " ]] ; then
# OpenTX on X7
rm -rf *
@@ -105,6 +114,15 @@ if [[ " XLITE ALL " =~ " ${FLAVOR} " ]] ; then
make -j${CORES} gtests ; ./gtests ${TEST_OPTIONS}
fi
+if [[ " XLITES ALL " =~ " ${FLAVOR} " ]] ; then
+ # OpenTX on X-Lites
+ rm -rf *
+ cmake ${COMMON_OPTIONS} -DPCB=XLITES -DHELI=YES -DGVARS=YES ${SRCDIR}
+ make -j${CORES} ${FIRMARE_TARGET}
+ make -j${CORES} libsimulator
+ make -j${CORES} gtests ; ./gtests ${TEST_OPTIONS}
+fi
+
if [[ " X9D X9 ALL " =~ " ${FLAVOR} " ]] ; then
# OpenTX on X9D
rm -rf *